[
  {
    "path": ".eslintrc",
    "content": "{\n  \"env\": {\n    \"browser\": true,\n    \"es6\": true,\n    \"node\": true\n  },\n  \"extends\": [\n    \"eslint:recommended\",\n    \"plugin:react/recommended\",\n    \"plugin:@typescript-eslint/eslint-recommended\",\n    \"plugin:@typescript-eslint/recommended\",\n    \"plugin:import/errors\",\n    \"plugin:import/warnings\"\n  ],\n  \"parser\": \"@typescript-eslint/parser\",\n  \"settings\": {\n    \"import/resolver\": {\n      \"node\": {\n        \"extensions\": [\".js\", \".jsx\", \".ts\", \".tsx\"]\n      },\n      \"alias\": {\n        \"map\": [\n          [\"@renderer\", \"./src/renderer\"],\n          [\"@components\", \"./src/renderer/components\"],\n          [\"@common\", \"./src/common\"],\n          [\"@main\", \"./src/main\"],\n          [\"@src\", \"./src\"],\n          [\"@misc\", \"./misc\"],\n          [\"@assets\", \"./assets\"]\n        ],\n        \"extensions\": [\".js\", \".jsx\", \".ts\", \".tsx\"]\n      }\n    },\n    \"react\": {\n      \"version\": \"latest\"\n    }\n  },\n  \"rules\": {\n    \"react/prop-types\": \"off\",\n    \"@typescript-eslint/no-var-requires\": \"off\"\n  }\n}\n"
  },
  {
    "path": ".gitattributes",
    "content": "*.scss linguist-detectable=false\n*.sass linguist-detectable=false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Desktop (please complete the following information):**\n - OS: [e.g. Windows, macOS, Linux]\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: enhancement\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*\n\n# Diagnostic reports (https://nodejs.org/api/report.html)\nreport.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n.DS_Store\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n*.lcov\n\n# nyc test coverage\n.nyc_output\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (https://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# TypeScript cache\n*.tsbuildinfo\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n.env.test\n\n# parcel-bundler cache (https://parceljs.org/)\n.cache\n\n# next.js build output\n.next\n\n# nuxt.js build output\n.nuxt\n\n# vuepress build output\n.vuepress/dist\n\n# Serverless directories\n.serverless/\n\n# FuseBox cache\n.fusebox/\n\n# DynamoDB Local files\n.dynamodb/\n\n# Webpack\n.webpack/\n\n# Electron-Forge\nout/\n"
  },
  {
    "path": ".hintrc",
    "content": "{\n  \"extends\": [\n    \"development\"\n  ],\n  \"hints\": {\n    \"axe/text-alternatives\": [\n      \"default\",\n      {\n        \"image-alt\": \"off\"\n      }\n    ],\n    \"meta-viewport\": \"off\",\n    \"no-inline-styles\": \"off\",\n    \"axe/name-role-value\": [\n      \"default\",\n      {\n        \"button-name\": \"off\"\n      }\n    ],\n    \"typescript-config/strict\": \"off\"\n  },\n  \"browserslist\": [\n    \"defaults\",\n    \"not ie 11\",\n    \"not and_ff <= 107\",\n    \"not firefox <= 109\",\n    \"not ios_saf <= 16.2\",\n    \"not safari <= 16.2\"\n  ]\n}"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"singleQuote\": true,\n  \"trailingComma\": \"all\",\n  \"jsxSingleQuote\": true\n}\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, religion, or sexual identity\nand orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n* Demonstrating empathy and kindness toward other people\n* Being respectful of differing opinions, viewpoints, and experiences\n* Giving and gracefully accepting constructive feedback\n* Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n* Focusing on what is best not just for us as individuals, but for the\n  overall community\n\nExamples of unacceptable behavior include:\n\n* The use of sexualized language or imagery, and sexual attention or\n  advances of any kind\n* Trolling, insulting or derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or email\n  address, without their explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\nRepository Discussions.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series\nof actions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or\npermanent ban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior,  harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within\nthe community.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.0, available at\nhttps://www.contributor-covenant.org/version/2/0/code_of_conduct.html.\n\nCommunity Impact Guidelines were inspired by [Mozilla's code of conduct\nenforcement ladder](https://github.com/mozilla/diversity).\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see the FAQ at\nhttps://www.contributor-covenant.org/faq. Translations are available at\nhttps://www.contributor-covenant.org/translations.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to Mathberet\n\nThank you for investing your time in contributing to our project!\n\nRead our [Code of Conduct](./CODE_OF_CONDUCT.md) to keep our community approachable and respectable.\n\n<br>\n\n## How to Contribute?\n\nYou can contribute to our project by providing `features/bugfixes/improvements` related Pull Requests.\n<br>\nJust make sure to test all the changes you provide before submission anything into this project.\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2023 Mathberet\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": "\n<div align=\"center\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://github.com/yonatanmgr/mathberet/assets/31913495/380ecf5e-5449-4646-ab4d-ac305bc96286\">\n    <source media=\"(prefers-color-scheme: light)\" srcset=\"https://github.com/yonatanmgr/mathberet/assets/31913495/557554da-7617-4b1b-b34b-79d4e34b4c78\">\n    <img width=500 src=\"https://github.com/yonatanmgr/mathberet/assets/31913495/380ecf5e-5449-4646-ab4d-ac305bc96286\" alt=\"mathberet logo\">\n  </picture>\n  <p><b>📝 Mathberet (Hebrew: מַתְבֶּרֶת)</b> - A self-hosted digital mathematics notebook, written in React and built with Electron</p>\n  <p><b>🚧 In active development, open for contributions! 🚧</b></p>\n</div>\n\n---\n\n> Currently works in Hebrew, English, Arabic, Russian and Spanish, localized using [i18next](https://github.com/i18next/i18next). Still buggy.\n\n## :white_check_mark: Features\n\n- [x] Block based drag-n-drop editor\n- [x] Text, Math, Graph and Drawing blocks are currently available\n- [x] LaTeX shortcuts and snippets\n- [x] Local files can be saved and loaded from the file system\n- [x] File tags (currently useless)\n- [x] Command bar (currently only used for user preferences)\n- [x] 6 color themes and light/dark theme\n- [ ] Customize LaTeX shortcuts\n- [ ] Shortcuts help menu\n- [ ] Searching from command bar\n- [ ] Adding points and polygons to graph blocks\n- [ ] Math memory sidebar (for variable assignments and quick functions)\n- [ ] Archive\n\n## :camera_flash: Screenshots\n\n### Hebrew\n\n![image](https://user-images.githubusercontent.com/31913495/225077627-82fa032c-88e7-4e25-971f-98a37a436d40.jpg)\n</details>\n\n### English\n\n<details><summary><b>Dark theme and purple accent color</b></summary>\n\n![image](https://user-images.githubusercontent.com/31913495/225168731-13afd8f2-7e17-448d-a434-5b6bd1f43494.png)\n</details>\n\n<details><summary><b>Light theme and green accent color</b></summary>\n\n![image](https://user-images.githubusercontent.com/31913495/225170025-65b7cde0-434d-4c66-8d9a-1c9237a92f3b.png)\n</details>\n\n<details><summary><b>Command bar (<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>)</b></summary>\n\n![image](https://user-images.githubusercontent.com/31913495/225170120-e3dcdeb3-bdf2-4fa9-80dc-f2ebbfe2051b.png)\n</details>\n\n## :bricks: Built With\n\n- [ERWT](https://github.com/codesbiome/electron-react-webpack-typescript-2023): Electron + React apps boilerplate\n- [react-grid-layout](https://github.com/react-grid-layout/react-grid-layout): Grid layout for the blocks\n- [slate](https://github.com/ianstormtaylor/slate): Text block component\n- [MathLive](https://cortexjs.io/mathlive/) ([react-math-view](https://github.com/arnog/react-mathlive)): Math block component\n- [Mafs](https://mafs.dev/): Graph block component\n- [tldraw](https://github.com/tldraw/tldraw): Drawing block component\n- [kbar](https://kbar.vercel.app/): Command bar\n- [react-complex-tree](https://rct.lukasbach.com/): Used for displaying the file system\n- [UIcons](https://github.com/freepik-company/flaticon-uicons): App icons\n\n## :building_construction: Building from source\n\n1. Clone the repository to a folder on your machine:\n```bash\ngit clone https://github.com/yonatanmgr/mathberet.git\n```\n2. Run `npm install` in the project root folder\n3. Run `npm start` in the project root folder\n\n## :handshake: Contributing\n\nWe welcome any positive contribution towards our project's growth! Whether you choose to work on a [listed feature](https://github.com/yonatanmgr/mathberet#white_check_mark-features) or create a new one, your help is appreciated. Simply submit a Pull Request after adding your code. To ensure a smooth process, please review our `CODE OF CONDUCT` and read the `CONTRIBUTING` guidelines for further details on submitting pull requests.\n\nMake sure to visit Mathberet's [project](https://github.com/users/yonatanmgr/projects/2) to view our roadmap and plans, and our [wiki](https://github.com/yonatanmgr/mathberet/wiki/%F0%9F%8F%A0-Home) to read the documentation!\n\n## :balance_scale: Liscense\n\nThis project is licensed under the MIT License - see the `LICENSE` file for details.\n\n## :technologist: Contributors\n\n<table>\n  <tbody>\n    <tr>\n      <td align=\"center\"><a href=\"https://github.com/yonatanmgr\"><img src=\"https://avatars.githubusercontent.com/u/31913495?v=3?s=100\" width=\"100px;\" alt=\"Yonatan Magier\"/><br /><sub><b>Yonatan Magier</b></sub></a><br />\n        <span title=\"Ideas & Planning\">🤔</span>\n        <a href=\"https://github.com/yonatanmgr/mathberet/commits?author=yonatanmgr\" title=\"Code\">💻</a>\n        <a href=\"https://github.com/yonatanmgr/mathberet/commits?author=yonatanmgr\" title=\"Maintenance\">🚧</a>\n        <a href=\"https://github.com/yonatanmgr/mathberet/tree/master/src/common/locals\" title=\"Translation\">🌍</a>\n        <span title=\"Design\">🎨</span>\n      </td>\n      <td align=\"center\"><a href=\"https://github.com/ErezBiren\"><img src=\"https://avatars.githubusercontent.com/u/7828909?v=3?s=100\" width=\"100px;\" alt=\"Erez Birenholz\"/><br /><sub><b>Erez Birenholz</b></sub></a><br />\n        <span title=\"Mentoring\">🧑‍🏫</span>\n        <a href=\"https://github.com/yonatanmgr/mathberet/commits?author=ErezBiren\" title=\"Code\">💻</a>\n        <a href=\"https://github.com/yonatanmgr/mathberet/commits?author=ErezBiren\" title=\"Maintenance\">🚧</a>\n        <a href=\"https://github.com/yonatanmgr/mathberet/tree/master/src/common/locals\" title=\"Translation\">🌍</a>\n      </td>\n      <td align=\"center\"><a href=\"https://github.com/Nadav0077\"><img src=\"https://avatars.githubusercontent.com/u/18245584?v=3?s=100\" width=\"100px;\" alt=\"Nadav Magier\"/><br /><sub><b>Nadav Magier</b></sub></a><br />\n        <a href=\"https://github.com/yonatanmgr/mathberet/commits?author=Nadav0077\" title=\"Code\">💻</a>\n        <a href=\"https://github.com/yonatanmgr/mathberet/commits?author=Nadav0077\" title=\"Maintenance\">🚧</a>\n        <a href=\"https://github.com/yonatanmgr/mathberet/tree/master/src/common/locals\" title=\"Translation\">🌍</a>\n        <span title=\"Security\">🛡️</span>\n      </td>\n      <td align=\"center\"><a href=\"https://github.com/zivnadel\"><img src=\"https://avatars.githubusercontent.com/u/52624380?v=3?s=100\" width=\"100px;\" alt=\"Ziv Nadel\"/><br /><sub><b>Ziv Nadel</b></sub></a><br />\n        <a href=\"https://github.com/yonatanmgr/mathberet/commits?author=zivnadel\" title=\"Code\">💻</a>\n        <a href=\"https://github.com/yonatanmgr/mathberet/commits?author=zivnadel\" title=\"Maintenance\">🚧</a>\n      </td>\n    </tr>\n  </tbody>\n</table>\n"
  },
  {
    "path": "assets/icons/uicons.css",
    "content": "@font-face{font-family:uicons-regular-rounded;src:url(../webfonts/uicons-regular-rounded-BG3GDTFR.eot) format(\"embedded-opentype\"),url(../webfonts/uicons-regular-rounded-3OJX2N3K.woff2) format(\"woff2\"),url(../webfonts/uicons-regular-rounded-ATYWIXGY.woff) format(\"woff\")}i[class^=fi-rr-]:before,i[class*=\" fi-rr-\"]:before,span[class^=fi-rr-]:before,span[class*=fi-rr-]:before{font-family:uicons-regular-rounded!important;font-style:normal;font-weight:400!important;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fi-rr-0:before{content:\"\\f101\"}.fi-rr-1:before{content:\"\\f102\"}.fi-rr-2:before{content:\"\\f103\"}.fi-rr-3:before{content:\"\\f104\"}.fi-rr-4:before{content:\"\\f105\"}.fi-rr-5:before{content:\"\\f106\"}.fi-rr-6:before{content:\"\\f107\"}.fi-rr-7:before{content:\"\\f108\"}.fi-rr-8:before{content:\"\\f109\"}.fi-rr-9:before{content:\"\\f10a\"}.fi-rr-a:before{content:\"\\f10b\"}.fi-rr-acorn:before{content:\"\\f10c\"}.fi-rr-ad:before{content:\"\\f10d\"}.fi-rr-add-document:before{content:\"\\f10e\"}.fi-rr-add-folder:before{content:\"\\f10f\"}.fi-rr-add:before{content:\"\\f110\"}.fi-rr-address-book:before{content:\"\\f111\"}.fi-rr-air-conditioner:before{content:\"\\f112\"}.fi-rr-air-freshener:before{content:\"\\f113\"}.fi-rr-alarm-clock:before{content:\"\\f114\"}.fi-rr-alarm-exclamation:before{content:\"\\f115\"}.fi-rr-alarm-plus:before{content:\"\\f116\"}.fi-rr-alarm-snooze:before{content:\"\\f117\"}.fi-rr-album-circle-plus:before{content:\"\\f118\"}.fi-rr-album-circle-user:before{content:\"\\f119\"}.fi-rr-album-collection:before{content:\"\\f11a\"}.fi-rr-album:before{content:\"\\f11b\"}.fi-rr-align-justify:before{content:\"\\f11c\"}.fi-rr-align-left:before{content:\"\\f11d\"}.fi-rr-ambulance:before{content:\"\\f11e\"}.fi-rr-angle-circle-down:before{content:\"\\f11f\"}.fi-rr-angle-circle-left:before{content:\"\\f120\"}.fi-rr-angle-circle-right:before{content:\"\\f121\"}.fi-rr-angle-circle-up:before{content:\"\\f122\"}.fi-rr-angle-double-left:before{content:\"\\f123\"}.fi-rr-angle-double-right:before{content:\"\\f124\"}.fi-rr-angle-double-small-down:before{content:\"\\f125\"}.fi-rr-angle-double-small-left:before{content:\"\\f126\"}.fi-rr-angle-double-small-right:before{content:\"\\f127\"}.fi-rr-angle-double-small-up:before{content:\"\\f128\"}.fi-rr-angle-down:before{content:\"\\f129\"}.fi-rr-angle-left:before{content:\"\\f12a\"}.fi-rr-angle-right:before{content:\"\\f12b\"}.fi-rr-angle-small-down:before{content:\"\\f12c\"}.fi-rr-angle-small-left:before{content:\"\\f12d\"}.fi-rr-angle-small-right:before{content:\"\\f12e\"}.fi-rr-angle-small-up:before{content:\"\\f12f\"}.fi-rr-angle-square-down:before{content:\"\\f130\"}.fi-rr-angle-square-left:before{content:\"\\f131\"}.fi-rr-angle-square-right:before{content:\"\\f132\"}.fi-rr-angle-square-up:before{content:\"\\f133\"}.fi-rr-angle-up:before{content:\"\\f134\"}.fi-rr-angry:before{content:\"\\f135\"}.fi-rr-animated-icon:before{content:\"\\f136\"}.fi-rr-apartment:before{content:\"\\f137\"}.fi-rr-api:before{content:\"\\f138\"}.fi-rr-apple-crate:before{content:\"\\f139\"}.fi-rr-apple-whole:before{content:\"\\f13a\"}.fi-rr-apps-add:before{content:\"\\f13b\"}.fi-rr-apps-delete:before{content:\"\\f13c\"}.fi-rr-apps-sort:before{content:\"\\f13d\"}.fi-rr-apps:before{content:\"\\f13e\"}.fi-rr-archive:before{content:\"\\f13f\"}.fi-rr-archway:before{content:\"\\f140\"}.fi-rr-arrow-alt-circle-down:before{content:\"\\f141\"}.fi-rr-arrow-alt-circle-left:before{content:\"\\f142\"}.fi-rr-arrow-alt-circle-right:before{content:\"\\f143\"}.fi-rr-arrow-alt-circle-up:before{content:\"\\f144\"}.fi-rr-arrow-alt-down:before{content:\"\\f145\"}.fi-rr-arrow-alt-from-bottom:before{content:\"\\f146\"}.fi-rr-arrow-alt-from-left:before{content:\"\\f147\"}.fi-rr-arrow-alt-from-right:before{content:\"\\f148\"}.fi-rr-arrow-alt-from-top:before{content:\"\\f149\"}.fi-rr-arrow-alt-left:before{content:\"\\f14a\"}.fi-rr-arrow-alt-right:before{content:\"\\f14b\"}.fi-rr-arrow-alt-square-down:before{content:\"\\f14c\"}.fi-rr-arrow-alt-square-left:before{content:\"\\f14d\"}.fi-rr-arrow-alt-square-right:before{content:\"\\f14e\"}.fi-rr-arrow-alt-square-up:before{content:\"\\f14f\"}.fi-rr-arrow-alt-to-bottom:before{content:\"\\f150\"}.fi-rr-arrow-alt-to-left:before{content:\"\\f151\"}.fi-rr-arrow-alt-to-right:before{content:\"\\f152\"}.fi-rr-arrow-alt-to-top:before{content:\"\\f153\"}.fi-rr-arrow-alt-up:before{content:\"\\f154\"}.fi-rr-arrow-circle-down:before{content:\"\\f155\"}.fi-rr-arrow-circle-left:before{content:\"\\f156\"}.fi-rr-arrow-circle-right:before{content:\"\\f157\"}.fi-rr-arrow-circle-up:before{content:\"\\f158\"}.fi-rr-arrow-down-from-dotted-line:before{content:\"\\f159\"}.fi-rr-arrow-down-small-big:before{content:\"\\f15a\"}.fi-rr-arrow-down-to-dotted-line:before{content:\"\\f15b\"}.fi-rr-arrow-down-to-square:before{content:\"\\f15c\"}.fi-rr-arrow-down-triangle-square:before{content:\"\\f15d\"}.fi-rr-arrow-down:before{content:\"\\f15e\"}.fi-rr-arrow-from-bottom:before{content:\"\\f15f\"}.fi-rr-arrow-from-left:before{content:\"\\f160\"}.fi-rr-arrow-from-right:before{content:\"\\f161\"}.fi-rr-arrow-from-top:before{content:\"\\f162\"}.fi-rr-arrow-left-from-line:before{content:\"\\f163\"}.fi-rr-arrow-left:before{content:\"\\f164\"}.fi-rr-arrow-right-to-bracket:before{content:\"\\f165\"}.fi-rr-arrow-right:before{content:\"\\f166\"}.fi-rr-arrow-small-down:before{content:\"\\f167\"}.fi-rr-arrow-small-left:before{content:\"\\f168\"}.fi-rr-arrow-small-right:before{content:\"\\f169\"}.fi-rr-arrow-small-up:before{content:\"\\f16a\"}.fi-rr-arrow-square-down:before{content:\"\\f16b\"}.fi-rr-arrow-square-left:before{content:\"\\f16c\"}.fi-rr-arrow-square-right:before{content:\"\\f16d\"}.fi-rr-arrow-square-up:before{content:\"\\f16e\"}.fi-rr-arrow-to-bottom:before{content:\"\\f16f\"}.fi-rr-arrow-to-left:before{content:\"\\f170\"}.fi-rr-arrow-to-right:before{content:\"\\f171\"}.fi-rr-arrow-to-top:before{content:\"\\f172\"}.fi-rr-arrow-trend-down:before{content:\"\\f173\"}.fi-rr-arrow-trend-up:before{content:\"\\f174\"}.fi-rr-arrow-turn-down-left:before{content:\"\\f175\"}.fi-rr-arrow-turn-down-right:before{content:\"\\f176\"}.fi-rr-arrow-up-from-dotted-line:before{content:\"\\f177\"}.fi-rr-arrow-up-from-square:before{content:\"\\f178\"}.fi-rr-arrow-up-left-from-circle:before{content:\"\\f179\"}.fi-rr-arrow-up-left:before{content:\"\\f17a\"}.fi-rr-arrow-up-right-and-arrow-down-left-from-center:before{content:\"\\f17b\"}.fi-rr-arrow-up-right-from-square:before{content:\"\\f17c\"}.fi-rr-arrow-up-right:before{content:\"\\f17d\"}.fi-rr-arrow-up-small-big:before{content:\"\\f17e\"}.fi-rr-arrow-up-square-triangle:before{content:\"\\f17f\"}.fi-rr-arrow-up-to-dotted-line:before{content:\"\\f180\"}.fi-rr-arrow-up:before{content:\"\\f181\"}.fi-rr-arrows-alt-h:before{content:\"\\f182\"}.fi-rr-arrows-alt-v:before{content:\"\\f183\"}.fi-rr-arrows-alt:before{content:\"\\f184\"}.fi-rr-arrows-cross:before{content:\"\\f185\"}.fi-rr-arrows-from-dotted-line:before{content:\"\\f186\"}.fi-rr-arrows-from-line:before{content:\"\\f187\"}.fi-rr-arrows-h-copy:before{content:\"\\f188\"}.fi-rr-arrows-h:before{content:\"\\f189\"}.fi-rr-arrows-repeat-1:before{content:\"\\f18a\"}.fi-rr-arrows-repeat:before{content:\"\\f18b\"}.fi-rr-arrows-retweet:before{content:\"\\f18c\"}.fi-rr-arrows-to-dotted-line:before{content:\"\\f18d\"}.fi-rr-arrows-to-line:before{content:\"\\f18e\"}.fi-rr-arrows:before{content:\"\\f18f\"}.fi-rr-assept-document:before{content:\"\\f190\"}.fi-rr-assistive-listening-systems:before{content:\"\\f191\"}.fi-rr-asterik:before{content:\"\\f192\"}.fi-rr-at:before{content:\"\\f193\"}.fi-rr-attribution-pen:before{content:\"\\f194\"}.fi-rr-attribution-pencil:before{content:\"\\f195\"}.fi-rr-aubergine:before{content:\"\\f196\"}.fi-rr-audio-description-slash:before{content:\"\\f197\"}.fi-rr-avocado:before{content:\"\\f198\"}.fi-rr-b:before{content:\"\\f199\"}.fi-rr-baby-carriage:before{content:\"\\f19a\"}.fi-rr-background:before{content:\"\\f19b\"}.fi-rr-backpack:before{content:\"\\f19c\"}.fi-rr-bacon:before{content:\"\\f19d\"}.fi-rr-badge-check:before{content:\"\\f19e\"}.fi-rr-badge-dollar:before{content:\"\\f19f\"}.fi-rr-badge-percent:before{content:\"\\f1a0\"}.fi-rr-badge-sheriff:before{content:\"\\f1a1\"}.fi-rr-badge:before{content:\"\\f1a2\"}.fi-rr-bags-shopping:before{content:\"\\f1a3\"}.fi-rr-bahai:before{content:\"\\f1a4\"}.fi-rr-balance-scale-left:before{content:\"\\f1a5\"}.fi-rr-balance-scale-right:before{content:\"\\f1a6\"}.fi-rr-ball:before{content:\"\\f1a7\"}.fi-rr-balloons:before{content:\"\\f1a8\"}.fi-rr-ballot:before{content:\"\\f1a9\"}.fi-rr-ban-bug:before{content:\"\\f1aa\"}.fi-rr-ban:before{content:\"\\f1ab\"}.fi-rr-band-aid:before{content:\"\\f1ac\"}.fi-rr-bank:before{content:\"\\f1ad\"}.fi-rr-barber-shop:before{content:\"\\f1ae\"}.fi-rr-barcode-read:before{content:\"\\f1af\"}.fi-rr-barcode-scan:before{content:\"\\f1b0\"}.fi-rr-barcode:before{content:\"\\f1b1\"}.fi-rr-bars-filter:before{content:\"\\f1b2\"}.fi-rr-bars-progress:before{content:\"\\f1b3\"}.fi-rr-bars-sort:before{content:\"\\f1b4\"}.fi-rr-baseball-alt:before{content:\"\\f1b5\"}.fi-rr-baseball:before{content:\"\\f1b6\"}.fi-rr-basket:before{content:\"\\f1b7\"}.fi-rr-basketball:before{content:\"\\f1b8\"}.fi-rr-battery-bolt:before{content:\"\\f1b9\"}.fi-rr-battery-empty:before{content:\"\\f1ba\"}.fi-rr-battery-full:before{content:\"\\f1bb\"}.fi-rr-battery-half:before{content:\"\\f1bc\"}.fi-rr-battery-quarter:before{content:\"\\f1bd\"}.fi-rr-battery-slash:before{content:\"\\f1be\"}.fi-rr-battery-three-quarters:before{content:\"\\f1bf\"}.fi-rr-beacon:before{content:\"\\f1c0\"}.fi-rr-bed-alt:before{content:\"\\f1c1\"}.fi-rr-bed:before{content:\"\\f1c2\"}.fi-rr-beer:before{content:\"\\f1c3\"}.fi-rr-bell-ring:before{content:\"\\f1c4\"}.fi-rr-bell-school:before{content:\"\\f1c5\"}.fi-rr-bell:before{content:\"\\f1c6\"}.fi-rr-bells:before{content:\"\\f1c7\"}.fi-rr-bench-tree:before{content:\"\\f1c8\"}.fi-rr-betamax:before{content:\"\\f1c9\"}.fi-rr-bike:before{content:\"\\f1ca\"}.fi-rr-biking-mountain:before{content:\"\\f1cb\"}.fi-rr-biking:before{content:\"\\f1cc\"}.fi-rr-billiard:before{content:\"\\f1cd\"}.fi-rr-binary-circle-check:before{content:\"\\f1ce\"}.fi-rr-binary-lock:before{content:\"\\f1cf\"}.fi-rr-binary-slash:before{content:\"\\f1d0\"}.fi-rr-binary:before{content:\"\\f1d1\"}.fi-rr-binoculars:before{content:\"\\f1d2\"}.fi-rr-blinds-open:before{content:\"\\f1d3\"}.fi-rr-blinds-raised:before{content:\"\\f1d4\"}.fi-rr-blinds:before{content:\"\\f1d5\"}.fi-rr-block-brick:before{content:\"\\f1d6\"}.fi-rr-block:before{content:\"\\f1d7\"}.fi-rr-blog-pencil:before{content:\"\\f1d8\"}.fi-rr-blog-text:before{content:\"\\f1d9\"}.fi-rr-bold:before{content:\"\\f1da\"}.fi-rr-bolt:before{content:\"\\f1db\"}.fi-rr-bomb:before{content:\"\\f1dc\"}.fi-rr-bone:before{content:\"\\f1dd\"}.fi-rr-book-alt:before{content:\"\\f1de\"}.fi-rr-book-arrow-right:before{content:\"\\f1df\"}.fi-rr-book-arrow-up:before{content:\"\\f1e0\"}.fi-rr-book-atlas:before{content:\"\\f1e1\"}.fi-rr-book-bookmark:before{content:\"\\f1e2\"}.fi-rr-book-font:before{content:\"\\f1e3\"}.fi-rr-book-open-cover:before{content:\"\\f1e4\"}.fi-rr-book-open-reader:before{content:\"\\f1e5\"}.fi-rr-book:before{content:\"\\f1e6\"}.fi-rr-bookmark:before{content:\"\\f1e7\"}.fi-rr-books:before{content:\"\\f1e8\"}.fi-rr-border-all:before{content:\"\\f1e9\"}.fi-rr-border-bottom:before{content:\"\\f1ea\"}.fi-rr-border-center-h:before{content:\"\\f1eb\"}.fi-rr-border-center-v:before{content:\"\\f1ec\"}.fi-rr-border-inner:before{content:\"\\f1ed\"}.fi-rr-border-left:before{content:\"\\f1ee\"}.fi-rr-border-none:before{content:\"\\f1ef\"}.fi-rr-border-outer:before{content:\"\\f1f0\"}.fi-rr-border-right:before{content:\"\\f1f1\"}.fi-rr-border-style-alt:before{content:\"\\f1f2\"}.fi-rr-border-style:before{content:\"\\f1f3\"}.fi-rr-border-top:before{content:\"\\f1f4\"}.fi-rr-bottle:before{content:\"\\f1f5\"}.fi-rr-bow-arrow:before{content:\"\\f1f6\"}.fi-rr-bowling-ball:before{content:\"\\f1f7\"}.fi-rr-bowling-pins:before{content:\"\\f1f8\"}.fi-rr-bowling:before{content:\"\\f1f9\"}.fi-rr-box-alt:before{content:\"\\f1fa\"}.fi-rr-box-ballot:before{content:\"\\f1fb\"}.fi-rr-box-check:before{content:\"\\f1fc\"}.fi-rr-box-fragile:before{content:\"\\f1fd\"}.fi-rr-box-open-full:before{content:\"\\f1fe\"}.fi-rr-box-open:before{content:\"\\f1ff\"}.fi-rr-box-tissue:before{content:\"\\f200\"}.fi-rr-box-up:before{content:\"\\f201\"}.fi-rr-box:before{content:\"\\f202\"}.fi-rr-boxes:before{content:\"\\f203\"}.fi-rr-boxing-glove:before{content:\"\\f204\"}.fi-rr-bracket-curly-right:before{content:\"\\f205\"}.fi-rr-bracket-curly:before{content:\"\\f206\"}.fi-rr-bracket-round-right:before{content:\"\\f207\"}.fi-rr-bracket-round:before{content:\"\\f208\"}.fi-rr-bracket-square-right:before{content:\"\\f209\"}.fi-rr-bracket-square:before{content:\"\\f20a\"}.fi-rr-brackets-curly:before{content:\"\\f20b\"}.fi-rr-brackets-round:before{content:\"\\f20c\"}.fi-rr-brackets-square:before{content:\"\\f20d\"}.fi-rr-braille:before{content:\"\\f20e\"}.fi-rr-brain-circuit:before{content:\"\\f20f\"}.fi-rr-brain:before{content:\"\\f210\"}.fi-rr-bread-loaf:before{content:\"\\f211\"}.fi-rr-bread-slice:before{content:\"\\f212\"}.fi-rr-bread:before{content:\"\\f213\"}.fi-rr-briefcase:before{content:\"\\f214\"}.fi-rr-brightness-low:before{content:\"\\f215\"}.fi-rr-brightness:before{content:\"\\f216\"}.fi-rr-bring-forward:before{content:\"\\f217\"}.fi-rr-bring-front:before{content:\"\\f218\"}.fi-rr-broccoli:before{content:\"\\f219\"}.fi-rr-broken-image:before{content:\"\\f21a\"}.fi-rr-broom:before{content:\"\\f21b\"}.fi-rr-browser:before{content:\"\\f21c\"}.fi-rr-browsers:before{content:\"\\f21d\"}.fi-rr-brush:before{content:\"\\f21e\"}.fi-rr-bug-slash:before{content:\"\\f21f\"}.fi-rr-bug:before{content:\"\\f220\"}.fi-rr-building:before{content:\"\\f221\"}.fi-rr-bulb:before{content:\"\\f222\"}.fi-rr-bullet:before{content:\"\\f223\"}.fi-rr-bullseye-pointer:before{content:\"\\f224\"}.fi-rr-bullseye:before{content:\"\\f225\"}.fi-rr-burger-alt:before{content:\"\\f226\"}.fi-rr-burger-fries:before{content:\"\\f227\"}.fi-rr-burger-glass:before{content:\"\\f228\"}.fi-rr-burrito:before{content:\"\\f229\"}.fi-rr-bus-alt:before{content:\"\\f22a\"}.fi-rr-bus:before{content:\"\\f22b\"}.fi-rr-business-time:before{content:\"\\f22c\"}.fi-rr-butterfly:before{content:\"\\f22d\"}.fi-rr-c:before{content:\"\\f22e\"}.fi-rr-cabin:before{content:\"\\f22f\"}.fi-rr-cake-birthday:before{content:\"\\f230\"}.fi-rr-cake-wedding:before{content:\"\\f231\"}.fi-rr-calculator:before{content:\"\\f232\"}.fi-rr-calendar-check:before{content:\"\\f233\"}.fi-rr-calendar-clock:before{content:\"\\f234\"}.fi-rr-calendar-exclamation:before{content:\"\\f235\"}.fi-rr-calendar-lines-pen:before{content:\"\\f236\"}.fi-rr-calendar-lines:before{content:\"\\f237\"}.fi-rr-calendar-minus:before{content:\"\\f238\"}.fi-rr-calendar-pen:before{content:\"\\f239\"}.fi-rr-calendar-plus:before{content:\"\\f23a\"}.fi-rr-calendar:before{content:\"\\f23b\"}.fi-rr-calendars:before{content:\"\\f23c\"}.fi-rr-call-history:before{content:\"\\f23d\"}.fi-rr-call-incoming:before{content:\"\\f23e\"}.fi-rr-call-missed:before{content:\"\\f23f\"}.fi-rr-call-outgoing:before{content:\"\\f240\"}.fi-rr-camcorder:before{content:\"\\f241\"}.fi-rr-camera:before{content:\"\\f242\"}.fi-rr-camping:before{content:\"\\f243\"}.fi-rr-candy-alt:before{content:\"\\f244\"}.fi-rr-candy-cane:before{content:\"\\f245\"}.fi-rr-candy-corn:before{content:\"\\f246\"}.fi-rr-candy:before{content:\"\\f247\"}.fi-rr-canned-food:before{content:\"\\f248\"}.fi-rr-car-alt:before{content:\"\\f249\"}.fi-rr-car-battery:before{content:\"\\f24a\"}.fi-rr-car-bolt:before{content:\"\\f24b\"}.fi-rr-car-building:before{content:\"\\f24c\"}.fi-rr-car-bump:before{content:\"\\f24d\"}.fi-rr-car-bus:before{content:\"\\f24e\"}.fi-rr-car-circle-bolt:before{content:\"\\f24f\"}.fi-rr-car-crash:before{content:\"\\f250\"}.fi-rr-car-garage:before{content:\"\\f251\"}.fi-rr-car-mechanic:before{content:\"\\f252\"}.fi-rr-car-side-bolt:before{content:\"\\f253\"}.fi-rr-car-side:before{content:\"\\f254\"}.fi-rr-car-tilt:before{content:\"\\f255\"}.fi-rr-car-wash:before{content:\"\\f256\"}.fi-rr-car:before{content:\"\\f257\"}.fi-rr-caravan-alt:before{content:\"\\f258\"}.fi-rr-caravan:before{content:\"\\f259\"}.fi-rr-caret-circle-down:before{content:\"\\f25a\"}.fi-rr-caret-circle-right:before{content:\"\\f25b\"}.fi-rr-caret-circle-up:before{content:\"\\f25c\"}.fi-rr-caret-down:before{content:\"\\f25d\"}.fi-rr-caret-left:before{content:\"\\f25e\"}.fi-rr-caret-quare-up:before{content:\"\\f25f\"}.fi-rr-caret-right:before{content:\"\\f260\"}.fi-rr-caret-square-down:before{content:\"\\f261\"}.fi-rr-caret-square-left_1:before{content:\"\\f262\"}.fi-rr-caret-square-left:before{content:\"\\f263\"}.fi-rr-caret-square-right:before{content:\"\\f264\"}.fi-rr-caret-up:before{content:\"\\f265\"}.fi-rr-carrot:before{content:\"\\f266\"}.fi-rr-cars:before{content:\"\\f267\"}.fi-rr-cash-register:before{content:\"\\f268\"}.fi-rr-cassette-tape:before{content:\"\\f269\"}.fi-rr-cassette-vhs:before{content:\"\\f26a\"}.fi-rr-castle:before{content:\"\\f26b\"}.fi-rr-chair-office:before{content:\"\\f26c\"}.fi-rr-chair:before{content:\"\\f26d\"}.fi-rr-charging-station:before{content:\"\\f26e\"}.fi-rr-chart-area:before{content:\"\\f26f\"}.fi-rr-chart-bullet:before{content:\"\\f270\"}.fi-rr-chart-candlestick:before{content:\"\\f271\"}.fi-rr-chart-connected:before{content:\"\\f272\"}.fi-rr-chart-gantt:before{content:\"\\f273\"}.fi-rr-chart-histogram:before{content:\"\\f274\"}.fi-rr-chart-line-up:before{content:\"\\f275\"}.fi-rr-chart-mixed:before{content:\"\\f276\"}.fi-rr-chart-network:before{content:\"\\f277\"}.fi-rr-chart-pie-alt:before{content:\"\\f278\"}.fi-rr-chart-pie:before{content:\"\\f279\"}.fi-rr-chart-pyramid:before{content:\"\\f27a\"}.fi-rr-chart-radar:before{content:\"\\f27b\"}.fi-rr-chart-scatter-3d:before{content:\"\\f27c\"}.fi-rr-chart-scatter-bubble:before{content:\"\\f27d\"}.fi-rr-chart-scatter:before{content:\"\\f27e\"}.fi-rr-chart-set-theory:before{content:\"\\f27f\"}.fi-rr-chart-tree:before{content:\"\\f280\"}.fi-rr-chart-waterfall:before{content:\"\\f281\"}.fi-rr-chat-arrow-down:before{content:\"\\f282\"}.fi-rr-chat-arrow-grow:before{content:\"\\f283\"}.fi-rr-check:before{content:\"\\f284\"}.fi-rr-checkbox:before{content:\"\\f285\"}.fi-rr-cheese-alt:before{content:\"\\f286\"}.fi-rr-cheese:before{content:\"\\f287\"}.fi-rr-cherry:before{content:\"\\f288\"}.fi-rr-chess-bishop:before{content:\"\\f289\"}.fi-rr-chess-board:before{content:\"\\f28a\"}.fi-rr-chess-clock-alt:before{content:\"\\f28b\"}.fi-rr-chess-clock:before{content:\"\\f28c\"}.fi-rr-chess-king-alt:before{content:\"\\f28d\"}.fi-rr-chess-king:before{content:\"\\f28e\"}.fi-rr-chess-knight-alt:before{content:\"\\f28f\"}.fi-rr-chess-knight:before{content:\"\\f290\"}.fi-rr-chess-pawn-alt:before{content:\"\\f291\"}.fi-rr-chess-piece:before{content:\"\\f292\"}.fi-rr-chess-queen-alt:before{content:\"\\f293\"}.fi-rr-chess-queen:before{content:\"\\f294\"}.fi-rr-chess-rook-alt:before{content:\"\\f295\"}.fi-rr-chess-rook:before{content:\"\\f296\"}.fi-rr-chess:before{content:\"\\f297\"}.fi-rr-chevron-double-down:before{content:\"\\f298\"}.fi-rr-chevron-double-up:before{content:\"\\f299\"}.fi-rr-child-head:before{content:\"\\f29a\"}.fi-rr-chocolate:before{content:\"\\f29b\"}.fi-rr-circle-0:before{content:\"\\f29c\"}.fi-rr-circle-1:before{content:\"\\f29d\"}.fi-rr-circle-2:before{content:\"\\f29e\"}.fi-rr-circle-3:before{content:\"\\f29f\"}.fi-rr-circle-4:before{content:\"\\f2a0\"}.fi-rr-circle-5:before{content:\"\\f2a1\"}.fi-rr-circle-6:before{content:\"\\f2a2\"}.fi-rr-circle-7:before{content:\"\\f2a3\"}.fi-rr-circle-8:before{content:\"\\f2a4\"}.fi-rr-circle-9:before{content:\"\\f2a5\"}.fi-rr-circle-dashed:before{content:\"\\f2a6\"}.fi-rr-circle-envelope:before{content:\"\\f2a7\"}.fi-rr-circle-half-stroke:before{content:\"\\f2a8\"}.fi-rr-circle-heart:before{content:\"\\f2a9\"}.fi-rr-circle-phone-flip:before{content:\"\\f2aa\"}.fi-rr-circle-phone-hangup:before{content:\"\\f2ab\"}.fi-rr-circle-phone:before{content:\"\\f2ac\"}.fi-rr-circle-small:before{content:\"\\f2ad\"}.fi-rr-circle:before{content:\"\\f2ae\"}.fi-rr-city:before{content:\"\\f2af\"}.fi-rr-clip:before{content:\"\\f2b0\"}.fi-rr-clipboard-list-check:before{content:\"\\f2b1\"}.fi-rr-clipboard-list:before{content:\"\\f2b2\"}.fi-rr-clock-eight-thirty:before{content:\"\\f2b3\"}.fi-rr-clock-eleven-thirty:before{content:\"\\f2b4\"}.fi-rr-clock-eleven:before{content:\"\\f2b5\"}.fi-rr-clock-five-thirty:before{content:\"\\f2b6\"}.fi-rr-clock-five:before{content:\"\\f2b7\"}.fi-rr-clock-four-thirty:before{content:\"\\f2b8\"}.fi-rr-clock-nine-thirty:before{content:\"\\f2b9\"}.fi-rr-clock-nine:before{content:\"\\f2ba\"}.fi-rr-clock-one-thirty:before{content:\"\\f2bb\"}.fi-rr-clock-one:before{content:\"\\f2bc\"}.fi-rr-clock-seven-thirty:before{content:\"\\f2bd\"}.fi-rr-clock-seven:before{content:\"\\f2be\"}.fi-rr-clock-six-thirty:before{content:\"\\f2bf\"}.fi-rr-clock-six:before{content:\"\\f2c0\"}.fi-rr-clock-ten-thirty:before{content:\"\\f2c1\"}.fi-rr-clock-ten:before{content:\"\\f2c2\"}.fi-rr-clock-three-thirty:before{content:\"\\f2c3\"}.fi-rr-clock-three:before{content:\"\\f2c4\"}.fi-rr-clock-twelve-thirty:before{content:\"\\f2c5\"}.fi-rr-clock-twelve:before{content:\"\\f2c6\"}.fi-rr-clock-two-thirty:before{content:\"\\f2c7\"}.fi-rr-clock-two:before{content:\"\\f2c8\"}.fi-rr-clock:before{content:\"\\f2c9\"}.fi-rr-closed-captioning-slash:before{content:\"\\f2ca\"}.fi-rr-cloud-check:before{content:\"\\f2cb\"}.fi-rr-cloud-disabled:before{content:\"\\f2cc\"}.fi-rr-cloud-download-alt:before{content:\"\\f2cd\"}.fi-rr-cloud-download:before{content:\"\\f2ce\"}.fi-rr-cloud-drizzle:before{content:\"\\f2cf\"}.fi-rr-cloud-hail-mixed:before{content:\"\\f2d0\"}.fi-rr-cloud-hail:before{content:\"\\f2d1\"}.fi-rr-cloud-moon-rain:before{content:\"\\f2d2\"}.fi-rr-cloud-moon:before{content:\"\\f2d3\"}.fi-rr-cloud-rain:before{content:\"\\f2d4\"}.fi-rr-cloud-rainbow:before{content:\"\\f2d5\"}.fi-rr-cloud-share:before{content:\"\\f2d6\"}.fi-rr-cloud-showers-heavy:before{content:\"\\f2d7\"}.fi-rr-cloud-showers:before{content:\"\\f2d8\"}.fi-rr-cloud-sleet:before{content:\"\\f2d9\"}.fi-rr-cloud-snow:before{content:\"\\f2da\"}.fi-rr-cloud-sun-rain:before{content:\"\\f2db\"}.fi-rr-cloud-sun:before{content:\"\\f2dc\"}.fi-rr-cloud-upload-alt:before{content:\"\\f2dd\"}.fi-rr-cloud-upload:before{content:\"\\f2de\"}.fi-rr-cloud:before{content:\"\\f2df\"}.fi-rr-clouds-moon:before{content:\"\\f2e0\"}.fi-rr-clouds-sun:before{content:\"\\f2e1\"}.fi-rr-clouds:before{content:\"\\f2e2\"}.fi-rr-club:before{content:\"\\f2e3\"}.fi-rr-cocktail-alt:before{content:\"\\f2e4\"}.fi-rr-cocktail:before{content:\"\\f2e5\"}.fi-rr-code-branch:before{content:\"\\f2e6\"}.fi-rr-code-commit:before{content:\"\\f2e7\"}.fi-rr-code-compare:before{content:\"\\f2e8\"}.fi-rr-code-fork:before{content:\"\\f2e9\"}.fi-rr-code-merge:before{content:\"\\f2ea\"}.fi-rr-code-pull-request-closed:before{content:\"\\f2eb\"}.fi-rr-code-pull-request-draft:before{content:\"\\f2ec\"}.fi-rr-code-pull-request:before{content:\"\\f2ed\"}.fi-rr-code-simple:before{content:\"\\f2ee\"}.fi-rr-coffee-pot:before{content:\"\\f2ef\"}.fi-rr-coffee:before{content:\"\\f2f0\"}.fi-rr-coin:before{content:\"\\f2f1\"}.fi-rr-coins:before{content:\"\\f2f2\"}.fi-rr-comet:before{content:\"\\f2f3\"}.fi-rr-comment-alt-middle-top:before{content:\"\\f2f4\"}.fi-rr-comment-alt-middle:before{content:\"\\f2f5\"}.fi-rr-comment-alt:before{content:\"\\f2f6\"}.fi-rr-comment-arrow-down:before{content:\"\\f2f7\"}.fi-rr-comment-arrow-up-right:before{content:\"\\f2f8\"}.fi-rr-comment-arrow-up:before{content:\"\\f2f9\"}.fi-rr-comment-check:before{content:\"\\f2fa\"}.fi-rr-comment-code:before{content:\"\\f2fb\"}.fi-rr-comment-dollar:before{content:\"\\f2fc\"}.fi-rr-comment-exclamation:before{content:\"\\f2fd\"}.fi-rr-comment-heart:before{content:\"\\f2fe\"}.fi-rr-comment-image:before{content:\"\\f2ff\"}.fi-rr-comment-info:before{content:\"\\f300\"}.fi-rr-comment-pen:before{content:\"\\f301\"}.fi-rr-comment-question:before{content:\"\\f302\"}.fi-rr-comment-quote:before{content:\"\\f303\"}.fi-rr-comment-slash:before{content:\"\\f304\"}.fi-rr-comment-sms:before{content:\"\\f305\"}.fi-rr-comment-text:before{content:\"\\f306\"}.fi-rr-comment-user:before{content:\"\\f307\"}.fi-rr-comment-xmark:before{content:\"\\f308\"}.fi-rr-comment:before{content:\"\\f309\"}.fi-rr-comments-dollar:before{content:\"\\f30a\"}.fi-rr-comments-question-check:before{content:\"\\f30b\"}.fi-rr-comments-question:before{content:\"\\f30c\"}.fi-rr-comments:before{content:\"\\f30d\"}.fi-rr-compress-alt:before{content:\"\\f30e\"}.fi-rr-compress:before{content:\"\\f30f\"}.fi-rr-computer:before{content:\"\\f310\"}.fi-rr-concierge-bell:before{content:\"\\f311\"}.fi-rr-confetti:before{content:\"\\f312\"}.fi-rr-cookie:before{content:\"\\f313\"}.fi-rr-copy-alt:before{content:\"\\f314\"}.fi-rr-copy-image:before{content:\"\\f315\"}.fi-rr-copy:before{content:\"\\f316\"}.fi-rr-copyright:before{content:\"\\f317\"}.fi-rr-corn:before{content:\"\\f318\"}.fi-rr-cow:before{content:\"\\f319\"}.fi-rr-cowbell-more:before{content:\"\\f31a\"}.fi-rr-cowbell:before{content:\"\\f31b\"}.fi-rr-cream:before{content:\"\\f31c\"}.fi-rr-credit-card:before{content:\"\\f31d\"}.fi-rr-cricket:before{content:\"\\f31e\"}.fi-rr-croissant:before{content:\"\\f31f\"}.fi-rr-cross-circle:before{content:\"\\f320\"}.fi-rr-cross-religion:before{content:\"\\f321\"}.fi-rr-cross-small:before{content:\"\\f322\"}.fi-rr-cross:before{content:\"\\f323\"}.fi-rr-crown:before{content:\"\\f324\"}.fi-rr-crystal-ball:before{content:\"\\f325\"}.fi-rr-cube:before{content:\"\\f326\"}.fi-rr-cubes:before{content:\"\\f327\"}.fi-rr-cupcake:before{content:\"\\f328\"}.fi-rr-curling:before{content:\"\\f329\"}.fi-rr-cursor-finger:before{content:\"\\f32a\"}.fi-rr-cursor-plus:before{content:\"\\f32b\"}.fi-rr-cursor-text-alt:before{content:\"\\f32c\"}.fi-rr-cursor-text:before{content:\"\\f32d\"}.fi-rr-cursor:before{content:\"\\f32e\"}.fi-rr-d:before{content:\"\\f32f\"}.fi-rr-dart:before{content:\"\\f330\"}.fi-rr-dashboard:before{content:\"\\f331\"}.fi-rr-data-transfer:before{content:\"\\f332\"}.fi-rr-database:before{content:\"\\f333\"}.fi-rr-delete-document:before{content:\"\\f334\"}.fi-rr-delete-user:before{content:\"\\f335\"}.fi-rr-delete:before{content:\"\\f336\"}.fi-rr-democrat:before{content:\"\\f337\"}.fi-rr-desktop-wallpaper:before{content:\"\\f338\"}.fi-rr-devices:before{content:\"\\f339\"}.fi-rr-dewpoint:before{content:\"\\f33a\"}.fi-rr-diagram-cells:before{content:\"\\f33b\"}.fi-rr-diagram-lean-canvas:before{content:\"\\f33c\"}.fi-rr-diagram-nested:before{content:\"\\f33d\"}.fi-rr-diagram-next:before{content:\"\\f33e\"}.fi-rr-diagram-predecessor:before{content:\"\\f33f\"}.fi-rr-diagram-previous:before{content:\"\\f340\"}.fi-rr-diagram-project:before{content:\"\\f341\"}.fi-rr-diagram-sankey:before{content:\"\\f342\"}.fi-rr-diagram-subtask:before{content:\"\\f343\"}.fi-rr-diagram-successor:before{content:\"\\f344\"}.fi-rr-diamond-turn-right:before{content:\"\\f345\"}.fi-rr-diamond:before{content:\"\\f346\"}.fi-rr-dice-alt:before{content:\"\\f347\"}.fi-rr-dice-d10:before{content:\"\\f348\"}.fi-rr-dice-d12:before{content:\"\\f349\"}.fi-rr-dice-d20:before{content:\"\\f34a\"}.fi-rr-dice-d4:before{content:\"\\f34b\"}.fi-rr-dice-d6:before{content:\"\\f34c\"}.fi-rr-dice-d8:before{content:\"\\f34d\"}.fi-rr-dice-four:before{content:\"\\f34e\"}.fi-rr-dice-one:before{content:\"\\f34f\"}.fi-rr-dice-six:before{content:\"\\f350\"}.fi-rr-dice-three:before{content:\"\\f351\"}.fi-rr-dice-two:before{content:\"\\f352\"}.fi-rr-dice:before{content:\"\\f353\"}.fi-rr-diploma:before{content:\"\\f354\"}.fi-rr-disco-ball:before{content:\"\\f355\"}.fi-rr-disk:before{content:\"\\f356\"}.fi-rr-display-code:before{content:\"\\f357\"}.fi-rr-distribute-spacing-horizontal:before{content:\"\\f358\"}.fi-rr-distribute-spacing-vertical:before{content:\"\\f359\"}.fi-rr-dizzy:before{content:\"\\f35a\"}.fi-rr-doctor:before{content:\"\\f35b\"}.fi-rr-document-signed:before{content:\"\\f35c\"}.fi-rr-document:before{content:\"\\f35d\"}.fi-rr-dollar:before{content:\"\\f35e\"}.fi-rr-donate:before{content:\"\\f35f\"}.fi-rr-door-closed:before{content:\"\\f360\"}.fi-rr-door-open:before{content:\"\\f361\"}.fi-rr-down-left-and-up-right-to-center:before{content:\"\\f362\"}.fi-rr-down-left:before{content:\"\\f363\"}.fi-rr-down-right:before{content:\"\\f364\"}.fi-rr-down-to-line:before{content:\"\\f365\"}.fi-rr-down:before{content:\"\\f366\"}.fi-rr-download:before{content:\"\\f367\"}.fi-rr-drafting-compass:before{content:\"\\f368\"}.fi-rr-dreidel:before{content:\"\\f369\"}.fi-rr-drink-alt:before{content:\"\\f36a\"}.fi-rr-drumstick:before{content:\"\\f36b\"}.fi-rr-dungeon:before{content:\"\\f36c\"}.fi-rr-duplicate:before{content:\"\\f36d\"}.fi-rr-e-learning:before{content:\"\\f36e\"}.fi-rr-e:before{content:\"\\f36f\"}.fi-rr-ear-deaf:before{content:\"\\f370\"}.fi-rr-earnings:before{content:\"\\f371\"}.fi-rr-eclipse-alt:before{content:\"\\f372\"}.fi-rr-eclipse:before{content:\"\\f373\"}.fi-rr-edit-alt:before{content:\"\\f374\"}.fi-rr-edit:before{content:\"\\f375\"}.fi-rr-egg-fried:before{content:\"\\f376\"}.fi-rr-egg:before{content:\"\\f377\"}.fi-rr-engine-warning:before{content:\"\\f378\"}.fi-rr-enter:before{content:\"\\f379\"}.fi-rr-envelope-ban:before{content:\"\\f37a\"}.fi-rr-envelope-bulk:before{content:\"\\f37b\"}.fi-rr-envelope-download:before{content:\"\\f37c\"}.fi-rr-envelope-marker:before{content:\"\\f37d\"}.fi-rr-envelope-open-dollar:before{content:\"\\f37e\"}.fi-rr-envelope-open-text:before{content:\"\\f37f\"}.fi-rr-envelope-open:before{content:\"\\f380\"}.fi-rr-envelope-plus:before{content:\"\\f381\"}.fi-rr-envelope:before{content:\"\\f382\"}.fi-rr-equality:before{content:\"\\f383\"}.fi-rr-euro:before{content:\"\\f384\"}.fi-rr-exchange-alt:before{content:\"\\f385\"}.fi-rr-exchange:before{content:\"\\f386\"}.fi-rr-exclamation:before{content:\"\\f387\"}.fi-rr-exit:before{content:\"\\f388\"}.fi-rr-expand-arrows-alt:before{content:\"\\f389\"}.fi-rr-expand-arrows:before{content:\"\\f38a\"}.fi-rr-expand:before{content:\"\\f38b\"}.fi-rr-eye-crossed:before{content:\"\\f38c\"}.fi-rr-eye-dropper:before{content:\"\\f38d\"}.fi-rr-eye:before{content:\"\\f38e\"}.fi-rr-f:before{content:\"\\f38f\"}.fi-rr-face-awesome:before{content:\"\\f390\"}.fi-rr-face-head-bandage:before{content:\"\\f391\"}.fi-rr-farm:before{content:\"\\f392\"}.fi-rr-feather:before{content:\"\\f393\"}.fi-rr-fence:before{content:\"\\f394\"}.fi-rr-ferris-wheel:before{content:\"\\f395\"}.fi-rr-fighter-jet:before{content:\"\\f396\"}.fi-rr-file-ai:before{content:\"\\f397\"}.fi-rr-file-binary:before{content:\"\\f398\"}.fi-rr-file-chart-line:before{content:\"\\f399\"}.fi-rr-file-chart-pie:before{content:\"\\f39a\"}.fi-rr-file-code:before{content:\"\\f39b\"}.fi-rr-file-eps:before{content:\"\\f39c\"}.fi-rr-file-excel:before{content:\"\\f39d\"}.fi-rr-file-export:before{content:\"\\f39e\"}.fi-rr-file-invoice-dollar:before{content:\"\\f39f\"}.fi-rr-file-invoice:before{content:\"\\f3a0\"}.fi-rr-file-pdf:before{content:\"\\f3a1\"}.fi-rr-file-powerpoint:before{content:\"\\f3a2\"}.fi-rr-file-psd:before{content:\"\\f3a3\"}.fi-rr-file-spreadsheet:before{content:\"\\f3a4\"}.fi-rr-file-video:before{content:\"\\f3a5\"}.fi-rr-file-word:before{content:\"\\f3a6\"}.fi-rr-file:before{content:\"\\f3a7\"}.fi-rr-fill:before{content:\"\\f3a8\"}.fi-rr-film-slash:before{content:\"\\f3a9\"}.fi-rr-film:before{content:\"\\f3aa\"}.fi-rr-filter-slash:before{content:\"\\f3ab\"}.fi-rr-filter:before{content:\"\\f3ac\"}.fi-rr-filters:before{content:\"\\f3ad\"}.fi-rr-fingerprint:before{content:\"\\f3ae\"}.fi-rr-fire-flame-curved:before{content:\"\\f3af\"}.fi-rr-fire-smoke:before{content:\"\\f3b0\"}.fi-rr-fish:before{content:\"\\f3b1\"}.fi-rr-fishing-rod:before{content:\"\\f3b2\"}.fi-rr-flag-alt:before{content:\"\\f3b3\"}.fi-rr-flag-checkered:before{content:\"\\f3b4\"}.fi-rr-flag-usa:before{content:\"\\f3b5\"}.fi-rr-flag:before{content:\"\\f3b6\"}.fi-rr-flame:before{content:\"\\f3b7\"}.fi-rr-flip-horizontal:before{content:\"\\f3b8\"}.fi-rr-flower-bouquet:before{content:\"\\f3b9\"}.fi-rr-flower-tulip:before{content:\"\\f3ba\"}.fi-rr-flower:before{content:\"\\f3bb\"}.fi-rr-flushed:before{content:\"\\f3bc\"}.fi-rr-fog:before{content:\"\\f3bd\"}.fi-rr-folder-download:before{content:\"\\f3be\"}.fi-rr-folder-minus:before{content:\"\\f3bf\"}.fi-rr-folder-times:before{content:\"\\f3c0\"}.fi-rr-folder-tree:before{content:\"\\f3c1\"}.fi-rr-folder-upload:before{content:\"\\f3c2\"}.fi-rr-folder:before{content:\"\\f3c3\"}.fi-rr-folders:before{content:\"\\f3c4\"}.fi-rr-follow-folder:before{content:\"\\f3c5\"}.fi-rr-followcollection:before{content:\"\\f3c6\"}.fi-rr-following:before{content:\"\\f3c7\"}.fi-rr-football:before{content:\"\\f3c8\"}.fi-rr-fork:before{content:\"\\f3c9\"}.fi-rr-form:before{content:\"\\f3ca\"}.fi-rr-fort:before{content:\"\\f3cb\"}.fi-rr-forward:before{content:\"\\f3cc\"}.fi-rr-fox:before{content:\"\\f3cd\"}.fi-rr-french-fries:before{content:\"\\f3ce\"}.fi-rr-frown:before{content:\"\\f3cf\"}.fi-rr-ftp:before{content:\"\\f3d0\"}.fi-rr-funnel-dollar:before{content:\"\\f3d1\"}.fi-rr-g:before{content:\"\\f3d2\"}.fi-rr-gallery-thumbnails:before{content:\"\\f3d3\"}.fi-rr-gallery:before{content:\"\\f3d4\"}.fi-rr-game-board-alt:before{content:\"\\f3d5\"}.fi-rr-gamepad:before{content:\"\\f3d6\"}.fi-rr-garage-car:before{content:\"\\f3d7\"}.fi-rr-garage-open:before{content:\"\\f3d8\"}.fi-rr-garage:before{content:\"\\f3d9\"}.fi-rr-garlic:before{content:\"\\f3da\"}.fi-rr-gas-pump-alt:before{content:\"\\f3db\"}.fi-rr-gas-pump-slash:before{content:\"\\f3dc\"}.fi-rr-gas-pump:before{content:\"\\f3dd\"}.fi-rr-gavel:before{content:\"\\f3de\"}.fi-rr-gears:before{content:\"\\f3df\"}.fi-rr-gem:before{content:\"\\f3e0\"}.fi-rr-gif:before{content:\"\\f3e1\"}.fi-rr-gift-card:before{content:\"\\f3e2\"}.fi-rr-gift:before{content:\"\\f3e3\"}.fi-rr-gifts:before{content:\"\\f3e4\"}.fi-rr-gingerbread-man:before{content:\"\\f3e5\"}.fi-rr-glass-cheers:before{content:\"\\f3e6\"}.fi-rr-glass:before{content:\"\\f3e7\"}.fi-rr-glasses:before{content:\"\\f3e8\"}.fi-rr-globe-alt:before{content:\"\\f3e9\"}.fi-rr-globe:before{content:\"\\f3ea\"}.fi-rr-golf-ball:before{content:\"\\f3eb\"}.fi-rr-golf:before{content:\"\\f3ec\"}.fi-rr-graduation-cap:before{content:\"\\f3ed\"}.fi-rr-grape:before{content:\"\\f3ee\"}.fi-rr-graphic-style:before{content:\"\\f3ef\"}.fi-rr-graphic-tablet:before{content:\"\\f3f0\"}.fi-rr-grid-alt:before{content:\"\\f3f1\"}.fi-rr-grid-dividers:before{content:\"\\f3f2\"}.fi-rr-grid:before{content:\"\\f3f3\"}.fi-rr-grill:before{content:\"\\f3f4\"}.fi-rr-grimace:before{content:\"\\f3f5\"}.fi-rr-grin-alt:before{content:\"\\f3f6\"}.fi-rr-grin-beam-sweat:before{content:\"\\f3f7\"}.fi-rr-grin-beam:before{content:\"\\f3f8\"}.fi-rr-grin-hearts:before{content:\"\\f3f9\"}.fi-rr-grin-squint-tears:before{content:\"\\f3fa\"}.fi-rr-grin-squint:before{content:\"\\f3fb\"}.fi-rr-grin-stars:before{content:\"\\f3fc\"}.fi-rr-grin-tears:before{content:\"\\f3fd\"}.fi-rr-grin-tongue-squint:before{content:\"\\f3fe\"}.fi-rr-grin-tongue-wink:before{content:\"\\f3ff\"}.fi-rr-grin-tongue:before{content:\"\\f400\"}.fi-rr-grin-wink:before{content:\"\\f401\"}.fi-rr-grin:before{content:\"\\f402\"}.fi-rr-guitar:before{content:\"\\f403\"}.fi-rr-gym:before{content:\"\\f404\"}.fi-rr-h:before{content:\"\\f405\"}.fi-rr-hamburger-soda:before{content:\"\\f406\"}.fi-rr-hamburger:before{content:\"\\f407\"}.fi-rr-hammer-crash:before{content:\"\\f408\"}.fi-rr-hammer-war:before{content:\"\\f409\"}.fi-rr-hammer:before{content:\"\\f40a\"}.fi-rr-hand-holding-box:before{content:\"\\f40b\"}.fi-rr-hand-holding-heart:before{content:\"\\f40c\"}.fi-rr-hand-holding-seeding:before{content:\"\\f40d\"}.fi-rr-hand-horns:before{content:\"\\f40e\"}.fi-rr-hand-lizard:before{content:\"\\f40f\"}.fi-rr-hand-peace:before{content:\"\\f410\"}.fi-rr-hand:before{content:\"\\f411\"}.fi-rr-hands-clapping:before{content:\"\\f412\"}.fi-rr-handshake-angle:before{content:\"\\f413\"}.fi-rr-handshake:before{content:\"\\f414\"}.fi-rr-hastag:before{content:\"\\f415\"}.fi-rr-hat-birthday:before{content:\"\\f416\"}.fi-rr-hat-chef:before{content:\"\\f417\"}.fi-rr-hdd:before{content:\"\\f418\"}.fi-rr-head-side-brain:before{content:\"\\f419\"}.fi-rr-head-side-cough-slash:before{content:\"\\f41a\"}.fi-rr-head-side-cough:before{content:\"\\f41b\"}.fi-rr-head-side-heart:before{content:\"\\f41c\"}.fi-rr-head-side-mask:before{content:\"\\f41d\"}.fi-rr-head-side-medical:before{content:\"\\f41e\"}.fi-rr-head-side-thinking:before{content:\"\\f41f\"}.fi-rr-head-side-virus:before{content:\"\\f420\"}.fi-rr-head-side:before{content:\"\\f421\"}.fi-rr-head-vr:before{content:\"\\f422\"}.fi-rr-headphones:before{content:\"\\f423\"}.fi-rr-headset:before{content:\"\\f424\"}.fi-rr-heart-arrow:before{content:\"\\f425\"}.fi-rr-heart-crack:before{content:\"\\f426\"}.fi-rr-heart:before{content:\"\\f427\"}.fi-rr-heat:before{content:\"\\f428\"}.fi-rr-helicopter-side:before{content:\"\\f429\"}.fi-rr-highlighter-line:before{content:\"\\f42a\"}.fi-rr-highlighter:before{content:\"\\f42b\"}.fi-rr-hiking:before{content:\"\\f42c\"}.fi-rr-hockey-puck:before{content:\"\\f42d\"}.fi-rr-hockey-sticks:before{content:\"\\f42e\"}.fi-rr-home-location-alt:before{content:\"\\f42f\"}.fi-rr-home-location:before{content:\"\\f430\"}.fi-rr-home:before{content:\"\\f431\"}.fi-rr-horizontal-rule:before{content:\"\\f432\"}.fi-rr-hot-tub:before{content:\"\\f433\"}.fi-rr-hotdog:before{content:\"\\f434\"}.fi-rr-hotel:before{content:\"\\f435\"}.fi-rr-hourglass-end:before{content:\"\\f436\"}.fi-rr-hourglass:before{content:\"\\f437\"}.fi-rr-house-blank:before{content:\"\\f438\"}.fi-rr-house-building:before{content:\"\\f439\"}.fi-rr-house-chimney-blank:before{content:\"\\f43a\"}.fi-rr-house-chimney-crack:before{content:\"\\f43b\"}.fi-rr-house-chimney-medical:before{content:\"\\f43c\"}.fi-rr-house-chimney-window:before{content:\"\\f43d\"}.fi-rr-house-chimney:before{content:\"\\f43e\"}.fi-rr-house-crack:before{content:\"\\f43f\"}.fi-rr-house-flood:before{content:\"\\f440\"}.fi-rr-house-medical:before{content:\"\\f441\"}.fi-rr-house-tree:before{content:\"\\f442\"}.fi-rr-house-turret:before{content:\"\\f443\"}.fi-rr-house-window:before{content:\"\\f444\"}.fi-rr-hryvnia:before{content:\"\\f445\"}.fi-rr-humidity:before{content:\"\\f446\"}.fi-rr-hurricane:before{content:\"\\f447\"}.fi-rr-i:before{content:\"\\f448\"}.fi-rr-ice-cream:before{content:\"\\f449\"}.fi-rr-ice-skate:before{content:\"\\f44a\"}.fi-rr-icon-star:before{content:\"\\f44b\"}.fi-rr-id-badge:before{content:\"\\f44c\"}.fi-rr-igloo:before{content:\"\\f44d\"}.fi-rr-images:before{content:\"\\f44e\"}.fi-rr-inbox-in:before{content:\"\\f44f\"}.fi-rr-inbox-out:before{content:\"\\f450\"}.fi-rr-inbox:before{content:\"\\f451\"}.fi-rr-incognito:before{content:\"\\f452\"}.fi-rr-indent:before{content:\"\\f453\"}.fi-rr-industry-windows:before{content:\"\\f454\"}.fi-rr-infinity:before{content:\"\\f455\"}.fi-rr-info:before{content:\"\\f456\"}.fi-rr-interactive:before{content:\"\\f457\"}.fi-rr-interlining:before{content:\"\\f458\"}.fi-rr-interrogation:before{content:\"\\f459\"}.fi-rr-island-tropical:before{content:\"\\f45a\"}.fi-rr-italic:before{content:\"\\f45b\"}.fi-rr-j:before{content:\"\\f45c\"}.fi-rr-jam:before{content:\"\\f45d\"}.fi-rr-jpg:before{content:\"\\f45e\"}.fi-rr-jug:before{content:\"\\f45f\"}.fi-rr-k:before{content:\"\\f460\"}.fi-rr-kerning:before{content:\"\\f461\"}.fi-rr-key-skeleton-left-right:before{content:\"\\f462\"}.fi-rr-key:before{content:\"\\f463\"}.fi-rr-keyboard-brightness-low:before{content:\"\\f464\"}.fi-rr-keyboard-brightness:before{content:\"\\f465\"}.fi-rr-keyboard:before{content:\"\\f466\"}.fi-rr-keynote:before{content:\"\\f467\"}.fi-rr-kiss-beam:before{content:\"\\f468\"}.fi-rr-kiss-wink-heart:before{content:\"\\f469\"}.fi-rr-kiss:before{content:\"\\f46a\"}.fi-rr-kite:before{content:\"\\f46b\"}.fi-rr-knife:before{content:\"\\f46c\"}.fi-rr-l:before{content:\"\\f46d\"}.fi-rr-label:before{content:\"\\f46e\"}.fi-rr-landmark-alt:before{content:\"\\f46f\"}.fi-rr-laptop-code:before{content:\"\\f470\"}.fi-rr-laptop-mobile:before{content:\"\\f471\"}.fi-rr-laptop:before{content:\"\\f472\"}.fi-rr-lasso-sparkles:before{content:\"\\f473\"}.fi-rr-lasso:before{content:\"\\f474\"}.fi-rr-laugh-beam:before{content:\"\\f475\"}.fi-rr-laugh-squint:before{content:\"\\f476\"}.fi-rr-laugh-wink:before{content:\"\\f477\"}.fi-rr-laugh:before{content:\"\\f478\"}.fi-rr-layer-minus:before{content:\"\\f479\"}.fi-rr-layer-plus:before{content:\"\\f47a\"}.fi-rr-layers:before{content:\"\\f47b\"}.fi-rr-layout-fluid:before{content:\"\\f47c\"}.fi-rr-leaf:before{content:\"\\f47d\"}.fi-rr-lemon:before{content:\"\\f47e\"}.fi-rr-letter-case:before{content:\"\\f47f\"}.fi-rr-lettuce:before{content:\"\\f480\"}.fi-rr-level-down-alt:before{content:\"\\f481\"}.fi-rr-level-down:before{content:\"\\f482\"}.fi-rr-level-up-alt:before{content:\"\\f483\"}.fi-rr-level-up:before{content:\"\\f484\"}.fi-rr-license:before{content:\"\\f485\"}.fi-rr-life-ring:before{content:\"\\f486\"}.fi-rr-light-switch-off:before{content:\"\\f487\"}.fi-rr-light-switch-on:before{content:\"\\f488\"}.fi-rr-light-switch:before{content:\"\\f489\"}.fi-rr-lightbulb-dollar:before{content:\"\\f48a\"}.fi-rr-line-width:before{content:\"\\f48b\"}.fi-rr-link-alt:before{content:\"\\f48c\"}.fi-rr-link-horizontal-slash:before{content:\"\\f48d\"}.fi-rr-link-horizontal:before{content:\"\\f48e\"}.fi-rr-link-slash-alt:before{content:\"\\f48f\"}.fi-rr-link-slash:before{content:\"\\f490\"}.fi-rr-link:before{content:\"\\f491\"}.fi-rr-lipstick:before{content:\"\\f492\"}.fi-rr-lira-sign:before{content:\"\\f493\"}.fi-rr-list-check:before{content:\"\\f494\"}.fi-rr-list:before{content:\"\\f495\"}.fi-rr-loading:before{content:\"\\f496\"}.fi-rr-location-alt:before{content:\"\\f497\"}.fi-rr-location-crosshairs-slash:before{content:\"\\f498\"}.fi-rr-location-crosshairs:before{content:\"\\f499\"}.fi-rr-location-dot-slash:before{content:\"\\f49a\"}.fi-rr-lock-alt:before{content:\"\\f49b\"}.fi-rr-lock:before{content:\"\\f49c\"}.fi-rr-luchador:before{content:\"\\f49d\"}.fi-rr-luggage-cart:before{content:\"\\f49e\"}.fi-rr-luggage-rolling:before{content:\"\\f49f\"}.fi-rr-m:before{content:\"\\f4a0\"}.fi-rr-magic-wand:before{content:\"\\f4a1\"}.fi-rr-mailbox:before{content:\"\\f4a2\"}.fi-rr-makeup-brush:before{content:\"\\f4a3\"}.fi-rr-man-head:before{content:\"\\f4a4\"}.fi-rr-map-marker-check:before{content:\"\\f4a5\"}.fi-rr-map-marker-cross:before{content:\"\\f4a6\"}.fi-rr-map-marker-edit:before{content:\"\\f4a7\"}.fi-rr-map-marker-home:before{content:\"\\f4a8\"}.fi-rr-map-marker-minus:before{content:\"\\f4a9\"}.fi-rr-map-marker-plus:before{content:\"\\f4aa\"}.fi-rr-map-marker-question:before{content:\"\\f4ab\"}.fi-rr-map-marker-slash:before{content:\"\\f4ac\"}.fi-rr-map-marker-smile:before{content:\"\\f4ad\"}.fi-rr-map-marker:before{content:\"\\f4ae\"}.fi-rr-map-pin:before{content:\"\\f4af\"}.fi-rr-map:before{content:\"\\f4b0\"}.fi-rr-marker-time:before{content:\"\\f4b1\"}.fi-rr-marker:before{content:\"\\f4b2\"}.fi-rr-mars-double:before{content:\"\\f4b3\"}.fi-rr-mars:before{content:\"\\f4b4\"}.fi-rr-mask-carnival:before{content:\"\\f4b5\"}.fi-rr-mask:before{content:\"\\f4b6\"}.fi-rr-medicine:before{content:\"\\f4b7\"}.fi-rr-megaphone:before{content:\"\\f4b8\"}.fi-rr-meh-blank:before{content:\"\\f4b9\"}.fi-rr-meh-rolling-eyes:before{content:\"\\f4ba\"}.fi-rr-meh:before{content:\"\\f4bb\"}.fi-rr-melon:before{content:\"\\f4bc\"}.fi-rr-memory:before{content:\"\\f4bd\"}.fi-rr-menu-burger:before{content:\"\\f4be\"}.fi-rr-menu-dots-vertical:before{content:\"\\f4bf\"}.fi-rr-menu-dots:before{content:\"\\f4c0\"}.fi-rr-message-code:before{content:\"\\f4c1\"}.fi-rr-meteor:before{content:\"\\f4c2\"}.fi-rr-microchip:before{content:\"\\f4c3\"}.fi-rr-microphone-alt:before{content:\"\\f4c4\"}.fi-rr-microphone:before{content:\"\\f4c5\"}.fi-rr-mind-share:before{content:\"\\f4c6\"}.fi-rr-minus-small:before{content:\"\\f4c7\"}.fi-rr-minus:before{content:\"\\f4c8\"}.fi-rr-mobile-button:before{content:\"\\f4c9\"}.fi-rr-mobile-notch:before{content:\"\\f4ca\"}.fi-rr-mobile:before{content:\"\\f4cb\"}.fi-rr-mockup:before{content:\"\\f4cc\"}.fi-rr-mode-landscape:before{content:\"\\f4cd\"}.fi-rr-mode-portrait:before{content:\"\\f4ce\"}.fi-rr-money-bill-wave-alt:before{content:\"\\f4cf\"}.fi-rr-money-bill-wave:before{content:\"\\f4d0\"}.fi-rr-money-check-edit-alt:before{content:\"\\f4d1\"}.fi-rr-money-check-edit:before{content:\"\\f4d2\"}.fi-rr-money-check:before{content:\"\\f4d3\"}.fi-rr-money:before{content:\"\\f4d4\"}.fi-rr-monument:before{content:\"\\f4d5\"}.fi-rr-moon-stars:before{content:\"\\f4d6\"}.fi-rr-moon:before{content:\"\\f4d7\"}.fi-rr-motorcycle:before{content:\"\\f4d8\"}.fi-rr-mountains:before{content:\"\\f4d9\"}.fi-rr-mouse:before{content:\"\\f4da\"}.fi-rr-move-to-folder-2:before{content:\"\\f4db\"}.fi-rr-move-to-folder:before{content:\"\\f4dc\"}.fi-rr-mug-alt:before{content:\"\\f4dd\"}.fi-rr-mug-hot-alt:before{content:\"\\f4de\"}.fi-rr-mug-hot:before{content:\"\\f4df\"}.fi-rr-mug-tea:before{content:\"\\f4e0\"}.fi-rr-mug:before{content:\"\\f4e1\"}.fi-rr-mushroom:before{content:\"\\f4e2\"}.fi-rr-music-alt:before{content:\"\\f4e3\"}.fi-rr-music-file:before{content:\"\\f4e4\"}.fi-rr-music:before{content:\"\\f4e5\"}.fi-rr-n:before{content:\"\\f4e6\"}.fi-rr-navigation:before{content:\"\\f4e7\"}.fi-rr-network-cloud:before{content:\"\\f4e8\"}.fi-rr-network:before{content:\"\\f4e9\"}.fi-rr-no-people:before{content:\"\\f4ea\"}.fi-rr-noodles:before{content:\"\\f4eb\"}.fi-rr-notdef:before{content:\"\\f4ec\"}.fi-rr-notebook:before{content:\"\\f4ed\"}.fi-rr-o:before{content:\"\\f4ee\"}.fi-rr-object-exclude:before{content:\"\\f4ef\"}.fi-rr-object-intersect:before{content:\"\\f4f0\"}.fi-rr-object-subtract:before{content:\"\\f4f1\"}.fi-rr-object-union:before{content:\"\\f4f2\"}.fi-rr-octagon:before{content:\"\\f4f3\"}.fi-rr-oil-can:before{content:\"\\f4f4\"}.fi-rr-oil-temp:before{content:\"\\f4f5\"}.fi-rr-olive-oil:before{content:\"\\f4f6\"}.fi-rr-olives:before{content:\"\\f4f7\"}.fi-rr-onion:before{content:\"\\f4f8\"}.fi-rr-opacity:before{content:\"\\f4f9\"}.fi-rr-overline:before{content:\"\\f4fa\"}.fi-rr-p:before{content:\"\\f4fb\"}.fi-rr-package:before{content:\"\\f4fc\"}.fi-rr-page-break:before{content:\"\\f4fd\"}.fi-rr-paint-brush:before{content:\"\\f4fe\"}.fi-rr-paint-roller:before{content:\"\\f4ff\"}.fi-rr-palette:before{content:\"\\f500\"}.fi-rr-pan:before{content:\"\\f501\"}.fi-rr-paper-plane:before{content:\"\\f502\"}.fi-rr-parking-circle-slash:before{content:\"\\f503\"}.fi-rr-parking-circle:before{content:\"\\f504\"}.fi-rr-parking-slash:before{content:\"\\f505\"}.fi-rr-parking:before{content:\"\\f506\"}.fi-rr-passport:before{content:\"\\f507\"}.fi-rr-password:before{content:\"\\f508\"}.fi-rr-paste:before{content:\"\\f509\"}.fi-rr-pattern:before{content:\"\\f50a\"}.fi-rr-pause:before{content:\"\\f50b\"}.fi-rr-paw:before{content:\"\\f50c\"}.fi-rr-peach:before{content:\"\\f50d\"}.fi-rr-pencil-ruler:before{content:\"\\f50e\"}.fi-rr-pencil:before{content:\"\\f50f\"}.fi-rr-pennant:before{content:\"\\f510\"}.fi-rr-people-arrows-left-right:before{content:\"\\f511\"}.fi-rr-people-carry-box:before{content:\"\\f512\"}.fi-rr-people-dress:before{content:\"\\f513\"}.fi-rr-people-pants:before{content:\"\\f514\"}.fi-rr-people-poll:before{content:\"\\f515\"}.fi-rr-people:before{content:\"\\f516\"}.fi-rr-pepper-hot:before{content:\"\\f517\"}.fi-rr-pepper:before{content:\"\\f518\"}.fi-rr-percentage:before{content:\"\\f519\"}.fi-rr-person-walking-with-cane:before{content:\"\\f51a\"}.fi-rr-pharmacy:before{content:\"\\f51b\"}.fi-rr-phone-call:before{content:\"\\f51c\"}.fi-rr-phone-cross:before{content:\"\\f51d\"}.fi-rr-phone-office:before{content:\"\\f51e\"}.fi-rr-phone-pause:before{content:\"\\f51f\"}.fi-rr-phone-slash:before{content:\"\\f520\"}.fi-rr-photo-film-music:before{content:\"\\f521\"}.fi-rr-photo-video:before{content:\"\\f522\"}.fi-rr-physics:before{content:\"\\f523\"}.fi-rr-picnic:before{content:\"\\f524\"}.fi-rr-picpeople-filled:before{content:\"\\f525\"}.fi-rr-picpeople:before{content:\"\\f526\"}.fi-rr-picture:before{content:\"\\f527\"}.fi-rr-pie:before{content:\"\\f528\"}.fi-rr-piece:before{content:\"\\f529\"}.fi-rr-piggy-bank:before{content:\"\\f52a\"}.fi-rr-pineapple:before{content:\"\\f52b\"}.fi-rr-ping-pong:before{content:\"\\f52c\"}.fi-rr-pizza-slice:before{content:\"\\f52d\"}.fi-rr-plane-alt:before{content:\"\\f52e\"}.fi-rr-plane-arrival:before{content:\"\\f52f\"}.fi-rr-plane-departure:before{content:\"\\f530\"}.fi-rr-plane-prop:before{content:\"\\f531\"}.fi-rr-plane-tail:before{content:\"\\f532\"}.fi-rr-plane:before{content:\"\\f533\"}.fi-rr-plate:before{content:\"\\f534\"}.fi-rr-play-alt:before{content:\"\\f535\"}.fi-rr-play-pause:before{content:\"\\f536\"}.fi-rr-play:before{content:\"\\f537\"}.fi-rr-playing-cards:before{content:\"\\f538\"}.fi-rr-plus-small:before{content:\"\\f539\"}.fi-rr-plus:before{content:\"\\f53a\"}.fi-rr-podium-star:before{content:\"\\f53b\"}.fi-rr-podium:before{content:\"\\f53c\"}.fi-rr-poker-chip:before{content:\"\\f53d\"}.fi-rr-poo:before{content:\"\\f53e\"}.fi-rr-popcorn:before{content:\"\\f53f\"}.fi-rr-portrait:before{content:\"\\f540\"}.fi-rr-pot:before{content:\"\\f541\"}.fi-rr-pound:before{content:\"\\f542\"}.fi-rr-power:before{content:\"\\f543\"}.fi-rr-presentation:before{content:\"\\f544\"}.fi-rr-print:before{content:\"\\f545\"}.fi-rr-projector:before{content:\"\\f546\"}.fi-rr-protractor:before{content:\"\\f547\"}.fi-rr-pulse:before{content:\"\\f548\"}.fi-rr-pumpkin:before{content:\"\\f549\"}.fi-rr-puzzle:before{content:\"\\f54a\"}.fi-rr-pyramid:before{content:\"\\f54b\"}.fi-rr-q:before{content:\"\\f54c\"}.fi-rr-qrcode:before{content:\"\\f54d\"}.fi-rr-question-square:before{content:\"\\f54e\"}.fi-rr-question:before{content:\"\\f54f\"}.fi-rr-quote-right:before{content:\"\\f550\"}.fi-rr-r:before{content:\"\\f551\"}.fi-rr-racquet:before{content:\"\\f552\"}.fi-rr-radish:before{content:\"\\f553\"}.fi-rr-rainbow:before{content:\"\\f554\"}.fi-rr-raindrops:before{content:\"\\f555\"}.fi-rr-ramp-loading:before{content:\"\\f556\"}.fi-rr-rec:before{content:\"\\f557\"}.fi-rr-receipt:before{content:\"\\f558\"}.fi-rr-record-vinyl:before{content:\"\\f559\"}.fi-rr-rectabgle-vertical:before{content:\"\\f55a\"}.fi-rr-rectangle-barcode:before{content:\"\\f55b\"}.fi-rr-rectangle-code:before{content:\"\\f55c\"}.fi-rr-rectangle-horizontal:before{content:\"\\f55d\"}.fi-rr-rectangle-panoramic:before{content:\"\\f55e\"}.fi-rr-rectangle-xmark:before{content:\"\\f55f\"}.fi-rr-recycle:before{content:\"\\f560\"}.fi-rr-redo-alt:before{content:\"\\f561\"}.fi-rr-redo:before{content:\"\\f562\"}.fi-rr-reflect-horizontal:before{content:\"\\f563\"}.fi-rr-reflect-vertical:before{content:\"\\f564\"}.fi-rr-reflect:before{content:\"\\f565\"}.fi-rr-refresh:before{content:\"\\f566\"}.fi-rr-registered:before{content:\"\\f567\"}.fi-rr-remove-folder:before{content:\"\\f568\"}.fi-rr-remove-user:before{content:\"\\f569\"}.fi-rr-replace:before{content:\"\\f56a\"}.fi-rr-reply-all:before{content:\"\\f56b\"}.fi-rr-republican:before{content:\"\\f56c\"}.fi-rr-resize:before{content:\"\\f56d\"}.fi-rr-resources:before{content:\"\\f56e\"}.fi-rr-restaurant:before{content:\"\\f56f\"}.fi-rr-rewind:before{content:\"\\f570\"}.fi-rr-rhombus:before{content:\"\\f571\"}.fi-rr-rings-wedding:before{content:\"\\f572\"}.fi-rr-road:before{content:\"\\f573\"}.fi-rr-rocket-lunch:before{content:\"\\f574\"}.fi-rr-rocket:before{content:\"\\f575\"}.fi-rr-roller-coaster:before{content:\"\\f576\"}.fi-rr-room-service:before{content:\"\\f577\"}.fi-rr-rotate-left:before{content:\"\\f578\"}.fi-rr-rotate-right:before{content:\"\\f579\"}.fi-rr-route-highway:before{content:\"\\f57a\"}.fi-rr-route-interstate:before{content:\"\\f57b\"}.fi-rr-route:before{content:\"\\f57c\"}.fi-rr-ruble-sign:before{content:\"\\f57d\"}.fi-rr-rugby:before{content:\"\\f57e\"}.fi-rr-ruler-combined:before{content:\"\\f57f\"}.fi-rr-ruler-horizontal:before{content:\"\\f580\"}.fi-rr-ruler-triangle:before{content:\"\\f581\"}.fi-rr-ruler-vertical:before{content:\"\\f582\"}.fi-rr-running:before{content:\"\\f583\"}.fi-rr-rupee-sign:before{content:\"\\f584\"}.fi-rr-rv:before{content:\"\\f585\"}.fi-rr-s:before{content:\"\\f586\"}.fi-rr-sack-dollar:before{content:\"\\f587\"}.fi-rr-sack:before{content:\"\\f588\"}.fi-rr-sad-cry:before{content:\"\\f589\"}.fi-rr-sad-tear:before{content:\"\\f58a\"}.fi-rr-sad:before{content:\"\\f58b\"}.fi-rr-salad:before{content:\"\\f58c\"}.fi-rr-salt-pepper:before{content:\"\\f58d\"}.fi-rr-sandwich:before{content:\"\\f58e\"}.fi-rr-sauce:before{content:\"\\f58f\"}.fi-rr-sausage:before{content:\"\\f590\"}.fi-rr-scale:before{content:\"\\f591\"}.fi-rr-school-bus:before{content:\"\\f592\"}.fi-rr-school:before{content:\"\\f593\"}.fi-rr-scissors:before{content:\"\\f594\"}.fi-rr-screen:before{content:\"\\f595\"}.fi-rr-search-alt:before{content:\"\\f596\"}.fi-rr-search-dollar:before{content:\"\\f597\"}.fi-rr-search-heart:before{content:\"\\f598\"}.fi-rr-search-location:before{content:\"\\f599\"}.fi-rr-search:before{content:\"\\f59a\"}.fi-rr-seat-airline:before{content:\"\\f59b\"}.fi-rr-security:before{content:\"\\f59c\"}.fi-rr-sensor-alert:before{content:\"\\f59d\"}.fi-rr-sensor-fire:before{content:\"\\f59e\"}.fi-rr-sensor-on:before{content:\"\\f59f\"}.fi-rr-sensor-smoke:before{content:\"\\f5a0\"}.fi-rr-sensor:before{content:\"\\f5a1\"}.fi-rr-settings-sliders:before{content:\"\\f5a2\"}.fi-rr-settings:before{content:\"\\f5a3\"}.fi-rr-share:before{content:\"\\f5a4\"}.fi-rr-shekel-sign:before{content:\"\\f5a5\"}.fi-rr-shield-check:before{content:\"\\f5a6\"}.fi-rr-shield-exclamation:before{content:\"\\f5a7\"}.fi-rr-shield-interrogation:before{content:\"\\f5a8\"}.fi-rr-shield-plus:before{content:\"\\f5a9\"}.fi-rr-shield:before{content:\"\\f5aa\"}.fi-rr-ship-side:before{content:\"\\f5ab\"}.fi-rr-ship:before{content:\"\\f5ac\"}.fi-rr-shoe-prints:before{content:\"\\f5ad\"}.fi-rr-shop-lock:before{content:\"\\f5ae\"}.fi-rr-shop:before{content:\"\\f5af\"}.fi-rr-shopping-bag-add:before{content:\"\\f5b0\"}.fi-rr-shopping-bag:before{content:\"\\f5b1\"}.fi-rr-shopping-basket:before{content:\"\\f5b2\"}.fi-rr-shopping-cart-add:before{content:\"\\f5b3\"}.fi-rr-shopping-cart-check:before{content:\"\\f5b4\"}.fi-rr-shopping-cart:before{content:\"\\f5b5\"}.fi-rr-shrimp:before{content:\"\\f5b6\"}.fi-rr-shuffle:before{content:\"\\f5b7\"}.fi-rr-shuttle-van:before{content:\"\\f5b8\"}.fi-rr-shuttlecock:before{content:\"\\f5b9\"}.fi-rr-sidebar-flip:before{content:\"\\f5ba\"}.fi-rr-sidebar:before{content:\"\\f5bb\"}.fi-rr-sign-hanging:before{content:\"\\f5bc\"}.fi-rr-sign-in-alt:before{content:\"\\f5bd\"}.fi-rr-sign-out-alt:before{content:\"\\f5be\"}.fi-rr-signal-alt-1:before{content:\"\\f5bf\"}.fi-rr-signal-alt-2:before{content:\"\\f5c0\"}.fi-rr-signal-alt:before{content:\"\\f5c1\"}.fi-rr-signal-stream-slash:before{content:\"\\f5c2\"}.fi-rr-signal-stream:before{content:\"\\f5c3\"}.fi-rr-sitemap:before{content:\"\\f5c4\"}.fi-rr-skateboard:before{content:\"\\f5c5\"}.fi-rr-skating:before{content:\"\\f5c6\"}.fi-rr-skewer:before{content:\"\\f5c7\"}.fi-rr-ski-jump:before{content:\"\\f5c8\"}.fi-rr-ski-lift:before{content:\"\\f5c9\"}.fi-rr-skiing-nordic:before{content:\"\\f5ca\"}.fi-rr-skiing:before{content:\"\\f5cb\"}.fi-rr-slash:before{content:\"\\f5cc\"}.fi-rr-sledding:before{content:\"\\f5cd\"}.fi-rr-sleigh:before{content:\"\\f5ce\"}.fi-rr-smartphone:before{content:\"\\f5cf\"}.fi-rr-smile-beam:before{content:\"\\f5d0\"}.fi-rr-smile-wink:before{content:\"\\f5d1\"}.fi-rr-smile:before{content:\"\\f5d2\"}.fi-rr-smiley-comment-alt:before{content:\"\\f5d3\"}.fi-rr-smog:before{content:\"\\f5d4\"}.fi-rr-smoke:before{content:\"\\f5d5\"}.fi-rr-snow-blowing:before{content:\"\\f5d6\"}.fi-rr-snowboarding:before{content:\"\\f5d7\"}.fi-rr-snowflake:before{content:\"\\f5d8\"}.fi-rr-snowflakes:before{content:\"\\f5d9\"}.fi-rr-snowmobile:before{content:\"\\f5da\"}.fi-rr-snowplow:before{content:\"\\f5db\"}.fi-rr-soap:before{content:\"\\f5dc\"}.fi-rr-social-network:before{content:\"\\f5dd\"}.fi-rr-sort-alpha-down-alt:before{content:\"\\f5de\"}.fi-rr-sort-alpha-down:before{content:\"\\f5df\"}.fi-rr-sort-alpha-up-alt:before{content:\"\\f5e0\"}.fi-rr-sort-alpha-up:before{content:\"\\f5e1\"}.fi-rr-sort-alt:before{content:\"\\f5e2\"}.fi-rr-sort-amount-down-alt:before{content:\"\\f5e3\"}.fi-rr-sort-amount-down:before{content:\"\\f5e4\"}.fi-rr-sort-amount-up-alt:before{content:\"\\f5e5\"}.fi-rr-sort-amount-up:before{content:\"\\f5e6\"}.fi-rr-sort-down:before{content:\"\\f5e7\"}.fi-rr-sort-numeric-down-alt:before{content:\"\\f5e8\"}.fi-rr-sort-numeric-down:before{content:\"\\f5e9\"}.fi-rr-sort-shapes-down:before{content:\"\\f5ea\"}.fi-rr-sort-shapes-up:before{content:\"\\f5eb\"}.fi-rr-sort-size-down:before{content:\"\\f5ec\"}.fi-rr-sort-size-up:before{content:\"\\f5ed\"}.fi-rr-sort:before{content:\"\\f5ee\"}.fi-rr-soup:before{content:\"\\f5ef\"}.fi-rr-spa:before{content:\"\\f5f0\"}.fi-rr-space-shuttle:before{content:\"\\f5f1\"}.fi-rr-spade:before{content:\"\\f5f2\"}.fi-rr-sparkles:before{content:\"\\f5f3\"}.fi-rr-speaker:before{content:\"\\f5f4\"}.fi-rr-sphere:before{content:\"\\f5f5\"}.fi-rr-spinner:before{content:\"\\f5f6\"}.fi-rr-spoon:before{content:\"\\f5f7\"}.fi-rr-sport:before{content:\"\\f5f8\"}.fi-rr-square-0:before{content:\"\\f5f9\"}.fi-rr-square-1:before{content:\"\\f5fa\"}.fi-rr-square-2:before{content:\"\\f5fb\"}.fi-rr-square-3:before{content:\"\\f5fc\"}.fi-rr-square-4:before{content:\"\\f5fd\"}.fi-rr-square-5:before{content:\"\\f5fe\"}.fi-rr-square-6:before{content:\"\\f5ff\"}.fi-rr-square-7:before{content:\"\\f600\"}.fi-rr-square-8:before{content:\"\\f601\"}.fi-rr-square-9:before{content:\"\\f602\"}.fi-rr-square-code:before{content:\"\\f603\"}.fi-rr-square-heart:before{content:\"\\f604\"}.fi-rr-square-info:before{content:\"\\f605\"}.fi-rr-square-plus:before{content:\"\\f606\"}.fi-rr-square-root:before{content:\"\\f607\"}.fi-rr-square-terminal:before{content:\"\\f608\"}.fi-rr-square:before{content:\"\\f609\"}.fi-rr-squircle:before{content:\"\\f60a\"}.fi-rr-stamp:before{content:\"\\f60b\"}.fi-rr-star-comment-alt:before{content:\"\\f60c\"}.fi-rr-star-octogram:before{content:\"\\f60d\"}.fi-rr-star:before{content:\"\\f60e\"}.fi-rr-starfighter:before{content:\"\\f60f\"}.fi-rr-stars:before{content:\"\\f610\"}.fi-rr-stats:before{content:\"\\f611\"}.fi-rr-steak:before{content:\"\\f612\"}.fi-rr-steering-wheel:before{content:\"\\f613\"}.fi-rr-stethoscope:before{content:\"\\f614\"}.fi-rr-sticker:before{content:\"\\f615\"}.fi-rr-stop:before{content:\"\\f616\"}.fi-rr-stopwatch:before{content:\"\\f617\"}.fi-rr-store-alt:before{content:\"\\f618\"}.fi-rr-store-lock:before{content:\"\\f619\"}.fi-rr-strawberry:before{content:\"\\f61a\"}.fi-rr-street-view:before{content:\"\\f61b\"}.fi-rr-subtitles:before{content:\"\\f61c\"}.fi-rr-subway:before{content:\"\\f61d\"}.fi-rr-suitcase-alt:before{content:\"\\f61e\"}.fi-rr-summer:before{content:\"\\f61f\"}.fi-rr-sun:before{content:\"\\f620\"}.fi-rr-sunrise-alt:before{content:\"\\f621\"}.fi-rr-sunrise:before{content:\"\\f622\"}.fi-rr-sunset:before{content:\"\\f623\"}.fi-rr-surfing:before{content:\"\\f624\"}.fi-rr-surprise:before{content:\"\\f625\"}.fi-rr-sushi:before{content:\"\\f626\"}.fi-rr-swimmer:before{content:\"\\f627\"}.fi-rr-sword:before{content:\"\\f628\"}.fi-rr-symbol:before{content:\"\\f629\"}.fi-rr-syringe:before{content:\"\\f62a\"}.fi-rr-t:before{content:\"\\f62b\"}.fi-rr-table-columns:before{content:\"\\f62c\"}.fi-rr-table-layout:before{content:\"\\f62d\"}.fi-rr-table-picnic:before{content:\"\\f62e\"}.fi-rr-table-pivot:before{content:\"\\f62f\"}.fi-rr-table-rows:before{content:\"\\f630\"}.fi-rr-table-tree:before{content:\"\\f631\"}.fi-rr-tablet:before{content:\"\\f632\"}.fi-rr-tachometer-alt-average:before{content:\"\\f633\"}.fi-rr-tachometer-alt-fastest:before{content:\"\\f634\"}.fi-rr-tachometer-alt-slow:before{content:\"\\f635\"}.fi-rr-tachometer-alt-slowest:before{content:\"\\f636\"}.fi-rr-tachometer-average:before{content:\"\\f637\"}.fi-rr-tachometer-fast:before{content:\"\\f638\"}.fi-rr-tachometer-fastest:before{content:\"\\f639\"}.fi-rr-tachometer-slow:before{content:\"\\f63a\"}.fi-rr-tachometer-slowest:before{content:\"\\f63b\"}.fi-rr-tachometer:before{content:\"\\f63c\"}.fi-rr-taco:before{content:\"\\f63d\"}.fi-rr-tags:before{content:\"\\f63e\"}.fi-rr-tally:before{content:\"\\f63f\"}.fi-rr-target:before{content:\"\\f640\"}.fi-rr-taxi-bus:before{content:\"\\f641\"}.fi-rr-taxi:before{content:\"\\f642\"}.fi-rr-temperature-down:before{content:\"\\f643\"}.fi-rr-temperature-frigid:before{content:\"\\f644\"}.fi-rr-temperature-high:before{content:\"\\f645\"}.fi-rr-temperature-low:before{content:\"\\f646\"}.fi-rr-temperature-up:before{content:\"\\f647\"}.fi-rr-template-alt:before{content:\"\\f648\"}.fi-rr-template:before{content:\"\\f649\"}.fi-rr-tenge:before{content:\"\\f64a\"}.fi-rr-tennis:before{content:\"\\f64b\"}.fi-rr-terminal:before{content:\"\\f64c\"}.fi-rr-terrace:before{content:\"\\f64d\"}.fi-rr-test-tube:before{content:\"\\f64e\"}.fi-rr-test:before{content:\"\\f64f\"}.fi-rr-text-check:before{content:\"\\f650\"}.fi-rr-text-height:before{content:\"\\f651\"}.fi-rr-text-shadow:before{content:\"\\f652\"}.fi-rr-text-size:before{content:\"\\f653\"}.fi-rr-text-slash:before{content:\"\\f654\"}.fi-rr-text-width:before{content:\"\\f655\"}.fi-rr-text:before{content:\"\\f656\"}.fi-rr-thermometer-half:before{content:\"\\f657\"}.fi-rr-thumbtack:before{content:\"\\f658\"}.fi-rr-thunderstorm-moon:before{content:\"\\f659\"}.fi-rr-thunderstorm-sun:before{content:\"\\f65a\"}.fi-rr-thunderstorm:before{content:\"\\f65b\"}.fi-rr-ticket-alt:before{content:\"\\f65c\"}.fi-rr-ticket:before{content:\"\\f65d\"}.fi-rr-time-add:before{content:\"\\f65e\"}.fi-rr-time-check:before{content:\"\\f65f\"}.fi-rr-time-delete:before{content:\"\\f660\"}.fi-rr-time-fast:before{content:\"\\f661\"}.fi-rr-time-forward-sixty:before{content:\"\\f662\"}.fi-rr-time-forward-ten:before{content:\"\\f663\"}.fi-rr-time-forward:before{content:\"\\f664\"}.fi-rr-time-half-past:before{content:\"\\f665\"}.fi-rr-time-oclock:before{content:\"\\f666\"}.fi-rr-time-past:before{content:\"\\f667\"}.fi-rr-time-quarter-past:before{content:\"\\f668\"}.fi-rr-time-quarter-to:before{content:\"\\f669\"}.fi-rr-time-twenty-four:before{content:\"\\f66a\"}.fi-rr-tire-flat:before{content:\"\\f66b\"}.fi-rr-tire-pressure-warning:before{content:\"\\f66c\"}.fi-rr-tire-rugged:before{content:\"\\f66d\"}.fi-rr-tire:before{content:\"\\f66e\"}.fi-rr-tired:before{content:\"\\f66f\"}.fi-rr-toilet-paper-blank:before{content:\"\\f670\"}.fi-rr-tomato:before{content:\"\\f671\"}.fi-rr-tool-box:before{content:\"\\f672\"}.fi-rr-tool-crop:before{content:\"\\f673\"}.fi-rr-tool-marquee:before{content:\"\\f674\"}.fi-rr-tooth:before{content:\"\\f675\"}.fi-rr-tornado:before{content:\"\\f676\"}.fi-rr-tower-control:before{content:\"\\f677\"}.fi-rr-tractor:before{content:\"\\f678\"}.fi-rr-traffic-light-go:before{content:\"\\f679\"}.fi-rr-traffic-light-slow:before{content:\"\\f67a\"}.fi-rr-traffic-light-stop:before{content:\"\\f67b\"}.fi-rr-traffic-light:before{content:\"\\f67c\"}.fi-rr-trailer:before{content:\"\\f67d\"}.fi-rr-train-side:before{content:\"\\f67e\"}.fi-rr-train-subway-tunnel:before{content:\"\\f67f\"}.fi-rr-train-tram:before{content:\"\\f680\"}.fi-rr-train:before{content:\"\\f681\"}.fi-rr-tram:before{content:\"\\f682\"}.fi-rr-transform:before{content:\"\\f683\"}.fi-rr-trash:before{content:\"\\f684\"}.fi-rr-treasure-chest:before{content:\"\\f685\"}.fi-rr-treatment:before{content:\"\\f686\"}.fi-rr-tree-christmas:before{content:\"\\f687\"}.fi-rr-tree-deciduous:before{content:\"\\f688\"}.fi-rr-tree:before{content:\"\\f689\"}.fi-rr-triangle-warning:before{content:\"\\f68a\"}.fi-rr-triangle:before{content:\"\\f68b\"}.fi-rr-trophy-star:before{content:\"\\f68c\"}.fi-rr-trophy:before{content:\"\\f68d\"}.fi-rr-truck-container:before{content:\"\\f68e\"}.fi-rr-truck-couch:before{content:\"\\f68f\"}.fi-rr-truck-loading:before{content:\"\\f690\"}.fi-rr-truck-monster:before{content:\"\\f691\"}.fi-rr-truck-moving:before{content:\"\\f692\"}.fi-rr-truck-pickup:before{content:\"\\f693\"}.fi-rr-truck-plow:before{content:\"\\f694\"}.fi-rr-truck-ramp:before{content:\"\\f695\"}.fi-rr-truck-side:before{content:\"\\f696\"}.fi-rr-tty:before{content:\"\\f697\"}.fi-rr-turkey:before{content:\"\\f698\"}.fi-rr-tv-music:before{content:\"\\f699\"}.fi-rr-typewriter:before{content:\"\\f69a\"}.fi-rr-u:before{content:\"\\f69b\"}.fi-rr-umbrella-beach:before{content:\"\\f69c\"}.fi-rr-umbrella:before{content:\"\\f69d\"}.fi-rr-underline:before{content:\"\\f69e\"}.fi-rr-undo-alt:before{content:\"\\f69f\"}.fi-rr-undo:before{content:\"\\f6a0\"}.fi-rr-universal-access:before{content:\"\\f6a1\"}.fi-rr-unlock:before{content:\"\\f6a2\"}.fi-rr-up-left:before{content:\"\\f6a3\"}.fi-rr-up-right:before{content:\"\\f6a4\"}.fi-rr-up:before{content:\"\\f6a5\"}.fi-rr-upload:before{content:\"\\f6a6\"}.fi-rr-usb-pendrive:before{content:\"\\f6a7\"}.fi-rr-usd-circle:before{content:\"\\f6a8\"}.fi-rr-usd-square:before{content:\"\\f6a9\"}.fi-rr-user-add:before{content:\"\\f6aa\"}.fi-rr-user-time:before{content:\"\\f6ab\"}.fi-rr-user:before{content:\"\\f6ac\"}.fi-rr-users-alt:before{content:\"\\f6ad\"}.fi-rr-users:before{content:\"\\f6ae\"}.fi-rr-utensils:before{content:\"\\f6af\"}.fi-rr-v:before{content:\"\\f6b0\"}.fi-rr-vector-alt:before{content:\"\\f6b1\"}.fi-rr-vector:before{content:\"\\f6b2\"}.fi-rr-venus-double:before{content:\"\\f6b3\"}.fi-rr-venus-mars:before{content:\"\\f6b4\"}.fi-rr-venus:before{content:\"\\f6b5\"}.fi-rr-vest-patches:before{content:\"\\f6b6\"}.fi-rr-vest:before{content:\"\\f6b7\"}.fi-rr-video-arrow-down-left:before{content:\"\\f6b8\"}.fi-rr-video-arrow-up-right:before{content:\"\\f6b9\"}.fi-rr-video-camera-alt:before{content:\"\\f6ba\"}.fi-rr-video-camera:before{content:\"\\f6bb\"}.fi-rr-video-plus:before{content:\"\\f6bc\"}.fi-rr-video-slash:before{content:\"\\f6bd\"}.fi-rr-volcano:before{content:\"\\f6be\"}.fi-rr-volleyball:before{content:\"\\f6bf\"}.fi-rr-volume:before{content:\"\\f6c0\"}.fi-rr-w:before{content:\"\\f6c1\"}.fi-rr-wagon-covered:before{content:\"\\f6c2\"}.fi-rr-wallet:before{content:\"\\f6c3\"}.fi-rr-warehouse-alt:before{content:\"\\f6c4\"}.fi-rr-water-bottle:before{content:\"\\f6c5\"}.fi-rr-water-lower:before{content:\"\\f6c6\"}.fi-rr-water-rise:before{content:\"\\f6c7\"}.fi-rr-water:before{content:\"\\f6c8\"}.fi-rr-watermelon:before{content:\"\\f6c9\"}.fi-rr-wheat:before{content:\"\\f6ca\"}.fi-rr-wheelchair-move:before{content:\"\\f6cb\"}.fi-rr-wheelchair:before{content:\"\\f6cc\"}.fi-rr-whistle:before{content:\"\\f6cd\"}.fi-rr-wifi-1:before{content:\"\\f6ce\"}.fi-rr-wifi-2:before{content:\"\\f6cf\"}.fi-rr-wifi-alt:before{content:\"\\f6d0\"}.fi-rr-wifi-exclamation:before{content:\"\\f6d1\"}.fi-rr-wifi-slash:before{content:\"\\f6d2\"}.fi-rr-wifi:before{content:\"\\f6d3\"}.fi-rr-wind-warning:before{content:\"\\f6d4\"}.fi-rr-wind:before{content:\"\\f6d5\"}.fi-rr-window-alt:before{content:\"\\f6d6\"}.fi-rr-window-maximize:before{content:\"\\f6d7\"}.fi-rr-window-minimize:before{content:\"\\f6d8\"}.fi-rr-window-restore:before{content:\"\\f6d9\"}.fi-rr-windsock:before{content:\"\\f6da\"}.fi-rr-wine-glass-crack:before{content:\"\\f6db\"}.fi-rr-woman-head:before{content:\"\\f6dc\"}.fi-rr-world:before{content:\"\\f6dd\"}.fi-rr-wrench-simple:before{content:\"\\f6de\"}.fi-rr-x:before{content:\"\\f6df\"}.fi-rr-y:before{content:\"\\f6e0\"}.fi-rr-yen:before{content:\"\\f6e1\"}.fi-rr-yin-yang:before{content:\"\\f6e2\"}.fi-rr-z:before{content:\"\\f6e3\"}.fi-rr-zoom-in:before{content:\"\\f6e4\"}.fi-rr-zoom-out:before{content:\"\\f6e5\"}\n/*# sourceMappingURL=rounded.css.map */\n"
  },
  {
    "path": "assets/webfonts/OFL.txt",
    "content": "﻿Copyright 2019 The Baloo 2 Project Authors (https://github.com/EkType/Baloo2)\n\nThis Font Software is licensed under the SIL Open Font License, Version 1.1.\nThis license is copied below, and is also available with a FAQ at:\nhttp://scripts.sil.org/OFL\n\n\n-----------------------------------------------------------\nSIL OPEN FONT LICENSE Version 1.1 - 26 February 2007\n-----------------------------------------------------------\n\nPREAMBLE\nThe goals of the Open Font License (OFL) are to stimulate worldwide\ndevelopment of collaborative font projects, to support the font creation\nefforts of academic and linguistic communities, and to provide a free and\nopen framework in which fonts may be shared and improved in partnership\nwith others.\n\nThe OFL allows the licensed fonts to be used, studied, modified and\nredistributed freely as long as they are not sold by themselves. The\nfonts, including any derivative works, can be bundled, embedded, \nredistributed and/or sold with any software provided that any reserved\nnames are not used by derivative works. The fonts and derivatives,\nhowever, cannot be released under any other type of license. The\nrequirement for fonts to remain under this license does not apply\nto any document created using the fonts or their derivatives.\n\nDEFINITIONS\n\"Font Software\" refers to the set of files released by the Copyright\nHolder(s) under this license and clearly marked as such. This may\ninclude source files, build scripts and documentation.\n\n\"Reserved Font Name\" refers to any names specified as such after the\ncopyright statement(s).\n\n\"Original Version\" refers to the collection of Font Software components as\ndistributed by the Copyright Holder(s).\n\n\"Modified Version\" refers to any derivative made by adding to, deleting,\nor substituting -- in part or in whole -- any of the components of the\nOriginal Version, by changing formats or by porting the Font Software to a\nnew environment.\n\n\"Author\" refers to any designer, engineer, programmer, technical\nwriter or other person who contributed to the Font Software.\n\nPERMISSION & CONDITIONS\nPermission is hereby granted, free of charge, to any person obtaining\na copy of the Font Software, to use, study, copy, merge, embed, modify,\nredistribute, and sell modified and unmodified copies of the Font\nSoftware, subject to the following conditions:\n\n1) Neither the Font Software nor any of its individual components,\nin Original or Modified Versions, may be sold by itself.\n\n2) Original or Modified Versions of the Font Software may be bundled,\nredistributed and/or sold with any software, provided that each copy\ncontains the above copyright notice and this license. These can be\nincluded either as stand-alone text files, human-readable headers or\nin the appropriate machine-readable metadata fields within text or\nbinary files as long as those fields can be easily viewed by the user.\n\n3) No Modified Version of the Font Software may use the Reserved Font\nName(s) unless explicit written permission is granted by the corresponding\nCopyright Holder. This restriction only applies to the primary font name as\npresented to the users.\n\n4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font\nSoftware shall not be used to promote, endorse or advertise any\nModified Version, except to acknowledge the contribution(s) of the\nCopyright Holder(s) and the Author(s) or with their explicit written\npermission.\n\n5) The Font Software, modified or unmodified, in part or in whole,\nmust be distributed entirely under this license, and must not be\ndistributed under any other license. The requirement for fonts to\nremain under this license does not apply to any document created\nusing the Font Software.\n\nTERMINATION\nThis license becomes null and void if any of the above conditions are\nnot met.\n\nDISCLAIMER\nTHE FONT SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT\nOF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE\nCOPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nINCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL\nDAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM\nOTHER DEALINGS IN THE FONT SOFTWARE.\n"
  },
  {
    "path": "misc/window/LICENSE",
    "content": "Copyright (c) 2021-2022 Guasam\n\nThis software is provided \"as-is\", without any express or implied warranty. In no event\nwill the authors be held liable for any damages arising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose, including commercial\napplications, and to alter it and redistribute it freely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must not claim that you\nwrote the original software. If you use this software in a product, an acknowledgment\nin the product documentation would be appreciated but is not required.\n\n2. Altered source versions must be plainly marked as such, and must not be misrepresented\nas being the original software.\n\n3. This notice may not be removed or altered from any source distribution."
  },
  {
    "path": "misc/window/components/ControlButton.tsx",
    "content": "import classNames from 'classnames';\nimport React from 'react';\n\ninterface IControlButtonProps {\n  readonly name: string;\n  readonly path: string;\n  readonly title: string;\n}\n\nconst ControlButton: React.FC<\n  IControlButtonProps & React.HTMLAttributes<HTMLDivElement>\n> = (props) => {\n  const { name, path, title, ...rest } = props;\n  const { onClick } = rest;\n\n  const className = classNames('control', name);\n\n  return (\n    <div\n      data-label={name}\n      className={className}\n      onClick={onClick}\n      title={title}\n      {...rest}\n    >\n      <svg aria-hidden='true' version='1.1' width='10' height='10'>\n        <path fill='currentColor' d={path} />\n      </svg>\n    </div>\n  );\n};\n\nexport default ControlButton;\n"
  },
  {
    "path": "misc/window/components/Titlebar.less",
    "content": "/**\n * Copyright (c) 2021, Guasam\n *\n * This software is provided \"as-is\", without any express or implied warranty. In no event\n * will the authors be held liable for any damages arising from the use of this software.\n * Read the LICENSE file for more details.\n *\n * @author  : guasam\n * @project : Electron Window\n * @package : Window Components Stylesheet\n*/\n// @import '/src/renderer/components/Theme.scss';\n@titlebar-baseSize: 16px;\n@titlebar-height: 28px;\n@titlebar-bg: #171b21;\n@titlebar-iconSize: 16px;\n@em: @titlebar-baseSize*1em;\n\n//-----------------------------------------\n// Mixins\n//-----------------------------------------\n\n.flex-strech() {\n  display: flex;\n  align-items: stretch;\n}\n.flex-align-center() {\n  display: flex;\n  align-items: center;\n}\n\n//-----------------------------------------\n// Stylesheet\n//-----------------------------------------\n\n.window-content {\n  position: relative;\n  overflow: auto;\n  flex: 1;\n}\n\n.window-titlebar {\n  .flex-strech();\n  display: none;\n  font-size: @titlebar-baseSize;\n  height: @titlebar-height;\n  background: @titlebar-bg;\n  // -webkit-app-region: drag; // Draggable\n  user-select: none;\n  position: relative;\n\n  & > section {\n    .flex-align-center();\n  }\n\n  &-content {\n    flex: 1;\n    font-size: calc(@titlebar-baseSize - 3px);\n    color: #a9b0bb;\n\n    &.centered {\n      width: 100%;\n      height: 100%;\n      position: absolute;\n      justify-content: center;\n    }\n  }\n\n  // Titlebar icon\n  &-icon {\n    padding: 0 0.75em;\n    img {\n      width: @titlebar-iconSize;\n      height: @titlebar-iconSize;\n    }\n  }\n\n  // Titlebar Menu\n  &-menu {\n    flex: 1;\n  }\n\n  .menu {\n    &-item {\n      position: relative;\n    }\n\n    &-item.active {\n      .menu-title {\n        background: #3c4043;\n        color: #bfbfbf;\n      }\n    }\n\n    &-title {\n      padding: 4px 10px;\n      font-size: 0.8125rem;\n      text-shadow: 0px 1px 1px black;\n      -webkit-app-region: no-drag;\n      color: #97a0b1;\n\n      &:hover {\n        background-color: #1f252c;\n      }\n    }\n\n    &-popup {\n      display: none;\n      position: fixed;\n      background: #292a2d;\n      min-width: 70px;\n      border: 1px solid #3c4043;\n      padding: 0.25rem 0;\n      box-shadow: 2px 1px 4px hsla(0, 0%, 0%, 0.5);\n      z-index: 10000;\n\n      &.active {\n        display: block;\n      }\n\n      &-item {\n        display: flex;\n        justify-content: space-between;\n        font-size: 0.8125rem;\n        text-shadow: 0px 1px 1px black;\n        padding: 0.375rem 1rem;\n\n        &:hover {\n          background: #1761cb;\n\n          .popup-item-shortcut {\n            color: #8cbbff;\n          }\n        }\n      }\n    }\n  }\n\n  .popup-item {\n    &-name {\n      padding-right: 2rem;\n      color: #d8d8d8;\n    }\n    &-shortcut {\n      color: #73757c;\n      text-shadow: none;\n    }\n    &-separator {\n      height: 1px;\n      background: #3c4043;\n      margin: 4px 0;\n    }\n  }\n\n  // Titlebar controls\n  &-controls {\n    .flex-strech();\n    position: absolute;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    color: hsla(var(--app-text-color), 0.5);\n\n    &.type-windows {\n      .control {\n        padding: 0 1.15em;\n        font-size: 0.875em;\n        display: flex;\n        height: 100%;\n        align-items: center;\n        -webkit-app-region: no-drag;\n      }\n    }\n\n    &.type-mac {\n      display: none !important;\n\n      .control {\n        width: 16px;\n        height: 16px;\n        background: #0e0e0e99;\n        border-radius: 50%;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        margin-right: 0.675rem;\n        color: transparent;\n        -webkit-app-region: no-drag;\n        opacity: 0.8;\n\n        &:hover {\n          opacity: 1;\n        }\n      }\n\n      .control.close {\n        background: #f46d60;\n      }\n      .control.maximize {\n        background: #59ca56;\n      }\n      .control.minimize {\n        background: #f9c04e;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "misc/window/components/Titlebar.tsx",
    "content": "/**\n * Copyright (c) 2021, Guasam\n *\n * This software is provided \"as-is\", without any express or implied warranty. In no event\n * will the authors be held liable for any damages arising from the use of this software.\n * Read the LICENSE file for more details.\n *\n * @author  : guasam\n * @project : Electron Window\n * @package : Window Titlebar (Component)\n */\n\nimport React, { createRef, useContext, useEffect, useRef, useState } from 'react';\nimport titlebarMenus from '../titlebarMenus';\nimport classNames from 'classnames';\nimport WindowControls from './WindowControls';\nimport context from '../titlebarContextApi';\nimport { WindowContext } from './WindowFrame';\nimport './Titlebar.less';\n\ntype Props = {\n  title: string;\n  mode: 'centered-title';\n  icon?: string;\n};\n\nconst Titlebar: React.FC<Props> = (props) => {\n  const activeMenuIndex = useRef<number | null>(null);\n  const menusRef = titlebarMenus.map(() => createRef<HTMLDivElement>());\n  const [menusVisible, setMenusVisible] = useState(true);\n  const windowContext = useContext(WindowContext);\n\n  useEffect(() => {\n    const handleKeyDown = (e: KeyboardEvent) => {\n      if (e.repeat) return; // Prevent repeatation of toggle when key holding\n      if (e.altKey && e.ctrlKey) {\n        // Hiding menus? close active menu popup\n        if (menusVisible) {\n          closeActiveMenu();\n        }\n        setMenusVisible(!menusVisible);\n      }\n    };\n\n    document.addEventListener('keydown', handleKeyDown);\n\n    return () => {\n      document.removeEventListener('keydown', handleKeyDown);\n    };\n  }, [menusVisible, menusRef]);\n\n  useEffect(() => {\n    function handleClickOutside(event: MouseEvent) {\n      if (activeMenuIndex.current != null) {\n        if (\n          menusRef[activeMenuIndex.current].current &&\n          !menusRef[activeMenuIndex.current].current?.contains(event.target as Node)\n        ) {\n          // console.log('You clicked outside of me!');\n          closeActiveMenu();\n        }\n      }\n    }\n\n    if (activeMenuIndex != null) {\n      document.addEventListener('mousedown', handleClickOutside);\n      // console.log('added event');\n    }\n\n    return () => {\n      document.removeEventListener('mousedown', handleClickOutside);\n      // console.log('remove event');\n    };\n  }, [activeMenuIndex, menusRef]);\n\n  function showMenu(index: number, e: React.MouseEvent<HTMLDivElement>) {\n    e.stopPropagation();\n    e.preventDefault();\n\n    if (menusRef[index].current?.classList.contains('active')) {\n      // close..\n      closeActiveMenu();\n    } else {\n      // open..\n      menusRef[index].current?.classList.add('active');\n      activeMenuIndex.current = index;\n      menusRef[index].current?.parentElement?.classList.add('active');\n    }\n  }\n\n  function onMenuHover(index: number) {\n    if (activeMenuIndex.current != null) {\n      menusRef[activeMenuIndex.current].current?.classList.toggle('active');\n      menusRef[index].current?.classList.toggle('active');\n      menusRef[index].current?.parentElement?.classList.toggle('active');\n      menusRef[activeMenuIndex.current].current?.parentElement?.classList.toggle(\n        'active',\n      );\n\n      activeMenuIndex.current = index;\n    }\n  }\n\n  function closeActiveMenu() {\n    if (activeMenuIndex.current != null) {\n      menusRef[activeMenuIndex.current].current?.classList.remove('active');\n      menusRef[activeMenuIndex.current]?.current?.parentElement?.classList.remove('active');\n      activeMenuIndex.current = null;\n    }\n  }\n\n  function handleAction(action?: string, value?: string | number) {\n    closeActiveMenu();\n    const c: Record<string, CallableFunction> = context;\n    if (action) {\n      if (typeof c[action] === 'function') {\n        c[action](value);\n      } else {\n        console.log(`action [${action}] is not available in titlebar context`);\n      }\n    }\n  }\n\n  return (\n    <div className='window-titlebar'>\n      {props.icon ? (\n        <section className='window-titlebar-icon'>\n          <img src={props.icon} alt='titlebar icon' />\n        </section>\n      ) : (\n        ''\n      )}\n\n      <section\n        className={classNames('window-titlebar-content', {\n          centered: props.mode === 'centered-title',\n        })}\n      >\n        {menusVisible ? '' : <div className='window-title'>{props.title}</div>}\n      </section>\n\n      <section\n        className={classNames('window-titlebar-menu', {\n          hidden: !menusVisible,\n        })}\n      >\n        {titlebarMenus.map((item, menuIndex) => {\n          return (\n            <div className='menu-item' key={`menu_${menuIndex}`}>\n              <div\n                className='menu-title'\n                onClick={(e) => showMenu(menuIndex, e)}\n                onMouseEnter={() => onMenuHover(menuIndex)}\n                onMouseDown={(e) => e.preventDefault()}\n              >\n                {item.name}\n              </div>\n              <div className='menu-popup' ref={menusRef[menuIndex]}>\n                {item.items?.map((menuItem, menuItemIndex) => {\n                  if (menuItem.name === '__') {\n                    return (\n                      <div\n                        key={`menu_${menuIndex}_popup_item_${menuItemIndex}`}\n                        className='popup-item-separator'\n                      ></div>\n                    );\n                  }\n\n                  return (\n                    <div\n                      key={`menu_${menuIndex}_popup_item_${menuItemIndex}`}\n                      className='menu-popup-item'\n                      onClick={() =>\n                        handleAction(menuItem.action, menuItem.value)\n                      }\n                      onMouseDown={(e) => e.preventDefault()}\n                    >\n                      <div className='popup-item-name'>{menuItem.name}</div>\n                      <div className='popup-item-shortcut'>\n                        {menuItem.shortcut}\n                      </div>\n                    </div>\n                  );\n                })}\n              </div>\n            </div>\n          );\n        })}\n      </section>\n\n      <WindowControls platform={windowContext.platform} tooltips={true} />\n    </div>\n  );\n};\n\nexport default Titlebar;\n"
  },
  {
    "path": "misc/window/components/WindowControls.tsx",
    "content": "/**\n * Copyright (c) 2021, Guasam\n *\n * This software is provided \"as-is\", without any express or implied warranty. In no event\n * will the authors be held liable for any damages arising from the use of this software.\n * Read the LICENSE file for more details.\n *\n * @author  : guasam\n * @project : Electron Window\n * @package : Window Controls - Close, Minimize, Maximize (Component)\n */\n\nimport classNames from 'classnames';\nimport React from 'react';\nimport context from '../titlebarContextApi';\n\nimport ControlButton from './ControlButton';\n\ntype Props = {\n  platform: string;\n  tooltips?: boolean;\n};\n\nconst closePath =\n  'M 0,0 0,0.7 4.3,5 0,9.3 0,10 0.7,10 5,5.7 9.3,10 10,10 10,9.3 5.7,5 10,0.7 10,0 9.3,0 5,4.3 0.7,0 Z';\nconst maximizePath = 'M 0,0 0,10 10,10 10,0 Z M 1,1 9,1 9,9 1,9 Z';\nconst minimizePath = 'M 0,5 10,5 10,6 0,6 Z';\n\nconst WindowControls: React.FC<Props> = (props) => {\n  return (\n    <section\n      className={classNames(\n        'window-titlebar-controls',\n        `type-${props.platform}`,\n      )}\n    >\n      <ControlButton\n        name='minimize'\n        onClick={() => context.minimize()}\n        path={minimizePath}\n        title={props.tooltips ? 'Minimize' : null}\n      />\n      <ControlButton\n        name='maximize'\n        onClick={() => context.toggle_maximize()}\n        path={maximizePath}\n        title={props.tooltips ? 'Maximize' : null}\n      />\n      <ControlButton\n        name='close'\n        onClick={() => context.exit()}\n        path={closePath}\n        title={props.tooltips ? 'Close' : null}\n      />\n    </section>\n  );\n};\n\nexport default WindowControls;\n"
  },
  {
    "path": "misc/window/components/WindowFrame.tsx",
    "content": "/**\n * Copyright (c) 2021, Guasam\n *\n * This software is provided \"as-is\", without any express or implied warranty. In no event\n * will the authors be held liable for any damages arising from the use of this software.\n * Read the LICENSE file for more details.\n *\n * @author  : guasam\n * @project : Electron Window\n * @package : Window Frame (Component)\n */\n\nimport React, { useEffect, useRef } from 'react';\nimport Titlebar from './Titlebar';\nconst logo = require('@assets/images/logo.png')\n\ntype Props = {\n  title?: string;\n  borderColor?: string;\n  platform: 'windows' | 'mac';\n  children: React.ReactNode;\n};\n\ntype Context = {\n  platform: 'windows' | 'mac';\n};\n\nexport const WindowContext = React.createContext<Context>({\n  platform: 'windows',\n});\n\nconst WindowFrame: React.FC<Props> = (props) => {\n  const itsRef = useRef<HTMLDivElement>(null);\n\n  useEffect(() => {\n    const { parentElement } = itsRef.current;\n    parentElement.classList.add('has-electron-window');\n    parentElement.classList.add('has-border');\n\n    // Apply border color if prop given\n    if (props.borderColor) {\n      parentElement.style.borderColor = props.borderColor;\n    }\n  }, []);\n\n  return (\n    <WindowContext.Provider value={{ platform: props.platform }}>\n      {/* Reference creator */}\n      <div className='start-electron-window' ref={itsRef}></div>\n      {/* Window Titlebar */}\n      <Titlebar\n        title={props.title ?? 'Electron Window'}\n        mode='centered-title'\n        icon={logo}\n      />\n      {/* Window Content (Application to render) */}\n      <div className='window-content'>{props.children}</div>\n    </WindowContext.Provider>\n  );\n};\n\nexport default WindowFrame;\n"
  },
  {
    "path": "misc/window/titlebarContext.ts",
    "content": "/**\n * Copyright (c) 2021, Guasam\n *\n * This software is provided \"as-is\", without any express or implied warranty. In no event\n * will the authors be held liable for any damages arising from the use of this software.\n * Read the LICENSE file for more details.\n *\n * @author  : guasam\n * @project : Electron Window\n * @package : Titlebar IPC (Renderer Process)\n */\n\nimport { ipcRenderer } from 'electron';\n\nconst titlebarContext = {\n  exit() {\n    ipcRenderer.invoke('window-close');\n  },\n  undo() {\n    ipcRenderer.invoke('web-undo');\n  },\n  redo() {\n    ipcRenderer.invoke('web-redo');\n  },\n  cut() {\n    ipcRenderer.invoke('web-cut');\n  },\n  copy() {\n    ipcRenderer.invoke('web-copy');\n  },\n  paste() {\n    ipcRenderer.invoke('web-paste');\n  },\n  delete() {\n    ipcRenderer.invoke('web-delete');\n  },\n  select_all() {\n    ipcRenderer.invoke('web-select-all');\n  },\n  reload() {\n    ipcRenderer.invoke('web-reload');\n  },\n  force_reload() {\n    ipcRenderer.invoke('web-force-reload');\n  },\n  toggle_devtools() {\n    ipcRenderer.invoke('web-toggle-devtools');\n  },\n  actual_size() {\n    ipcRenderer.invoke('web-actual-size');\n  },\n  zoom_in() {\n    ipcRenderer.invoke('web-zoom-in');\n  },\n  zoom_out() {\n    ipcRenderer.invoke('web-zoom-out');\n  },\n  toggle_fullscreen() {\n    ipcRenderer.invoke('web-toggle-fullscreen');\n  },\n  minimize() {\n    ipcRenderer.invoke('window-minimize');\n  },\n  toggle_maximize() {\n    ipcRenderer.invoke('window-toggle-maximize');\n  },\n  open_url(url: string) {\n    ipcRenderer.invoke('open-url', url);\n  },\n};\n\nexport type TitlebarContextApi = typeof titlebarContext;\n\nexport default titlebarContext;\n"
  },
  {
    "path": "misc/window/titlebarContextApi.ts",
    "content": "/**\n * Copyright (c) 2021, Guasam\n *\n * This software is provided \"as-is\", without any express or implied warranty. In no event\n * will the authors be held liable for any damages arising from the use of this software.\n * Read the LICENSE file for more details.\n *\n * @author  : guasam\n * @project : Electron Window\n * @package : Titlebar Context API\n */\n\nimport { TitlebarContextApi } from './titlebarContext';\n\nconst context: TitlebarContextApi = (window as any).api?.titlebar;\n\nexport default context;\n"
  },
  {
    "path": "misc/window/titlebarIPC.ts",
    "content": "/**\n * Copyright (c) 2021, Guasam\n *\n * This software is provided \"as-is\", without any express or implied warranty. In no event\n * will the authors be held liable for any damages arising from the use of this software.\n * Read the LICENSE file for more details.\n *\n * @author  : guasam\n * @project : Electron Window\n * @package : Titlebar IPC (Main Process)\n */\n\nimport { BrowserWindow, ipcMain, shell } from 'electron';\n\nexport const registerTitlebarIpc = (mainWindow: BrowserWindow) => {\n  ipcMain.handle('window-minimize', () => {\n    mainWindow.minimize();\n  });\n\n  ipcMain.handle('window-maximize', () => {\n    mainWindow.maximize();\n  });\n\n  ipcMain.handle('window-toggle-maximize', () => {\n    if (mainWindow.isMaximized()) {\n      mainWindow.unmaximize();\n    } else {\n      mainWindow.maximize();\n    }\n  });\n\n  ipcMain.handle('window-close', () => {\n    mainWindow.close();\n  });\n\n  ipcMain.handle('web-undo', () => {\n    mainWindow.webContents.undo();\n  });\n\n  ipcMain.handle('web-redo', () => {\n    mainWindow.webContents.redo();\n  });\n\n  ipcMain.handle('web-cut', () => {\n    mainWindow.webContents.cut();\n  });\n\n  ipcMain.handle('web-copy', () => {\n    mainWindow.webContents.copy();\n  });\n\n  ipcMain.handle('web-paste', () => {\n    mainWindow.webContents.paste();\n  });\n\n  ipcMain.handle('web-delete', () => {\n    mainWindow.webContents.delete();\n  });\n\n  ipcMain.handle('web-select-all', () => {\n    mainWindow.webContents.selectAll();\n  });\n\n  ipcMain.handle('web-reload', () => {\n    mainWindow.webContents.reload();\n  });\n\n  ipcMain.handle('web-force-reload', () => {\n    mainWindow.webContents.reloadIgnoringCache();\n  });\n\n  ipcMain.handle('web-toggle-devtools', () => {\n    mainWindow.webContents.toggleDevTools();\n  });\n\n  ipcMain.handle('web-actual-size', () => {\n    mainWindow.webContents.setZoomLevel(0);\n  });\n\n  ipcMain.handle('web-zoom-in', () => {\n    mainWindow.webContents.setZoomLevel(mainWindow.webContents.zoomLevel + 0.5);\n  });\n\n  ipcMain.handle('web-zoom-out', () => {\n    mainWindow.webContents.setZoomLevel(mainWindow.webContents.zoomLevel - 0.5);\n  });\n\n  ipcMain.handle('web-toggle-fullscreen', () => {\n    mainWindow.setFullScreen(!mainWindow.fullScreen);\n  });\n\n  ipcMain.handle('open-url', (e, url) => {\n    shell.openExternal(url);\n  });\n};\n"
  },
  {
    "path": "misc/window/titlebarMenus.ts",
    "content": "/**\n * Copyright (c) 2021, Guasam\n *\n * This software is provided \"as-is\", without any express or implied warranty. In no event\n * will the authors be held liable for any damages arising from the use of this software.\n * Read the LICENSE file for more details.\n *\n * @author  : guasam\n * @project : Electron Window\n * @package : Titlebar Menu Items\n */\n\nexport type TitlebarMenuItem = {\n  name: string;\n  action?: string;\n  shortcut?: string;\n  value?: string | number;\n  items?: TitlebarMenuItem[];\n};\n\nexport type TitlebarMenu = {\n  name: string;\n  items: TitlebarMenuItem[];\n};\n\nconst titlebarMenus: TitlebarMenu[] = [\n  {\n    name: 'File',\n    items: [\n      {\n        name: 'Exit',\n        action: 'exit',\n      },\n    ],\n  },\n  {\n    name: 'Edit',\n    items: [\n      {\n        name: 'Undo',\n        action: 'undo',\n        shortcut: 'Ctrl+Z',\n      },\n      {\n        name: 'Redo',\n        action: 'redo',\n        shortcut: 'Ctrl+Y',\n      },\n      {\n        name: '__',\n      },\n      {\n        name: 'Cut',\n        action: 'cut',\n        shortcut: 'Ctrl+X',\n      },\n      {\n        name: 'Copy',\n        action: 'copy',\n        shortcut: 'Ctrl+C',\n      },\n      {\n        name: 'Paste',\n        action: 'paste',\n        shortcut: 'Ctrl+V',\n      },\n      {\n        name: 'Delete',\n        action: 'delete',\n      },\n      {\n        name: '__',\n      },\n      {\n        name: 'Select All',\n        action: 'select_all',\n        shortcut: 'Ctrl+A',\n      },\n    ],\n  },\n  {\n    name: 'View',\n    items: [\n      {\n        name: 'Reload',\n        action: 'reload',\n        shortcut: 'Ctrl+R',\n      },\n      {\n        name: 'Force Reload',\n        action: 'force_reload',\n        shortcut: 'Ctrl+Shift+R',\n      },\n      {\n        name: 'Toogle Developer Tools',\n        action: 'toggle_devtools',\n        shortcut: 'Ctrl+Shift+I',\n      },\n      {\n        name: '__',\n      },\n      {\n        name: 'Actual Size',\n        action: 'actual_size',\n        shortcut: 'Ctrl+0',\n      },\n      {\n        name: 'Zoom In',\n        action: 'zoom_in',\n        shortcut: 'Ctrl++',\n      },\n      {\n        name: 'Zoom Out',\n        action: 'zoom_out',\n        shortcut: 'Ctrl+-',\n      },\n      {\n        name: '__',\n      },\n      {\n        name: 'Toggle Fullscreen',\n        action: 'toggle_fullscreen',\n        shortcut: 'F11',\n      },\n    ],\n  },\n  {\n    name: 'Window',\n    items: [\n      {\n        name: 'Minimize',\n        action: 'minimize',\n        shortcut: 'Ctrl+M',\n      },\n      {\n        name: 'Close',\n        action: 'exit',\n        shortcut: 'Ctrl+W',\n      },\n    ],\n  },\n  {\n    name: 'Author',\n    items: [\n      {\n        name: 'Guasam',\n        action: 'open_url',\n        value: 'https://github.com/guasam',\n        shortcut: '@guasam',\n      },\n    ],\n  },\n];\n\nexport default titlebarMenus;\n"
  },
  {
    "path": "misc/window/windowPreload.ts",
    "content": "import { contextBridge, ipcRenderer } from 'electron';\nimport titlebarContext from './titlebarContext';\n\ncontextBridge.exposeInMainWorld('api', {\n  titlebar: titlebarContext,\n  send: (channel: string, data: string) => {\n    // whitelist channels\n    const validChannels = ['toMain'];\n    if (validChannels.includes(channel)) {\n      ipcRenderer.send(channel, data);\n    }\n  },\n  receive: (channel: string, func: () => void) => {\n    const validChannels = [\n      'gotLoadedDataX',\n      'Home',\n      'Picture',\n      'gotAllPictures',\n      'gotPicture',\n      'Shortcuts',\n      'gotAllBlocks',\n      'openArchive',\n      'gotPageStyle',\n      'gotUserTheme',\n      'gotArchive',\n      'gotUserColor',\n      'gotOS',\n      'openFiles',\n      'newFile',\n      'Save',\n      'fromMain',\n      'Text',\n      'Graph',\n      'Math',\n      'Group',\n      'gotNotebooks',\n      'toggleNotebooks',\n      'Search',\n    ];\n    if (validChannels.includes(channel)) {\n      // Deliberately strip event as it includes `sender`\n      ipcRenderer.on(channel, (event, ...args) => func(...(args as [])));\n    }\n  },\n  getNotebooks: () => {\n    ipcRenderer.send('getNotebooks');\n  },\n  delete: (path: string, isFolder: boolean) => {\n    ipcRenderer.send('delete', path, isFolder);\n  },\n  newFile: (filePath: string) => {\n    ipcRenderer.send('newFile', filePath);\n  },\n  newFolder: (folderPath: string) => {\n    ipcRenderer.send('newFolder', folderPath);\n  },\n  openFiles: () => {\n    ipcRenderer.send('openFiles');\n  },\n  move: (oldPath: string, newPath: string) => {\n    ipcRenderer.send('move', oldPath, newPath);\n  },\n  save: (data: string, file: string, newName: string) => {\n    ipcRenderer.send('save', data, file, newName);\n  },\n  load: (file: string) => {\n    ipcRenderer.send('load', file);\n  },\n  saveX: (data: string, filePath: string) => {\n    ipcRenderer.send('saveX', data, filePath);\n  },\n  loadX: (filePath: string) => {\n    ipcRenderer.send('loadX',filePath);\n  },\n  getOS: () => {\n    ipcRenderer.send('getOS');\n  },\n  maximize: () => {\n    ipcRenderer.send('maximize');\n  },\n  unmaximize: () => {\n    ipcRenderer.send('unmaximize');\n  },\n  minimize: () => {\n    ipcRenderer.send('minimize');\n  },\n  close: () => {\n    ipcRenderer.send('close');\n  },\n  setUserColor: (color: string) => {\n    ipcRenderer.send('setUserColor', color);\n  },\n  setPageStyle: (style: string) => {\n    ipcRenderer.send('setPageStyle', style);\n  },\n  toggle: () => {\n    ipcRenderer.send('dark-mode');\n  },\n  getUserColor: () => {\n    ipcRenderer.send('getUserColor');\n  },\n  getPageStyle: () => {\n    ipcRenderer.send('getPageStyle');\n  },\n  getUserTheme: () => {\n    ipcRenderer.send('getUserTheme');\n  },\n  getPicture: (id: string) => {\n    ipcRenderer.send('getPicture', id);\n  },\n  getAllPictures: (path: string) => {\n    ipcRenderer.send('getAllPictures', path);\n  },\n  getArchive: () => {\n    ipcRenderer.send('getArchive');\n  },\n  startSearch: () => {\n    ipcRenderer.send('startSearch');\n  },\n});\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"mathberet\",\n  \"productName\": \"Mathberet\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Digital Mathematics Notebook\",\n  \"main\": \".webpack/main\",\n  \"scripts\": {\n    \"start\": \"cross-env NODE_ENV=development electron-forge start\",\n    \"package\": \"electron-forge package\",\n    \"make\": \"electron-forge make\",\n    \"publish\": \"electron-forge publish\",\n    \"lint\": \"eslint src/ --ext .ts,.js,.tsx,.jsx\"\n  },\n  \"keywords\": [\n    \"react\",\n    \"javascript\",\n    \"typescript\",\n    \"math\",\n    \"mathematics\",\n    \"notebook\",\n    \"notes\"\n  ],\n  \"author\": {\n    \"name\": \"yonatanmgr\",\n    \"url\": \"https://github.com/yonatanmgr\"\n  },\n  \"contributors\": [\n    {\n      \"name\": \"Erez Birenholz\",\n      \"url\": \"https://github.com/ErezBiren\"\n    },\n    {\n      \"name\": \"Ziv Nadel\",\n      \"url\": \"https://github.com/zivnadel\"\n    },\n    {\n      \"name\": \"Nadav Magier\",\n      \"url\": \"https://github.com/Nadav0077\"\n    }\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/yonatanmgr/mathberet\"\n  },\n  \"license\": \"MIT\",\n  \"config\": {\n    \"forge\": \"./tools/forge/forge.config.js\"\n  },\n  \"devDependencies\": {\n    \"@electron-forge/cli\": \"6.0.5\",\n    \"@electron-forge/maker-deb\": \"6.0.5\",\n    \"@electron-forge/maker-rpm\": \"6.0.5\",\n    \"@electron-forge/maker-squirrel\": \"6.0.5\",\n    \"@electron-forge/maker-zip\": \"6.0.5\",\n    \"@electron-forge/plugin-webpack\": \"6.0.5\",\n    \"@marshallofsound/webpack-asset-relocator-loader\": \"^0.5.0\",\n    \"@pmmmwh/react-refresh-webpack-plugin\": \"^0.5.10\",\n    \"@types/node\": \"^18.13.0\",\n    \"@types/react\": \"^18.0.27\",\n    \"@types/react-dom\": \"^18.0.10\",\n    \"@types/react-grid-layout\": \"^1.3.2\",\n    \"@types/webpack-env\": \"^1.18.0\",\n    \"@typescript-eslint/eslint-plugin\": \"^5.51.0\",\n    \"@typescript-eslint/parser\": \"^5.51.0\",\n    \"@vercel/webpack-asset-relocator-loader\": \"^1.7.3\",\n    \"classnames\": \"^2.3.2\",\n    \"cross-env\": \"^7.0.3\",\n    \"css-loader\": \"^6.7.3\",\n    \"electron\": \"^23.0.0\",\n    \"eslint\": \"^8.33.0\",\n    \"eslint-import-resolver-alias\": \"^1.1.2\",\n    \"eslint-plugin-import\": \"^2.27.5\",\n    \"eslint-plugin-react\": \"^7.32.2\",\n    \"file-loader\": \"^6.2.0\",\n    \"fork-ts-checker-webpack-plugin\": \"^7.3.0\",\n    \"less\": \"^4.1.3\",\n    \"less-loader\": \"11.1.0\",\n    \"node-loader\": \"^2.0.0\",\n    \"react-refresh\": \"^0.14.0\",\n    \"sass\": \"^1.58.0\",\n    \"sass-loader\": \"^13.2.0\",\n    \"style-loader\": \"^3.3.1\",\n    \"ts-loader\": \"9.4.2\",\n    \"typescript\": \"^4.9.5\",\n    \"webpack\": \"^5.75.0\"\n  },\n  \"dependencies\": {\n    \"@cortex-js/compute-engine\": \"^0.12.2\",\n    \"@flaticon/flaticon-uicons\": \"^2.0.1\",\n    \"@tldraw/tldraw\": \"^1.28.0\",\n    \"electron-squirrel-startup\": \"^1.0.0\",\n    \"electron-store\": \"^8.1.0\",\n    \"gridstack\": \"^7.2.3\",\n    \"i18next\": \"^22.4.11\",\n    \"kbar\": \"^0.1.0-beta.40\",\n    \"keyboard-css\": \"^1.2.4\",\n    \"mafs\": \"^0.15.2\",\n    \"mathjs\": \"^11.6.0\",\n    \"mathlive\": \"^0.87.1\",\n    \"react\": \"^18.2.0\",\n    \"react-complex-tree\": \"^2.1.1\",\n    \"react-dom\": \"^18.2.0\",\n    \"react-grid-layout\": \"^1.3.4\",\n    \"react-i18next\": \"^12.2.0\",\n    \"react-math-view\": \"^1.3.2\",\n    \"react-mathlive\": \"^3.0.5-preview.1\",\n    \"react-resizable\": \"^3.0.4\",\n    \"slate\": \"^0.91.4\",\n    \"slate-history\": \"^0.86.0\",\n    \"slate-react\": \"^0.91.8\",\n    \"tex-math-parser\": \"^2.0.4\"\n  }\n}\n"
  },
  {
    "path": "src/common/helpers.ts",
    "content": "/**\n * Checks if process NODE_ENV in 'development' mode\n */\nexport function inDev(): boolean {\n  return process.env.NODE_ENV == 'development';\n}\n"
  },
  {
    "path": "src/common/i18n.ts",
    "content": "import i18n from 'i18next';\nimport { initReactI18next } from 'react-i18next';\nimport { HE_TRANSLATION } from './locals/he';\nimport { EN_TRANSLATION } from './locals/en';\nimport { RU_TRANSLATION } from './locals/ru';\nimport { AR_TRANSLATION } from './locals/ar';\nimport { ES_TRANSLATION } from './locals/es';\nimport { ZH_TRANSLATION } from './locals/zh';\nimport { FR_TRANSLATION } from './locals/fr';\nimport { HI_TRANSLATION } from './locals/hi';\n\nconst resources = {\n  ar: { translation: AR_TRANSLATION },\n  en: { translation: EN_TRANSLATION },\n  es: { translation: ES_TRANSLATION },\n  fr: { translation: FR_TRANSLATION },\n  he: { translation: HE_TRANSLATION },\n  hi: { translation: HI_TRANSLATION },\n  ru: { translation: RU_TRANSLATION },\n  zh: { translation: ZH_TRANSLATION },\n};\n\ni18n.use(initReactI18next).init({\n  resources,\n  lng: 'en',\n  fallbackLng: ['en', 'he'],\n  interpolation: {\n    escapeValue: false,\n  },\n});\n\nexport default i18n;\n"
  },
  {
    "path": "src/common/keybindings.ts",
    "content": "import { Keybinding } from \"mathlive\"\n\nconst DEFAULT_KEYBINDINGS: Array<Keybinding> = [\n    { key: \"left\", command: \"moveToPreviousChar\" },\n    { key: \"right\", command: \"moveToNextChar\" },\n    { key: \"up\", command: \"moveUp\" },\n    { key: \"down\", command: \"moveDown\" },\n    { key: \"shift+[ArrowLeft]\", command: \"extendSelectionBackward\" },\n    { key: \"shift+[ArrowRight]\", command: \"extendSelectionForward\" },\n    { key: \"shift+[ArrowUp]\", command: \"extendSelectionUpward\" },\n    { key: \"shift+[ArrowDown]\", command: \"extendSelectionDownward\" },\n    { key: \"[Backspace]\", command: \"deleteBackward\" },\n    { key: \"alt+[Delete]\", command: \"deleteBackward\" },\n    { key: \"[Delete]\", command: \"deleteForward\" },\n    { key: \"alt+[Backspace]\", command: \"deleteForward\" },\n    { key: \"alt+[ArrowLeft]\", command: \"moveToPreviousWord\" },\n    { key: \"alt+[ArrowRight]\", command: \"moveToNextWord\" },\n    { key: \"shift+alt+[ArrowLeft]\", command: \"extendToPreviousWord\" },\n    { key: \"shift+alt+[ArrowRight]\", command: \"extendToNextWord\" },\n    { key: \"ctrl+[ArrowLeft]\", command: \"moveToGroupStart\" },\n    { key: \"ctrl+[ArrowRight]\", command: \"moveToGroupEnd\" },\n    { key: \"shift+ctrl+[ArrowLeft]\", command: \"extendToGroupStart\" },\n    { key: \"shift+ctrl+[ArrowRight]\", command: \"extendToGroupEnd\" },\n    { key: \"[Space]\", ifMode: \"math\", command: \"moveAfterParent\" },\n    { key: \"shift+[Space]\", ifMode: \"math\", command: \"moveBeforeParent\" },\n    { key: \"[Home]\", command: \"moveToMathfieldStart\" },\n    { key: \"cmd+[ArrowLeft]\", command: \"moveToMathfieldStart\" },\n    { key: \"shift+[Home]\", command: \"extendToMathFieldStart\" },\n    { key: \"shift+cmd+[ArrowLeft]\", command: \"extendToMathFieldStart\" },\n    { key: \"[End]\", command: \"moveToMathfieldEnd\" },\n    { key: \"cmd+[ArrowRight]\", command: \"moveToMathfieldEnd\" },\n    { key: \"shift+[End]\", command: \"extendToMathFieldEnd\" },\n    { key: \"shift+cmd+[ArrowRight]\", command: \"extendToMathFieldEnd\" },\n    { key: \"[Pageup]\", command: \"moveToGroupStart\" },\n    { key: \"[Pagedown]\", command: \"moveToGroupEnd\" },\n    { key: \"[Tab]\", ifMode: \"math\", command: \"moveToNextPlaceholder\" },\n    {\n      key: \"shift+[Tab]\",\n      ifMode: \"math\",\n      command: \"moveToPreviousPlaceholder\"\n    },\n    { key: \"[Tab]\", ifMode: \"text\", command: \"moveToNextPlaceholder\" },\n    {\n      key: \"shift+[Tab]\",\n      ifMode: \"text\",\n      command: \"moveToPreviousPlaceholder\"\n    },\n    { key: \"[Escape]\", ifMode: \"math\", command: [\"switchMode\", \"latex\"] },\n    { key: \"[Escape]\", ifMode: \"text\", command: [\"switchMode\", \"latex\"] },\n    {\n      key: \"[Escape]\",\n      ifMode: \"latex\",\n      command: [\"complete\", \"complete\", { selectItem: \"true\" }]\n    },\n    // Accept the entry (without the suggestion) and select\n    {\n      key: \"\\\\\",\n      ifMode: \"math\",\n      command: [\"switchMode\", \"latex\", \"\\\\\"]\n    },\n    // { key: '[Backslash]', ifMode: 'math', command: ['switchMode', 'latex'] },\n    {\n      key: \"[IntlBackslash]\",\n      ifMode: \"math\",\n      command: [\"switchMode\", \"latex\", \"\\\\\"]\n    },\n    // On UK QWERTY keyboards\n    {\n      key: \"[Tab]\",\n      ifMode: \"latex\",\n      command: [\"complete\", \"accept-suggestion\"]\n    },\n    // Complete the suggestion\n    { key: \"[Return]\", ifMode: \"latex\", command: \"complete\" },\n    { key: \"[Enter]\", ifMode: \"latex\", command: \"complete\" },\n    {\n      key: \"shift+[Escape]\",\n      ifMode: \"latex\",\n      command: [\"complete\", \"reject\"]\n    },\n    // Some keyboards can't generate\n    // this combination, for example in 60% keyboards it is mapped to ~\n    { key: \"[ArrowDown]\", ifMode: \"latex\", command: \"nextSuggestion\" },\n    // { key: 'ios:command:[Tab]', ifMode: 'latex',command: 'nextSuggestion' },\n    { key: \"[ArrowUp]\", ifMode: \"latex\", command: \"previousSuggestion\" },\n    { key: \"ctrl+a\", ifPlatform: \"!macos\", command: \"selectAll\" },\n    { key: \"cmd+a\", command: \"selectAll\" },\n    // Rare keys on some extended keyboards\n    { key: \"[Cut]\", command: \"cutToClipboard\" },\n    { key: \"[Copy]\", command: \"copyToClipboard\" },\n    { key: \"[Paste]\", command: \"pasteFromClipboard\" },\n    { key: \"[Clear]\", command: \"deleteBackward\" },\n    { key: \"ctrl+z\", ifPlatform: \"!macos\", command: \"undo\" },\n    { key: \"cmd+z\", command: \"undo\" },\n    { key: \"[Undo]\", command: \"undo\" },\n    { key: \"ctrl+y\", ifPlatform: \"!macos\", command: \"redo\" },\n    // ARIA recommendation\n    { key: \"shift+cmd+y\", command: \"redo\" },\n    { key: \"shift+ctrl+z\", ifPlatform: \"!macos\", command: \"redo\" },\n    { key: \"shift+cmd+z\", command: \"redo\" },\n    { key: \"[Redo]\", command: \"redo\" },\n    { key: \"[EraseEof]\", command: \"deleteToGroupEnd\" },\n    // EMACS/MACOS BINDINGS\n    { key: \"ctrl+b\", ifPlatform: \"macos\", command: \"moveToPreviousChar\" },\n    { key: \"ctrl+f\", ifPlatform: \"macos\", command: \"moveToNextChar\" },\n    { key: \"ctrl+p\", ifPlatform: \"macos\", command: \"moveUp\" },\n    { key: \"ctrl+n\", ifPlatform: \"macos\", command: \"moveDown\" },\n    { key: \"ctrl+a\", ifPlatform: \"macos\", command: \"moveToMathfieldStart\" },\n    { key: \"ctrl+e\", ifPlatform: \"macos\", command: \"moveToMathfieldEnd\" },\n    {\n      key: \"shift+ctrl+b\",\n      ifPlatform: \"macos\",\n      command: \"extendSelectionBackward\"\n    },\n    {\n      key: \"shift+ctrl+f\",\n      ifPlatform: \"macos\",\n      command: \"extendSelectionForward\"\n    },\n    {\n      key: \"shift+ctrl+p\",\n      ifPlatform: \"macos\",\n      command: \"extendSelectionUpward\"\n    },\n    {\n      key: \"shift+ctrl+n\",\n      ifPlatform: \"macos\",\n      command: \"extendSelectionDownward\"\n    },\n    {\n      key: \"shift+ctrl+a\",\n      ifPlatform: \"macos\",\n      command: \"extendToMathFieldStart\"\n    },\n    {\n      key: \"shift+ctrl+e\",\n      ifPlatform: \"macos\",\n      command: \"extendToMathFieldEnd\"\n    },\n    { key: \"alt+ctrl+b\", ifPlatform: \"macos\", command: \"moveToPreviousWord\" },\n    { key: \"alt+ctrl+f\", ifPlatform: \"macos\", command: \"moveToNextWord\" },\n    {\n      key: \"shift+alt+ctrl+b\",\n      ifPlatform: \"macos\",\n      command: \"extendToPreviousWord\"\n    },\n    {\n      key: \"shift+alt+ctrl+f\",\n      ifPlatform: \"macos\",\n      command: \"extendToNextWord\"\n    },\n    { key: \"ctrl+h\", ifPlatform: \"macos\", command: \"deleteBackward\" },\n    { key: \"ctrl+d\", ifPlatform: \"macos\", command: \"deleteForward\" },\n    { key: \"ctrl+l\", ifPlatform: \"macos\", command: \"scrollIntoView\" },\n    // { key: 'ctrl+t', ifPlatform: 'macos', command: 'transpose' },\n    // WOLFRAM MATHEMATICA BINDINGS\n    {\n      key: \"ctrl+[Digit2]\",\n      ifMode: \"math\",\n      command: [\"insert\", \"\\\\sqrt{#0}\"]\n    },\n    { key: \"ctrl+[Digit5]\", ifMode: \"math\", command: \"moveToOpposite\" },\n    { key: \"ctrl+[Digit6]\", ifMode: \"math\", command: \"moveToSuperscript\" },\n    { key: \"ctrl+[Return]\", ifMode: \"math\", command: \"addRowAfter\" },\n    { key: \"ctrl+[Enter]\", ifMode: \"math\", command: \"addRowAfter\" },\n    { key: \"cmd+[Return]\", ifMode: \"math\", command: \"addRowAfter\" },\n    { key: \"cmd+[Enter]\", ifMode: \"math\", command: \"addRowAfter\" },\n    // Excel keybindings:\n    // shift+space: select entire row, ctrl+space: select an entire column\n    // shift+ctrl++ or ctrl+numpad+\n    // ctrl+- to delete a row or columns\n    // MATHLIVE BINDINGS\n    // { key: 'alt+a', command: ['insert', '\\\\theta'] },\n    { key: \"alt+p\", ifMode: \"math\", command: [\"insert\", \"\\\\pi\"] },\n    { key: \"alt+v\", ifMode: \"math\", command: [\"insert\", \"\\\\sqrt{#0}\"] },\n    {\n      key: \"alt+w\",\n      ifMode: \"math\",\n      command: [\"insert\", \"\\\\sum_{i=#?}^{#?}\"]\n    },\n    { key: \"alt+b\", command: [\"insert\", \"\\\\int_{#?}^{#?}\"] },\n    { key: \"alt+u\", ifMode: \"math\", command: [\"insert\", \"\\\\cup\"] },\n    { key: \"alt+n\", ifMode: \"math\", command: [\"insert\", \"\\\\cap\"] },\n    { key: \"alt+o\", ifMode: \"math\", command: [\"insert\", \"\\\\emptyset\"] },\n    {\n      key: \"alt+d\",\n      ifMode: \"math\",\n      command: [\"insert\", \"\\\\differentialD\"]\n    },\n    {\n      key: \"shift+alt+o\",\n      ifMode: \"math\",\n      command: [\"insert\", \"\\\\varnothing\"]\n    },\n    {\n      key: \"shift+alt+d\",\n      ifMode: \"math\",\n      command: [\"insert\", \"\\\\partial\"]\n    },\n    {\n      key: \"shift+alt+p\",\n      ifMode: \"math\",\n      command: [\"insert\", \"\\\\prod_{i=#?}^{#?}\"]\n    },\n    { key: \"shift+alt+u\", ifMode: \"math\", command: [\"insert\", \"\\\\bigcup\"] },\n    { key: \"shift+alt+n\", ifMode: \"math\", command: [\"insert\", \"\\\\bigcap\"] },\n    { key: \"shift+alt+a\", ifMode: \"math\", command: [\"insert\", \"\\\\forall\"] },\n    { key: \"shift+alt+e\", ifMode: \"math\", command: [\"insert\", \"\\\\exists\"] },\n    {\n      key: \"alt+[Backslash]\",\n      ifMode: \"math\",\n      command: [\"insert\", \"\\\\backslash\"]\n    },\n    // \"|\" key} override command mode\n    {\n      key: \"[NumpadDivide]\",\n      ifMode: \"math\",\n      command: [\"insert\", \"\\\\frac{#@}{#?}\"]\n    },\n    // ??\n    {\n      key: \"alt+[NumpadDivide]\",\n      ifMode: \"math\",\n      command: [\"insert\", \"\\\\frac{#?}{#@}\"]\n    },\n    // ??\n    // Accessibility\n    { key: \"alt+k\", command: \"toggleVirtualKeyboard\" },\n    // Note: On Mac OS (as of 10.12), there is a bug/behavior that causes\n    // a beep to be generated with certain command+control key combinations.\n    // The workaround is to create a default binding file to silence them.\n    // In ~/Library/KeyBindings/DefaultKeyBinding.dict add these entries:\n    //\n    //   {\n    //      \"^@\\UF701\" = \"noop:\";\n    //    \"^@\\UF702\" = \"noop:\";\n    //      \"^@\\UF703\" = \"noop:\";\n    //  }\n    // {\n    //   key: \"alt+ctrl+[ArrowUp]\",\n    //   command: [\"speak\", \"all\", { withHighlighting: false }]\n    // },\n    // {\n    //   key: \"alt+ctrl+[ArrowDown]\",\n    //   command: [\"speak\", \"selection\", { withHighlighting: false }]\n    // },\n    //\n    // Punctuations and some non-alpha key combinations\n    // only work with specific keyboard layouts\n    //\n    {\n      key: \"alt+[Equal]\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: [\"applyStyle\", { mode: \"text\" }]\n    },\n    {\n      key: \"alt+[Equal]\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"text\",\n      command: [\"applyStyle\", { mode: \"math\" }]\n    },\n    {\n      key: \"shift+[Quote]\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: [\"switchMode\", \"text\", \"\", \"\"]\n    },\n    {\n      key: \"shift+[Quote]\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"text\",\n      command: [\"switchMode\", \"math\", \"\", \"\"]\n    },\n    {\n      key: \"/\",\n      ifMode: \"math\",\n      command: [\"insert\", \"\\\\frac{#@}{#?}\"]\n    },\n    {\n      key: \"alt+/\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: [\"insert\", \"\\\\/\"]\n    },\n    {\n      key: \"alt+[BracketLeft]\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: [\"insert\", \"\\\\left\\\\lbrack #0 \\\\right\\\\rbrack\"]\n    },\n    // ??\n    // {\n    //   key: \"ctrl+[Minus]\",\n    //   ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n    //   ifMode: \"math\",\n    //   command: \"moveToSubscript\"\n    // },\n    // ??\n    {\n      key: \"shift+alt+[BracketLeft]\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: [\"insert\", \"\\\\left\\\\lbrace #0 \\\\right\\\\rbrace\"]\n    },\n    // ??\n    {\n      key: \"ctrl+;\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: \"addRowAfter\"\n    },\n    {\n      key: \"cmd+;\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: \"addRowAfter\"\n    },\n    {\n      key: \"shift+ctrl+;\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: \"addRowBefore\"\n    },\n    {\n      key: \"shift+cmd+;\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: \"addRowBefore\"\n    },\n    {\n      key: \"ctrl+[Backspace]\",\n      ifMode: \"math\",\n      command: \"removeRow\"\n    },\n    {\n      key: \"cmd+[Backspace]\",\n      ifMode: \"math\",\n      command: \"removeRow\"\n    },\n    {\n      key: \"ctrl+[Comma]\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: \"addColumnAfter\"\n    },\n    {\n      key: \"cmd+[Comma]\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: \"addColumnAfter\"\n    },\n    {\n      key: \"shift+ctrl+[Comma]\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: \"addColumnBefore\"\n    },\n    {\n      key: \"shift+cmd+[Comma]\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: \"addColumnBefore\"\n    },\n    {\n      key: \"shift+[Backspace]\",\n      ifMode: \"math\",\n      command: \"removeColumn\"\n    },\n    {\n      key: \"alt+[Digit5]\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: [\"insert\", \"$\\\\infty\"]\n    },\n    // \"%\" key\n    {\n      key: \"alt+[Digit6]\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: [\"insert\", \"\\\\wedge\"]\n    },\n    // \"^\" key\n    {\n      key: \"shift+alt+[Digit6]\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: [\"insert\", \"\\\\vee\"]\n    },\n    // \"^\" key\n    {\n      key: \"alt+[Digit9]\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: [\"insert\", \"(\"]\n    },\n    // \"(\" key} override smartFence\n    {\n      key: \"alt+[Digit0]\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: [\"insert\", \")\"]\n    },\n    // \")\" key} override smartFence\n    {\n      key: \"alt+|\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: [\"insert\", \"|\"]\n    },\n    // \"|\" key} override smartFence\n    {\n      key: \"shift+[Backquote]\",\n      ifLayout: [\"apple.en-intl\", \"windows.en-intl\", \"linux.en\"],\n      ifMode: \"math\",\n      command: [\"insert\", \"\\\\~\"]\n    },\n    // ??\n    {\n      key: \"[Backquote]\",\n      ifLayout: [\"windows.french\", \"linux.french\"],\n      ifMode: \"math\",\n      command: [\"insert\", \"^2\"]\n    }\n]\n\nconst CUSTOM_KEYBINDINGS: Array<Keybinding> = [\n    {\n        key: 'alt+[Equal]',\n        ifMode: 'math',\n        command: ['insert', '\\\\approx']\n    },\n    {\n        key: 'alt+[Comma]',\n        ifMode: 'math',\n        command: ['insert', '\\\\measuredangle']\n    },\n    {\n        key: 'alt+[Digit0]',\n        ifMode: 'math',\n        command: ['insert', '\\\\emptyset']\n    },\n    {\n        key: 'alt+[Enter]',\n        ifMode: 'math',\n        command: ['insert', '\\\\begin{gathered} {#?} \\\\end{gathered}']\n    },\n    {\n        key: 'alt+shift+c',\n        ifMode: 'math',\n        command: ['insert', '\\\\complement']\n    },\n    {\n        key: 'alt+shift+t',\n        ifMode: 'math',\n        command: ['insert', '\\\\triangle']\n    },\n    {\n        key: 'shift+[Enter]',\n        ifMode: 'math',\n        command: 'addRowAfter'\n    },\n    {\n        key: 'ctrl+[Equal]',\n        ifMode: 'math',\n        command: 'addColumnAfter'\n    },\n    {\n        key: 'ctrl+[Minus]',\n        ifMode: 'math',\n        command: 'removeColumn'\n    },\n]\n\nconst ML_KEYBINDINGS = [DEFAULT_KEYBINDINGS, CUSTOM_KEYBINDINGS].flat()\n\nexport default ML_KEYBINDINGS"
  },
  {
    "path": "src/common/locals/ar.ts",
    "content": "export const AR_TRANSLATION = {\n  'My Notebooks': 'دفاتري',\n  'Command Bar': 'شريط الأوامر',\n  'Math Panel': 'لوحة الرياضيات',\n  Archive: 'الأرشيف',\n  'New Folder': 'مجلد جديد',\n  'New File': 'ملف جديد',\n  'Notebooks Tooltip': 'انقر مرتين لفتح الموقع',\n  Variables: 'متغيرات',\n  Functions: 'وظائف',\n  Prompt: 'اكتب أمرًا أو ابحث...',\n  Preferences: 'تفضيلات',\n  Theme: 'الوضع',\n  Color: 'لون التمييز',\n  Dark: 'مظلم',\n  Light: 'فاتح',\n  Language: 'اللغة 🌍',\n  Hebrew: 'العبرية - עברית',\n  Russian: 'الروسية - Русский',\n  'Mandarin Chinese': 'الصينية الماندرين - 中文普通话',\n  Hindi: 'هندي - हिंदी',\n  French: 'فرنسي - Française',\n  English: 'الإنجليزية - English',\n  Arabic: 'العربية',\n  Spanish: 'الأسبانية - Español',\n  Red: 'أحمر',\n  Blue: 'أزرق',\n  Green: 'أخضر',\n  Yellow: 'أصفر',\n  Purple: 'أرجواني',\n  Pink: 'وردي',\n  'Text Block': 'إضافة كتلة نصية',\n  'Math Block': 'إضافة كتلة رياضية',\n  'Graph Block': 'إضافة كتلة رسم بياني',\n  'Draw Block': 'إضافة كتلة رسم',\n  Divider: 'إضافة فاصل',\n  Clear: 'مسح الصفحة',\n  Save: 'حفظ',\n  'Add Tag': 'إضافة وسم',\n  'Placeholder 1': 'للبدء',\n  'Placeholder 2': 'انقر على رمز الدفتر على اليمين',\n  'Placeholder 3': 'وافتح / أنشئ ملفًا',\n  'Placeholder Or': 'أو',\n  'Modal 1': 'محو محتوى الصفحة؟',\n  'Modal 2': 'يوجد ملف جديد بالفعل',\n  'Modal 3': 'يوجد مجلد جديد بالفعل',\n  'Modal 4': 'هذا الاسم موجود بالفعل',\n  'Modal 5': 'لا يمكنك نقل هذا الملف هنا!',\n  Cancel: 'إلغاء',\n  OK: 'موافق',\n  Saved: 'تم حفظ الملف!',\n  'Save Error': 'خطأ أثناء حفظ الملف',\n  'Text Placeholder': 'إدراج نص...',\n  Press: 'اضغط على',\n  'Delete Item': 'على العنصر لحذفه',\n  'Rename Item': 'على العنصر لإعادة تسميته',\n};\n"
  },
  {
    "path": "src/common/locals/en.ts",
    "content": "export const EN_TRANSLATION = {\n  'My Notebooks': 'Notebooks',\n  'Command Bar': 'Command Bar',\n  'Math Panel': 'Math Panel',\n  Archive: 'Archive',\n  'New Folder': 'New Folder',\n  'New File': 'New File',\n  'Notebooks Tooltip': 'Double click to open location',\n  Variables: 'Variables',\n  Functions: 'Functions',\n  Prompt: 'Type a command or search...',\n  Preferences: 'Preferences',\n  Theme: 'Theme',\n  Color: 'Accent Color',\n  Dark: 'Dark Theme',\n  Light: 'Light Theme',\n  Language: 'Language 🌍',\n  Hebrew: 'Hebrew - עברית',\n  Russian: 'Russian - Русский',\n  English: 'English',\n  Arabic: 'Arabic - العربية',\n  Spanish: 'Spanish - Español',\n  Hindi: 'Hindi - हिंदी',\n  'Mandarin Chinese': 'Mandarin Chinese - 中文普通话',\n  French: 'French - Française',\n  Red: 'Red',\n  Blue: 'Blue',\n  Green: 'Green',\n  Yellow: 'Yellow',\n  Purple: 'Purple',\n  Pink: 'Pink',\n  'Text Block': 'Add Text Block',\n  'Math Block': 'Add Math Block',\n  'Graph Block': 'Add Graph Block',\n  'Draw Block': 'Add Draw Block',\n  Divider: 'Add Divider',\n  Clear: 'Clear Page',\n  Save: 'Save',\n  'Add Tag': 'Add Tag',\n  'Placeholder 1': 'To begin',\n  'Placeholder 2': 'Click on the notebook icon on your left',\n  'Placeholder 3': 'and open/create a file',\n  'Placeholder Or': 'or',\n  'Modal 1': 'Clear page content?',\n  'Modal 2': 'A new file already exists',\n  'Modal 3': 'A new folder already exists',\n  'Modal 4': 'This name already exists',\n  'Modal 5': 'You cannot move this file here!',\n  Cancel: 'Cancel',\n  OK: 'OK',\n  Saved: 'File saved!',\n  'Save Error': 'Error while saving file',\n  'Text Placeholder': 'Insert text...',\n  Press: 'Press',\n  'Delete Item': 'on item to delete it',\n  'Rename Item': 'on item to rename it',\n};\n"
  },
  {
    "path": "src/common/locals/es.ts",
    "content": "export const ES_TRANSLATION = {\n  'My Notebooks': 'Mis Cuadernos',\n  'Command Bar': 'Barra de Comandos',\n  'Math Panel': 'Panel de Matemáticas',\n  Archive: 'Archivo',\n  'New Folder': 'Nueva Carpeta',\n  'New File': 'Nuevo Archivo',\n  'Notebooks Tooltip': 'Haz doble clic para abrir la ubicación',\n  Variables: 'Variables',\n  Functions: 'Funciones',\n  Prompt: 'Escriba un comando o busque...',\n  Preferences: 'Preferencias',\n  Theme: 'Tema',\n  Color: 'Color de Acento',\n  Dark: 'Tema Oscuro',\n  Light: 'Tema Claro',\n  Language: 'Idioma 🌍',\n  Hebrew: 'Hebreo - עברית',\n  Russian: 'Ruso - Русский',\n  English: 'Inglés - English',\n  Arabic: 'Árabe - العربية',\n  Spanish: 'Español',\n  French: 'Francés - Française',\n  Hindi: 'hindi - हिंदी',\n  'Mandarin Chinese': 'Chino mandarín - 中文普通话',\n  Red: 'Rojo',\n  Blue: 'Azul',\n  Green: 'Verde',\n  Yellow: 'Amarillo',\n  Purple: 'Morado',\n  Pink: 'Rosado',\n  'Text Block': 'Agregar Bloque de Texto',\n  'Math Block': 'Agregar Bloque de Matemáticas',\n  'Graph Block': 'Agregar Bloque de Gráfico',\n  'Draw Block': 'Agregar Bloque de Dibujo',\n  Divider: 'Agregar Divisor',\n  Clear: 'Limpiar Página',\n  Save: 'Guardar',\n  'Add Tag': 'Agregar Etiqueta',\n  'Placeholder 1': 'Para comenzar',\n  'Placeholder 2': 'Haz clic en el icono del cuaderno a tu izquierda',\n  'Placeholder 3': 'y abre/crea un archivo',\n  'Placeholder Or': 'o',\n  'Modal 1': '¿Borrar contenido de la página?',\n  'Modal 2': 'Ya existe un nuevo archivo',\n  'Modal 3': 'Ya existe una nueva carpeta',\n  'Modal 4': 'Este nombre ya existe',\n  'Modal 5': '¡No puede mover este archivo aquí!',\n  Cancel: 'Cancelar',\n  OK: 'OK',\n  Saved: '¡Archivo guardado!',\n  'Save Error': 'Error al guardar archivo',\n  'Text Placeholder': 'Inserte texto...',\n  Press: 'Prensa',\n  'Delete Item': 'en el elemento para eliminarlo',\n  'Rename Item': 'en el elemento para cambiarle el nombre',\n};\n"
  },
  {
    "path": "src/common/locals/fr.ts",
    "content": "export const FR_TRANSLATION = {\n    'My Notebooks': 'Mes carnets',\n    'Command Bar': 'Barre de commande',\n    'Math Panel': 'Panneau mathématique',\n    Archive: 'Archivo',\n    'New Folder': 'Nouveau dossier',\n    'New File': 'Nouveau fichier',\n    'Notebooks Tooltip': `Double-cliquez pour ouvrir l'emplacement`,\n    Variables: 'Variables',\n    Functions: 'Les fonctions',\n    Prompt: 'Tapez une commande ou recherchez...',\n    Preferences: 'Préférences',\n    Theme: 'Thème',\n    Color: `Couleur d'accentuation`,\n    Dark: 'Mode sombre',\n    Light: 'Mode lumière',\n    Language: 'Langue 🌍',\n    Hebrew: 'Hébreu - עברית',\n    Russian: 'Russe - Русский',\n    English: 'Anglaise - English',\n    Arabic: 'Arabe - العربية',\n    Hindi: 'hindi - हिंदी',\n    'Mandarin Chinese': 'Chinois Mandarin - 中文普通话',\n    French: 'Française',\n    Red: 'Rouge',\n    Blue: 'Bleu',\n    Green: 'Vert',\n    Yellow: 'Jaune',\n    Purple: 'Violet',\n    Pink: 'Rose',\n    'Text Block': 'Ajouter un bloc de texte',\n    'Math Block': 'Ajouter un bloc mathématique',\n    'Graph Block': 'Ajouter un bloc graphique',\n    'Draw Block': 'Ajouter un bloc de dessin',\n    Divider: 'Ajouter un diviseur',\n    Clear: 'Effacer la page',\n    Save: 'Enregistrer le fichier',\n    'Add Tag': 'Ajouter une étiquette',\n    'Placeholder 1': 'Pour commencer',\n    'Placeholder 2': `Cliquez sur l'icône du bloc-notes à votre gauche`,\n    'Placeholder 3': 'et ouvrir/créer un fichier',\n    'Placeholder Or': 'ou',\n    'Modal 1': 'Effacer le contenu de la page ?',\n    'Modal 2': 'Un nouveau fichier existe déjà',\n    'Modal 3': 'Un nouveau dossier existe déjà',\n    'Modal 4': 'Ce nom existe déjà',\n    'Modal 5': 'Vous ne pouvez pas déplacer ce fichier ici !',\n    Cancel: 'Annuler',\n    OK: 'OK',\n    Saved: 'Fichier enregistré !',\n    'Save Error': `Erreur lors de l'enregistrement du fichier`,\n    'Text Placeholder': 'Insérer du texte...',\n    Press: 'Appuyez',\n    'Delete Item': \"sur l'élément pour le supprimer\",\n    'Rename Item': \"sur l'élément pour le renommer\",\n  };\n  "
  },
  {
    "path": "src/common/locals/he.ts",
    "content": "export const HE_TRANSLATION = {\n  'My Notebooks': 'המחברות שלי',\n  'Command Bar': 'חיפוש ופקודות',\n  'Math Panel': 'זיכרון מתמטי',\n  Archive: 'הארכיון שלי',\n  'New Folder': 'תיקייה חדשה',\n  'New File': 'קובץ חדש',\n  'Notebooks Tooltip': 'לחצו פעמיים כדי לפתוח את התיקייה',\n  Variables: 'משתנים',\n  Functions: 'פונקציות',\n  Prompt: 'הקלידו פקודה או חפשו...',\n  Preferences: 'העדפות משתמש',\n  Theme: 'ערכת נושא',\n  Color: 'צבע נושא',\n  Dark: 'מצב חושך',\n  Light: 'מצב אור',\n  Language: 'שפה 🌍',\n  Hebrew: 'עברית',\n  Russian: 'רוסית - Русский',\n  English: 'אנגלית - English',\n  Spanish: 'ספרדית - Español',\n  Arabic: 'ערבית - العربية',\n  Hindi: 'הינדי - हिंदी',\n  'Mandarin Chinese': 'סינית מנדרינית - 中文普通话',\n  French: 'צרפתית - Française',\n  Red: 'אדום',\n  Blue: 'כחול',\n  Green: 'ירוק',\n  Yellow: 'צהוב',\n  Purple: 'סגול',\n  Pink: 'ורוד',\n  'Text Block': 'הוספת בלוק טקסט',\n  'Math Block': 'הוספת בלוק מתמטי',\n  'Graph Block': 'הוספת בלוק גרפי',\n  'Draw Block': 'הוספת בלוק ציור',\n  Divider: 'הוספת קו מפריד',\n  Clear: 'ניקוי הדף',\n  Save: 'שמירה',\n  'Add Tag': 'הוספת תגית',\n  'Placeholder 1': 'כדי להתחיל',\n  'Placeholder 2': 'לחצו על כפתור המחברות בצד ימין',\n  'Placeholder 3': 'ובחרו/צרו קובץ',\n  'Placeholder Or': 'או',\n  'Modal 1': 'לנקות את כל תוכן הדף?',\n  'Modal 2': 'קובץ חדש כבר קיים',\n  'Modal 3': 'תיקייה חדשה כבר קיימת',\n  'Modal 4': 'השם הזה כבר קיים',\n  'Modal 5': 'לא ניתן לגרור קובץ זה לכאן!',\n  Cancel: 'ביטול',\n  OK: 'אישור',\n  Saved: 'הקובץ נשמר!',\n  'Save Error': 'התרחשה שגיאה בשמירת הקובץ',\n  'Text Placeholder': 'כתבו טקסט כאן...',\n  Press: 'לחצו',\n  'Delete Item': 'על פריט כדי למחוק אותו',\n  'Rename Item': 'על פריט כדי לשנות את שמו',\n};\n"
  },
  {
    "path": "src/common/locals/hi.ts",
    "content": "export const HI_TRANSLATION = {\n  'My Notebooks': 'नोटबुक',\n  'Command Bar': 'कमांड बार',\n  'Math Panel': 'गणित पैनल',\n  Archive: 'आर्काइव',\n  'New Folder': 'नया फ़ोल्डर',\n  'New File': 'नया फ़ाइल',\n  'Notebooks Tooltip': 'जगह खोलने के लिए दोहराएँ क्लिक करें',\n  Variables: 'वेरिएबल्स',\n  Functions: 'फंक्शन्स',\n  Prompt: 'कमांड टाइप करें या खोजें...',\n  Preferences: 'प्राथमिकताएं',\n  Theme: 'थीम',\n  Color: 'एक्सेंट रंग',\n  Dark: 'डार्क थीम',\n  Light: 'लाइट थीम',\n  Language: 'भाषा 🌍',\n  Hebrew: 'हिब्रू - עברית',\n  Russian: 'रूसी - Русский',\n  English: 'अंग्रेज़ी - English',\n  Arabic: 'अरबी - العربية',\n  Spanish: 'स्पेनिश - Español',\n  Hindi: 'हिंदी',\n  'Mandarin Chinese': 'मंडारिन चाइनीज़ - 中文普通话',\n  French: 'फ़्रेंच - Française',\n  Red: 'लाल',\n  Blue: 'नीला',\n  Green: 'हरा',\n  Yellow: 'पीला',\n  Purple: 'बैंगनी',\n  Pink: 'गुलाबी',\n  'Text Block': 'टेक्स्ट ब्लॉक जोड़ें',\n  'Math Block': 'गणित ब्लॉक जोड़ें',\n  'Graph Block': 'ग्राफ़ ब्लॉक जोड़ें',\n  'Draw Block': 'ड्रॉ ब्लॉक जोड़ें',\n  Divider: 'डिवाइडर जोड़ें',\n  Clear: 'पृष्ठ साफ करें',\n  Save: 'सहेजें',\n  'Add Tag': 'टैग जोड़ें',\n  'Placeholder 1': 'शुरू करने के लिए',\n  'Placeholder 2': 'अपने बाएँ नोटबुक',\n  'Placeholder 3': 'और फ़ाइल खोलें/बनाएं',\n  'Placeholder Or': 'या',\n  'Modal 1': 'पृष्ठ साफ़ करें?',\n  'Modal 2': 'एक नया फ़ाइल पहले से ही मौजूद है',\n  'Modal 3': 'एक नया फ़ोल्डर पहले से ही मौजूद है',\n  'Modal 4': 'यह नाम पहले से ही मौजूद है',\n  'Modal 5': 'आप इस फाइल को यहां नहीं ले जा सकते!',\n  Cancel: 'रद्द करें',\n  OK: 'ठीक है',\n  Saved: 'फ़ाइल सहेजी गई!',\n  'Save Error': 'फ़ाइल सहेजते समय त्रुटि',\n  'Text Placeholder': 'टेक्स्ट डालें...',\n  Press: 'प्रेस',\n  'Delete Item': 'इसे हटाने के लिए आइटम पर',\n  'Rename Item': 'इसका नाम बदलने के लिए आइटम पर',\n};\n"
  },
  {
    "path": "src/common/locals/ru.ts",
    "content": "export const RU_TRANSLATION = {\n  'My Notebooks': 'Мои блокноты',\n  'Command Bar': 'Поиск и команды',\n  'Math Panel': 'Математическая панель',\n  Archive: 'Архив',\n  'New Folder': 'Новая папка',\n  'New File': 'Новый файл',\n  'Notebooks Tooltip': 'Дважды щелкните, чтобы открыть папку',\n  Variables: 'Переменные',\n  Functions: 'Функции',\n  Prompt: 'Введите команду или искать...',\n  Preferences: 'Настройки пользователя',\n  Theme: 'Тема',\n  Color: 'Цвет темы',\n  Dark: 'Темный режим',\n  Light: 'Светлый режим',\n  Language: 'Язык 🌍',\n  Hebrew: 'Иврит - עברית',\n  English: 'Английский - English',\n  Russian: 'Русский',\n  Arabic: 'арабский - العربية',\n  Spanish: 'испанский - Español',\n  Hindi: 'хинди - हिंदी',\n  'Mandarin Chinese': 'Мандариновый китайский - 中文普通话',\n  French: 'Французский - Française',\n  Red: 'Красный',\n  Blue: 'Синий',\n  Green: 'Зеленый',\n  Yellow: 'Желтый',\n  Purple: 'Фиолетовый',\n  Pink: 'Розовый',\n  'Text Block': 'Добавить блок текста',\n  'Math Block': 'Добавить математический блок',\n  'Graph Block': 'Добавить блок графика',\n  'Draw Block': 'Добавить блок рисунка',\n  Divider: 'Добавить разделитель',\n  Clear: 'Очистить страницу',\n  Save: 'Сохранить',\n  'Add Tag': 'Добавить тег',\n  'Placeholder 1': 'Чтобы начать',\n  'Placeholder 2': 'Нажмите на кнопку блокнотов в правой панели',\n  'Placeholder 3': 'Выберите/создайте файл',\n  'Placeholder Or': 'или',\n  'Modal 1': 'Очистить всё содержимое страницы?',\n  'Modal 2': 'Такой файл уже существует',\n  'Modal 3': 'Такая папка уже существует',\n  'Modal 4': 'Это имя уже используется',\n  'Modal 5': 'Вы не можете переместить этот файл сюда!',\n  Cancel: 'Отмена',\n  OK: 'ОК',\n  Saved: 'Файл сохранен!',\n  'Save Error': 'Произошла ошибка при сохранении файла',\n  'Text Placeholder': 'Введите текст здесь...',\n  Press: 'Нажмите',\n  'Delete Item': 'на элементе, чтобы удалить его',\n  'Rename Item': 'на элементе, чтобы переименовать его',\n};\n"
  },
  {
    "path": "src/common/locals/zh.ts",
    "content": "//Mandarin Chinese\nexport const ZH_TRANSLATION = {\n  'My Notebooks': '笔记本',\n  'Command Bar': '命令栏',\n  'Math Panel': '数学面板',\n  Archive: '存档',\n  'New Folder': '新建文件夹',\n  'New File': '新建文件',\n  'Notebooks Tooltip': '双击打开位置',\n  Variables: '变量',\n  Functions: '函数',\n  Prompt: '输入命令或搜索...',\n  Preferences: '首选项',\n  Theme: '主题',\n  Color: '强调颜色',\n  Dark: '暗色主题',\n  Light: '亮色主题',\n  Language: '语言 🌍',\n  Hebrew: '希伯来语 - עברית',\n  Russian: '俄语 - Русский',\n  English: '英语 - English',\n  Arabic: '阿拉伯语 - العربية',\n  Spanish: '西班牙语 - Español',\n  French: '法语 - Française',\n  'Mandarin Chinese': '中文普通话',\n  Hindi: '印地语 - हिंदी',\n  Red: '红色',\n  Blue: '蓝色',\n  Green: '绿色',\n  Yellow: '黄色',\n  Purple: '紫色',\n  Pink: '粉红色',\n  'Text Block': '添加文本块',\n  'Math Block': '添加数学块',\n  'Graph Block': '添加图表块',\n  'Draw Block': '添加绘图块',\n  Divider: '添加分隔线',\n  Clear: '清空页面',\n  Save: '保存',\n  'Add Tag': '添加标签',\n  'Placeholder 1': '开始',\n  'Placeholder 2': '单击左侧的笔记本图标',\n  'Placeholder 3': '并打开/创建文件',\n  'Placeholder Or': '或',\n  'Modal 1': '清空页面内容？',\n  'Modal 2': '一个新文件已经存在',\n  'Modal 3': '一个新文件夹已经存在',\n  'Modal 4': '此名称已经存在',\n  'Modal 5': '您不能在此处移动此文件',\n  Cancel: '取消',\n  OK: '确定',\n  Saved: '文件已保存！',\n  'Save Error': '保存文件时出错',\n  'Text Placeholder': '插入文本...',\n  Press: '按',\n  'Delete Item': '在项目上删除它',\n  'Rename Item': '在项目上重命名它',\n};\n"
  },
  {
    "path": "src/common/shortcuts.ts",
    "content": "import { InlineShortcutDefinition } from \"mathlive\";\n\nconst ML_SHORTCUTS: Record<string, InlineShortcutDefinition> = {\n    'sr': {after: 'letter+digit', value: '^2'},\n    'cu': {after: 'letter+digit', value: '^3'},\n    '&': '\\\\&',\n    '%': '\\\\%',\n    '@': '\\\\degree',\n    'nCk': '\\\\binom',\n    'vec': '\\\\vec{#?}',\n    'gg': '\\\\hat{#?}',\n    '^^': '\\\\land', \n    'tbl': '\\\\begin{array}{|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|} {#?} & {#?} \\\\\\\\ {#?} & {#?} \\\\end{array}',\n    'mx': '\\\\begin{matrix} {#?} & {#?} \\\\\\\\ {#?} & {#?} \\\\end{matrix}',\n    'mx22': '\\\\begin{matrix} {#?} & {#?} \\\\\\\\ {#?} & {#?} \\\\end{matrix}',\n    'mx32': '\\\\begin{matrix} {#?} & {#?} \\\\\\\\ {#?} & {#?} \\\\\\\\ {#?} & {#?} \\\\end{matrix}',\n    'mx42': '\\\\begin{matrix} {#?} & {#?} \\\\\\\\ {#?} & {#?} \\\\\\\\ {#?} & {#?} \\\\\\\\ {#?} & {#?} \\\\end{matrix}',\n    'mx23': '\\\\begin{matrix} {#?} & {#?} & {#?} \\\\\\\\ {#?} & {#?} & {#?} \\\\end{matrix}',\n    'mx33': '\\\\begin{matrix} {#?} & {#?} & {#?} \\\\\\\\ {#?} & {#?} & {#?} \\\\\\\\ {#?} & {#?} & {#?} \\\\end{matrix}',\n    'mx43': '\\\\begin{matrix} {#?} & {#?} & {#?} \\\\\\\\ {#?} & {#?} & {#?} \\\\\\\\ {#?} & {#?} & {#?} \\\\\\\\ {#?} & {#?} & {#?} \\\\end{matrix}',\n    'mx24': '\\\\begin{matrix} {#?} & {#?} & {#?} & {#?} \\\\\\\\ {#?} & {#?} & {#?} & {#?} \\\\end{matrix}',\n    'mx34': '\\\\begin{matrix} {#?} & {#?} & {#?} & {#?} \\\\\\\\ {#?} & {#?} & {#?} & {#?} \\\\\\\\ {#?} & {#?} & {#?} & {#?} \\\\end{matrix}',\n    'mx44': '\\\\begin{matrix} {#?} & {#?} & {#?} & {#?} \\\\\\\\ {#?} & {#?} & {#?} & {#?} \\\\\\\\ {#?} & {#?} & {#?} & {#?} \\\\\\\\ {#?} & {#?} & {#?} & {#?} \\\\end{matrix}',\n    'cas': '\\\\begin{cases} {#?} & {#?} \\\\\\\\ {#?} & {#?} \\\\end{cases}',\n    'mul': '\\\\begin{gather} {#?} \\\\end{gather}',\n    \n    // Primes\n    \"''\": '^{\\\\doubleprime}',\n  \n    '&a': '\\\\alpha',\n    '&b': '\\\\beta',\n    '&g': '\\\\gamma',\n    '&d': '\\\\delta',\n    '&e': '\\\\varepsilon',\n    '&z': '\\\\zeta',\n    '&et': '\\\\eta',\n    '&t': '\\\\theta',\n    '&i': '\\\\iota',\n    '&k': '\\\\kappa',\n    '&l': '\\\\lambda',\n    '&m': '\\\\mu',\n    '&n': '\\\\nu',\n    '&x': '\\\\xi',\n    '&o': '\\\\omicron',\n    '&p': '\\\\pi',\n    '&r': '\\\\rho',\n    '&s': '\\\\sigma',\n    '&ta': '\\\\tau',\n    '&u': '\\\\upsilon',\n    '&ph': '\\\\phi',\n    '&c': '\\\\chi',\n    '&ps': '\\\\psi',\n    '&om': '\\\\omega',\n\n    '&A': '\\\\Alpha',\n    '&B': '\\\\Beta',\n    '&G': '\\\\Gamma',\n    '&D': '\\\\Delta',\n    '&E': '\\\\Epsilon',\n    '&Z': '\\\\Zeta',\n    '&Et': '\\\\Eta',\n    '&T': '\\\\Theta',\n    '&I': '\\\\Iota',\n    '&K': '\\\\Kappa',\n    '&L': '\\\\Lambda',\n    '&M': '\\\\Mu',\n    '&N': '\\\\Nu',\n    '&X': '\\\\Xi',\n    '&O': '\\\\Omicron',\n    '&P': '\\\\Pi',\n    '&R': '\\\\Rho',\n    '&S': '\\\\Sigma',\n    '&Ta': '\\\\Tau',\n    '&U': '\\\\Upsilon',\n    '&Ph': '\\\\Phi',\n    '&C': '\\\\Chi',\n    '&Ps': '\\\\Psi',\n    '&Om': '\\\\Omega',\n\n    // Greek letters\n    'alpha': '\\\\alpha',\n    'delta': '\\\\delta',\n    'Delta': '\\\\Delta',\n    'pi': '\\\\pi',\n    'Pi': '\\\\Pi',\n    'theta': '\\\\theta',\n    'Theta': '\\\\Theta',\n  \n    '0': {after: 'letter', value: '_0'},\n    '1': {after: 'letter', value: '_1'},\n    '2': {after: 'letter', value: '_2'},\n    '3': {after: 'letter', value: '_3'},\n    '4': {after: 'letter', value: '_4'},\n    '5': {after: 'letter', value: '_5'},\n    '6': {after: 'letter', value: '_6'},\n    '7': {after: 'letter', value: '_7'},\n    '8': {after: 'letter', value: '_8'},\n    '9': {after: 'letter', value: '_9'},\n    'x': {after: 'function', value: '(x)'},\n    'an': 'a_n',\n    'ann': '\\\\{ a_n \\\\} _{n=1}^{\\\\infty}',\n\n    // Letter-like\n    'ii': {\n      after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',\n      value: '\\\\imaginaryI',\n    },\n    'jj': {\n      after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',\n      value: '\\\\imaginaryJ',\n    },\n    'ee': {\n      after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',\n      value: '\\\\exponentialE',\n    },\n  \n    'nabla': '\\\\nabla',\n    'grad': '\\\\nabla',\n    'del': '\\\\partial',\n    'deg': {\n      after: 'digit+space',\n      value: '\\\\degree'\n    },\n  \n    'infty': '\\\\infty',\n  \n    '\\u221E': '\\\\infty', // @TODO: doesn't work\n    // '&infin;': '\\\\infty',\n    // '&#8734;': '\\\\infty',\n    'oo': {\n      after: 'nothing+digit+frac+surd+binop+relop+punct+array+openfence+closefence+space',\n      value: '\\\\infty',\n    },\n  \n    // Big operators\n    '∑': '\\\\sum',\n    'abs': '||{#?}||',\n    'sum': '\\\\sum_{#?}^{#?}',\n    'intt': '\\\\int',\n    'int': '\\\\int_{#?}^{#?}',\n    'intfx': '\\\\int_{#?}^{#?} f(x) \\\\differentialD x =',\n    'intgx': '\\\\int_{#?}^{#?} g(x) \\\\differentialD x =',\n    'inthx': '\\\\int_{#?}^{#?} h(x) \\\\differentialD x =',\n    'prod': '\\\\prod_{#?}^{#?}',\n    'nv': '\\\\sqrt[#?]{#?}',\n    // '∫':                    '\\\\int',             // There's a alt-B command for this\n    '∆': '\\\\differentialD', // @TODO: is \\\\diffD most common?\n    '∂': '\\\\differentialD',\n  \n    // Functions\n    'arcsin': '\\\\arcsin',\n    'arccos': '\\\\arccos',\n    'arctan': '\\\\arctan',\n    'arcsec': '\\\\arcsec',\n    'arccsc': '\\\\arccsc',\n  \n    'arsinh': '\\\\arsinh',\n    'arcosh': '\\\\arcosh',\n    'artanh': '\\\\artanh',\n    'arcsech': '\\\\arcsech',\n    'arccsch': '\\\\arccsch',\n    'arg': '\\\\arg',\n    'ch': '\\\\ch',\n    'cosec': '\\\\cosec',\n    'cosh': '\\\\cosh',\n    'cot': '\\\\cot',\n    'cotg': '\\\\cotg',\n    'coth': '\\\\coth',\n    'csc': '\\\\csc',\n    'ctg': '\\\\ctg',\n    'cth': '\\\\cth',\n    'sec': '\\\\sec',\n    'sinh': '\\\\sinh',\n    'sh': '\\\\sh',\n    'tanh': '\\\\tanh',\n    'tg': '\\\\tg',\n    'th': '\\\\th',\n  \n    'sin': '\\\\sin',\n    'cos': '\\\\cos',\n    'tan': '\\\\tan',\n  \n    'lg': '\\\\lg',\n    'lb': '\\\\lb',\n    'log': '\\\\log',\n    'ln': '\\\\ln',\n    'exp': '\\\\exp',\n    'lim': '\\\\lim_{#?}',\n    'limfx': '\\\\lim_{x \\\\to a} f(x)=',\n    'limgx': '\\\\lim_{x \\\\to a} g(x)=',\n    'limhx': '\\\\lim_{x \\\\to a} h(x)=',\n  \n    // Differentials\n    // According to ISO31/XI (ISO 80000-2), differentials should be upright\n    'dx': {\n      after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',\n      value: '\\\\differentialD x',\n    },\n    'dy': {\n      after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',\n      value: '\\\\differentialD y',\n    },\n    'dt': {\n      after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',\n      value: '\\\\differentialD t',\n    },\n  \n    // Logic\n    'AA': '\\\\forall',\n    'EE': '\\\\exists',\n    '!EE': '\\\\nexists',\n    '&&': '\\\\land',\n    'VV': '\\\\lor',\n    // The shortcut for the greek letter \"xi\" is interfering with \"x in\"\n    'xin': {\n      after: 'nothing+text+relop+punct+openfence+space',\n      value: 'x \\\\in',\n    },\n    'in': {\n      after: 'nothing+letter+closefence',\n      value: '\\\\in',\n    },\n    '!in': '\\\\notin',\n    'sub': '\\\\subset',\n    'subb': '\\\\subseteq',\n    'set': '\\\\Set{ {#?} | {#?} }',\n  \n    // Sets\n    'NN': '\\\\mathbb{N}', // Natural numbers\n    'ZZ': '\\\\Z', // Integers\n    'QQ': '\\\\Q', // Rational numbers\n    'RR': '\\\\R', // Real numbers\n    'CC': '\\\\C', // Complex numbers\n  \n    // Operators\n    'xx': '\\\\times',\n    '+-': '\\\\pm',\n    '-+': '\\\\mp',\n  \n    // Relational operators\n    '≠': '\\\\ne',\n    '!=': '\\\\ne',\n    '\\u2265': '\\\\ge',\n    '>=': '\\\\ge',\n    '\\u2264': '\\\\le',\n    '<=': '\\\\le',\n    '<<': '\\\\ll',\n    '>>': '\\\\gg',\n    '~~': '\\\\approx',\n  \n    // More operators\n    '≈': '\\\\approx',\n    '?=': '\\\\questeq',\n    '÷': '\\\\div',\n    '¬': '\\\\neg',\n    'not': '\\\\neg',\n    ':=': '\\\\coloneq',\n    '::': '\\\\coloneq',\n  \n    'TT': '\\\\perp',\n    'II': '\\\\parallel',\n\n    // Fences\n    '(:': '\\\\langle',\n    ':)': '\\\\rangle',\n  \n    // More Greek letters\n    'beta': '\\\\beta',\n    'chi': '\\\\chi',\n    'eps': '\\\\epsilon',\n    'varepsilon': '\\\\varepsilon',\n    'eta': {\n      after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',\n      value: '\\\\eta',\n    },\n    'gamma': '\\\\gamma',\n    'Gamma': '\\\\Gamma',\n    'iota': '\\\\iota',\n    'kappa': '\\\\kappa',\n    'lambda': '\\\\lambda',\n    'Lambda': '\\\\Lambda',\n    'mu': {\n      after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',\n      value: '\\\\mu',\n    },\n    'nu': {\n      after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',\n      value: '\\\\nu',\n    },\n    'µ': '\\\\mu', // @TODO: or micro?\n    'phi': {\n      after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',\n      value: '\\\\phi',\n    },\n    'Phi': {\n      after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',\n      value: '\\\\Phi',\n    },\n    'varphi': '\\\\varphi',\n    'psi': {\n      after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',\n      value: '\\\\psi',\n    },\n    'Psi': {\n      after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',\n      value: '\\\\Psi',\n    },\n    'rho': {\n      after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',\n      value: '\\\\rho',\n    },\n    'sigma': '\\\\sigma',\n    'Sigma': '\\\\Sigma',\n    'tau': {\n      after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',\n      value: '\\\\tau',\n    },\n    'vartheta': '\\\\vartheta',\n    'ups': '\\\\upsilon',\n    'xi': {\n      after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space',\n      value: '\\\\xi',\n    },\n    'Xi': {\n      after: 'nothing+digit+function+frac+surd+binop+relop+punct+array+openfence+closefence+space+text',\n      value: '\\\\Xi',\n    },\n    'zeta': '\\\\zeta',\n    'omega': '\\\\omega',\n    'Omega': '\\\\Omega',\n    'Ω': '\\\\omega', // @TODO: or ohm?\n  \n    // More Logic\n    'forall': '\\\\forall',\n    'exists': '\\\\exists',\n    '!exists': '\\\\nexists',\n    ':.': '\\\\therefore',\n    '.:': '\\\\because',\n    // MORE FUNCTIONS\n    // 'arg': '\\\\arg',\n    'liminf': '\\\\liminf_{#?}',\n    'limsup': '\\\\limsup_{#?}',\n    'argmin': '\\\\operatorname*{arg~min}_{#?}',\n    'argmax': '\\\\operatorname*{arg~max}_{#?}',\n    'det': '\\\\det',\n    'mod': '\\\\mod',\n    'max': '\\\\max',\n    'min': '\\\\min',\n  \n    'erf': '\\\\operatorname{erf}',\n    'erfc': '\\\\operatorname{erfc}',\n    'bessel': '\\\\operatorname{bessel}',\n    'mean': '\\\\operatorname{mean}',\n    'median': '\\\\operatorname{median}',\n  \n    'fft': '\\\\operatorname{fft}',\n  \n    'lcm': '\\\\operatorname{lcm}',\n  \n    'gcd': '\\\\operatorname{gcd}',\n  \n    'randomReal': '\\\\operatorname{randomReal}',\n    'randomInteger': '\\\\operatorname{randomInteger}',\n    'Re': '\\\\operatorname{Re}',\n  \n    'Im': '\\\\operatorname{Im}',\n  \n    // UNITS\n    'mm': {\n      after: 'nothing+digit+operator',\n      value: '\\\\operatorname{mm}', // Millimeter\n    },\n    'cm': {\n      after: 'nothing+digit+operator',\n      value: '\\\\operatorname{cm}', // Centimeter\n    },\n    'km': {\n      after: 'nothing+digit+operator',\n      value: '\\\\operatorname{km}', // Kilometer\n    },\n    'kg': {\n      after: 'nothing+digit+operator',\n      value: '\\\\operatorname{kg}', // Kilogram\n    },\n  \n    // '||':                   '\\\\lor',\n    '...': '\\\\ldots', // In general, use \\ldots\n    '+...': '+\\\\cdots', // ... but use \\cdots after + ...\n    '-...': '-\\\\cdots', // ... - and ...\n    '->...': '\\\\to\\\\cdots', // ->\n  \n    'to': '\\\\to',\n    '->': '\\\\to',\n    '|->': '\\\\mapsto',\n    '-->': '\\\\longrightarrow',\n    'up': '\\\\nearrow',\n    'down': '\\\\searrow',\n    //    '<-':                   '\\\\leftarrow',\n    '<--': '\\\\longleftarrow',\n    '=>': '\\\\Rightarrow',\n    '==': '\\\\equiv',\n    '==>': '\\\\Longrightarrow',\n    // '<=': '\\\\Leftarrow',     // CONFLICTS WITH LESS THAN OR EQUAL\n    '<=>': '\\\\Leftrightarrow',\n    '<->': '\\\\leftrightarrow',\n  \n    '(.)': '\\\\odot',\n    '(+)': '\\\\oplus',\n    '(/)': '\\\\oslash',\n    '(*)': '\\\\otimes',\n    '(-)': '\\\\ominus',\n    // '(-)':                  '\\\\circleddash',\n  \n    '||': '\\\\Vert',\n    '{': '\\\\{',\n    '}': '\\\\}',\n  \n    '*': '\\\\cdot',\n  \n    /*\n        //\n        // ASCIIIMath\n        //\n        // Binary operation symbols\n        '**':                   '\\\\ast',\n        '***':                  '\\\\star',\n        '//':                   '\\\\slash',\n        '\\\\\\\\':                 '\\\\backslash',\n        'setminus':             '\\\\backslash',\n        '|><':                  '\\\\ltimes',\n        '><|':                  '\\\\rtimes',\n        '|><|':                 '\\\\bowtie',\n        '-:':                   '\\\\div',\n        'divide':               '\\\\div',\n        '@':                    '\\\\circ',\n        'o+':                   '\\\\oplus',\n        'ox':                   '\\\\otimes',\n        'o.':                   '\\\\odot',\n        '^^':                   '\\\\wedge',\n        '^^^':                  '\\\\bigwedge',\n        'vv':                   '\\\\vee',\n        'vvv':                  '\\\\bigvee',\n        'nn':                   '\\\\cap',\n        'nnn':                  '\\\\bigcap',\n        'uu':                   '\\\\cup',\n        'uuu':                  '\\\\bigcup',\n        // Binary relation symbols\n        '-=':                   '\\\\equiv',\n        '~=':                   '\\\\cong',\n        'lt':                   '<',\n        'lt=':                  '\\\\leq',\n        'gt':                   '>',\n        'gt=':                  '\\\\geq',\n        '-<':                   '\\\\prec',\n        '-lt':                  '\\\\prec',\n        '-<=':                  '\\\\preceq',\n        // '>-':                   '\\\\succ',\n        '>-=':                  '\\\\succeq',\n        'prop':                 '\\\\propto',\n        'diamond':              '\\\\diamond',\n        'square':               '\\\\square',\n        'iff':                  '\\\\iff',\n        'sub':                  '\\\\subset',\n        'sup':                  '\\\\supset',\n        'sube':                 '\\\\subseteq',\n        'supe':                 '\\\\supseteq',\n        'uarr':                 '\\\\uparrow',\n        'darr':                 '\\\\downarrow',\n        'rarr':                 '\\\\rightarrow',\n        'rArr':                 '\\\\Rightarrow',\n        'larr':                 '\\\\leftarrow',\n        'lArr':                 '\\\\Leftarrow',\n        'harr':                 '\\\\leftrightarrow',\n        'hArr':                 '\\\\Leftrightarrow',\n        'aleph':                '\\\\aleph',\n        // Logic\n        'and':                  '\\\\land',\n        'or':                   '\\\\lor',\n        'not':                  '\\\\neg',\n        '_|_':                   '\\\\bot',\n        'TT':                   '\\\\top',\n        '|--':                  '\\\\vdash',\n        '|==':                  '\\\\models',\n        \n        // Other functions\n        '|__':                  '\\\\lfloor',\n        '__|':                  '\\\\rfloor',\n        '|~':                   '\\\\lceil',\n        '~|':                   '\\\\rceil',\n        // Arrows\n        '>->':                   '\\\\rightarrowtail',\n        '->>':                   '\\\\twoheadrightarrow',\n        '>->>':                  '\\\\twoheadrightarrowtail'\n    */\n};\n\nexport default ML_SHORTCUTS"
  },
  {
    "path": "src/main/Onboarding.js",
    "content": "const onboardingContent = {\n  \"blocks\": [\n    {\n      \"w\": 8,\n      \"h\": 2,\n      \"x\": 0,\n      \"y\": 0,\n      \"i\": \"de34c56c-ffa2-467a-a769-f5827c8c8802\",\n      \"minW\": 1,\n      \"maxW\": 8,\n      \"minH\": 1,\n      \"maxH\": 100,\n      \"moved\": false,\n      \"static\": false,\n      \"type\": 3,\n      \"metaData\": {\n        \"content\": [\n          {\n            \"type\": \"heading-one\",\n            \"children\": [{ \"text\": \"Welcome to Mathberet! 👋\" }]\n          }\n        ]\n      }\n    },\n    {\n      \"w\": 8,\n      \"h\": 5,\n      \"x\": 0,\n      \"y\": 2,\n      \"i\": \"a1ec4ffb-20d8-4972-b5bb-9ef3efcc5711\",\n      \"minW\": 1,\n      \"maxW\": 8,\n      \"minH\": 1,\n      \"maxH\": 100,\n      \"moved\": false,\n      \"static\": false,\n      \"type\": 3,\n      \"metaData\": {\n        \"content\": [\n          {\n            \"type\": \"paragraph\",\n            \"children\": [\n              {\n                \"text\": \"Mathberet is an open-source digital mathematics notebook written in React and TypeScript, designed for math students who need a platform for graphing, sketching, and writing in LaTeX. The goal here is to create a learning platform that allows students to write mathematical statements fluently and easily, in addition to sketching, graphing and arranging notes as freely as in a real-life notebook. We're also trying to keep the UI as clean and user-friendly as possible, allowing students to make the most out of their learning without thinking about the app itself. As a self-hosted application, Mathberet is both free and customizable, providing a reliable and efficient tool that works anywhere and anytime.\"\n              }\n            ]\n          },\n          { \"type\": \"paragraph\", \"children\": [{ \"text\": \"Important note:\" }] },\n          {\n            \"type\": \"paragraph\",\n            \"children\": [\n              {\n                \"text\": \"🚧 Mathberet is still in development! 🚧 - If you encounter a bug, please open an issue on our GitHub repo!\"\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"w\": 3,\n      \"h\": 4,\n      \"x\": 0,\n      \"y\": 10,\n      \"i\": \"4c8f483d-88a3-43a3-ac4c-5ed69a8af189\",\n      \"minW\": 1,\n      \"maxW\": 8,\n      \"minH\": 1,\n      \"maxH\": 100,\n      \"moved\": false,\n      \"static\": false,\n      \"type\": 3,\n      \"metaData\": {\n        \"content\": [\n          {\n            \"type\": \"heading-two\",\n            \"children\": [{ \"text\": \"How do I add blocks?\" }]\n          },\n          {\n            \"type\": \"bulleted-list\",\n            \"children\": [\n              {\n                \"type\": \"list-item\",\n                \"children\": [\n                  {\n                    \"text\": \"Move your mouse to the bottom of this page to view the toolbar.\"\n                  }\n                ]\n              },\n              {\n                \"type\": \"list-item\",\n                \"children\": [{ \"text\": \"Click on any of the buttons.\" }]\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"w\": 8,\n      \"h\": 1,\n      \"x\": 0,\n      \"y\": 7,\n      \"i\": \"b7fb5109-713d-4ee2-aa4b-d2734b87e466\",\n      \"minW\": 1,\n      \"maxW\": 8,\n      \"minH\": 1,\n      \"maxH\": 1,\n      \"moved\": false,\n      \"static\": false,\n      \"type\": 0,\n      \"metaData\": {}\n    },\n    {\n      \"w\": 3,\n      \"h\": 4,\n      \"x\": 0,\n      \"y\": 18,\n      \"i\": \"348f049f-3c34-4da9-bab4-6c49e637a494\",\n      \"minW\": 1,\n      \"maxW\": 8,\n      \"minH\": 1,\n      \"maxH\": 100,\n      \"moved\": false,\n      \"static\": false,\n      \"type\": 3,\n      \"metaData\": {\n        \"content\": [\n          {\n            \"type\": \"heading-two\",\n            \"children\": [{ \"text\": \"How do I save files?\" }]\n          },\n          {\n            \"type\": \"bulleted-list\",\n            \"children\": [\n              {\n                \"type\": \"list-item\",\n                \"children\": [\n                  {\n                    \"text\": \"Move your mouse to the bottom of this page to view the toolbar.\"\n                  }\n                ]\n              },\n              {\n                \"type\": \"list-item\",\n                \"children\": [{ \"text\": \"Click on the save button.\" }]\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"w\": 3,\n      \"h\": 4,\n      \"x\": 0,\n      \"y\": 14,\n      \"i\": \"9249ad8b-238a-4020-a521-c41f961c5973\",\n      \"minW\": 1,\n      \"maxW\": 8,\n      \"minH\": 1,\n      \"maxH\": 100,\n      \"moved\": false,\n      \"static\": false,\n      \"type\": 3,\n      \"metaData\": {\n        \"content\": [\n          {\n            \"type\": \"heading-two\",\n            \"children\": [{ \"text\": \"How do I clear the page?\" }]\n          },\n          {\n            \"type\": \"bulleted-list\",\n            \"children\": [\n              {\n                \"type\": \"list-item\",\n                \"children\": [\n                  {\n                    \"text\": \"Move your mouse to the bottom of this page to view the toolbar.\"\n                  }\n                ]\n              },\n              {\n                \"type\": \"list-item\",\n                \"children\": [{ \"text\": \"Click on the trash button.\" }]\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"w\": 5,\n      \"h\": 2,\n      \"x\": 3,\n      \"y\": 8,\n      \"i\": \"d90c4f52-e515-4017-8927-19c1e9c02640\",\n      \"minW\": 1,\n      \"maxW\": 8,\n      \"minH\": 1,\n      \"maxH\": 100,\n      \"moved\": false,\n      \"static\": false,\n      \"type\": 3,\n      \"metaData\": {\n        \"content\": [\n          { \"type\": \"heading-one\", \"children\": [{ \"text\": \"Block Examples\" }] }\n        ]\n      }\n    },\n    {\n      \"w\": 5,\n      \"h\": 2,\n      \"x\": 3,\n      \"y\": 15,\n      \"i\": \"65e61c01-c999-411c-8c4d-4c7242d1a274\",\n      \"minW\": 1,\n      \"maxW\": 8,\n      \"minH\": 1,\n      \"maxH\": 100,\n      \"moved\": false,\n      \"static\": false,\n      \"type\": 4,\n      \"metaData\": { \"content\": \"x_{1,2}=\\\\frac{-b\\\\pm\\\\sqrt{b^2-4ac}}{2a}\" }\n    },\n    {\n      \"w\": 5,\n      \"h\": 3,\n      \"x\": 3,\n      \"y\": 12,\n      \"i\": \"630fc019-caff-43f3-a629-d91ffa34e635\",\n      \"minW\": 1,\n      \"maxW\": 8,\n      \"minH\": 1,\n      \"maxH\": 100,\n      \"moved\": false,\n      \"static\": false,\n      \"type\": 3,\n      \"metaData\": {\n        \"content\": [\n          { \"type\": \"heading-three\", \"children\": [{ \"text\": \"Math block\" }] },\n          {\n            \"type\": \"paragraph\",\n            \"children\": [\n              {\n                \"text\": \"In addition to writing in LaTeX, we've added dozens of keyboard shortcuts to help you write faster in math blocks. For example, try writing \\\"intfx\\\" in a math block. Keyboard shortcuts help menu coming soon!\"\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"w\": 5,\n      \"h\": 3,\n      \"x\": 3,\n      \"y\": 17,\n      \"i\": \"997ff1a3-8919-4302-8d6a-47e3d8fb397d\",\n      \"minW\": 1,\n      \"maxW\": 8,\n      \"minH\": 1,\n      \"maxH\": 100,\n      \"moved\": false,\n      \"static\": false,\n      \"type\": 3,\n      \"metaData\": {\n        \"content\": [\n          { \"type\": \"heading-three\", \"children\": [{ \"text\": \"Graph Block\" }] },\n          {\n            \"type\": \"paragraph\",\n            \"children\": [\n              {\n                \"text\": \"Currently, the only functions supported in the graph block are trigonometric and polynomial functions. More functions to be supported soon!\"\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"w\": 5,\n      \"h\": 5,\n      \"x\": 3,\n      \"y\": 20,\n      \"i\": \"4455135f-af3c-454d-bb87-d393b7814b1f\",\n      \"minW\": 2,\n      \"maxW\": 8,\n      \"minH\": 2,\n      \"maxH\": 100,\n      \"moved\": false,\n      \"static\": false,\n      \"type\": 1,\n      \"metaData\": { \"content\": [\"\\\\sin(x)\\\\cdot\\\\tan(x)\"] }\n    },\n    {\n      \"w\": 5,\n      \"h\": 4,\n      \"x\": 3,\n      \"y\": 27,\n      \"i\": \"2c7648cb-bad0-4d17-8101-b6044f2f12d3\",\n      \"minW\": 4,\n      \"maxW\": 8,\n      \"minH\": 4,\n      \"maxH\": 100,\n      \"moved\": false,\n      \"static\": false,\n      \"type\": 6,\n      \"metaData\": {\n        \"content\": {\n          \"shapes\": [],\n          \"bindings\": [],\n          \"assets\": []\n        }\n      }\n    },\n    {\n      \"w\": 5,\n      \"h\": 2,\n      \"x\": 3,\n      \"y\": 25,\n      \"i\": \"bbd2df59-7777-4353-8ee2-c6e1942fba57\",\n      \"minW\": 1,\n      \"maxW\": 8,\n      \"minH\": 1,\n      \"maxH\": 100,\n      \"moved\": false,\n      \"static\": false,\n      \"type\": 3,\n      \"metaData\": {\n        \"content\": [\n          {\n            \"type\": \"heading-three\",\n            \"children\": [{ \"text\": \"Drawing Block\" }]\n          },\n          {\n            \"type\": \"paragraph\",\n            \"children\": [\n              { \"text\": \"Based on tldraw. Draw to your heart content!\" }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"w\": 5,\n      \"h\": 2,\n      \"x\": 3,\n      \"y\": 10,\n      \"i\": \"64fbccd1-e25d-4a01-8749-aa4a23507519\",\n      \"minW\": 1,\n      \"maxW\": 8,\n      \"minH\": 1,\n      \"maxH\": 100,\n      \"moved\": false,\n      \"static\": false,\n      \"type\": 3,\n      \"metaData\": {\n        \"content\": [\n          { \"type\": \"heading-three\", \"children\": [{ \"text\": \"Text Block\" }] },\n          {\n            \"type\": \"paragraph\",\n            \"children\": [\n              {\n                \"text\": \"Written in markdown (currently limited to headers and unordered lists).\"\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"w\": 3,\n      \"h\": 4,\n      \"x\": 0,\n      \"y\": 22,\n      \"i\": \"c0e9fa2b-6b44-44bc-a7b4-564ae5dbc6b5\",\n      \"minW\": 1,\n      \"maxW\": 8,\n      \"minH\": 1,\n      \"maxH\": 100,\n      \"moved\": false,\n      \"static\": false,\n      \"type\": 3,\n      \"metaData\": {\n        \"content\": [\n          {\n            \"type\": \"heading-two\",\n            \"children\": [{ \"text\": \"How do I create a file/folder?\" }]\n          },\n          {\n            \"type\": \"bulleted-list\",\n            \"children\": [\n              {\n                \"type\": \"list-item\",\n                \"children\": [\n                  {\n                    \"text\": \"Click on the notebooks button in the left sidebar.\"\n                  }\n                ]\n              },\n              {\n                \"type\": \"list-item\",\n                \"children\": [\n                  { \"text\": \"Click on the create file/folder button.\" }\n                ]\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"w\": 3,\n      \"h\": 4,\n      \"x\": 0,\n      \"y\": 26,\n      \"i\": \"6900c23a-d4b5-42c5-92a5-01c5b6f32e89\",\n      \"minW\": 1,\n      \"maxW\": 8,\n      \"minH\": 1,\n      \"maxH\": 100,\n      \"moved\": false,\n      \"static\": false,\n      \"type\": 3,\n      \"metaData\": {\n        \"content\": [\n          {\n            \"type\": \"heading-two\",\n            \"children\": [{ \"text\": \"How do I change themes?\" }]\n          },\n          {\n            \"type\": \"bulleted-list\",\n            \"children\": [\n              {\n                \"type\": \"list-item\",\n                \"children\": [\n                  {\n                    \"text\": \"Click on the command button in the left sidebar (or press Ctrl+Shift+P).\"\n                  }\n                ]\n              },\n              {\n                \"type\": \"list-item\",\n                \"children\": [{ \"text\": \"Click on Preferences -> Theme.\" }]\n              }\n            ]\n          }\n        ]\n      }\n    },\n    {\n      \"w\": 3,\n      \"h\": 2,\n      \"x\": 0,\n      \"y\": 8,\n      \"i\": \"d76c816e-9e3b-4f29-83b8-4f5c2104ef81\",\n      \"minW\": 1,\n      \"maxW\": 8,\n      \"minH\": 1,\n      \"maxH\": 100,\n      \"moved\": false,\n      \"static\": false,\n      \"type\": 3,\n      \"metaData\": {\n        \"content\": [{ \"type\": \"heading-one\", \"children\": [{ \"text\": \"FAQ\" }] }]\n      }\n    }\n  ],\n  \"tags\": [],\n  \"mathMemory\": {}\n}\n\nexport default onboardingContent;"
  },
  {
    "path": "src/main/app.ts",
    "content": "import { app, BrowserWindow } from 'electron';\nimport { createAppWindow } from './appWindow';\n\n/** Handle creating/removing shortcuts on Windows when installing/uninstalling. */\nif (require('electron-squirrel-startup')) {\n  app.quit();\n}\n\n/**\n * This method will be called when Electron has finished\n * initialization and is ready to create browser windows.\n * Some APIs can only be used after this event occurs.\n */\napp.on('ready', createAppWindow);\n\n/**\n * Emitted when the application is activated. Various actions can\n * trigger this event, such as launching the application for the first time,\n * attempting to re-launch the application when it's already running,\n * or clicking on the application's dock or taskbar icon.\n */\napp.on('activate', () => {\n  /**\n   * On OS X it's common to re-create a window in the app when the\n   * dock icon is clicked and there are no other windows open.\n   */\n  if (BrowserWindow.getAllWindows().length === 0) {\n    createAppWindow();\n  }\n});\n\n/**\n * Emitted when all windows have been closed.\n */\napp.on('window-all-closed', () => {\n  /**\n   * On OS X it is common for applications and their menu bar\n   * to stay active until the user quits explicitly with Cmd + Q\n   */\n  if (process.platform !== 'darwin') {\n    app.quit();\n  }\n});\n\n/**\n * In this file you can include the rest of your app's specific main process code.\n * You can also put them in separate files and import them here.\n */\n"
  },
  {
    "path": "src/main/appWindow.ts",
    "content": "import { app, BrowserWindow, ipcMain, shell } from 'electron';\nimport path from 'path';\nimport { registerTitlebarIpc } from '@misc/window/titlebarIPC';\nimport * as fs from 'fs';\nconst { resolve } = require('path');\nconst os = require('os');\nimport onboardingContent from './Onboarding';\n\n// Electron Forge automatically creates these entry points\ndeclare const APP_WINDOW_WEBPACK_ENTRY: string;\ndeclare const APP_WINDOW_PRELOAD_WEBPACK_ENTRY: string;\n\nlet appWindow: BrowserWindow;\n\n/**\n * Create Application Window\n * @returns {BrowserWindow} Application Window Instance\n */\nexport function createAppWindow(): BrowserWindow {\n  // Create new window instance\n  appWindow = new BrowserWindow({\n    width: 800,\n    height: 600,\n    minWidth: 700,\n    minHeight: 400,\n    backgroundColor: '#202020',\n    show: false,\n    autoHideMenuBar: true,\n    frame: false,\n    titleBarStyle: 'hidden',\n    icon: resolve('assets/images/appIcon.ico'),\n    webPreferences: {\n      nodeIntegration: false,\n      contextIsolation: true,\n      nodeIntegrationInWorker: false,\n      nodeIntegrationInSubFrames: false,\n      preload: APP_WINDOW_PRELOAD_WEBPACK_ENTRY,\n      sandbox: false,\n    },\n  });\n\n  // Load the index.html of the app window.\n  appWindow.loadURL(APP_WINDOW_WEBPACK_ENTRY);\n\n  // Show window when its ready to\n  appWindow.on('ready-to-show', () => appWindow.show());\n\n  // Register Inter Process Communication for main process\n  registerMainIPC();\n\n  // Close all windows when main window is closed\n  appWindow.on('close', () => {\n    appWindow = null;\n    app.quit();\n  });\n\n  return appWindow;\n}\n\nipcMain.on('getOS', () => {\n  let OS = '';\n  switch (os.platform()) {\n    case \"darwin\":\n      OS = \"mac\";\n      break;\n    case \"win32\":\n      OS = \"windows\"\n      break;\n    case \"linux\":\n      OS = \"linux\"\n      break;\n  \n    default:\n      break;\n  }\n  appWindow.webContents.send('gotOS', OS);\n});\n\nipcMain.on('saveX', (event, data, filePath) => {\n  const filesPath = path.join(app.getPath('documents'), 'Mathberet', 'files');\n\n  if (fs.existsSync(filesPath)) {\n    fs.writeFileSync(path.join(filePath), data, 'utf-8');\n  } else {\n    fs.mkdirSync(filesPath, { recursive: true });\n    fs.writeFileSync(path.join(filePath), data, 'utf-8');\n  }\n});\n\nipcMain.on('loadX', (event, filePath) => {\n\n  if (fs.existsSync(filePath)) {\n    fs.readFile(filePath, 'utf-8', (error, data) => {\n      error\n        ? console.error('Error Reading file: ', error)\n        : appWindow.webContents.send('gotLoadedDataX', data);\n    });\n  } else {\n    console.error('File not found!');\n  }\n});\n\nipcMain.on('openFiles', () => {\n  shell\n    .openPath(path.join(app.getPath('documents'), 'Mathberet', 'files'))\n    .catch((error) => {\n      console.error(error);\n    });\n});\n\nipcMain.on('move', (event, oldDir, newDir) => {\n  fs.renameSync(oldDir, newDir);\n});\n\nipcMain.on('delete', (event, path, isFolder) => {\n  isFolder ? fs.rmSync(path, { recursive: true, force: true }) : fs.rmSync(path);\n});\n\nipcMain.on('load', (event, file) => {\n  fs.readFile(file, 'utf-8', (error, data) => {\n    appWindow.webContents.send('fromMain', data);\n  });\n});\n\nipcMain.on('newFile', (event, filePath) => {\n  fs.writeFileSync(filePath, '{}');\n});\n\nipcMain.on('newFolder', (event, folderPath) => {\n  fs.mkdirSync(folderPath);\n});\n\n\nlet firstTime = true;\n\nfunction buildTree(dir: string, root: any) {\n  const stats = fs.statSync(dir);\n  let name = path.basename(dir).split('.')[0];\n  let key = dir;\n\n  if (firstTime) {\n    name = 'root';\n    key = 'root';\n    firstTime = false;\n  }\n\n  if (!stats.isDirectory()) {\n    root[key] = {\n      index: key,\n      data: name,\n      children: [],\n      path: dir,\n      isFolder: false,\n    };\n\n    return key;\n  }\n\n  const children = fs\n    .readdirSync(dir)\n    .map((child) => buildTree(path.join(dir, child), root));\n\n  root[key] = {\n    index: key,\n    isFolder: true,\n    data: name,\n    children,\n    path: dir,\n  };\n\n  return key;\n}\n\nipcMain.on('getNotebooks', () => {\n  const filesPath = path.join(app.getPath('documents'), 'Mathberet', 'files');\n\n  if (!fs.existsSync(filesPath)) {\n    fs.mkdirSync(filesPath, {recursive: true});\n    fs.writeFileSync(path.join(filesPath, \"Welcome to Mathberet!.json\"), JSON.stringify(onboardingContent))\n  }\n\n  const root = {};\n  buildTree(filesPath, root);\n  firstTime = true;\n  appWindow.webContents.send('gotNotebooks', { filesPath, root });\n});\n\nipcMain.on('getPicture', (event, id) => {\n  const allPics = fs.readdirSync(path.join(__dirname, '..', 'attachments'), {\n    withFileTypes: true,\n  });\n  let foundPath, b64;\n  for (const picture of allPics) {\n    if (picture.name.split('.')[0] == id.toString()) {\n      foundPath = path.join(__dirname, '..', 'attachments', picture.name);\n      b64 = fs.readFileSync(foundPath, 'base64');\n      break;\n    }\n  }\n  appWindow.webContents.send('gotPicture', `data:image/png;base64,${b64}`);\n  return;\n});\n\n\nipcMain.on('getArchive', () => {\n  const filesPath = path.join(__dirname, '..', 'files');\n\n  const groupsToFilter: [] = [];\n  function getAllGroups() {\n    const allGroups = [];\n    const allFiles = fs.readdirSync(filesPath, { withFileTypes: true });\n    for (const file of allFiles) {\n      if (file.isDirectory()) {\n        const subFiles = fs.readdirSync(path.join(filesPath, file.name), {\n          withFileTypes: true,\n        });\n        for (const subfile of subFiles) {\n          if (subfile.name.split('.')[1] == 'json') {\n            const readFile = fs.readFileSync(\n              path.join(filesPath, file.name, subfile.name),\n              'utf-8',\n            );\n            for (const block of JSON.parse(readFile)) {\n              if (block.type == 'Group') {\n                allGroups.push(block);\n              }\n            }\n          }\n        }\n      } else {\n        if (file.name.split('.')[1] == 'json') {\n          const readFile = fs.readFileSync(\n            path.join(filesPath, file.name),\n            'utf-8',\n          );\n          for (const block of JSON.parse(readFile)) {\n            if (block.type == 'Group') {\n              allGroups.push(block);\n            }\n          }\n        }\n      }\n    }\n    return allGroups;\n  }\n\n  const allGroups = getAllGroups();\n\n  function removeDups(arr: any[]) {\n    const uniqueIds: any[] = [];\n    const unique = arr.filter((element) => {\n      const isDuplicate = uniqueIds.includes(element);\n      if (!isDuplicate) {\n        uniqueIds.push(element);\n        return true;\n      }\n      return false;\n    });\n    return unique.map(\n      (groupTitle) => (groupTitle = { groupName: groupTitle, subGroups: [] }),\n    );\n  }\n\n  const finalArr = [];\n  for (const group of removeDups(groupsToFilter)) {\n    if (group.groupName != 'קבוצה') {\n      for (const subGroup of allGroups) {\n        if (subGroup.groupTitle == group.groupName) {\n          group.subGroups.push(subGroup);\n        }\n      }\n      finalArr.push(group);\n    }\n  }\n\n  appWindow.webContents.send('gotArchive', finalArr);\n});\n\nipcMain.on('startSearch', (event, args) => {\n  const filesPath = path.join(__dirname, '..', 'files');\n  function getAllBlocks() {\n    const allGroups = [];\n    const allFiles = fs.readdirSync(filesPath, { withFileTypes: true });\n    for (const file of allFiles) {\n      if (file.isDirectory()) {\n        const subFiles = fs.readdirSync(path.join(filesPath, file.name), {\n          withFileTypes: true,\n        });\n        for (const subfile of subFiles) {\n          const readFile = fs.readFileSync(\n            path.join(filesPath, file.name, subfile.name),\n            'utf-8',\n          );\n          allGroups.push({\n            filePath: path.join(filesPath, file.name, subfile.name),\n            fileName: subfile.name.replace('.json', ''),\n            blocks: JSON.parse(readFile),\n          });\n        }\n      } else {\n        const readFile = fs.readFileSync(\n          path.join(filesPath, file.name),\n          'utf-8',\n        );\n        allGroups.push({\n          filePath: path.join(filesPath, file.name),\n          fileName: file.name.replace('.json', ''),\n          blocks: JSON.parse(readFile),\n        });\n      }\n    }\n    return allGroups;\n  }\n  const allGroups = getAllBlocks();\n  appWindow.webContents.send('gotAllBlocks', allGroups);\n});\n\n/**\n * Register Inter Process Communication\n */\nfunction registerMainIPC() {\n  /**\n   * Here you can assign IPC related codes for the application window\n   * to Communicate asynchronously from the main process to renderer processes.\n   */\n  registerTitlebarIpc(appWindow);\n}\n"
  },
  {
    "path": "src/renderer/app.html",
    "content": "<!DOCTYPE html>\n<html lang=\"he\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>מתברת</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "src/renderer/appPreload.tsx",
    "content": "import '@misc/window/windowPreload';\n\n// Say something\nconsole.log('[ERWT] : Preload execution started');\n\n// Get versions\nwindow.addEventListener('DOMContentLoaded', () => {\n  const { env } = process;\n  const versions: Record<string, unknown> = {};\n\n  // ERWT Package version\n  versions['erwt'] = env['npm_package_version'];\n  versions['license'] = env['npm_package_license'];\n\n  // Process versions\n  for (const type of ['chrome', 'node', 'electron']) {\n    versions[type] = process.versions[type].replace('+', '');\n  }\n\n  // NPM deps versions\n  for (const type of ['react']) {\n    const v = env['npm_package_dependencies_' + type];\n    if (v) versions[type] = v.replace('^', '');\n  }\n\n  // NPM @dev deps versions\n  for (const type of ['webpack', 'typescript']) {\n    const v = env['npm_package_devDependencies_' + type];\n    if (v) versions[type] = v.replace('^', '');\n  }\n\n  // Set versions to app data\n  // app.setAttribute('data-versions', JSON.stringify(versions));\n});\n"
  },
  {
    "path": "src/renderer/appRenderer.tsx",
    "content": "import React from 'react';\nimport { createRoot } from 'react-dom/client';\nimport WindowFrame from '@misc/window/components/WindowFrame';\nimport Application from '@components/Application';\n\n// Say something\nconsole.log('[ERWT] : Renderer execution started');\n\n// Application to Render\nconst app = (\n  <WindowFrame title='מתברת' platform='windows'>\n    <Application />\n    <div id=\"portal\"></div>\n  </WindowFrame>\n);\n\n// Render application in DOM\ncreateRoot(document.getElementById('app')).render(app);\n"
  },
  {
    "path": "src/renderer/common/types.ts",
    "content": "import { TDShape, TDBinding, TDAsset } from '@tldraw/tldraw';\n// eslint-disable-next-line import/named\nimport { Descendant } from 'slate';\n\nexport enum WidgetType {\n  Divider,\n  Graph,\n  Group,\n  Text,\n  Math,\n  Picture,\n  Draw,\n}\n\nexport type canvasProps = {\n  shapes: TDShape[];\n  bindings?: TDBinding[];\n  assets?: TDAsset[];\n};\n\nexport type ValueProps = {\n  blockStateFunction: (...args: unknown[]) => unknown;\n  content: string | string[] | Descendant[] | canvasProps;\n};\n\nexport type BlockState = {\n  id: string,\n  metaData: {content: string | string[] | Descendant[] | canvasProps},\n}\n\nexport type FileStructure = {\n  tags: string[];\n  blocks: Array<BlockElement>;\n  mathMemory: object;\n};\n\nexport type BlockElement = {\n  type: WidgetType;\n  metaData?: ValueProps;\n} & ReactGridLayout.Layout;\n\nexport type newWidgetRequest = {\n  widgetType: WidgetType;\n};\n\nexport type PageGridState = {\n  items: BlockElement[];\n  breakpoint: string;\n  cols: number;\n};\n"
  },
  {
    "path": "src/renderer/components/Application.scss",
    "content": "/**\n * Licensed under the MIT License. See LICENSE file in the project root for license information.\n * Copyright (c) 2022 Codesbiome, guasam\n *\n * @author  : guasam\n * @project : ERWT Boilerplate\n * @package : Application Sass Stylesheet\n*/\n@import '../../../assets/icons/uicons.css';\n@import './Theme.scss';\n@import './Fonts.css';\n\n::selection {\n  background: var(--selection-bgcolor);\n  color: var(--selection-color);\n}\n\n::-webkit-scrollbar {\n  width: var(--scroll-width);\n\n  &-track {\n    background: transparent;\n  }\n\n  &-thumb {\n    background: var(--scroll-thumb-bgcolor);\n    border-radius: 50px;\n  }\n\n  &-thumb:hover {\n    background: var(--scroll-thumb-hover-bgcolor);\n  }\n}\n\nhtml,\nbody,\n#app {\n  transition: 0.3s;\n  height: 100%;\n  overflow: hidden;\n  direction: var(--app-direction);\n}\n\nbody {\n  margin: 0;\n  margin-right: 0 !important;\n  font-size: var(--app-font-size);\n  font-family: var(--app-font-family);\n  color: var(--app-color);\n  background: var(--app-bgcolor);\n  line-height: 1.5;\n}\n\nh1 {\n  margin: 0;\n}\n\n#app {\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n  -webkit-user-select: none;\n  user-select: none;\n\n  &.has-border {\n    border: var(--app-border-color);\n  }\n}\n\nbutton {\n  background: var(--button-bgcolor);\n  color: var(--button-color);\n  font-weight: normal;\n  text-shadow: 0px 1px var(--button-shadow-color);\n  font-family: var(--app-font-family);\n  border: none;\n  padding: 0.5rem 1rem;\n  font-size: 0.875rem;\n  cursor: pointer;\n  transition: 0.1s;\n  display: inline-flex;\n  justify-content: space-around;\n  align-items: center;\n  outline: none;\n\n  &.tool {\n    background-color: #1a2428;\n  }\n\n  &:hover {\n    background: var(--button-hover-bgcolor);\n  }\n  &:active {\n    background: var(--button-active-bgcolor);\n  }\n}\n\n.rotate {\n  animation: rotate 4.5s linear infinite;\n}\n\n@keyframes rotate {\n  to {\n    transform: rotate(360deg);\n  }\n}\n\n.hidden {\n  display: none !important;\n}\n\n.center {\n  text-align: center;\n}\n\n#main-app {\n  display: flex;\n  flex-direction: column;\n  height: 100%;\n  gap: 5px;\n  overflow-x: hidden;\n\n  .workspace {\n    width: calc(100% - 20px);\n    align-self: center;\n    height: 100%;\n    display: flex;\n    flex-direction: row;\n    direction: var(--app-direction);\n    justify-content: center;\n    gap: 10px;\n\n    .math-sidebar.open {\n      width: 100%;\n      min-width: 230px;\n      max-width: 15vw;\n    }\n\n    .math-sidebar {\n      transition: 0.2s;\n      width: 45px;\n      min-width: 45px;\n      max-width: 45px;\n      height: 100%;\n      display: flex;\n      flex-direction: column;\n      gap: 20px;\n    }\n  }\n}"
  },
  {
    "path": "src/renderer/components/Application.tsx",
    "content": "import React from 'react';\nimport '../../../node_modules/react-grid-layout/css/styles.css';\nimport '../../../node_modules/react-resizable/css/styles.css';\nimport './Application.scss';\nimport { CommandBar } from './CommandBar/CommandBar';\nimport FilesSidebar from './FilesSidebar/FilesSidebar';\nimport { GeneralContextProvider } from './GeneralContext';\nimport Header from './Header/Header';\nimport MathSidebar from './MathSidebar/MathSidebar';\nimport Page from './Page/Page';\n\nconst Application = () => {\n  return (\n    <GeneralContextProvider>\n      <div id='main-app'>\n        <Header />\n        <div className='workspace'>\n          <FilesSidebar />\n          <CommandBar />\n          <Page />\n          <MathSidebar />\n        </div>\n      </div>\n    </GeneralContextProvider>\n  );\n};\n\nexport default Application;\n"
  },
  {
    "path": "src/renderer/components/CommandBar/CommandBar.scss",
    "content": "@import '../Theme.scss';\n\n.command-bar {\n  &-search {\n    padding: 12px 16px;\n    font-size: 16px;\n    width: 100%;\n    font-family: 'Rubik2', 'NotoSansArabic';\n    box-sizing: border-box;\n    outline: none;\n    border: none;\n    background: transparent;\n    color: hsla(var(--app-text-color), 1);\n  }\n\n  &-result {\n    padding: 14px 10px;\n    border-radius: 8px;\n    font-size: 16px;\n    user-select: none;\n    background: transparent;\n\n    &.active {\n      background: hsla(var(--theme-hue), 50%, 50%, 0.1);\n    }\n  }\n}\n\nbody:has(#main-app.rtl) {\n  .command-bar-search,\n  .command-bar-result {\n    direction: rtl !important;\n  }\n}\n"
  },
  {
    "path": "src/renderer/components/CommandBar/CommandBar.tsx",
    "content": "import React from 'react';\nimport './CommandBar.scss';\n\nimport {\n  KBarPortal,\n  KBarPositioner,\n  KBarAnimator,\n  KBarResults,\n  KBarSearch,\n  useMatches,\n  useRegisterActions,\n} from 'kbar';\n\nimport { useTranslation } from 'react-i18next';\nimport { useGeneralContext } from '@components/GeneralContext';\n\nexport function CommandBar() {\n  const { t } = useTranslation();\n\n  const { actions } = useGeneralContext();\n\n  function RenderResults() {\n    // updating the actions using `useRegisterActions` *before*\n    // getting the results from `useMatches` so the results\n    // are always up to date. the actions are also up to date\n    // cause they are now stateful\n\n    useRegisterActions(actions);\n    const { results } = useMatches();\n\n    return (\n      <KBarResults\n        items={results}\n        onRender={({ item, active }) =>\n          typeof item === 'string' ? (\n            <div>{item}</div>\n          ) : (\n            <div className={`command-bar-result${active ? ' active' : ''}`}>\n              {item.name}\n            </div>\n          )\n        }\n      />\n    );\n  }\n\n  const animatorStyle = {\n    maxWidth: '600px',\n    width: '100%',\n    zIndex: '10000',\n    padding: '10px 8px',\n    outline: '1px solid var(--page-border)',\n    backdropFilter: 'blur(7px)',\n    background: 'var(--command-bar-bg)',\n    color: 'hsla(var(--app-text-color), 1)',\n    borderRadius: '12px',\n    boxShadow: '0 0 10px 1px rgba(0, 0, 0, .25)',\n    overflow: 'hidden',\n  };\n\n  return (\n    <KBarPortal>\n      <KBarPositioner style={{ width: 'unset' }}>\n        <KBarAnimator style={animatorStyle}>\n          <KBarSearch\n            className='command-bar-search'\n            defaultPlaceholder={t('Prompt')}\n          />\n          <RenderResults />\n        </KBarAnimator>\n      </KBarPositioner>\n    </KBarPortal>\n  );\n}\n"
  },
  {
    "path": "src/renderer/components/FilesSidebar/FileSystem.scss",
    "content": "@import '~react-complex-tree/lib/style-modern.css';\n@import '../Theme.scss';\n\n#main-app.rtl .rct-tree-item-title-container {\n  margin-inline-end: 10px !important;\n  margin-inline-start: unset !important;\n}\n\n.file-system {\n  display: flex;\n  flex-direction: column;\n  width: 100%;\n  height: 100%;\n  min-width: 190px;\n  max-width: 230px;\n\n  .file-system-header {\n    display: flex;\n    flex-direction: row;\n    direction: var(--app-direction);\n    height: max-content;\n    padding-bottom: 10px;\n    padding-top: 3px;\n    align-items: center;\n\n    .file-system-header-title {\n      cursor: alias;\n      color: hsla(var(--app-text-color), 0.6);\n      white-space: nowrap;\n      font-size: 21px;\n      font-weight: 700;\n      width: 100%;\n\n      &:hover::after {\n        content: attr(data-tooltip);\n        color: hsla(var(--app-text-color), 1);\n        font-size: 14px;\n        font-weight: 400;\n        min-width: max-content;\n        position: fixed;\n        margin-top: 40px;\n        margin-inline-start: -130px;\n        z-index: 1000;\n        padding: 6px 10px 6px 10px;\n        background-color: var(--button-bgcolor);\n        text-shadow: none;\n        border: 1px solid var(--page-border);\n        border-radius: 6px;\n        opacity: 0%;\n        animation: tooltip 0.1s ease-in-out 0.2s forwards;\n      }\n    }\n\n    .file-system-header-buttons {\n      border-radius: 10px;\n      display: flex;\n      flex-direction: row;\n      direction: var(--app-direction);\n      width: max-content;\n      gap: 3px;\n\n      button {\n        background: none;\n        padding: 5px !important;\n        color: var(--tool-color);\n        transition: 0.1s;\n\n        &:hover {\n          background: none;\n          color: var(--button-color);\n\n          &::after {\n            content: attr(data-tooltip);\n            color: hsla(var(--app-text-color), 1);\n            min-width: max-content;\n            position: fixed;\n            margin-top: 80px;\n            z-index: 1000;\n            padding: 6px 10px 6px 10px;\n            background-color: var(--button-bgcolor);\n            text-shadow: none;\n            border: 1px solid var(--page-border);\n            border-radius: 6px;\n            opacity: 0%;\n            animation: tooltip 0.1s ease-in-out 0.2s forwards;\n          }\n        }\n\n        &:active {\n          transform: scale(0.92);\n        }\n\n        i {\n          font-size: 18px;\n          height: 18px;\n        }\n      }\n    }\n  }\n\n  .files-tree-container {\n    width: 100%;\n    display: flex;\n    flex-direction: column;\n    justify-content: space-between;\n    min-width: inherit;\n    max-width: inherit;\n\n    .rct-tree-root {\n      height: 90%;\n\n      [role='tree'] {\n        height: inherit;\n\n        & > .rct-tree-items-container {\n          height: inherit;\n\n          [role='treeitem'] {\n            input {\n              text-shadow: none;\n              font-family: 'Rubik2', 'NotoSansArabic';\n              font-size: 16px;\n              height: 40px;\n            }\n\n            .rct-tree-item-title-container {\n              margin-inline-start: 10px;\n              margin-inline-end: unset;            \n              padding-inline-end: 10px !important;\n              padding-right: 0px !important;\n              padding-left: 0px !important;\n\n              .rct-tree-item-button {\n                overflow: hidden;\n                min-width: inherit;\n                text-overflow: ellipsis;\n                white-space: nowrap;\n                height: 100%;\n                direction: var(--app-direction);\n                background-color: transparent;\n                color: hsla(var(--app-text-color), 1);\n                border-radius: 10px;\n                text-shadow: none;\n                font-family: 'Rubik2', 'NotoSansArabic';\n                font-size: 16px;\n                height: 40px;\n                flex-direction: row;\n                justify-content: flex-start;\n                padding-inline-start: 10px;\n                // direction: ltr;\n                // padding: 0 var(--rct-item-padding) 0\n                //   calc(\n                //     var(--rct-item-padding) + var(--rct-arrow-container-size) +\n                //       var(--rct-arrow-padding)\n                //   );\n                // margin-right: calc(-1 * var(--rct-arrow-size));\n                // margin-left: calc(-1 * var(--rct-arrow-size));\n                // padding-right: 12px;\n                cursor: var(--rct-cursor);\n                transition: color 100ms ease-out,\n                  background-color 100ms ease-out, font-weight 100ms ease-in;\n\n                &:hover {\n                  background-color: var(--file-hover-bgcolor);\n                  color: hsla(var(--app-text-color), 1);\n                }\n\n                &:active {\n                  background-color: var(--file-active-bgcolor);\n                  color: hsla(var(--app-text-color), 1);\n                }\n\n                &::before {\n                  // Override\n                  position: unset;\n                  top: unset;\n                  left: unset;\n                  height: unset;\n                  width: unset;\n                  background-color: unset;\n                  border-radius: unset;\n\n                  // Custom\n                  color: var(--tool-color);\n                  font-family: 'uicons-regular-rounded';\n                  font-weight: 300;\n                  font-size: large;\n                  content: '\\f35d';\n                  padding-inline-end: 10px !important;\n\n                  // padding-left: 10px;\n                }\n\n                &.rct-tree-item-button-isFolder {\n                  &::after {\n                    display: none;\n                  }\n\n                  &.rct-tree-item-button-expanded {\n                    &::before {\n                      font-family: 'uicons-regular-rounded';\n                      font-weight: 300;\n                      font-size: large;\n                      content: '\\f1de';\n                    }\n                  }\n\n                  &::before {\n                    font-family: 'uicons-regular-rounded';\n                    font-weight: 300;\n                    font-size: large;\n                    content: '\\f1e6';\n                  }\n                }\n              }\n\n              .rct-tree-item-button-focused {\n                background-color: var(--selected-transparent);\n              }\n\n              .rct-tree-item-button-expanded {\n                background-color: var(--selected-bgcolor);\n                color: hsla(var(--app-text-color), 1);\n                font-weight: 700;\n\n                &:hover {\n                  background-color: var(--selected-hover-bgcolor);\n                }\n\n                &:active {\n                  background-color: var(--selected-active-bgcolor);\n                }\n              }\n\n              .rct-tree-item-arrow {\n                display: none;\n              }\n            }\n\n            [role='group'] {\n              height: fit-content;\n              // padding-top: 10px;\n              padding-inline-start: 20px;\n            }\n          }\n        }\n      }\n    }\n\n    .instruction-p {\n      color: hsla(var(--app-text-color), 0.6);\n      font-size: smaller;\n      .button-text {\n        background-color: var(--selected-bgcolor);\n        padding: 2px 6px;\n        border-radius: 15px;\n      }\n    }\n  }\n}\n\n@keyframes tooltip {\n  from {\n    transform: scale(0.95);\n    opacity: 0%;\n    box-shadow: 0px 1px 3px #00000000;\n  }\n\n  to {\n    transform: scale(1);\n    opacity: 100%;\n    box-shadow: 0px 1px 3px #0000002a;\n  }\n}\n"
  },
  {
    "path": "src/renderer/components/FilesSidebar/FileSystem.tsx",
    "content": "/* eslint-disable import/named */\nimport ErrorModal from '@components/common/Modals/ErrorModal';\nimport { useGeneralContext } from '@components/GeneralContext';\nimport React, { SetStateAction, useEffect, useState } from 'react';\nimport {\n  Tree,\n  ControlledTreeEnvironment,\n  DraggingPositionItem,\n  TreeItem,\n  DraggingPositionBetweenItems,\n  TreeItemIndex,\n} from 'react-complex-tree';\nimport './FileSystem.scss';\nimport {\n  draggedToTheSameParent,\n  updateItemsPosition,\n  changeItemPath,\n  generateStateWithNewFolder,\n  newFolderName,\n  generateStateWithNewFile,\n  newFileName,\n  itemExistsInParent,\n  getFileNameFromPath,\n  deleteItemFromItsPreviousParent,\n  getParent,\n} from './FileSystemHelpers';\nimport { MathTreeItem, TreeItemsObj } from './types';\nimport { useTranslation } from 'react-i18next';\n\ntype receivedProps = { filesPath: string; root: SetStateAction<TreeItemsObj> };\ndeclare global {\n  interface Window {\n    api: any;\n  }\n}\nfunction FileSystem() {\n  const { t } = useTranslation();\n  const { setSelectedFile } = useGeneralContext();\n\n  const [items, setItems] = useState<TreeItemsObj>({\n    root: {\n      index: 'root',\n      data: '',\n      path: '',\n    },\n  });\n\n  const [errorModalContent, setErrorModalContent] = useState('');\n  const [errorModalOpen, setErrorModalOpen] = useState(false);\n  const [expandedItems, setExpandedItems] = useState([]);\n  const [selectedItems, setSelectedItems] = useState([]);\n  const [selectedDirectory, setSelectedDirectory] =\n    useState<TreeItemIndex>('root');\n  const [focusedItem, setFocusedItem] = useState<TreeItemIndex>(-1);\n\n  useEffect(() => {\n    window.api.getNotebooks();\n  }, [items]);\n\n  useEffect(() => {\n    window.api.receive('gotNotebooks', (data: receivedProps) => {\n      setItems(data.root);\n    });\n  }, []);\n\n  const handleOnDrop = (\n    draggedItems: TreeItem[],\n    target: DraggingPositionItem | DraggingPositionBetweenItems,\n  ) => {\n    setItems((prev) => {\n      // Handle D&D intentionally only for one item\n      const draggedItem = draggedItems[0];\n      if (draggedToTheSameParent(prev, draggedItem, target)) return prev;\n      let dest: TreeItemIndex = '';\n      if (\n        'targetItem' in target &&\n        ((target as DraggingPositionItem | DraggingPositionBetweenItems)\n          .targetType !== 'item' ||\n          prev[target.targetItem].isFolder)\n      ) {\n        dest = target.targetItem;\n      } else {\n        dest = target.parentItem;\n      }\n      if (dest) {\n        for (const item of items[dest].children) {\n          if (\n            getFileNameFromPath(item as string) === draggedItem.data &&\n            items[item].isFolder === draggedItem.isFolder\n          ) {\n            setErrorModalContent(t('Modal 5'));\n            setErrorModalOpen(true);\n            return prev;\n          }\n        }\n      }\n      return updateItemsPosition(prev, draggedItem, target);\n    });\n  };\n\n  const addFolder = () => {\n    if (itemExistsInParent(newFolderName, selectedDirectory, items, true)) {\n      setErrorModalContent(t('Modal 3'));\n      setErrorModalOpen(true);\n      return;\n    }\n    setItems((prev) => generateStateWithNewFolder(prev, selectedDirectory));\n  };\n\n  const addFile = () => {\n    if (itemExistsInParent(newFileName, selectedDirectory, items, false)) {\n      setErrorModalContent(t('Modal 2'));\n      setErrorModalOpen(true);\n      return;\n    }\n    setItems((prev) => generateStateWithNewFile(prev, selectedDirectory));\n  };\n\n  const handleRenameItem = (item: MathTreeItem, name: string): void => {\n    if (\n      itemExistsInParent(\n        name,\n        getParent(items, item.index).index,\n        items,\n        item.isFolder,\n      )\n    ) {\n      setErrorModalContent(t('Modal 4'));\n      setErrorModalOpen(true);\n    } else {\n      setItems((prev) => {\n        let newPath: string;\n        const oldPath = item.index;\n\n        if (item.isFolder) {\n          const split = item.path.split('\\\\');\n          split.pop();\n          split.push(name);\n          newPath = split.join('\\\\');\n        } else {\n          const index = item.path.length - (item.data + '.json').length;\n          const dirName = item.path.slice(0, index);\n          newPath = dirName + name + '.json';\n        }\n\n        let newItems = { ...prev };\n\n        newItems = changeItemPath(newItems, item, newPath);\n\n        for (const [, value] of Object.entries(newItems)) {\n          const mathTreeItem = value as MathTreeItem;\n          if (mathTreeItem.children.includes(oldPath)) {\n            mathTreeItem.children = mathTreeItem.children.filter(\n              (child) => child !== oldPath,\n            );\n            mathTreeItem.children.push(newPath);\n          }\n        }\n\n        return newItems;\n      });\n    }\n  };\n\n  const handleClickedOutsideItem = (\n    event: React.MouseEvent<HTMLDivElement, MouseEvent>,\n  ) => {\n    const target = event.target as HTMLElement;\n    if (target.classList.contains('rct-tree-items-container')) {\n      setSelectedDirectory('root');\n      setFocusedItem(-1);\n      setSelectedItems([]);\n      setExpandedItems([]);\n    }\n  };\n\n  const handleDeleteItem = (event: React.KeyboardEvent<HTMLDivElement>) => {\n    if (event.key === 'Delete' && focusedItem != -1) {\n      window.api.delete(focusedItem, items[focusedItem].isFolder);\n      setItems((prev) => {\n        const newItems = { ...prev };\n        const item = newItems[focusedItem];\n        deleteItemFromItsPreviousParent(newItems, item);\n        if (item.isFolder) {\n          for (const [key] of Object.entries(newItems)) {\n            if (key.startsWith(focusedItem as string)) {\n              delete newItems[key];\n            }\n          }\n        }\n        return newItems;\n      });\n      setFocusedItem(-1);\n      setSelectedDirectory('root');\n    }\n  };\n\n  return (\n    <div className='file-system' onKeyUp={handleDeleteItem}>\n      <div className='file-system-header'>\n        <span\n          data-tooltip={t('Notebooks Tooltip')}\n          className='file-system-header-title'\n          onDoubleClick={() => window.api.openFiles()}\n        >\n          {t('My Notebooks')}\n        </span>\n        <div className='file-system-header-buttons'>\n          <button onClick={addFolder} data-tooltip={t('New Folder')}>\n            <i className='fi fi-rr-add-folder' />\n          </button>\n          <button onClick={addFile} data-tooltip={t('New File')}>\n            <i className='fi-rr-add-document' />\n          </button>\n        </div>\n      </div>\n      <div className='files-tree-container' onClick={handleClickedOutsideItem}>\n        {/* <button onClick={() => console.table(items)}>X</button> */}\n        <ControlledTreeEnvironment\n          items={items}\n          canDragAndDrop={true}\n          canReorderItems={true}\n          canDropOnFolder={true}\n          canDropOnNonFolder={true}\n          getItemTitle={(item) => item.data}\n          canSearch={false}\n          keyboardBindings={{ renameItem: ['shift+R'] }}\n          viewState={{\n            ['fileSystem']: {\n              focusedItem,\n              expandedItems,\n              selectedItems,\n            },\n          }}\n          onDrop={handleOnDrop}\n          onFocusItem={(item) => {\n            const mathTreeItem = item as MathTreeItem;\n            setFocusedItem(mathTreeItem.index);\n            item.isFolder\n              ? setSelectedDirectory(mathTreeItem.index)\n              : setSelectedFile(mathTreeItem.path);\n          }}\n          onExpandItem={(item) =>\n            setExpandedItems([...expandedItems, item.index])\n          }\n          onCollapseItem={(item) =>\n            setExpandedItems(\n              expandedItems.filter(\n                (expandedItemIndex) => expandedItemIndex !== item.index,\n              ),\n            )\n          }\n          onSelectItems={setSelectedItems}\n          onRenameItem={handleRenameItem}\n        >\n          <Tree treeId='fileSystem' rootItem='root' treeLabel='File System' />\n        </ControlledTreeEnvironment>\n        <div>\n          <p className='instruction-p'>\n            {t('Press')} <span className='button-text'>Delete</span>{' '}\n            {t('Delete Item')}\n          </p>\n          <p className='instruction-p'>\n            {t('Press')} <span className='button-text'>Shift+R</span>{' '}\n            {t('Rename Item')}\n          </p>\n        </div>\n      </div>\n      <ErrorModal\n        open={errorModalOpen}\n        onClose={() => setErrorModalOpen(false)}\n      >\n        {errorModalContent}\n      </ErrorModal>\n    </div>\n  );\n}\n\nexport default FileSystem;\n"
  },
  {
    "path": "src/renderer/components/FilesSidebar/FileSystemHelpers.ts",
    "content": "/* eslint-disable import/named */\nimport {\n  TreeItem,\n  DraggingPositionItem,\n  DraggingPositionBetweenItems,\n  TreeItemIndex,\n} from 'react-complex-tree';\nimport { TreeItemsObj, MathTreeItem } from './types';\n\nexport const draggedToTheSameParent = (\n  prev: TreeItemsObj,\n  item: TreeItem,\n  target: DraggingPositionItem | DraggingPositionBetweenItems,\n): boolean => {\n  let draggedToSameParent;\n\n  if (target.targetType === \"item\" && prev[target.targetItem].isFolder) {\n    draggedToSameParent = prev[target.targetItem].children.includes(item.index);\n  } else {\n    draggedToSameParent = prev[target.parentItem].children.includes(item.index);\n  }\n\n  return draggedToSameParent;\n};\n\nexport const changeItemPath = (prev: TreeItemsObj, item: MathTreeItem, newPath: string) => { \n  const oldPath = item.path;\n\n  window.api.move(oldPath, newPath)\n\n  const { [oldPath]: _, ...rest } = prev;\n  \n  const newState = {\n    ...rest,\n    [newPath]: {\n      ...item,\n      index: newPath,\n      path: newPath,\n    },\n  }\n\n  return newState;\n};\n\nexport const addItemToNewParent = (\n  target: DraggingPositionItem | DraggingPositionBetweenItems,\n  prev: TreeItemsObj,\n  item: MathTreeItem,\n) => {\n  if (target.targetType != 'item') {\n    const newPath = prev[target.parentItem].path +\n    '\\\\' +\n    item.data +\n    (item.isFolder ? '' : '.json');\n    prev = changeItemPath(prev, item, newPath);\n    prev[target.parentItem].children.push(newPath);\n  } else {\n    if (prev[target.targetItem].isFolder) {\n      const newPath = prev[target.targetItem].path +\n      '\\\\' +\n      item.data +\n      (item.isFolder ? '' : '.json');\n      prev = changeItemPath(prev, item, newPath);\n      prev[target.targetItem].children.push(newPath);\n    } else {\n      for (const [, value] of Object.entries(prev)) {\n        const mathTreeItem = value as MathTreeItem;\n\n        if (mathTreeItem.children.includes(target.targetItem)) {\n          const newPath = mathTreeItem.path +\n          '\\\\' +\n          item.data +\n          (item.isFolder ? '' : '.json');\n          prev = changeItemPath(prev, item, newPath);\n          mathTreeItem.children.push(newPath);\n        }\n      }\n    }\n  }\n  return prev;\n};\n\nexport const updateItemsPosition = (\n  prev: TreeItemsObj,\n  item: TreeItem,\n  target: DraggingPositionItem | DraggingPositionBetweenItems,\n) => {\n  deleteItemFromItsPreviousParent(prev, item);\n  if ((target as DraggingPositionItem).targetItem == 'root') return prev;\n  return addItemToNewParent(target, prev, item as MathTreeItem);\n};\n\nexport const deleteItemFromItsPreviousParent = (\n  prev: TreeItemsObj,\n  item: TreeItem,\n) => {\n  for (const [, value] of Object.entries(prev)) {\n    const mathItemTree = value as MathTreeItem;\n    if (mathItemTree.children.includes(item.index)) {\n      mathItemTree.children = mathItemTree.children.filter(\n        (child) => child !== item.index,\n      );\n    }\n  }\n};\n\nexport const newFolderName = 'New Folder';\n\nexport const generateStateWithNewFolder = (\n  prev: TreeItemsObj,\n  parentIndex: TreeItemIndex,\n) => {\n  let parentValue;\n  let parentKey;\n\n  if (parentIndex != 'root') {\n    parentValue = prev[parentIndex];\n    parentKey = parentIndex;\n  } else {\n    parentValue = prev['root'];\n    parentKey = 'root';\n  }\n\n  // TODO: format \\\\ and / correctly\n  const newFolderPath = parentValue.path + '\\\\' + newFolderName;\n  parentValue.children.push(newFolderPath);\n\n  const newState = {\n    ...prev,\n    [parentKey]: parentValue,\n    [newFolderPath]: {\n      index: newFolderPath,\n      data: newFolderName,\n      children: [] as TreeItemIndex[],\n      path: newFolderPath,\n      isFolder: true,\n    },\n  };\n\n  window.api.newFolder(newFolderPath);\n\n  return newState;\n};\n\nexport const newFileName = 'New File';\n\nexport const generateStateWithNewFile = (\n  prev: TreeItemsObj,\n  parentIndex: TreeItemIndex,\n) => {\n  let parentValue;\n  let parentKey;\n\n  if (parentIndex != 'root') {\n    parentValue = prev[parentIndex];\n    parentKey = parentIndex;\n  } else {\n    parentValue = prev['root'];\n    parentKey = 'root';\n  }\n\n  // TODO: format \\\\ and / correctly\n  const newFilePath = parentValue.path + '\\\\' + newFileName + '.json';\n  parentValue.children.push(newFilePath);\n\n  const newState = {\n    ...prev,\n    [parentKey]: parentValue,\n    [newFilePath]: {\n      index: newFilePath,\n      data: newFileName,\n      children: [] as Array<any>,\n      path: newFilePath,\n      isFolder: false,\n    },\n  };\n\n  window.api.newFile(newFilePath);\n\n  return newState;\n};\n\nexport function itemExistsInParent(\n  name: string,\n  parent: TreeItemIndex,\n  items: TreeItemsObj,\n  folder: boolean,\n): boolean {\n  const parentItem = items[parent];\n  if (!parentItem || !parentItem.children) {\n    return false; // the parent directory does not exist or is not a folder\n  }\n\n  for (const childIndex of parentItem.children) {\n    const childItem = items[childIndex];\n    if (getFileNameFromPath(childItem.path) === name) {\n      // if the name matches, check if the item is a folder or a file\n      return folder ? childItem.isFolder === true : !childItem.isFolder;\n    }\n  }\n\n  return false; // did not find a matching item\n}\n\nexport const getFileNameFromPath = (path: string) => {\n  // TODO: format \\\\ and / correctly\n  return path.split('\\\\').pop().split('.')[0];\n}\n\nexport const getParent = (items: TreeItemsObj, childIndex: TreeItemIndex) => {\n  for (const [, value] of Object.entries(items)) {\n    const mathItemTree = value as MathTreeItem;\n    if (mathItemTree.children.includes(childIndex)) {\n      return mathItemTree;\n    }\n  }\n}\n"
  },
  {
    "path": "src/renderer/components/FilesSidebar/FilesSidebar.scss",
    "content": ".files-sidebar {\n  transition: 0.2s;\n  display: flex;\n  flex-direction: row;\n  width: 45px;\n  min-width: 45px;\n  max-width: 45px;\n  gap: 10px;\n\n  .basic {\n    transition: 0.2s;\n    height: 100%;\n    display: flex;\n    flex-direction: column;\n    direction: var(--app-direction);\n    justify-content: space-between;\n    align-items: flex-start;\n\n    section {\n      display: flex;\n      flex-direction: column;\n      direction: var(--app-direction);\n      align-items: flex-start;\n      gap: 8px;\n      transition: 0.2s;\n\n      .sidebar-button {\n        transition: 0.2s;\n        background-color: transparent;\n        width: 45px;\n        height: 45px;\n        border-radius: 15px;\n        cursor: default;\n\n        &.open {\n          background-color: var(--page-border);\n\n          .fi {\n            color: var(--tool-color);\n          }\n        }\n\n        &:hover::after {\n          content: attr(data-tooltip);\n          color: hsla(var(--app-text-color), 1);\n          min-width: 95px;\n          position: fixed;\n          margin-inline-start: 170px;\n          z-index: 1000;\n          padding: 6px 10px 6px 10px;\n          background-color: var(--button-bgcolor);\n          text-shadow: none;\n          border: 1px solid var(--page-border);\n          border-radius: 6px;\n          opacity: 0%;\n          animation: tooltip 0.1s ease-in-out 0.3s forwards;\n        }\n\n        &:active::after {\n          display: none;\n        }\n\n        &:hover {\n          .fi {\n            color: var(--tool-color);\n          }\n        }\n\n        &:active {\n          transform: scale(0.9);\n        }\n\n        .fi {\n          transition: 0.2s color;\n          margin: auto;\n          font-size: 22px;\n          color: var(--sidebar-button-color);\n          text-shadow: none;\n          padding-top: 3px;\n        }\n      }\n    }\n\n    section#bottom {\n      padding-bottom: 10px;\n    }\n  }\n\n  .extension {\n    width: 45px;\n    height: 100%;\n  }\n\n  &.open {\n    width: 100%;\n    animation: openSidebar 0s linear 0.3s;\n    min-width: 230px;\n    animation-fill-mode: forwards;\n    max-width: 15vw;\n\n    .extension {\n      min-width: 210px;\n      max-width: 15vw;\n      width: 100%;\n    }\n  }\n}\n\n@keyframes openSidebar {\n  from {\n    min-width: 230px;\n  }\n\n  to {\n    min-width: max-content;\n  }\n}\n\n@keyframes tooltip {\n  from {\n    transform: scale(0.95);\n    opacity: 0%;\n    box-shadow: 0px 1px 3px #00000000;\n  }\n\n  to {\n    transform: scale(1);\n    opacity: 100%;\n    box-shadow: 0px 1px 3px #0000002a;\n  }\n}\n"
  },
  {
    "path": "src/renderer/components/FilesSidebar/FilesSidebar.tsx",
    "content": "import React from 'react';\nimport './FilesSidebar.scss';\nimport SidebarButton from './SidebarButton';\nimport FileSystem from './FileSystem';\nimport { useKBar } from 'kbar';\nimport { useGeneralContext } from '@components/GeneralContext';\nimport { useTranslation } from 'react-i18next';\n\nconst FilesSidebar = () => {\n  const { t, i18n } = useTranslation();\n\n  const { query } = useKBar();\n  const {\n    setIsMathSidebarOpen,\n    setIsFilesSidebarOpen,\n    isMathSidebarOpen,\n    isFilesSidebarOpen,\n  } = useGeneralContext();\n\n  const handleOnClickFiles = () => {\n    setIsFilesSidebarOpen((isFilesSidebarOpen: boolean) => !isFilesSidebarOpen);\n  };\n\n  const handleOnClickMathPanel = () => {\n    setIsMathSidebarOpen((isMathSidebarOpen: boolean) => !isMathSidebarOpen);\n  };\n\n  return (\n    <div className={`files-sidebar${isFilesSidebarOpen ? ' open' : ''}`}>\n      <div className='basic'>\n        <section id='top'>\n          <SidebarButton\n            title={t('My Notebooks')}\n            buttonType='files'\n            state={isFilesSidebarOpen}\n            icon='notebook'\n            onClick={handleOnClickFiles}\n          />\n          <SidebarButton\n            title={t('Command Bar')}\n            buttonType='search'\n            icon='terminal'\n            onClick={() => query.toggle()}\n          />\n        </section>\n        <section id='bottom'>\n          <SidebarButton\n            title={t('Math Panel')}\n            buttonType='mathPanel'\n            state={isMathSidebarOpen}\n            icon='calculator'\n            onClick={handleOnClickMathPanel}\n          />\n          <SidebarButton\n            title={t('Archive')}\n            buttonType='archive'\n            icon='archive'\n          />\n        </section>\n      </div>\n      {isFilesSidebarOpen && (\n        <section className='extension'>\n          <FileSystem />\n        </section>\n      )}\n    </div>\n  );\n};\n\nexport default FilesSidebar;\n"
  },
  {
    "path": "src/renderer/components/FilesSidebar/SidebarButton.tsx",
    "content": "import React from 'react';\nimport '../Application.scss';\nimport './FilesSidebar.scss';\n\ntype SidebarButtonProps = {\n  title: string;\n  state?: boolean;\n  buttonType: string;\n  icon?: string;\n  onClick?: React.MouseEventHandler<HTMLButtonElement>;\n};\n\nconst SidebarButton = ({\n  buttonType,\n  state,\n  title,\n  icon,\n  onClick,\n}: SidebarButtonProps) => {\n  const iconName = `fi fi-rr-${icon}`\n  return (\n    <div>\n      <button\n        data-tooltip={title}\n        className={'sidebar-button' + (state ? ' open' : '')}\n        id={buttonType}\n        onClick={onClick}\n      >\n        <i className={iconName}></i>\n      </button>\n    </div>\n  );\n};\n\nexport default SidebarButton;\n"
  },
  {
    "path": "src/renderer/components/FilesSidebar/types.ts",
    "content": "// eslint-disable-next-line import/named\nimport { TreeItem } from 'react-complex-tree';\n\nexport type MathTreeItem = {\n  path: string;\n} & TreeItem;\n\nexport type TreeItemsObj = {\n  [key: string]: MathTreeItem;\n};\n"
  },
  {
    "path": "src/renderer/components/Fonts.css",
    "content": "@import \"../../../node_modules/computer-modern/cmu-serif.css\";\n\n@font-face {\n    font-family: 'Rubik2';\n    src: url('../../../assets/webfonts/Rubik-VariableFont_wght.woff2') format('woff2-variations');\n    font-weight: 100 900;\n}\n\n@font-face {\n    font-family: 'NotoSansArabic';\n    src: url('../../../assets/webfonts/NotoSansArabic-VariableFont_wght.woff2') format('woff2-variations');\n    font-weight: 100 900;\n}"
  },
  {
    "path": "src/renderer/components/GeneralContext.tsx",
    "content": "import React, {\n  createContext,\n  PropsWithChildren,\n  useContext,\n  useEffect,\n  useState,\n} from 'react';\nimport { newWidgetRequest } from '@renderer/common/types';\nimport i18n from '@common/i18n';\nimport { Action, KBarProvider } from 'kbar';\n\nconst GeneralContext = createContext(null);\n\nfunction GeneralContextProvider({ children }: PropsWithChildren) {\n  // Needs to reordered properly\n  const getDefaultLang = () => {\n    return localStorage.getItem('language') ? localStorage.getItem('language') : 'en';\n  }\n\n  const [saveRequest, setSaveRequest] = useState({ cmd: '' });\n  const [clearPageRequest, setClearPageRequest] = useState({ cmd: '' });\n  const [newWidgetRequest, setNewWidgetRequest] = useState<newWidgetRequest>();\n  const [selectedFile, setSelectedFile] = useState<string>();\n  const [currentFileTags, setCurrentFileTags] = useState<string[]>([]);\n  const [isFilesSidebarOpen, setIsFilesSidebarOpen] = useState(false);\n  const [isMathSidebarOpen, setIsMathSidebarOpen] = useState(false);\n  const [isRtl, setIsRtl] = useState(true);\n  const [language, setLanguage] = useState(getDefaultLang());\n  const [darkTheme, setDarkTheme] = useState(true);\n  const [colorTheme, setColorTheme] = useState('');\n  const [currentOS, setCurrentOS] = useState('');\n\n  const setColor = (name: string, hue: number) => {\n    localStorage.setItem('color', name);\n    document.documentElement.style.setProperty('--theme-hue', hue.toString());\n  };\n\n  const setLang = (language: string) => {\n    i18n.changeLanguage(language);\n    setLanguage(language);\n\n    localStorage.setItem('language', language);\n    if (isRtlLang(language)) {\n      document.querySelector('#main-app').classList.add('rtl');\n    } else {\n      document.querySelector('#main-app').classList.remove('rtl');\n    }\n  };\n\n  const isRtlLang = (language: string) => {\n    const rtlLanguages = ['he', 'ar', 'ur'];\n    return rtlLanguages.includes(language);\n  };\n\n  const setTheme = (theme: number) => {\n    localStorage.setItem('dark-mode', theme.toString());\n    switch (theme) {\n      case 0:\n        document.body.classList.remove('dark-mode');\n        break;\n\n      case 1:\n        document.body.classList.add('dark-mode');\n        break;\n    }\n  };\n\n  const actions: Action[] = [\n    {\n      id: 'preferences',\n      name: i18n.t('Preferences'),\n    },\n    {\n      id: 'language',\n      name: i18n.t('Language'),\n      parent: 'preferences',\n    },\n    {\n      id: 'theme',\n      name: i18n.t('Theme'),\n      parent: 'preferences',\n    },\n    {\n      id: 'color',\n      name: i18n.t('Color'),\n      parent: 'preferences',\n    },\n    {\n      id: 'arabic',\n      name: i18n.t('Arabic'),\n      perform: () => {\n        setLang('ar');\n      },\n      parent: 'language',\n    },\n    {\n      id: 'english',\n      name: i18n.t('English'),\n      perform: () => {\n        setLang('en');\n      },\n      parent: 'language',\n    },\n    {\n      id: 'hebrew',\n      name: i18n.t('Hebrew'),\n      perform: () => {\n        setLang('he');\n      },\n      parent: 'language',\n    },\n    {\n      id: 'hindi',\n      name: i18n.t('Hindi'),\n      perform: () => {\n        setLang('hi');\n      },\n      parent: 'language',\n    },\n    {\n      id: 'mandarin Chinese',\n      name: i18n.t('Mandarin Chinese'),\n      perform: () => {\n        setLang('zh');\n      },\n      parent: 'language',\n    },\n    {\n      id: 'french',\n      name: i18n.t('French'),\n      perform: () => {\n        setLang('fr');\n      },\n      parent: 'language',\n    },\n    {\n      id: 'russian',\n      name: i18n.t('Russian'),\n      perform: () => {\n        setLang('ru');\n      },\n      parent: 'language',\n    },\n    {\n      id: 'spanish',\n      name: i18n.t('Spanish'),\n      perform: () => {\n        setLang('es');\n      },\n      parent: 'language',\n    },\n    {\n      id: 'blue',\n      name: i18n.t('Blue'),\n      perform: () => {\n        setColor('blue', 210);\n      },\n      parent: 'color',\n    },\n    {\n      id: 'pink',\n      name: i18n.t('Pink'),\n      perform: () => {\n        setColor('pink', 300);\n      },\n      parent: 'color',\n    },\n    {\n      id: 'yellow',\n      name: i18n.t('Yellow'),\n      perform: () => {\n        setColor('yellow', 35);\n      },\n      parent: 'color',\n    },\n    {\n      id: 'purple',\n      name: i18n.t('Purple'),\n      perform: () => {\n        setColor('purple', 250);\n      },\n      parent: 'color',\n    },\n    {\n      id: 'red',\n      name: i18n.t('Red'),\n      perform: () => {\n        setColor('red', 0);\n      },\n      parent: 'color',\n    },\n    {\n      id: 'green',\n      name: i18n.t('Green'),\n      perform: () => {\n        setColor('green', 140);\n      },\n      parent: 'color',\n    },\n    {\n      id: 'light',\n      name: i18n.t('Light'),\n      perform: () => {\n        setTheme(0);\n      },\n      parent: 'theme',\n    },\n    {\n      id: 'dark',\n      name: i18n.t('Dark'),\n      perform: () => {\n        setTheme(1);\n      },\n      parent: 'theme',\n    },\n  ];\n\n  useEffect(() => {\n    const useDarkTheme = parseInt(localStorage.getItem('dark-mode'));\n    if (isNaN(useDarkTheme)) {\n      setDarkTheme(true);\n    } else if (useDarkTheme == 1) {\n      setDarkTheme(true);\n    } else if (useDarkTheme == 0) {\n      setDarkTheme(false);\n    }\n\n    if (!localStorage.getItem('all-tags'))\n      localStorage.setItem('all-tags', JSON.stringify([]));\n\n    if (!localStorage.getItem('color')) localStorage.setItem('color', 'blue');\n    setColorTheme(localStorage.getItem('color'));\n\n    if (!localStorage.getItem('language'))\n      localStorage.setItem('language', 'en');\n    setLanguage(localStorage.getItem('language'));\n  }, []);\n\n  useEffect(() => {\n    if (darkTheme) {\n      setTheme(1);\n    } else {\n      setTheme(0);\n    }\n  }, [darkTheme]);\n\n  useEffect(() => {\n    setLang(language);\n  }, [language]);\n\n  useEffect(() => {\n    switch (colorTheme) {\n      case 'red':\n        setColor('red', 0);\n        break;\n      case 'yellow':\n        setColor('yellow', 35);\n        break;\n      case 'green':\n        setColor('green', 140);\n        break;\n      case 'blue':\n        setColor('blue', 210);\n        break;\n      case 'purple':\n        setColor('purple', 250);\n        break;\n      case 'pink':\n        setColor('pink', 300);\n        break;\n\n      default:\n        break;\n    }\n  }, [colorTheme]);\n\n  useEffect(() => {\n    window.api.getOS();\n\n    window.api.receive('gotOS', (data: string) => {\n      setCurrentOS(data);\n    });\n  }, []);\n\n  return (\n    <GeneralContext.Provider\n      value={{\n        newWidgetRequest,\n        setNewWidgetRequest,\n        clearPageRequest,\n        setClearPageRequest,\n        selectedFile,\n        setSelectedFile,\n        saveRequest,\n        setSaveRequest,\n        currentFileTags,\n        setCurrentFileTags,\n        isMathSidebarOpen,\n        setIsMathSidebarOpen,\n        isFilesSidebarOpen,\n        setIsFilesSidebarOpen,\n        isRtl,\n        setIsRtl,\n        language,\n        setLang,\n        darkTheme,\n        setTheme,\n        colorTheme,\n        setColor,\n        actions,\n        currentOS,\n      }}\n    >\n      <KBarProvider\n        actions={actions}\n        options={{ toggleShortcut: '$mod+Shift+p' }}\n      >\n        {children}\n      </KBarProvider>\n    </GeneralContext.Provider>\n  );\n}\n\nfunction useGeneralContext() {\n  const context = useContext(GeneralContext);\n  if (context === undefined) {\n    throw new Error('useMyContext must be used within a MyContextProvider');\n  }\n  return context;\n}\n\nexport { GeneralContextProvider, useGeneralContext };\n"
  },
  {
    "path": "src/renderer/components/Header/AddTag.tsx",
    "content": "import React, { useEffect, useState } from 'react';\nimport { TagProps } from './Tag';\nimport { useGeneralContext } from '@components/GeneralContext';\nimport { useTranslation } from 'react-i18next';\n\nconst AddTag = () => {\n  const { t, i18n } = useTranslation();\n\n  const [clickState, setClickState] = useState(false);\n  const [currentValue, setCurrentValue] = useState('');\n  const [savedValue, setSavedValue] = useState('');\n  const { setCurrentFileTags, currentFileTags } = useGeneralContext();\n\n  const addTagStyle = {\n    backgroundColor: 'unset',\n    height: '14px',\n    border: 'none',\n    color: 'unset',\n    fontFamily: 'unset',\n    fontSize: 'unset',\n    minWidth: `79px`,\n    width: `${currentValue.length * 9 + 10}px`,\n    outline: 'none',\n  };\n\n  const handleKeyDown = (e: React.KeyboardEvent) => {\n    if (e.key === 'Enter') {\n      setSavedValue(currentValue);\n      setClickState(false);\n    }\n  };\n\n  useEffect(() => {\n    if (!localStorage.getItem('all-tags'))\n      localStorage.setItem('all-tags', JSON.stringify([]));\n    else {\n      const allTags: TagProps[] = JSON.parse(localStorage.getItem('all-tags'));\n\n      const createdTag: TagProps = {\n        text: savedValue,\n        color: Math.floor(Math.random() * 359).toString(),\n      };\n\n      if (\n        !allTags.find((tag: TagProps) => tag.text == createdTag.text) &&\n        createdTag.text != ''\n      ) {\n        allTags.push(createdTag);\n      }\n\n      if (\n        !currentFileTags.find((tag: TagProps) => tag.text == createdTag.text) &&\n        createdTag.text != ''\n      ) {\n        setCurrentFileTags([...currentFileTags, createdTag.text].flat())\n      }\n\n      localStorage.setItem('all-tags', JSON.stringify(allTags));\n    }\n  }, [savedValue]);\n\n  useEffect(() => {\n    setCurrentValue('');\n  }, [clickState]);\n\n  const content = clickState ? (\n    <input\n      autoFocus={true}\n      type='text'\n      title=''\n      placeholder={t(\"Add Tag\")}\n      className='tag-text-adding'\n      onChange={(e) => setCurrentValue(e.target.value)}\n      onKeyDown={handleKeyDown}\n      style={addTagStyle}\n    />\n  ) : (\n    <>\n      <span className='tag-text'>{t(\"Add Tag\")}</span>\n    </>\n  );\n\n  return (\n    <div className='tag-pill new' onClick={() => setClickState(true)}>\n      {content}\n    </div>\n  );\n};\n\nexport default AddTag;\n"
  },
  {
    "path": "src/renderer/components/Header/FilePath.tsx",
    "content": "import React from 'react';\nimport './Header.scss';\n\ntype FilePathProps = { filePath: string };\n\nconst FilePath = ({ filePath }: FilePathProps) => {\n  const resolvedFilePath = filePath\n    ? filePath.split(/[\\/\\\\]/)\n    : [''];\n  \n  const folderPath = resolvedFilePath.slice(resolvedFilePath.length - 2)[0];\n  const fileName = resolvedFilePath.pop().replace('.json', '');\n\n  return (\n    <div className='filepath'>\n      <span className={`filepath-folder${folderPath == 'files' || fileName == '' ? ' hide': ''}`}>\n        {folderPath == 'files' || fileName == '' ? '' : `${folderPath} /`}\n      </span>\n      <span className='filepath-name'>{fileName}</span>\n    </div>\n  );\n};\n\nexport default FilePath;\n"
  },
  {
    "path": "src/renderer/components/Header/Header.scss",
    "content": "@import '../Theme.scss';\n\n.header {\n  width: calc(100% - 20px);\n  max-width: 100%;\n  align-self: center;\n  padding-top: 5px;\n  height: calc(0% + 45px);\n  display: flex;\n\n  .main-heading {\n    justify-content: space-between;\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n    direction: var(--app-direction);\n    height: 100%;\n    width: 100%;\n\n    .header-content {\n      gap: 10px;\n      display: flex;\n      flex-direction: row;\n      align-items: center;\n      direction: var(--app-direction);\n      height: 100%;\n      max-width: calc(100% - 200px);\n      white-space: nowrap;\n      width: max-content;\n      -webkit-app-region: no-drag;\n\n\n      div {\n        width: max-content;\n        font-weight: 300;\n        color: var(--erwt-heading-color);\n        line-height: 1;\n      }\n\n      .tags {\n        width: max-content;\n        max-width: inherit;\n        display: flex;\n        flex-direction: row;\n        direction: var(--app-direction);\n        padding-inline-start: 5px;\n        gap: 10px;\n      }\n\n      .tag-pill {\n        padding: 3px 12px 3px 12px;\n        display: flex;\n        justify-content: space-between;\n        background-color: var(--pill-bgcolor);\n        border-radius: 5px;\n        transition: 0.1s;\n        height: max-content;\n\n        .tag-action::before {\n          content: \"#\";\n        }\n\n        .tag-content {\n          width: max-content;\n          font-size: 16px;\n          display: flex;\n          gap: 5px;\n          height: 16px;\n        }\n\n        .tag-action {\n          opacity: 70%;\n          width: 16px;\n          font-size: 16px;\n\n          &:hover {\n            cursor: pointer;\n            opacity: 100%;\n          }\n        }\n\n        &:hover {\n          filter: var(--tag-filter);\n\n          .tag-action::before {\n            content: \"X\";\n            font-size: 14px;\n          }\n        }\n\n        &:active {\n          filter: var(--tag-filter);\n        }\n\n        &.new {\n          background-color: var(--pill-bgcolor);\n          font-size: 16px;\n          gap: 5px;\n\n          &::before {\n            opacity: 70%;\n            content: \"+\";\n          }\n\n          &:hover {\n            cursor: pointer;\n            filter: unset;\n            background-color: var(--pill-hover-bgcolor);\n          }\n\n          &:active {\n            cursor: pointer;\n            filter: unset;\n            background-color: var(--pill-active-bgcolor);\n            transform: scale(0.98);\n          }\n        }\n      }\n\n      .filepath {\n        max-width: 80%;\n        font-size: 23px;\n        display: flex;\n        flex-direction: row;\n        direction: var(--app-direction);\n        gap: 6px;\n        padding-bottom: 3px;\n\n        .filepath-name {\n          font-weight: 600;\n\n          &:focus {\n            outline: none;\n          }\n        }\n\n        &-folder.hide {\n          display: none;\n        }\n      }\n\n      #logo {\n        fill: hsla(var(--app-text-color), 1);\n        display: block;\n        width: 45px;\n        height: 55%;\n        filter: var(--logo-filter);\n      }\n\n      .logo {\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        width: 45px;\n        height: 100%;\n      }\n    }\n\n    .header-draggable {\n      height: 100%;\n      width: 100%;\n      -webkit-app-region: drag;\n\n    }\n\n    .header-controls {\n      z-index: 1000;\n      background-color: transparent;\n      height: inherit;\n      -webkit-app-region: no-drag;\n\n      .window-titlebar-controls {\n        height: inherit;\n        position: unset;\n\n        .control {\n          border-radius: 10px;\n          transition: 0.1s;\n          color: var(--app-text-color);\n\n          &:hover{\n            background-color: var(--file-hover-bgcolor);\n            &.close {\n              background: var(--button-danger);\n            }\n          }\n          &:active {\n            transform: scale(0.95);\n          }\n        }\n      }\n    }\n  }\n}"
  },
  {
    "path": "src/renderer/components/Header/Header.tsx",
    "content": "import React, { useEffect, useState } from 'react';\nimport '../Application.scss';\nimport { icons } from '../Icons';\nimport FilePath from './FilePath';\nimport { Tag, TagProps } from './Tag';\nimport AddTag from './AddTag';\nimport WindowControls from '@misc/window/components/WindowControls';\nimport { useGeneralContext } from '@components/GeneralContext';\n\nconst Header = () => {\n  const allTags = JSON.parse(localStorage.getItem('all-tags'));\n  const { selectedFile, currentFileTags, setCurrentFileTags, currentOS } = useGeneralContext();\n  const [currentFilePath, setCurrentFilePath] = useState('');\n\n  useEffect(() => {\n    setCurrentFilePath(selectedFile);\n    setCurrentFileTags([])\n  }, [selectedFile]);\n\n  return (\n    <div className='header'>\n      <div className='main-heading'>\n        <section className='header-content'>\n          <div className='logo'>\n            <img src={icons.logo} id='logo' alt='מתברת' />\n          </div>\n          <FilePath filePath={currentFilePath} />\n          <div className='tags'>\n            {currentFileTags\n              ? currentFileTags.map((tag: string) => {\n                  const foundTag = allTags.find(\n                    (searchTag: TagProps) => searchTag.text == tag,\n                  );\n                  return (\n                    <Tag\n                      key={`tag-${foundTag.text}`}\n                      text={foundTag.text}\n                      color={foundTag.color}\n                    />\n                  );\n                })\n              : null}\n            {currentFilePath ? <AddTag /> : <></>}\n          </div>\n        </section>\n        <section className='header-draggable'></section>\n        <section className='header-controls'>\n          <WindowControls platform={currentOS}></WindowControls>\n        </section>\n      </div>\n    </div>\n  );\n};\n\nexport default Header;\n"
  },
  {
    "path": "src/renderer/components/Header/Tag.tsx",
    "content": "import { useGeneralContext } from '@components/GeneralContext';\nimport React from 'react';\n\nexport type TagProps = {\n  text: string;\n  color: string;\n};\n\nexport const Tag = ({ text, color }: TagProps) => {\n  const { setCurrentFileTags, currentFileTags } = useGeneralContext();\n\n  const handleRemoveTag = () => {\n    setCurrentFileTags(currentFileTags.filter((tag: string) => tag != text));\n\n    //TODO: figure out how to check if tag is not in all of the files\n    \n    // localStorage.setItem(\n    //   'all-tags',\n    //   JSON.stringify(\n    //     JSON.parse(localStorage.getItem('all-tags')).filter(\n    //       (tag: TagProps) => tag.text != text,\n    //     ),\n    //   ),\n    // );\n  };\n\n  return (\n    <div\n      className='tag-pill'\n      style={{\n        backgroundColor: `hsl(${color}, var(--tag-saturation), var(--tag-lightness))`,\n      }}\n    >\n      <span className='tag-action' onClick={handleRemoveTag}></span>\n      <div className='tag-content'>{text}</div>\n    </div>\n  );\n};\n"
  },
  {
    "path": "src/renderer/components/Icons.tsx",
    "content": "const pngLogo = require('@assets/icons/pngLogo.png');\nconst logo = require('@assets/icons/logo.svg');\n\n\nexport const icons = {\n  pngLogo,\n  logo\n};\n"
  },
  {
    "path": "src/renderer/components/MathSidebar/ActionsGroup.tsx",
    "content": "import React from 'react';\nimport '../Application.scss';\nimport './MathSidebar.scss'\n\ntype ActionsGroupProps = { title: string; groupType: string };\nconst ActionsGroup = ({ groupType, title }: ActionsGroupProps) => {\n    return (\n        <section className='actions-group'>\n            <h1 className='actions-group-title' id={groupType}>{title}</h1>\n            <div className='actions-group-content'></div>\n        </section>\n    );\n}\n\nexport default ActionsGroup;\n"
  },
  {
    "path": "src/renderer/components/MathSidebar/MathSidebar.scss",
    "content": "@import '../Theme.scss';\n\n.actions-group {\n    display: none;\n}\n\n.math-sidebar.open{\n    min-width: max-content;\n\n    .actions-group {\n        display: flex;\n        flex-direction: column;\n        gap: 10px;\n    \n        .actions-group-title {\n            width: 100%;\n            margin: 0;\n            color: hsla(var(--app-text-color), 1);\n            font-size: 22px;\n            opacity: 50%;\n        }\n    \n        .actions-group-content{\n            width: 100%;\n            min-height: 100px;\n        }\n    }\n}\n"
  },
  {
    "path": "src/renderer/components/MathSidebar/MathSidebar.tsx",
    "content": "import React, { useEffect, useState } from 'react';\nimport ActionsGroup from './ActionsGroup';\nimport { useGeneralContext } from '@components/GeneralContext';\nimport { useTranslation } from 'react-i18next';\n\nconst MathSidebar = () => {\n  const { t, i18n } = useTranslation();\n  const { isMathSidebarOpen } = useGeneralContext()\n  const [showClass, setShowClass] = useState('');\n\n  useEffect(() => {\n    setShowClass(isMathSidebarOpen);\n  }, [isMathSidebarOpen])\n\n  return <div className={`math-sidebar${showClass ? ' open' : ''}`}>\n    <ActionsGroup title={t(\"Variables\")} groupType='variables'/>\n    <ActionsGroup title={t(\"Functions\")} groupType='functions'/>\n  </div>;\n};\n\nexport default MathSidebar;\n"
  },
  {
    "path": "src/renderer/components/Page/Grid/Blocks/Blocks.scss",
    "content": "@import '../../../Theme.scss';\n@import '../../Page.scss';\n@import '../Grid.scss';\n@import \"/node_modules/mafs/core.css\";\n\n.block-content{\n    transition: 0.2s;\n    width: 100%;\n    display: flex;\n    outline: 1px solid transparent;\n    border-radius: 5px;\n    margin: 3px;\n    direction: var(--app-direction);\n    overflow-y: auto;\n    overflow-x: hidden;\n\n    // Math\n    .math-field-element{\n        --hue: var(--theme-hue);\n        --selection-background-color: var(--math-block-selection-bg);\n        --selection-color: var(--math-block-selection);\n        font-size: 25px;\n        color: hsla(var(--app-text-color), 1);\n        width: 100%;\n        height: 100%;\n        outline: none;\n        display: flex;\n        justify-content: center;\n        background-color: var(--math-block-bgcolor);\n        &::part(content){\n            margin-top: 5px;\n        }\n    }\n\n    // Text\n    .textbox{\n        padding: 10px;\n        color: hsla(var(--app-text-color), 1);\n        width: 100%;\n        height: inherit;\n        overflow-wrap: anywhere !important;\n        font-size: larger;\n\n        p, h1, h2, h3, h4, h5, h6 {\n            &:first-child{\n                margin-top: 0 !important;\n            }\n        }\n\n        [role=\"math\"]{\n            --hue: var(--theme-hue);\n            --selection-background-color: var(--math-block-selection-bg);\n            --selection-color: var(--math-block-selection);\n            font-size: 25px;\n            color: hsla(var(--app-text-color), 1);\n            width: 100%;\n            height: 100%;\n            outline: none;\n            display: flex;\n            justify-content: center;\n            background-color: var(--math-block-bgcolor);\n            &::part(content){\n                margin-top: 5px;\n            }\n        }\n    }\n    \n    // Divider\n    &:has(.pageDivider){\n        background: gray;\n        opacity: 40%;\n        direction: var(--app-direction);\n        margin-right: 0px;\n        max-width: 100%;\n        width: 100%;\n        height: 1px;\n        border: none;\n        transition: 0.2s;\n        align-self: center;\n    }\n\n    // Graph\n    .graph-block-wrapper {\n        width: 100%;\n        height: 100%;\n        display: flex;\n        flex-direction: column-reverse;\n        justify-content: space-between;\n    \n        .math-field-element{\n            border-top: 1px solid var(--tool-hover-bgcolor);\n            height: 50px;\n            min-height: 50px;\n            max-height: max-content;\n            align-items: center;\n            &::part(content){\n                margin-top: unset;\n            }\n        }\n\n        .MafsView {\n            font-family: 'CMU Serif';\n            direction: ltr;\n            --mafs-line-color: var(--page-border);\n            --mafs-bg: var(--page-bgcolor);\n            --mafs-fg: hsla(var(--app-text-color), 1);\n            --mafs-blue: var(--mafs-plot-color);\n\n        }\n    }\n\n    // Draw\n    .draw-applet {\n        width: 100%;\n        height: 100%;\n\n        .t-ljGyqI{\n            border: 1px solid transparent !important;\n            border-radius: 6px !important;\n            width: calc(100% - 27px);\n            height: calc(100% - 6px);\n\n            .tl-positioned{\n                path:last-child{\n                    fill: hsla(var(--app-text-color), 1);\n                    stroke: hsla(var(--app-text-color), 1);    \n                }\n            }\n\n            #tl{\n                --tl-background: var(--math-block-bgcolor); \n            }\n\n            #TD-Tools{\n                --colors-panelContrast: var(--tool-hover-bgcolor);\n                --colors-panel: var(--panel-bgcolor);\n                --colors-hover: var(--tool-hover-bgcolor);\n                --colors-text: hsla(var(--app-text-color), 1);\n            }\n            .c-itYKbw{\n                display: none;\n            }\n            .c-dwQeTN{\n                padding: 0;\n            }\n\n            button {\n                background-color: unset;\n                &:hover{\n                    background-color: unset;\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/renderer/components/Page/Grid/Blocks/DrawBlock.tsx",
    "content": "import { ValueProps, canvasProps } from '@renderer/common/types';\nimport { Tldraw, TldrawApp } from '@tldraw/tldraw';\nimport React, { useEffect, useState } from 'react';\n\nfunction DrawBlockContent({ content, blockStateFunction }: ValueProps) {\n  const [canvasState, setCanvasState] = useState({ shapes: [] });\n\n  useEffect(() => {\n    blockStateFunction(canvasState);\n  }, [canvasState]);\n\n  return (\n    <div className='draw-applet'>\n      <Tldraw\n        autofocus={true}\n        showMenu={false}\n        showMultiplayerMenu={false}\n        showPages={false}\n        showStyles={false}\n        showZoom={false}\n        onMount={(app: TldrawApp) => {\n          // app.setSetting('showGrid', true);\n          app.insertContent(content ? (content as canvasProps) : { shapes: [] });\n          app.zoomToContent();\n        }}\n        onPersist={(app: TldrawApp) => setCanvasState(app.getContent())}\n      />\n    </div>\n  );\n}\n\nexport default DrawBlockContent;\n"
  },
  {
    "path": "src/renderer/components/Page/Grid/Blocks/GraphBlock.tsx",
    "content": "import { Mafs, Coordinates, Plot, Theme } from 'mafs';\nimport React, { useEffect, useRef, useState } from 'react';\n// eslint-disable-next-line import/named\nimport MathView, { MathViewRef } from 'react-math-view';\nimport { parseTex } from 'tex-math-parser';\nimport ML_SHORTCUTS from '@common/shortcuts';\nimport ML_KEYBINDINGS from '@common/keybindings';\nimport { ValueProps } from '@renderer/common/types';\n\nfunction latex2function(latex: string, i: number) {\n  if (latex != '') {\n    try {\n      const parsed = parseTex(String.raw`${latex}`);\n      return parsed.compile().evaluate({ x: i });\n    } catch (error) {\n      return;\n    }\n  }\n}\n\nfunction GraphBlockContent({ content, blockStateFunction }: ValueProps) {\n  const [value, setValue] = useState(content ? (content as string[]) : ['']);\n\n  useEffect(() => {\n    blockStateFunction(value);\n  }, [value]);\n\n  function GraphBlockSetter() {\n    const ref = useRef<MathViewRef>(null);\n\n    return (\n      <MathView\n        ref={ref}\n        value={value[0]}\n        inlineShortcuts={ML_SHORTCUTS}\n        keybindings={ML_KEYBINDINGS}\n        className='math-field-element'\n        onExport={(ref, latex) => latex}\n        onMathFieldBlur={() => {\n          setValue([ref.current?.getValue('latex')]);\n        }}\n        plonkSound={null}\n        keypressSound={null}\n      />\n    );\n  }\n\n  return (\n    <div className='graph-block-wrapper'>\n      <GraphBlockSetter />\n      <Mafs\n        preserveAspectRatio='contain'\n        zoom={{ min: 0.5, max: 2 }}\n        // onClick={\n        //     (point)=> {\n        //         const fixedPoint = {x: point[0], y: point[1]}\n        //         setPoints([...points, <Point key={JSON.stringify(fixedPoint)} x={fixedPoint.x} y={fixedPoint.y} />])\n        //     }\n        // }\n      >\n        <Coordinates.Cartesian />\n        <Plot.OfX\n          y={(x: number) => latex2function(value[0], x)}\n          color={Theme.blue}\n        />\n        {/* {points} */}\n      </Mafs>\n    </div>\n  );\n}\n\nexport default GraphBlockContent;\n\n// TESTS\n// function CreatePolygon() {\n//   const [pointsList, setPointsList] = React.useState([[1,1], [2,2], [3,-2]] as vec.Vector2[]);\n//   const [movePoints, setMovePoints] = React.useState(false);\n\n//   const handleMove = (point, newPoint) =>{\n//     setPointsList([...pointsList.filter((p) => p != point), newPoint])\n//   }\n//   return (\n//     <Mafs\n//       onClick={(point) =>\n//         movePoints\n//           ? setPointsList([...pointsList, point])\n//           : null\n//       }\n//     >\n//       <Coordinates.Cartesian />\n//       <Polygon points={pointsList} color={Theme.blue} />\n\n//       {pointsList.map((point, i) => (\n//         <MovablePoint\n//           key={i}\n//           point={point}\n//           onMove={newPoint => handleMove(point, newPoint)}\n//         />\n//       ))}\n//     </Mafs>\n//   );\n// }"
  },
  {
    "path": "src/renderer/components/Page/Grid/Blocks/MathBlock.tsx",
    "content": "import React, { useEffect, useRef, useState } from 'react';\n// eslint-disable-next-line import/named\nimport MathView, { MathViewRef } from 'react-math-view';\nimport ML_SHORTCUTS from '@common/shortcuts';\nimport ML_KEYBINDINGS from '@common/keybindings';\nimport { ValueProps } from '@renderer/common/types';\n\nfunction MathBlockContent({ content, blockStateFunction }: ValueProps) {\n  const defaultValue = '';\n  const ref = useRef<MathViewRef>(null);\n  const [value, setValue] = useState(defaultValue);\n\n  useEffect(() => {\n    blockStateFunction(value);\n  }, [value]);\n\n  return (\n    <MathView\n      ref={ref}\n      value={content ? content.toString() : defaultValue}\n      className='math-field-element'\n      inlineShortcuts={ML_SHORTCUTS}\n      keybindings={ML_KEYBINDINGS}\n      onChange={() => setValue(ref.current?.getValue())}\n      onExport={(ref, latex) => latex}\n      plonkSound={null}\n      keypressSound={null}\n    />\n  );\n}\n\nexport default MathBlockContent;\n"
  },
  {
    "path": "src/renderer/components/Page/Grid/Blocks/TextBlock.tsx",
    "content": "import React, { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n  createEditor,\n  // eslint-disable-next-line import/named\n  Descendant,\n  Editor,\n  Element as SlateElement,\n  Node as SlateNode,\n  Point,\n  Range,\n  Transforms,\n  // eslint-disable-next-line import/named\n  BaseElement,\n} from 'slate';\nimport { withHistory } from 'slate-history';\nimport { Editable, ReactEditor, Slate, withReact } from 'slate-react';\nimport { ValueProps, canvasProps } from '@renderer/common/types';\nimport { useTranslation } from 'react-i18next';\n// import MathView from 'react-math-view';\n// import ML_KEYBINDINGS from '@common/keybindings';\n// import ML_SHORTCUTS from '@common/shortcuts';\n\ntype BulletedListElement = {\n  type: 'bulleted-list';\n  align?: string;\n  children: Descendant[];\n};\n\ninterface CustomElement extends BaseElement {\n  type?: string;\n  children: Descendant[];\n  }\n\nconst SHORTCUTS = {\n  '*': 'list-item',\n  '-': 'list-item',\n  '+': 'list-item',\n  '>': 'block-quote',\n  '#': 'heading-one',\n  '##': 'heading-two',\n  '###': 'heading-three',\n  '####': 'heading-four',\n  '#####': 'heading-five',\n  '######': 'heading-six',\n  // '$$': 'math-inline',\n  // '---': 'divider',\n};\n\nfunction isDescendant(content: string | string[] | Descendant[] | canvasProps): content is Descendant[] {\n  return (content as Descendant[]) !== undefined;\n}\n\nconst TextBlockContent = ({ content, blockStateFunction }: ValueProps) => {\n  const { t, i18n } = useTranslation();\n  const valueToSet = isDescendant(content)\n    ? content\n    : [{ type: 'paragraph', children: [{ text: '' }] }];\n  const renderElement = useCallback(\n    (\n      props: JSX.IntrinsicAttributes & {\n        attributes: unknown;\n        children: unknown;\n        element: unknown;\n      },\n    ) => <Element {...props} />,\n    [],\n  );\n  const editor = useMemo(\n    () => withShortcuts(withReact(withHistory(createEditor()))),\n    [],\n  );\n\n  const [value, setValue] = useState(valueToSet);\n\n  useEffect(() => {\n    blockStateFunction(value);\n  }, [value]);\n\n  const handleDOMBeforeInput = useCallback(() => {\n    queueMicrotask(() => {\n      const pendingDiffs = ReactEditor.androidPendingDiffs(editor);\n\n      const scheduleFlush = pendingDiffs?.some(({ diff, path }) => {\n        if (!diff.text.endsWith(' ')) {\n          return false;\n        }\n\n        const { text } = SlateNode.leaf(editor, path);\n        const beforeText = text.slice(0, diff.start) + diff.text.slice(0, -1);\n        if (!(beforeText in SHORTCUTS)) {\n          return;\n        }\n\n        const blockEntry = Editor.above(editor, {\n          at: path,\n          match: (n) => SlateElement.isElement(n) && Editor.isBlock(editor, n),\n        });\n        if (!blockEntry) {\n          return false;\n        }\n\n        const [, blockPath] = blockEntry;\n        return Editor.isStart(editor, Editor.start(editor, path), blockPath);\n      });\n\n      if (scheduleFlush) {\n        ReactEditor.androidScheduleFlush(editor);\n      }\n    });\n  }, []);\n\n  return (\n    <Slate\n      editor={editor}\n      value={value}\n      onChange={(currentValue) => setValue(currentValue)}\n    >\n      <Editable\n        spellCheck={false}\n        className='textbox'\n        onDOMBeforeInput={handleDOMBeforeInput}\n        renderElement={renderElement}\n        placeholder={t(\"Text Placeholder\")}\n        autoFocus\n      />\n    </Slate>\n  );\n};\n\nconst withShortcuts = (editor: ReactEditor) => {\n  const { deleteBackward, insertText } = editor;\n\n  editor.insertText = (text) => {\n    const { selection } = editor;\n\n    if (text.endsWith(' ') && selection && Range.isCollapsed(selection)) {\n      const { anchor } = selection;\n      const block = Editor.above(editor, {\n        match: (n) => SlateElement.isElement(n) && Editor.isBlock(editor, n),\n      });\n      const path = block ? block[1] : [];\n      const start = Editor.start(editor, path);\n      const range = { anchor, focus: start };\n      const beforeText = Editor.string(editor, range) + text.slice(0, -1);\n      const type = (SHORTCUTS as any)[beforeText];\n\n      if (type) {\n        Transforms.select(editor, range);\n\n        if (!Range.isCollapsed(range)) {\n          Transforms.delete(editor);\n        }\n\n        const newProperties: Partial<CustomElement> = {\n          type,\n        };\n        Transforms.setNodes<SlateElement>(editor, newProperties, {\n          match: (n) => SlateElement.isElement(n) && Editor.isBlock(editor, n),\n        });\n\n        if (type === 'list-item') {\n          const list: BulletedListElement = {\n            type: 'bulleted-list',\n            children: [],\n          };\n          Transforms.wrapNodes(editor, list, {\n            match: (n) =>\n              !Editor.isEditor(n) &&\n              SlateElement.isElement(n) &&\n              (n as CustomElement).type === 'list-item',\n          });\n        }\n\n        return;\n      }\n    }\n\n    insertText(text);\n  };\n\n  editor.deleteBackward = (...args) => {\n    const { selection } = editor;\n\n    if (selection && Range.isCollapsed(selection)) {\n      const match = Editor.above(editor, {\n        match: (n) => SlateElement.isElement(n) && Editor.isBlock(editor, n),\n      });\n\n      if (match) {\n        const [block, path] = match;\n        const start = Editor.start(editor, path);\n\n        if (\n          !Editor.isEditor(block) &&\n          SlateElement.isElement(block) &&\n          (block as CustomElement).type !== 'paragraph' &&\n          Point.equals(selection.anchor, start)\n        ) {\n          const newProperties: CustomElement = {\n            type: 'paragraph',\n            children: []\n          };\n          Transforms.setNodes(editor, newProperties);\n\n          if ((block as CustomElement).type === 'list-item') {\n            Transforms.unwrapNodes(editor, {\n              match: (n) =>\n                !Editor.isEditor(n) &&\n                SlateElement.isElement(n) &&\n                (n as CustomElement).type === 'bulleted-list',\n              split: true,\n            });\n          }\n\n          return;\n        }\n      }\n\n      deleteBackward(...args);\n    }\n  };\n\n  return editor;\n};\n\nconst Element = ({ attributes, children, element }: any) => {\n  switch (element.type) {\n    case 'block-quote':\n      return <blockquote {...attributes}>{children}</blockquote>;\n    case 'bulleted-list':\n      return <ul {...attributes}>{children}</ul>;\n    case 'heading-one':\n      return <h1 {...attributes}>{children}</h1>;\n    case 'heading-two':\n      return <h2 {...attributes}>{children}</h2>;\n    case 'heading-three':\n      return <h3 {...attributes}>{children}</h3>;\n    case 'heading-four':\n      return <h4 {...attributes}>{children}</h4>;\n    case 'heading-five':\n      return <h5 {...attributes}>{children}</h5>;\n    case 'heading-six':\n      return <h6 {...attributes}>{children}</h6>;\n    case 'list-item':\n      return <li {...attributes}>{children}</li>;\n    // case 'divider':\n    //   return <div {...attributes} contentEditable={true}>\n    //   <hr />\n    //   {children}\n    // </div>;\n    // case 'math-inline':\n    //   return <div {...attributes} contentEditable={true}>\n    //     <MathView\n    //       value='x'\n    //       inlineShortcuts={ML_SHORTCUTS}\n    //       keybindings={ML_KEYBINDINGS}\n    //       onExport={(ref, latex) => latex}\n    //       plonkSound={null}\n    //       keypressSound={null}\n    //     />\n    //   {children}\n    // </div>;\n    default:\n      return <p {...attributes}>{children}</p>;\n  }\n};\n\nexport default TextBlockContent;\n"
  },
  {
    "path": "src/renderer/components/Page/Grid/Grid.scss",
    "content": "@import '../../Theme.scss';\n@import '../Page.scss';\n\n#main-app.rtl .block-remove-button {\n    left: 1px !important;\n    right: unset !important;\n}\n\n\n.layout {\n    height: 100% !important;\n    direction: ltr;\n    width: 100%;\n    max-height: 100%;\n    min-width: 100%;\n\n    .react-grid-placeholder{\n        transition: 0.2s;\n        background-color: var(--tool-bgcolor);\n        opacity: 20%;\n        border-radius: 5px;\n    }\n    \n    .block {\n        transition: 0.2s;\n        display: flex;\n        flex-direction: row;  \n        width: 100%;\n        height: 100%;\n        gap: 5px;\n        direction: var(--app-direction);\n\n        .react-resizable-handle {\n            z-index: 100;\n\n            &::after {\n                opacity: 20%;\n                border-right: 2px solid hsla(var(--app-text-color), 1);\n                border-bottom: 2px solid hsla(var(--app-text-color), 1);\n                border-radius: 0 0 5px 0;\n            }\n        }\n\n        .block-content {\n            transition: inherit;\n        }\n\n        .block-handle {\n            transition: 0.2s;\n            padding-top: 8px;\n            font-size: 16px;\n            opacity: 0%;\n            color: hsla(var(--app-text-color), 1);\n        }\n\n        .block-remove-button {\n            display: none;\n            position: absolute;\n            z-index: 10;\n            right: 1px;\n            left: unset;        \n            top: 1px;\n            background-color: transparent;\n            height: 30px;\n            width: 30px;\n            border-radius: 5px;\n            cursor: pointer;\n            align-items: center;\n            justify-content: center;\n            \n            .fi {\n                pointer-events: none;\n                color: hsla(var(--app-text-color), 1);\n                font-size: 10px;    \n            }\n        }\n\n        .block-content{\n            outline: 1px solid transparent;\n            transition: 0.2s;\n            &:has(.MafsView){\n                outline: 1px solid var(--tool-hover-bgcolor);\n            }\n        }\n\n        &:hover {\n            .block-content{\n                outline: 1px solid var(--tool-hover-bgcolor);\n                .block-remove-button{\n                    display: flex;\n                }\n            }\n\n\n            .block-handle {\n                opacity: 70%;\n\n                &:hover{\n                    cursor: pointer;\n                }\n            }\n        }  \n    }\n}"
  },
  {
    "path": "src/renderer/components/Page/Grid/Grid.tsx",
    "content": "import React, { useEffect, useState } from 'react';\nimport { useGeneralContext } from '@components/GeneralContext';\n\nimport { Notification } from '@components/common/Notification';\nimport ConfirmModal from '@components/common/Modals/ConfirmModal';\n\nimport { BlockElement, PageGridState } from '@renderer/common/types';\n\nimport '@components/Page/Page.scss';\nimport '@components/Page/Grid/Grid.scss';\nimport '@components/Page/Grid/Blocks/Blocks.scss';\nimport 'react-grid-layout/css/styles.css';\nimport 'react-resizable/css/styles.css';\n\nimport GridElement from './GridElement';\nimport { Responsive, WidthProvider } from 'react-grid-layout';\nimport { useAddBlock } from '@renderer/hooks/useAddBlock';\nimport { useDialog } from '@renderer/hooks/useDialog';\nimport { useFileSaveLoad } from '@renderer/hooks/useFileSaveLoad';\nimport { useTranslation } from 'react-i18next';\n\nconst ResponsiveGridLayout = WidthProvider(Responsive);\n\nconst PageGrid = () => {\n  const { t, i18n } = useTranslation();\n  const [state, setState] = useState<PageGridState>({\n    items: [],\n    breakpoint: 'lg',\n    cols: 8,\n  });\n  const [allBlockValues, setAllBlockValues] = useState([]);\n  const [popupType, setPopupType] = useState('');\n  const [clearModalOpen, setClearModalOpen] = useState(false);\n\n  const { isFilesSidebarOpen, isMathSidebarOpen } = useGeneralContext();\n\n  useEffect(\n    function adjustGridWidth() {\n      setTimeout(() => {\n        dispatchEvent(new Event('resize'));\n      }, 300);\n    },\n    [isFilesSidebarOpen, isMathSidebarOpen],\n  );\n\n  useFileSaveLoad(\n    state,\n    setState,\n    allBlockValues,\n    setAllBlockValues,\n    setPopupType,\n  );\n\n  useAddBlock(setState);\n\n  const ModalChoice = useDialog(setState, setAllBlockValues, setClearModalOpen);\n\n  const onLayoutChange = (layout: Array<BlockElement>) => {\n    layout.map((block) => {\n      block.type = state.items.find((item) => item.i == block.i).type;\n      block.metaData = state.items.find((item) => item.i == block.i).metaData;\n    });\n\n    setState((prev) => ({ ...prev, items: layout }));\n  };\n\n  const onBreakpointChange = (breakpoint: string, cols: number) => {\n    setState((prev) => ({ ...prev, breakpoint: breakpoint, cols: cols }));\n  };\n\n  const onRemoveItem = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {\n    setState((prev) => ({\n      ...prev,\n      items: prev.items.filter(\n        (item) => item.i !== (e.target as HTMLTextAreaElement).name,\n      ),\n    }));\n\n    setAllBlockValues((allValues) =>\n      allValues.filter(\n        (value) => value.id !== (e.target as HTMLTextAreaElement).name,\n      ),\n    );\n  };\n\n  return (\n    <div className='grid-container'>\n      <ResponsiveGridLayout\n        onLayoutChange={onLayoutChange}\n        onBreakpointChange={onBreakpointChange}\n        className='layout'\n        cols={{ lg: 8, md: 6, sm: 4, xs: 2, xss: 1 }}\n        rowHeight={50}\n        resizeHandles={\n          document.querySelector('#main-app').classList.contains('rtl')\n            ? ['sw']\n            : ['se']\n        }\n        containerPadding={[0, 0]}\n        breakpoints={{ lg: 800, md: 600, sm: 400, xs: 200, xss: 100 }}\n        draggableHandle='.block-handle'\n      >\n        {state.items.map((element) => (\n          <GridElement\n            blockElement={element}\n            onRemoveItem={onRemoveItem}\n            key={element.i}\n            data-grid={element}\n            blockValue={element.metaData}\n            setValuesFunction={setAllBlockValues}\n            allValues={allBlockValues}\n          />\n        ))}\n      </ResponsiveGridLayout>\n\n      <ConfirmModal\n        open={clearModalOpen}\n        onConfirm={ModalChoice.handleDialogConfirm}\n        onCancel={ModalChoice.handleDialogCancel}\n        text={t('Modal 1')}\n      />\n\n      <Notification scene={popupType} />\n    </div>\n  );\n};\n\nexport default PageGrid;\n"
  },
  {
    "path": "src/renderer/components/Page/Grid/GridElement.tsx",
    "content": "import React, { LegacyRef, useEffect, useState } from 'react';\nimport TextBlockContent from './Blocks/TextBlock';\nimport MathBlockContent from './Blocks/MathBlock';\nimport GraphBlockContent from './Blocks/GraphBlock';\nimport { BlockElement, ValueProps, WidgetType } from '@renderer/common/types';\nimport DrawBlockContent from './Blocks/DrawBlock';\nimport './Grid.scss';\n\ntype GridElementProps = {\n  allValues: any[];\n  setValuesFunction: (...args: unknown[]) => unknown;\n  blockElement: BlockElement;\n  blockValue: ValueProps;\n  onRemoveItem: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;\n  key?: string;\n  className?: string;\n  style?: React.CSSProperties;\n  children?: React.ReactNode[];\n  onMouseDown?: (e: React.MouseEvent) => unknown;\n  onMouseUp?: (e: React.MouseEvent) => unknown;\n  onTouchEnd?: (e: React.TouchEvent) => unknown;\n};\n\nfunction Switcher(\n  widgetType: WidgetType,\n  blockValue: ValueProps,\n  blockStateFunction: (...args: unknown[]) => unknown,\n) {\n\n  try {\n    switch (widgetType) {\n      case WidgetType.Text:\n        return (\n          <TextBlockContent\n            content={blockValue.content}\n            blockStateFunction={blockStateFunction}\n          />\n        );\n      case WidgetType.Math:\n        return (\n          <MathBlockContent\n            content={blockValue.content}\n            blockStateFunction={blockStateFunction}\n          />\n        );\n      case WidgetType.Graph:\n        return (\n          <GraphBlockContent\n            content={blockValue.content}\n            blockStateFunction={blockStateFunction}\n          />\n        );\n      case WidgetType.Divider:\n        return <hr className='pageDivider'></hr>;\n      case WidgetType.Draw:\n        return (\n          <DrawBlockContent\n            content={blockValue.content}\n            blockStateFunction={blockStateFunction}\n          />\n        );\n      default:\n        return null;\n    }\n  } catch (error) {\n    console.log(error);\n  }\n}\n\nconst GridElement = React.forwardRef(\n  (\n    {\n      blockElement,\n      setValuesFunction,\n      allValues,\n      blockValue,\n      key,\n      onRemoveItem,\n      style,\n      className,\n      onMouseDown,\n      onMouseUp,\n      onTouchEnd,\n      children,\n    }: GridElementProps,\n    ref,\n  ) => {\n    const [blockState, setBlockState] = useState();\n\n    useEffect(() => {\n      const currentState = {\n        id: blockElement.i,\n        metaData: {content: blockState},\n      };\n\n      const newAllValues = allValues.map((state) =>\n        state.id == currentState.id\n          ? { ...state, metaData: currentState.metaData }\n          : state,\n      );\n\n      if (!newAllValues.find((state) => state.id == currentState.id)) {\n        newAllValues.push(currentState);\n      }\n      \n      setValuesFunction(newAllValues);\n    }, [blockState]);\n\n    const ReactElement = (\n      <div\n        className={['block', className].join(' ')}\n        ref={(ref as LegacyRef<HTMLDivElement>)}\n        onMouseDown={onMouseDown}\n        onMouseUp={onMouseUp}\n        onTouchEnd={onTouchEnd}\n        style={{ ...style }}\n        key={key}\n        id={blockElement.i}\n      >\n        <div className='block-handle'>\n          <i className='fi fi-rr-menu-dots-vertical' />\n        </div>\n        <div className='block-content'>\n          {Switcher(blockElement.type, blockValue, setBlockState)}\n          <button\n            name={blockElement.i}\n            className='block-remove-button'\n            onClick={onRemoveItem}\n          >\n            <i className='fi fi-rr-x' />\n          </button>\n        </div>\n        {children}\n      </div>\n    );\n\n    return ReactElement;\n  },\n);\n\nGridElement.displayName = 'GridElement';\n\nexport default GridElement;\n"
  },
  {
    "path": "src/renderer/components/Page/Page.scss",
    "content": "@import '../Theme.scss';\n@import '~keyboard-css/dist/css/main.min.css';\n\n::-webkit-scrollbar {\n    width: 0;\n}\n\n.page {\n    transition: 0.3s;\n    width: 100%;\n    height: 100%;\n    max-width: calc(100% - 110px);\n    background: var(--page-bgcolor);\n    border-width: 2px 2px 0px 2px;\n    border-style: solid;\n    box-sizing: border-box;\n    border-color: var(--page-border);\n    border-radius: 15px 15px 0px 0px;\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    justify-content: flex-start;\n\n    .page-grid {\n        min-width: 60%;\n        width: 70%;\n        max-width: 80%;\n        height: 100%;\n\n        display: flex;\n        flex-direction: column;\n        overflow-y: auto;\n        align-items: center;\n\n        .grid-container {\n            padding-top: 100px;\n            margin-bottom: 80px;\n            height: 100%;\n            max-height: 100%;\n            width: 100%;\n            max-width: 100%;\n            overflow-x: hidden;\n            display: flex;\n            flex-direction: column;\n            align-self: center;\n            justify-content: space-between;\n        }\n    }\n\n    .page-placeholder {\n        align-self: center;\n        display: flex;\n        flex-direction: column;\n        justify-content: center;\n        height: 100%;\n\n        .placeholder-text {\n            line-height: 1.5;\n            opacity: 70%;\n            font-weight: 100;\n            text-align: center;\n            padding-bottom: 80px;\n            font-size: 20px;\n            color: hsla(var(--app-text-color), 1);\n\n            .fi{\n                height: 18px;\n                display: inline-block;\n                margin-bottom: 6px;\n                font-size: 18px;\n            }\n            .kbc-button {\n                font-family: 'Rubik2', 'NotoSansArabic' !important;\n                font-weight: 100;\n                color: hsla(var(--app-text-color), 1) !important;\n                box-shadow:\n                    0 0 var(--page-border),\n                    0 0 var(--page-border),\n                    0 1px var(--page-border),\n                    0 2px var(--page-border),\n                    0 3px var(--page-border),\n                    0 4px var(--page-border),\n                    0 5px var(--page-border),\n                    2px 2.5px 4px var(--page-border) !important;\n                background-color: var(--page-bgcolor) !important;\n                border: 1px solid var(--page-border) !important;\n                border-bottom: 1px solid var(--page-border) !important;\n\n                &::after {\n                    border: 1px solid var(--page-border) !important;\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/renderer/components/Page/Page.tsx",
    "content": "import React, { useEffect, useState } from 'react';\nimport '../Application.scss';\n\nimport './Page.scss';\n\nimport ToolsPanel from './ToolsPanel/ToolsPanel';\nimport './ToolsPanel/ToolsPanel.scss';\n\nimport { useGeneralContext } from '@components/GeneralContext';\nimport PagePlaceholder from './PagePlaceholder';\nimport PageGrid from './Grid/Grid';\n\nconst gridStyle = {\n  width: '100%',\n  height: '100%',\n  backgroundImage:\n    'radial-gradient(circle at 50% 100%, var(--tool-hover-bgcolor) 1px, transparent 1px)',\n  backgroundSize: '50px 50px',\n  color: 'white'\n};\n\nconst Page = () => {\n  const { selectedFile } = useGeneralContext();\n  const [currentFilePath, setCurrentFilePath] = useState(\"\")\n\n  useEffect(() => {\n    setCurrentFilePath(selectedFile)\n  }, [selectedFile])\n\n  return (\n    <div className='page' style={gridStyle}>\n      { currentFilePath ?\n        <div className='page-grid'>\n          <PageGrid />\n          <ToolsPanel />\n        </div> : <PagePlaceholder/>\n      }\n    </div>\n  );\n};\n\nexport default Page;\n"
  },
  {
    "path": "src/renderer/components/Page/PagePlaceholder.tsx",
    "content": "import React from 'react';\nimport Shortcut from '@components/common/Shortcut';\nimport './Page.scss';\nimport { useTranslation } from 'react-i18next';\n\nconst PagePlaceholder = () => {\n  const { t, i18n } = useTranslation();\n\n  return (\n    <div className='page-placeholder'>\n      <div className='placeholder-text'>\n        {t(\"Placeholder 1\")}, <br />\n        {t(\"Placeholder 2\")}{' '}\n        <kbd className='kbc-button'>\n          <i className='fi fi-rr-notebook'></i>\n        </kbd>{' '}\n        ({t(\"Placeholder Or\")} <Shortcut shortcut={['Ctrl', 'o']} />) {t(\"Placeholder 3\")}!\n      </div>\n    </div>\n  );\n};\n\nexport default PagePlaceholder;\n"
  },
  {
    "path": "src/renderer/components/Page/ToolsPanel/Tool.tsx",
    "content": "import React from 'react';\n\ntype ToolProps = {\n  title: string;\n  buttonType: string;\n  icon?: string;\n  onClick?: React.MouseEventHandler<HTMLButtonElement>;\n};\n\nconst Tool = ({ buttonType, title, icon, onClick }: ToolProps) => {\n  const iconName = `fi fi-rr-${icon}`;\n  return (\n    <button data-tooltip={title} id={buttonType} className='tool' onClick={onClick}>\n      {icon && <i className={iconName} />}\n    </button>\n  );\n};\n\nexport default Tool;\n"
  },
  {
    "path": "src/renderer/components/Page/ToolsPanel/ToolsPanel.scss",
    "content": "@import '../../Theme.scss';\n@import '../Page.scss';\n\n.tools-panel-container {\n    position: fixed;\n    height: 80px;\n    bottom: 0px;\n    width: 45vw;\n    z-index: 20;\n    display: flex;\n    justify-content: center;\n\n    .tools-panel {\n        direction: var(--app-direction);\n        transition: 0.2s;\n        position: fixed;\n        padding: 8px 10px 8px 10px;\n        height: 40px;\n        bottom: -50px;\n        width: max-content;\n        display: flex;\n        flex-direction: row;\n        border-radius: 8px;\n        gap: 8px;\n        background: var(--panel-bgcolor);\n        box-shadow: 0px 1px 12px rgba(0, 0, 0, 0.25);\n\n        .tool {\n            border-radius: 5px;\n            width: 40px;\n            height: 40px;\n            background-color: var(--tool-bgcolor);\n\n            &:hover {\n                background-color: var(--tool-hover-bgcolor);\n\n                &::after {\n                    content: attr(data-tooltip);\n                    color: hsla(var(--app-text-color), 1);\n                    min-width: max-content;\n                    position: fixed;\n                    margin-bottom: 100px;\n                    z-index: 1000;\n                    padding: 6px 10px 6px 10px;\n                    background-color: var(--button-bgcolor);\n                    text-shadow: none;\n                    border: 1px solid var(--page-border);\n                    border-radius: 6px;\n                    opacity: 0%;\n                    animation: tooltip 0.1s ease-in-out 0.2s forwards;\n                }\n            }\n\n            &:active {\n                transform: scale(0.9);\n                background-color: var(--tool-active-bgcolor);\n            }\n\n            .fi {\n                line-height: 1.6;\n                margin: auto;\n                font-size: 20px;\n                color: var(--tool-color);\n                text-shadow: none;\n            }\n\n            &#clearPage {\n                background-color: var(--clear-button-bgcolor);\n\n                &:hover {\n                    background-color: var(--clear-button-hover-bgcolor);\n                }\n\n                .fi {\n                    color: var(--clear-button-color);\n                }\n            }\n        }\n\n        .tool-divider {\n            fill: var(--tool-color);\n            opacity: 50%;\n            width: 20px;\n            height: 100%;\n        }\n    }\n\n    &:hover {\n        .tools-panel {\n            bottom: 14px;\n        }\n    }\n}\n\n@keyframes tooltip {\n    from {\n        transform: scale(0.95);\n        opacity: 0%;\n        box-shadow: 0px 1px 3px #00000000;\n    }\n\n    to {\n        transform: scale(1);\n        opacity: 100%;\n        box-shadow: 0px 1px 3px #0000002a;\n    }\n}"
  },
  {
    "path": "src/renderer/components/Page/ToolsPanel/ToolsPanel.tsx",
    "content": "import React from 'react';\nimport '../Page.scss';\nimport Tool from './Tool';\nimport { useGeneralContext } from '@components/GeneralContext';\nimport { WidgetType } from '@renderer/common/types';\nimport { useTranslation } from 'react-i18next';\n\nconst ToolsPanel = () => {\n  const { t, i18n } = useTranslation();\n  const { setNewWidgetRequest, setClearPageRequest, setSaveRequest } = useGeneralContext();\n\n  const handleOnClickTool = (widgetType: WidgetType) => {\n    setNewWidgetRequest({ widgetType });\n  };\n\n  const clearPage = () => {\n    setClearPageRequest({ cmd: 'clear' });\n  };\n\n  const savePage = () => {\n    setSaveRequest({ cmd: 'save' });\n  };\n\n  return (\n    <div className='tools-panel-container'>\n      <div className='tools-panel'>\n        <Tool\n          title={t(\"Text Block\")}\n          buttonType='addTextBlock'\n          icon='letter-case'\n          onClick={() => handleOnClickTool(WidgetType.Text)}\n        />\n        <Tool\n          title={t(\"Math Block\")}\n          buttonType='addMathBlock'\n          icon='square-root'\n          onClick={() => handleOnClickTool(WidgetType.Math)}\n        />\n        <Tool\n          title={t(\"Graph Block\")}\n          buttonType='addGraphBlock'\n          icon='chat-arrow-grow'\n          onClick={() => handleOnClickTool(WidgetType.Graph)}\n        />\n        {/* <Tool\n          title={t(\"Picture Block\")}\n          buttonType='addPictureBlock'\n          icon='picture'\n          onClick={() => handleOnClickTool(WidgetType.Picture)}\n        /> */}\n        <Tool\n          title={t(\"Draw Block\")}\n          buttonType='addDrawBlock'\n          icon='pencil'\n          onClick={() => handleOnClickTool(WidgetType.Draw)}\n        />\n        {/* <Tool title='הוספת קבוצה' buttonType='addGroupBlock' icon='apps-add' /> */}\n        <Tool\n          title={t(\"Divider\")}\n          buttonType='addDividerBlock'\n          icon='minus'\n          onClick={() => handleOnClickTool(WidgetType.Divider)}\n        />\n        <svg viewBox=\"0 0 24 24\" className='tool-divider'><path d=\"M11,3 L11,21 C11,21.5522847 11.4477153,22 12,22 C12.5522847,22 13,21.5522847 13,21 L13,3 C13,2.44771525 12.5522847,2 12,2 C11.4477153,2 11,2.44771525 11,3 Z\"></path></svg>\n        <Tool\n          title={t(\"Save\")}\n          buttonType='savePage'\n          icon={'disk'}\n          onClick={() => savePage()}\n        />\n        <Tool\n          title={t(\"Clear\")}\n          buttonType='clearPage'\n          icon={'trash'}\n          onClick={() => clearPage()}\n        />\n      </div>\n    </div>\n  );\n};\n\nexport default ToolsPanel;\n"
  },
  {
    "path": "src/renderer/components/Theme.scss",
    "content": "#main-app.rtl {\n  --app-direction: rtl;\n}\n\n:root {\n  --app-direction: unset;\n\n  // Logo \n  --logo-filter: brightness(1);\n\n  // Application\n  --app-accent-color: hsl(var(--theme-hue), 53%, 40%);\n  --app-font-size: 16px;\n  --app-font-family: 'Rubik2', 'NotoSansArabic';\n  --app-bgcolor: hsl(var(--theme-hue), 11%, 7%);\n  --app-border-color: hsl(var(--theme-hue), 7%, 25%);\n  --app-text-color: 0, 0%, 85%;\n\n  // Page\n  --page-bgcolor: hsl(var(--theme-hue), 26%, 9%);\n  --page-border: hsl(var(--theme-hue), 21%, 13%);\n\n  // Blocks\n  --math-block-bgcolor: hsl(var(--theme-hue), 21%, 13%);\n  --math-block-selection: hsl(0, 0%, 100%);\n  --math-block-selection-bg: hsl(var(--theme-hue), 21%, 25%);\n  --mafs-plot-color: hsl(var(--theme-hue), 40%, 50%);\n  --text-block-font-size: 20px;\n\n  // Tools Panel\n  --panel-bgcolor: hsl(var(--theme-hue), 26%, 18%);\n  --tool-bgcolor: hsl(var(--theme-hue), 31%, 14%);\n  --tool-hover-bgcolor: hsl(var(--theme-hue), 28%, 23%);\n  --tool-active-bgcolor: hsl(var(--theme-hue), 27%, 18%);\n\n\n  // Scrollbar\n  --scroll-width: 8px;\n  --scroll-track-bgcolor: hsla(0, 0%, 18%, 0.322);\n  --scroll-thumb-bgcolor: hsla(0, 0%, 23%, 0.747);\n  --scroll-thumb-hover-bgcolor: hsl(0, 0%, 33%);\n\n  // Selection\n  --selection-bgcolor: var(--app-accent-color);\n  --selection-color: hsl(0, 0%, 100%);\n\n  // Button\n  --button-color: hsl(0, 0%, 100%);\n  --button-border: 1px solid hsl(var(--theme-hue), 3%, 14%);\n  --button-bgcolor: hsl(var(--theme-hue), 26%, 9%);\n  --button-hover-bgcolor: hsl(var(--theme-hue), 25%, 12%);\n  --button-active-bgcolor: hsl(var(--theme-hue), 27%, 18%);\n  --button-shadow-color: hsla(0, 0%, 0%, 0.471);\n  --pill-bgcolor: hsl(var(--theme-hue), 33%, 13%);\n  --pill-hover-bgcolor: hsl(var(--theme-hue), 33%, 19%);\n  --pill-active-bgcolor: hsl(var(--theme-hue), 33%, 15%);\n  --tag-saturation: 19%;\n  --tag-lightness: 23%;\n  --tag-filter: brightness(110%);\n  --button-danger: hsl(0, 50%, 50%);\n  // --button-outline: 1px solid hsl(var(--theme-hue), 3%, 14%);\n  --clear-button-bgcolor: hsl(0, 15%, 32%);\n  --clear-button-hover-bgcolor: hsl(0, 16%, 39%);\n  --clear-button-color: hsl(0, 12%, 66%);\n  --sidebar-button-color: hsl(var(--theme-hue), 15%, 35%);\n  --tool-color: hsl(var(--theme-hue), 16%, 67%);\n\n  // File System\n  --file-bgcolor: hsl(var(--theme-hue), 25%, 10%);\n  --file-hover-bgcolor: hsl(var(--theme-hue), 25%, 12%);\n  --file-active-bgcolor: hsl(var(--theme-hue), 25%, 14%);\n  --selected-transparent: hsla(var(--theme-hue), 25%, 12%, 0.5);\n  --selected-bgcolor: hsl(var(--theme-hue), 25%, 12%);\n  --selected-hover-bgcolor: hsl(var(--theme-hue), 25%, 14%);\n  --selected-active-bgcolor: hsl(var(--theme-hue), 25%, 16%);\n\n\n  // Command Bar\n  --command-bar-bg: linear-gradient(120deg,\n      hsla(var(--theme-hue), 10%, 5%, 0.7),\n      hsla(var(--theme-hue), 10%, 9%, 0.9), 70%,\n      hsla(var(--theme-hue), 10%, 5%, 0.7));\n\n  // Titlebar\n  --titlebar-bgcolor: var(--app-bgcolor);\n  --titlebar-color: hsl(0, 0%, 85%);\n  --titlebar-title-color: hsl(0, 0%, 85%);\n  --titlebar-menu-border-color: hsl(0, 1%, 17%);\n  --titlebar-menu-title-hover-bgcolor: hsl(0deg 0% 12%);\n  --titlebar-menu-title-active-bgcolor: hsl(0deg 0% 14%);\n  --titlebar-menu-title-active-border-color: var(--titlebar-menu-border-color);\n  --titlebar-menu-separator-bgcolor: var(--titlebar-menu-border-color);\n  --titlebar-popup-bgcolor: hsl(0deg 0% 14%);\n  --titlebar-popup-border: 1px solid var(--titlebar-menu-border-color);\n  --titlebar-popup-shadow: 4px 10px 10px rgba(0, 0, 0, 0.2);\n  --titlebar-popup-item-name-color: hsl(0, 0%, 75%);\n  --titlebar-popup-item-shortcut-color: hsla(0, 0%, 55%, 0.8);\n  --titlebar-popup-item-hover-color: hsl(0, 0%, 85%);\n  --titlebar-popup-item-hover-bgcolor: hsl(0deg 0% 18%);\n  --titlebar-popup-item-hover-shortcut-color: var(--app-accent-color);\n  --titlebar-popup-item-name-shadow-color: hsl(0, 0%, 8%);\n\n  // ERWT\n  --erwt-heading-color: hsl(0, 0%, 87%);\n}\n\n/*\n *=========================================================================\n * ERWT Light Theme\n *=========================================================================\n *\n * Light theme for ERWT application.\n */\n\nbody:not(.dark-mode) {\n\n  // Logo \n  --logo-filter: brightness(0.1);\n\n  // Application\n  --app-accent-color: hsl(var(--theme-hue), 62%, 49%);\n  --app-bgcolor: hsl(var(--theme-hue), 78%, 98%);\n  --app-text-color: 0, 0%, 10%;\n\n  // Page\n  --page-bgcolor: hsl(0, 0%, 100%);\n  --page-border: hsl(var(--theme-hue), 51%, 86%);\n\n  // Blocks\n  --math-block-bgcolor: hsl(var(--theme-hue), 60%, 95%);\n  --math-block-selection: hsl(0, 0%, 0%);\n  --math-block-selection-bg: hsl(var(--theme-hue), 60%, 86%);\n  --mafs-plot-color: hsl(var(--theme-hue), 60%, 60%);\n\n\n  // Tools Panel\n  --panel-bgcolor: hsl(0, 0%, 100%);\n  --tool-bgcolor: hsl(var(--theme-hue), 51%, 86%);\n  --tool-hover-bgcolor: hsl(var(--theme-hue), 40%, 78%);\n  --tool-active-bgcolor: hsl(var(--theme-hue), 37%, 66%);\n\n  // Selection\n  --selection-bgcolor: var(--app-accent-color);\n  --selection-color: hsl(0, 0%, 100%);\n\n  // Scrollbar\n  --scroll-track-bgcolor: hsla(0, 0%, 18%, 0.122);\n  --scroll-thumb-bgcolor: hsla(0, 0%, 23%, 0.3);\n  --scroll-thumb-hover-bgcolor: var(--app-accent-color);\n\n  // Button\n  --button-border: 1px solid hsl(0, 0%, 92%);\n  --button-bgcolor: hsl(0, 0%, 100%);\n  --button-color: hsl(0, 0%, 26%);\n  --button-shadow-color: hsl(0, 0%, 100%);\n  --button-hover-bgcolor: hsl(0, 0%, 98%);\n  --button-active-bgcolor: hsl(0, 0%, 96%);\n  --pill-bgcolor: hsl(var(--theme-hue), 29%, 86%);\n  --pill-hover-bgcolor: hsl(var(--theme-hue), 29%, 75%);\n  --pill-active-bgcolor: hsl(var(--theme-hue), 29%, 80%);\n  --tag-saturation: 47%;\n  --tag-lightness: 93%;\n  --button-danger: hsl(0, 100%, 90%);\n  --tag-filter: brightness(90%);\n  --clear-button-bgcolor: hsl(0, 41%, 92%);\n  --clear-button-color: hsl(0, 34%, 40%);\n  --clear-button-hover-bgcolor: hsl(0, 44%, 85%);\n  --tool-color: hsl(var(--theme-hue), 23%, 28%);\n  --sidebar-button-color: hsl(var(--theme-hue), 15%, 35%);\n\n  // File System\n  --file-bgcolor: hsl(var(--theme-hue), 25%, 90%);\n  --file-hover-bgcolor: hsl(var(--theme-hue), 25%, 88%);\n  --file-active-bgcolor: hsl(var(--theme-hue), 25%, 86%);\n  --selected-transparent: hsl(var(--theme-hue), 25%, 88%, 0.5);\n  --selected-bgcolor: hsl(var(--theme-hue), 25%, 88%);\n  --selected-hover-bgcolor: hsl(var(--theme-hue), 25%, 86%);\n  --selected-active-bgcolor: hsl(var(--theme-hue), 25%, 84%);\n\n  // Command Bar\n  --command-bar-bg: linear-gradient(120deg,\n      hsla(var(--theme-hue), 30%, 90%, 0.7),\n      hsla(var(--theme-hue), 30%, 90%, 0.2), 70%,\n      hsla(var(--theme-hue), 30%, 90%, 0.7));\n\n  // Titlebar\n  --titlebar-bgcolor: var(--app-bgcolor);\n  --titlebar-color: hsl(0, 0%, 12%);\n  --titlebar-title-color: var(--titlebar-color);\n  --titlebar-menu-title-hover-bgcolor: hsl(0, 0%, 90%);\n  --titlebar-popup-item-hover-bgcolor: hsl(210deg 16% 92%);\n  --titlebar-popup-bgcolor: hsl(0deg 0% 99%);\n  --titlebar-menu-title-active-bgcolor: hsl(0deg 0% 99%);\n  --titlebar-menu-title-active-border-color: hsl(204, 6%, 84%);\n  --titlebar-popup-border: 1px solid hsl(204, 6%, 84%);\n  --titlebar-menu-separator-bgcolor: hsl(204, 6%, 84%);\n  --titlebar-popup-item-hover-bgcolor: hsl(210, 11%, 85%);\n  --titlebar-popup-item-name-color: hsl(0, 0%, 5%);\n  --titlebar-popup-item-name-shadow-color: hsla(0, 0%, 100%, 0.8);\n  --titlebar-popup-item-hover-color: hsl(0, 0%, 0%);\n  --titlebar-popup-item-hover-shortcut-color: var(--app-accent-color);\n  --titlebar-popup-item-hover-bgcolor: hsl(0, 0%, 90%);\n\n  // ERWT\n  --erwt-heading-color: hsl(0, 0%, 16%);\n\n  // Overrides\n  .main-teaser {\n    background: hsl(0, 0%, 100%);\n    color: hsl(0, 0%, 45%);\n\n    &:after {\n      box-shadow: none;\n    }\n  }\n\n  .versions .item {\n    color: hsl(0, 0%, 40%);\n    background: hsl(0, 0%, 100%);\n    box-shadow: 0 2px 4px hsla(0, 0%, 0%, 0.02);\n\n    &>span {\n      color: hsl(0, 0%, 60%);\n    }\n  }\n}"
  },
  {
    "path": "src/renderer/components/common/Modals/ConfirmModal.scss",
    "content": "@import '../../Theme.scss';\n\nbody:has(#main-app.rtl){\n  .modal-text{\n    direction: rtl;\n  }\n}\n\n#portal {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n\n  .overlay {\n    position: fixed;\n    height: 100%;\n    animation: blurPage 0.15s ease-in-out forwards;\n    left: 0;\n    right: 0;\n    bottom: 0;\n    background-color: rgba(0, 0, 0, 0.1);\n    transition: 0.2s;\n    z-index: 1000;\n  }\n\n  .modal {\n    transform-origin: center;\n    direction: var(--app-direction);\n    font-size: larger;\n    animation: popup 0.15s ease-in-out forwards;\n    color: hsla(var(--app-text-color), 1);\n    display: flex;\n    flex-direction: column;\n    position: absolute;\n    box-shadow: 0px 1px 10px #0000005c;\n    top: 40%;\n    background-color: var(--page-bgcolor);\n    padding: 2rem;\n    z-index: 1000;\n    border-radius: 10px;\n    border: 1px solid var(--page-border);\n    text-shadow: none;\n\n    .actions-container {\n      margin-top: 1rem;\n      display: flex;\n      flex-direction: row;\n      justify-content: space-between;\n      width: 100%;\n\n      button {\n        background-color: var(--tool-bgcolor);\n        border-radius: 8px;\n        width: 45%;\n        font-size: medium;\n        font-weight: 300;\n        transition: 0.05s;\n        text-shadow: none;\n        border: 1px solid var(--panel-bgcolor);\n\n        &:hover {\n          transform: scale(1.04);\n          font-weight: 700;\n          background-color: var(--tool-hover-bgcolor);\n        }\n\n        &:active {\n          transform: scale(0.98);\n          font-weight: 700;\n          background-color: var(--tool-active-bgcolor);\n        }\n\n        &.danger-button {\n          background-color: var(--button-danger);\n          border: 0px solid transparent;\n\n        }\n      }\n    }\n  }\n}\n\n\n\n@keyframes blurPage {\n  to {\n    -webkit-backdrop-filter: blur(3px);\n    -moz-backdrop-filter: blur(3px);\n    backdrop-filter: blur(3px);\n  }\n}\n\n@keyframes popup {\n  0% {\n    -webkit-filter: blur(3px);\n    -moz-filter: blur(3px);\n    filter: blur(3px);\n\n    transform: scale(0.95);\n  }\n\n  100% {\n    -webkit-filter: blur(0px);\n    -moz-filter: blur(0px);\n    filter: blur(0px);\n\n    transform: scale(1);\n  }\n}"
  },
  {
    "path": "src/renderer/components/common/Modals/ConfirmModal.tsx",
    "content": "import React from 'react';\nimport ReactDom from 'react-dom';\nimport './ConfirmModal.scss';\nimport { useTranslation } from 'react-i18next';\n\ninterface ConfirmModalProps {\n  open: boolean;\n  onConfirm: () => void;\n  onCancel: () => void;\n  text: string;\n}\n\nexport default function ConfirmModal({\n  open,\n  onConfirm,\n  onCancel,\n  text\n}: ConfirmModalProps) {\n  const { t, i18n } = useTranslation();\n\n  if (!open) return null;\n\n  return ReactDom.createPortal(\n    <>\n      <div className='overlay' />\n      <div className='modal'>\n        <span className='modal-text'>{text}</span>\n        <div className='actions-container'>\n          <button onClick={onConfirm} className='danger-button'>\n            {t(\"OK\")}\n          </button>\n          <button onClick={onCancel}>{t(\"Cancel\")}</button>\n        </div>\n      </div>\n    </>,\n    document.getElementById('portal'),\n  );\n}\n"
  },
  {
    "path": "src/renderer/components/common/Modals/ErrorModal.scss",
    "content": "@import '../../Theme.scss';\n\n#portal {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n\n  .overlay {\n    position: fixed;\n    height: 100%;\n    animation: blurPage 0.15s ease-in-out forwards;\n    left: 0;\n    right: 0;\n    bottom: 0;\n    background-color: rgba(0, 0, 0, 0.1);\n    transition: 0.2s;\n    z-index: 1000;\n  }\n\n  .modal {\n    transform-origin: center;\n    direction: var(--app-direction);\n    font-size: larger;\n    animation: popup 0.15s ease-in-out forwards;\n    color: hsla(var(--app-text-color), 1);\n    display: flex;\n    flex-direction: column;\n    position: absolute;\n    box-shadow: 0px 1px 10px #0000005c;\n    top: 40%;\n    background-color: var(--page-bgcolor);\n    padding: 2rem;\n    z-index: 1000;\n    border-radius: 10px;\n    border: 1px solid var(--page-border);\n    text-shadow: none;\n\n    .actions-container {\n      margin-top: 1rem;\n      display: flex;\n      flex-direction: row;\n      justify-content: space-between;\n      width: 100%;\n\n      button {\n        background-color: var(--tool-bgcolor);\n        border-radius: 8px;\n        width: 45%;\n        font-size: medium;\n        font-weight: 300;\n        transition: 0.05s;\n        text-shadow: none;\n        border: 1px solid var(--panel-bgcolor);\n\n        &:hover {\n          transform: scale(1.04);\n          font-weight: 700;\n          background-color: var(--tool-hover-bgcolor);\n        }\n\n        &:active {\n          transform: scale(0.98);\n          font-weight: 700;\n          background-color: var(--tool-active-bgcolor);\n        }\n\n        &.danger-button {\n          background-color: var(--button-danger);\n          border: 0px solid transparent;\n\n        }\n      }\n    }\n  }\n}\n\n\n\n@keyframes blurPage {\n  to {\n    -webkit-backdrop-filter: blur(3px);\n    -moz-backdrop-filter: blur(3px);\n    backdrop-filter: blur(3px);\n  }\n}\n\n@keyframes popup {\n  0% {\n    -webkit-filter: blur(3px);\n    -moz-filter: blur(3px);\n    filter: blur(3px);\n\n    transform: scale(0.95);\n  }\n\n  100% {\n    -webkit-filter: blur(0px);\n    -moz-filter: blur(0px);\n    filter: blur(0px);\n\n    transform: scale(1);\n  }\n}"
  },
  {
    "path": "src/renderer/components/common/Modals/ErrorModal.tsx",
    "content": "import React, { PropsWithChildren } from 'react';\nimport ReactDom from 'react-dom';\nimport './ErrorModal.scss';\nimport { useTranslation } from 'react-i18next';\n\ninterface ErrorModalProps extends PropsWithChildren {\n  open: boolean;\n  onClose: () => void;\n}\n\nexport default function ErrorModal({\n  open,\n  onClose,\n  children,\n}: ErrorModalProps) {\n  const { t, i18n } = useTranslation();\n\n  if (!open) return null;\n\n  return ReactDom.createPortal(\n    <>\n      <div className='overlay' />\n      <div className='modal'>\n        {children}\n        <div className='actions-container'>\n          <button onClick={onClose} className='danger-button'>\n            {t(\"OK\")}\n          </button>\n        </div>\n      </div>\n    </>,\n    document.getElementById('portal'),\n  );\n}\n"
  },
  {
    "path": "src/renderer/components/common/Notification.scss",
    "content": "@import '../Theme.scss';\n\n#notification {\n    direction: var(--app-direction);\n    visibility: hidden;\n    z-index: 1;\n    padding: 6px 10px 6px 10px;\n    background-color: var(--button-bgcolor);\n    text-shadow: none;\n    border: 1px solid var(--page-border);\n    border-radius: 6px;\n    color: hsla(var(--app-text-color), 1);\n    text-align: center;\n    align-self: center;\n    position: relative;\n    width: max-content;\n    box-shadow: 0px 1px 3px #0000002a;\n    display: block;\n    bottom: 1px;\n\n    &.show {\n        visibility: visible;\n        -webkit-animation: fadein 0.2s, fadeout 0.3s 1s;\n        animation: fadein 0.2s, fadeout 0.3s 1s;\n      }\n  }\n    \n@-webkit-keyframes fadein {\nfrom { bottom: 0; opacity: 0; }\nto { bottom: 1px; opacity: 1; }\n}\n\n@keyframes fadein {\nfrom { bottom: 0; opacity: 0; }\nto { bottom: 1px; opacity: 1; }\n}\n\n@-webkit-keyframes fadeout {\nfrom { bottom: 1px; opacity: 1; }\nto { bottom: 0; opacity: 0; }\n}\n\n@keyframes fadeout {\nfrom { bottom: 1px; opacity: 1; }\nto { bottom: 0; opacity: 0; }\n}"
  },
  {
    "path": "src/renderer/components/common/Notification.tsx",
    "content": "import React from 'react';\nimport './Notification.scss';\nimport { useTranslation } from 'react-i18next';\n\ntype NotificationProps = {\n  scene: string;\n};\n\nexport const Notification = ({ scene }: NotificationProps) => {\n  const { t, i18n } = useTranslation();\n  let content = '';\n\n  switch (scene) {\n    case '':\n      content = '';\n      break;\n    case 'save':\n      content = t(\"Saved\");\n      break;\n\n    case 'error':\n      content = t(\"Save Error\");\n      break;\n\n    default:\n      break;\n  }\n\n  return (\n    <div id='notification' className={content == '' ? '' : 'show'}>\n      {content}\n    </div>\n  );\n};\n\nexport const triggerPopupAnimation = (type: string, setPopupType: (args: string) => unknown) => {\n  setTimeout(() => {\n    setPopupType(type);\n    setTimeout(() => {\n      setPopupType('');\n    }, 1200);\n  }, 0);\n};"
  },
  {
    "path": "src/renderer/components/common/Shortcut.tsx",
    "content": "import React from 'react';\n\ntype ShortcutProps = {\n  shortcut: string[];\n};\n\nconst Shortcut = ({ shortcut }: ShortcutProps) => {\n  const keys = shortcut.map((k: string) => (\n    <span key={Math.random()}>\n      <>{k == shortcut[0] ? '' : '+'}</>\n      <kbd className='kbc-button'>{k}</kbd>\n    </span>\n  ));\n\n  return (\n    <span\n      style={{\n        display: 'inline-flex',\n        flexDirection: 'row',\n        alignItems: 'center',\n        direction: 'ltr',\n      }}\n      className='shortcut'\n    >\n      {keys ? keys : <></>}\n    </span>\n  );\n};\n\nexport default Shortcut;\n"
  },
  {
    "path": "src/renderer/hooks/useAddBlock.tsx",
    "content": "import { useEffect } from 'react';\nimport {\n  BlockElement,\n  WidgetType,\n  newWidgetRequest,\n} from '@renderer/common/types';\nimport { useGeneralContext } from '@components/GeneralContext';\n\nexport function useAddBlock(setStateFunction: (...args: unknown[]) => unknown) {\n  const { newWidgetRequest } = useGeneralContext();\n\n  useEffect(() => {\n    if (newWidgetRequest) AddWidget(newWidgetRequest);\n  }, [newWidgetRequest]);\n\n  const AddWidget = (newWidgetRequest: newWidgetRequest) => {\n    const handler = addWidgetHandlersMap.get(newWidgetRequest.widgetType);\n    if (handler) handler();\n  };\n\n  function addBlockByType(\n    blockType: number,\n    height: number,\n    width?: number,\n    minHeight?: number,\n    minWidth?: number,\n    maxHeight?: number,\n    maxWidth?: number,\n  ) {\n    setStateFunction((prev: { items: BlockElement[] }) => ({\n      ...prev,\n      items: [\n        ...prev.items,\n        {\n          type: blockType,\n          i: crypto.randomUUID(),\n          metaData: {},\n          x: Infinity,\n          y: Infinity,\n          h: height,\n          w: width ? width : 8,\n          minH: minHeight ? minHeight : 1,\n          minW: minWidth ? minWidth : 1,\n          maxH: maxHeight ? maxHeight : 100,\n          maxW: maxWidth ? maxWidth : 8,\n        } as BlockElement,\n      ],\n    }));\n  }\n\n  const addWidgetHandlersMap = new Map<WidgetType, () => void>([\n    [WidgetType.Divider, () => addBlockByType(WidgetType.Divider, 1, 8, 1, 1, 1)],\n    [WidgetType.Graph, () => addBlockByType(WidgetType.Graph, 6, 8, 2, 2)],\n    [WidgetType.Text, () => addBlockByType(WidgetType.Text, 2)],\n    [WidgetType.Math, () => addBlockByType(WidgetType.Math, 2)],\n    [WidgetType.Draw, () => addBlockByType(WidgetType.Draw, 6, 8, 4, 4)],\n    [WidgetType.Picture, () => console.error('not implemented')],\n    [WidgetType.Group, () => console.error('not implemented')],\n  ]);\n}\n"
  },
  {
    "path": "src/renderer/hooks/useDialog.tsx",
    "content": "import { BlockElement } from '@renderer/common/types';\nimport { useEffect } from 'react';\nimport { useGeneralContext } from '@components/GeneralContext';\n\nexport function useDialog(\n  setStateFunction: (...args: unknown[]) => unknown,\n  setAllBlockValues: (...args: unknown[]) => unknown,\n  setClearModalOpen: (args: boolean) => void,\n) {\n  const { clearPageRequest } = useGeneralContext();\n  const emptyArray: BlockElement[] = [];\n\n  useEffect(() => {\n    if (clearPageRequest.cmd === 'clear') setClearModalOpen(true);\n  }, [clearPageRequest]);\n\n  const handleDialogConfirm = () => {\n    setClearModalOpen(false);\n    setStateFunction((prev: { items: BlockElement[] }) => ({\n      ...prev,\n      items: emptyArray,\n    }));\n    setAllBlockValues([]);\n  };\n\n  const handleDialogCancel = () => setClearModalOpen(false);\n\n  return { handleDialogCancel, handleDialogConfirm };\n}\n"
  },
  {
    "path": "src/renderer/hooks/useFileSaveLoad.tsx",
    "content": "import { useGeneralContext } from '@components/GeneralContext';\nimport { useEffect } from 'react';\nimport { triggerPopupAnimation } from '@components/common/Notification';\nimport {\n  BlockElement,\n  FileStructure,\n  PageGridState,\n  BlockState,\n} from '@renderer/common/types';\n\nexport function useFileSaveLoad(\n  state: PageGridState,\n  setStateFunction: (...args: unknown[]) => unknown,\n  allBlockValues: BlockState[],\n  setAllBlockValues: (...args: unknown[]) => unknown,\n  setPopupType: (args: string) => void,\n) {\n  const emptyArray: BlockElement[] = [];\n  const { selectedFile, saveRequest, currentFileTags, setCurrentFileTags } =\n    useGeneralContext();\n\n  const setEmptyPage = () =>\n    setStateFunction((prev: { items: BlockElement[] }) => ({\n      ...prev,\n      items: emptyArray,\n    }));\n\n  useEffect(\n    function loadFile() {\n      if (selectedFile) window.api.loadX(selectedFile);\n      window.api.receive('gotLoadedDataX', (data: string) => {\n        if (!data) {\n          setEmptyPage();\n          return;\n        }\n\n        const parsedData = JSON.parse(data);\n\n        const blocksData: BlockElement[] = parsedData.blocks;\n        parsedData.tags\n          ? setCurrentFileTags(JSON.parse(data).tags)\n          : setCurrentFileTags([]);\n\n        if (!Array.isArray(blocksData)) {\n          setEmptyPage();\n          return;\n        }\n\n        blocksData.map((block: BlockElement) => {\n          if (block.y == null) {\n            block.y = Infinity;\n          }\n          if (block.x == null) {\n            block.x = Infinity;\n          }\n        });\n\n        setStateFunction((prev: { items: BlockElement[] }) => ({\n          ...prev,\n          items: blocksData,\n        }));\n\n        let newData: object[] = blocksData;\n        newData = newData.map((block: BlockElement) => {\n          return { id: block.i, metaData: block.metaData };\n        });\n\n        setAllBlockValues(newData);\n      });\n    },\n    [selectedFile],\n  );\n\n  useEffect(\n    function saveFile() {\n      if (saveRequest?.cmd === 'save') {\n        if (selectedFile) {\n          try {\n            saveGridDataToFile();\n            triggerPopupAnimation('save', setPopupType);\n          } catch (error) {\n            triggerPopupAnimation('error', setPopupType);\n            console.error(error);\n          }\n        } else triggerPopupAnimation('firstSelect', setPopupType);\n      }\n    },\n    [saveRequest],\n  );\n\n  const saveMetaDataPerBlock = (block: BlockElement) => {\n    const found = allBlockValues.find(\n      blockState => blockState.id == block.i,\n    ).metaData;\n\n    block.metaData = {\n      content: found.content,\n      blockStateFunction: () => null,\n    };\n  };\n\n  const saveGridDataToFile = () => {\n    const currentItems = state.items;\n    currentItems.map(saveMetaDataPerBlock);\n\n    const fileData: FileStructure = {\n      blocks: currentItems,\n      tags: currentFileTags,\n      mathMemory: {},\n    };\n\n    window.api.saveX(JSON.stringify(fileData), selectedFile);\n  };\n}\n"
  },
  {
    "path": "src/renderer/hooks/useSettings.tsx",
    "content": "import { useState } from 'react';\n\nfunction useSettings() {\n  const [isRtl, setIsRtl] = useState(true);\n  const [language, setLanguage] = useState('en');\n  const [darkTheme, setDarkTheme] = useState(true);\n  const [colorTheme, setColorTheme] = useState('');\n  const [currentOS, setCurrentOS] = useState('');\n  const [isFilesSidebarOpen, setIsFilesSidebarOpen] = useState(false);\n  const [isMathSidebarOpen, setIsMathSidebarOpen] = useState(false);\n\n  return {\n    isRtl,\n    setIsRtl,\n    language,\n    setLanguage,\n    darkTheme,\n    setDarkTheme,\n    colorTheme,\n    setColorTheme,\n    currentOS,\n    setCurrentOS,\n    isFilesSidebarOpen,\n    setIsFilesSidebarOpen,\n    isMathSidebarOpen,\n    setIsMathSidebarOpen,\n  };\n}\nexport default useSettings;\n"
  },
  {
    "path": "src/typings/index.d.ts",
    "content": "declare module '*.css';\ndeclare module '*.png';\ndeclare module '*.jpg';\ndeclare module '*.jpeg';\ndeclare module '*.svg';\nimport { DOMAttributes } from \"react\";\nimport { MathfieldElementAttributes } from 'mathlive'\n\ntype CustomElement<T> = Partial<T & DOMAttributes<T>>;\n\ndeclare global {\n  namespace JSX {\n    interface IntrinsicElements {\n      [\"math-field\"]: CustomElement<MathfieldElementAttributes>;\n    }\n  }\n}"
  },
  {
    "path": "tools/forge/forge.config.js",
    "content": "// Forge Configuration\nconst path = require('path');\nconst rootDir = process.cwd();\n\nmodule.exports = {\n  // Packager Config\n  packagerConfig: {\n    // Create asar archive for main, renderer process files\n    asar: true,\n    // Set executable name\n    executableName: 'Mathberet',\n    // Set application copyright\n    appCopyright: 'Copyright (C) 2023 Mathberet, yonatanmgr',\n    // Set application icon\n    icon: path.resolve('assets/images/appIcon.ico'),\n  },\n  // Forge Makers\n  makers: [\n    {\n      // Squirrel.Windows is a no-prompt, no-hassle, no-admin method of installing\n      // Windows applications and is therefore the most user friendly you can get.\n      name: '@electron-forge/maker-squirrel',\n      config: {\n        name: 'mathberet',\n      },\n    },\n    {\n      // The Zip target builds basic .zip files containing your packaged application.\n      // There are no platform specific dependencies for using this maker and it will run on any platform.\n      name: '@electron-forge/maker-zip',\n      platforms: ['darwin'],\n    },\n    {\n      // The deb target builds .deb packages, which are the standard package format for Debian-based\n      // Linux distributions such as Ubuntu.\n      name: '@electron-forge/maker-deb',\n      config: {},\n    },\n    {\n      // The RPM target builds .rpm files, which is the standard package format for\n      // RedHat-based Linux distributions such as Fedora.\n      name: '@electron-forge/maker-rpm',\n      config: {},\n    },\n  ],\n  // Forge Plugins\n  plugins: [\n    {\n      name: '@electron-forge/plugin-webpack',\n      config: {\n        // Fix content-security-policy error when image or video src isn't same origin\n        // Remove 'unsafe-eval' to get rid of console warning in development mode.\n        devContentSecurityPolicy: `default-src 'self' 'unsafe-inline' data:; script-src 'self' 'unsafe-inline' data:`,\n        // Ports\n        port: 3000, // Webpack Dev Server port\n        loggerPort: 9000, // Logger port\n        // Main process webpack configuration\n        mainConfig: path.join(rootDir, 'tools/webpack/webpack.main.js'),\n        // Renderer process webpack configuration\n        renderer: {\n          // Configuration file path\n          config: path.join(rootDir, 'tools/webpack/webpack.renderer.js'),\n          // Entrypoints of the application\n          entryPoints: [\n            {\n              // Window process name\n              name: 'app_window',\n              // React Hot Module Replacement (HMR)\n              rhmr: 'react-hot-loader/patch',\n              // HTML index file template\n              html: path.join(rootDir, 'src/renderer/app.html'),\n              // Renderer\n              js: path.join(rootDir, 'src/renderer/appRenderer.tsx'),\n              // Main Window\n              // Preload\n              preload: {\n                js: path.join(rootDir, 'src/renderer/appPreload.tsx'),\n              },\n            },\n          ],\n        },\n        devServer: {\n          liveReload: false,\n        },\n      },\n    },\n  ],\n};\n"
  },
  {
    "path": "tools/webpack/webpack.aliases.js",
    "content": "const { createWebpackAliases } = require('./webpack.helpers');\n\n// Export aliases\nmodule.exports = createWebpackAliases({\n  '@assets': 'assets',\n  '@components': 'src/renderer/components',\n  '@common': 'src/common',\n  '@main': 'src/main',\n  '@renderer': 'src/renderer',\n  '@src': 'src',\n  '@misc': 'misc',\n});\n"
  },
  {
    "path": "tools/webpack/webpack.helpers.js",
    "content": "const path = require('path');\nconst cwd = process.cwd();\n\n\nfunction inDev() {\n  return process.env.NODE_ENV == 'development';\n}\n\nfunction createWebpackAliases (aliases) {\n  const result = {};\n  for (const name in aliases) {\n    result[name] = path.join(cwd, aliases[name]);\n  }\n  return result;\n}\n\nmodule.exports = {\n  inDev,\n  createWebpackAliases,\n};\n"
  },
  {
    "path": "tools/webpack/webpack.main.js",
    "content": "module.exports = {\n  /**\n   * This is the main entry point for your application, it's the first file\n   * that runs in the main process.\n   */\n  entry: ['./src/main/app.ts'],\n  // Put your normal webpack config below here\n  module: {\n    rules: require('./webpack.rules'),\n  },\n  resolve: {\n    extensions: ['.js', '.ts', '.jsx', '.tsx', '.css', '.json'],\n    alias: require('./webpack.aliases'),\n  },\n  stats: 'minimal',\n};\n"
  },
  {
    "path": "tools/webpack/webpack.plugins.js",
    "content": "const webpack = require('webpack');\nconst ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');\nconst ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');\nconst { inDev } = require('./webpack.helpers');\n\nmodule.exports = [\n  new ForkTsCheckerWebpackPlugin(),\n  inDev() && new webpack.HotModuleReplacementPlugin(),\n  inDev() && new ReactRefreshWebpackPlugin(),\n].filter(Boolean);\n"
  },
  {
    "path": "tools/webpack/webpack.renderer.js",
    "content": "const rules = require('./webpack.rules');\nconst plugins = require('./webpack.plugins');\n\nmodule.exports = {\n  module: {\n    rules,\n  },\n  plugins: plugins,\n  resolve: {\n    extensions: ['.js', '.ts', '.jsx', '.tsx', '.css'],\n    alias: {\n      // Custom Aliases\n      ...require('./webpack.aliases'),\n    },\n  },\n  stats: 'minimal',\n  /**\n   * Fix: Enable inline-source-map to fix following:\n   * Dev tools: unable to load source maps over custom protocol\n   */\n  devtool: 'inline-source-map',\n};\n"
  },
  {
    "path": "tools/webpack/webpack.rules.js",
    "content": "module.exports = [\n  {\n    // Add support for native node modules\n    test: /native_modules\\/.+\\.node$/,\n    use: 'node-loader',\n  },\n  {\n    test: /\\.(m?js|node)$/,\n    parser: { amd: false },\n    use: {\n      loader: '@vercel/webpack-asset-relocator-loader',\n      options: {\n        outputAssetBase: 'native_modules',\n      },\n    },\n  },\n  {\n    // Typescript loader\n    test: /\\.tsx?$/,\n    exclude: /(node_modules|\\.webpack)/,\n    use: {\n      loader: 'ts-loader',\n      options: {\n        transpileOnly: true,\n      },\n    },\n  },\n  {\n    // CSS Loader\n    test: /\\.css$/,\n    use: [{ loader: 'style-loader' }, { loader: 'css-loader' }],\n  },\n  {\n    // SCSS (SASS) Loader\n    test: /\\.s[ac]ss$/i,\n    use: [\n      { loader: 'style-loader' },\n      { loader: 'css-loader' },\n      { loader: 'sass-loader' },\n    ],\n  },\n  {\n    // Less loader\n    test: /\\.less$/,\n    use: [\n      { loader: 'style-loader' },\n      { loader: 'css-loader' },\n      { loader: 'less-loader' },\n    ],\n  },\n  {\n    // Assets loader\n    // More information here https://webpack.js.org/guides/asset-modules/\n    test: /\\.(gif|jpe?g|tiff|png|webp|bmp|svg|eot|ttf|woff|woff2)$/i,\n    type: 'asset',\n    generator: {\n      filename: 'assets/[hash][ext][query]',\n    },\n  },\n];\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"forceConsistentCasingInFileNames\": true,\n    \"jsx\": \"react\",\n    \"allowJs\": true,\n    \"target\": \"ES6\",\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n    \"esModuleInterop\": true,\n    \"noImplicitAny\": true,\n    \"sourceMap\": true,\n    \"baseUrl\": \".\",\n    \"outDir\": \"dist\",\n    \"moduleResolution\": \"node\",\n    \"resolveJsonModule\": true,\n    \"paths\": {\n      \"*\": [\"node_modules/*\"],\n      \"@assets/*\": [\"./assets/*\"],\n      \"@components/*\": [\"./src/renderer/components/*\"],\n      \"@common/*\": [\"./src/common/*\"],\n      \"@main/*\": [\"./src/main/*\"],\n      \"@renderer/*\": [\"./src/renderer/*\"],\n      \"@src/*\": [\"./src/*\"],\n      \"@misc/*\": [\"./misc/*\"],\n    }\n  },\n  \"include\": [\"src/**/*\", \"tools/**/*\"]\n}\n"
  }
]