mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-12 22:25:24 +03:00
Use CodeMirror editor on mobile
This commit is contained in:
parent
7b57a66d45
commit
d70aeaeb04
653
web/package-lock.json
generated
653
web/package-lock.json
generated
@ -8,6 +8,9 @@
|
||||
"name": "web-new",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@codemirror/lang-yaml": "^6.1.1",
|
||||
"@codemirror/state": "^6.4.1",
|
||||
"@codemirror/view": "^6.28.1",
|
||||
"@cycjimmy/jsmpeg-player": "^6.0.5",
|
||||
"@hookform/resolvers": "^3.4.2",
|
||||
"@radix-ui/react-alert-dialog": "^1.0.5",
|
||||
@ -29,10 +32,12 @@
|
||||
"@radix-ui/react-toggle": "^1.0.3",
|
||||
"@radix-ui/react-toggle-group": "^1.0.4",
|
||||
"@radix-ui/react-tooltip": "^1.0.7",
|
||||
"@uiw/codemirror-themes-all": "^4.22.2",
|
||||
"apexcharts": "^3.49.1",
|
||||
"axios": "^1.7.2",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"codemirror": "^6.0.1",
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
"date-fns": "^3.6.0",
|
||||
"hls.js": "^1.5.8",
|
||||
@ -226,6 +231,103 @@
|
||||
"statuses": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/autocomplete": {
|
||||
"version": "6.16.3",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.16.3.tgz",
|
||||
"integrity": "sha512-Vl/tIeRVVUCRDuOG48lttBasNQu8usGgXQawBXI7WJAiUDSFOfzflmEsZFZo48mAvAaa4FZ/4/yLLxFtdJaKYA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.17.0",
|
||||
"@lezer/common": "^1.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/commands": {
|
||||
"version": "6.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.6.0.tgz",
|
||||
"integrity": "sha512-qnY+b7j1UNcTS31Eenuc/5YJB6gQOzkUoNmJQc0rznwqSRpeaWWpjkWy2C/MPTcePpsKJEM26hXrOXl1+nceXg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.4.0",
|
||||
"@codemirror/view": "^6.27.0",
|
||||
"@lezer/common": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-yaml": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-yaml/-/lang-yaml-6.1.1.tgz",
|
||||
"integrity": "sha512-HV2NzbK9bbVnjWxwObuZh5FuPCowx51mEfoFT9y3y+M37fA3+pbxx4I7uePuygFzDsAmCTwQSc/kXh/flab4uw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.2.0",
|
||||
"@lezer/yaml": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/language": {
|
||||
"version": "6.10.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.2.tgz",
|
||||
"integrity": "sha512-kgbTYTo0Au6dCSc/TFy7fK3fpJmgHDv1sG1KNQKJXVi+xBTEeBPY/M30YXiU6mMXeH+YIDLsbrT4ZwNRdtF+SA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.23.0",
|
||||
"@lezer/common": "^1.1.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0",
|
||||
"style-mod": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lint": {
|
||||
"version": "6.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.1.tgz",
|
||||
"integrity": "sha512-IZ0Y7S4/bpaunwggW2jYqwLuHj0QtESf5xcROewY6+lDNwZ/NzvR4t+vpYgg9m7V8UXLPYqG+lu3DF470E5Oxg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
"crelt": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/search": {
|
||||
"version": "6.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz",
|
||||
"integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
"crelt": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/state": {
|
||||
"version": "6.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz",
|
||||
"integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@codemirror/view": {
|
||||
"version": "6.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.28.1.tgz",
|
||||
"integrity": "sha512-BUWr+zCJpMkA/u69HlJmR+YkV4yPpM81HeMkOMZuwFa8iM5uJdEPKAs1icIRZKkKmy0Ub1x9/G3PQLTXdpBxrQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.4.0",
|
||||
"style-mod": "^4.1.0",
|
||||
"w3c-keyname": "^2.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@cycjimmy/jsmpeg-player": {
|
||||
"version": "6.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@cycjimmy/jsmpeg-player/-/jsmpeg-player-6.0.5.tgz",
|
||||
@ -846,6 +948,41 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/common": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz",
|
||||
"integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@lezer/highlight": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz",
|
||||
"integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/lr": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.1.tgz",
|
||||
"integrity": "sha512-CHsKq8DMKBf9b3yXPDIU4DbH+ZJd/sJdYOW2llbW/HudP5u0VS6Bfq1hLYfgU7uAYGFIyGGQIsSOXGPEErZiJw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/yaml": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/yaml/-/yaml-1.0.3.tgz",
|
||||
"integrity": "sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@mswjs/cookies": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-1.1.0.tgz",
|
||||
@ -2856,6 +2993,489 @@
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-abcdef": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-abcdef/-/codemirror-theme-abcdef-4.22.2.tgz",
|
||||
"integrity": "sha512-ouordQh/zUT1Y1htGZkWMtGTKgA5Zrb0Wxq6quS2cddx/4/ADAUAKzZCrOL0O6AB7XOH6WCnJWCqEbU2s1K6gg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-abyss": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-abyss/-/codemirror-theme-abyss-4.22.2.tgz",
|
||||
"integrity": "sha512-jTLq7xUwVOlv0+t516eNgEaJ4xbePXs8KryEsmFQ5sTh4hzKP0wxW/P3X0gxtz+ENXxaGYz8wiC4yeqJntuzjA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-androidstudio": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-androidstudio/-/codemirror-theme-androidstudio-4.22.2.tgz",
|
||||
"integrity": "sha512-GAk8Ux4FFUiqauXKKdvHsrcYQ26si/+98zheIc0K18kEr9KB1i0WP1mczrFO4yAQsMbpDBedQPJ1LTLhZZNyow==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-andromeda": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-andromeda/-/codemirror-theme-andromeda-4.22.2.tgz",
|
||||
"integrity": "sha512-CE9IvVjnPpRN+ZRbz7kA26mlQWxqHw3QqWc/3Z26mZwrQ2zNC3+oQJyy47GJSCGLyVrvvsKbvVqg9XPw5yrrvQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-atomone": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-atomone/-/codemirror-theme-atomone-4.22.2.tgz",
|
||||
"integrity": "sha512-3LKzF04rUuli0H6FZhxWicaYkKiucGEDERmkvr7mMPLMW7uwzRjv26GxhLCggtRD5dI1+XbAm9QstyweOWYAeg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-aura": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-aura/-/codemirror-theme-aura-4.22.2.tgz",
|
||||
"integrity": "sha512-/womOFwkrDFxKzqe13YZCtUmtljYeaYABpsDEyrJZnhtgW26i71tX4laDoI58DE9yuiyiAfgxWSDZhvmK/1mUA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-basic": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-basic/-/codemirror-theme-basic-4.22.2.tgz",
|
||||
"integrity": "sha512-RHWhWMhCzTGscfbJvJtIRW9dccPWYS/BJiE5DtCPk1IYPnJHrXF3hzCpTK2CYz1/d+6V/XRyIzujhyxrMs0+mw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-bbedit": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-bbedit/-/codemirror-theme-bbedit-4.22.2.tgz",
|
||||
"integrity": "sha512-adeyK7fbdfDS3zELSUPbce7xMEMNhJbSX0hXxaL6L4jdmt2/OTHCwovNPzlH6AWyMupE+WTQmVY6y67m14dikg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-bespin": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-bespin/-/codemirror-theme-bespin-4.22.2.tgz",
|
||||
"integrity": "sha512-NZ+kyWNzZgJq38Ba2FGl+nnZDAPdy97w5y160QiiAW+Vuwii24YnkYvoHVmMxsXDphwd/sLfVktfahbAh4ntpQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-console": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-console/-/codemirror-theme-console-4.22.2.tgz",
|
||||
"integrity": "sha512-K8fir17aBiwkTBwMbyVbnPD+3Sx5irRtFzwG6TSK+EciWofsVkWGbkIZpDQqbUYbf4WBf5dw3j5byl3isNTWnA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-copilot": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-copilot/-/codemirror-theme-copilot-4.22.2.tgz",
|
||||
"integrity": "sha512-M1mif1uqZdc49rPNCpXcs4gANr30w/I5C+dK+Mxwe6+RAkwcqNB/uHuIUj0UvARiSbwNUTpTMkMNXeuT//f3Pg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-darcula": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-darcula/-/codemirror-theme-darcula-4.22.2.tgz",
|
||||
"integrity": "sha512-YF3LTTc1Rus3atNuFvkLsZvhdtxRwGEAOcEGknu7by5jzZxLPHpDLzAF9VFOIKg6j/KBZ2RNmMicVTjrB8LXHg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-dracula": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-dracula/-/codemirror-theme-dracula-4.22.2.tgz",
|
||||
"integrity": "sha512-OEB5Tu0EHNDf99m5g39hoSqf0UICzWn+z3HLsOfdjzJz7hhZpQ99x/YEZ+j+utfLQbHcusvk06DrV+C88kRyyg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-duotone": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-duotone/-/codemirror-theme-duotone-4.22.2.tgz",
|
||||
"integrity": "sha512-bZ8CvPcnHDIbMLhDrmF4M084Zf5daKiGyrmCFhHeFUeKGbIgIUu+UnkmaNjz6jteOmYEZR05wh8h3NK4Ty2OtA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-eclipse": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-eclipse/-/codemirror-theme-eclipse-4.22.2.tgz",
|
||||
"integrity": "sha512-iYdl3wJ9D0e+z6opw5fLWzrJ1ge83/WpbPvtA++hqPZnFdoPfKynzdEq8U6V+uQpoVQnZuo0DRQljnWW070y2g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-github": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-github/-/codemirror-theme-github-4.22.2.tgz",
|
||||
"integrity": "sha512-tqGOOgVzbStJWUQmMLRWyymyD3DPF4TUSJx2DcXpeCF3YStWMd957I26uQQaqR1ppAcWFsprjkl2oL3piBxFdA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-gruvbox-dark": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-gruvbox-dark/-/codemirror-theme-gruvbox-dark-4.22.2.tgz",
|
||||
"integrity": "sha512-U2YHFguSOX5xmCW/E5h7sAWrnkYRlJB2yB9ucOs/u1TohG7wD9zbGu5lCN40xflAB1BJ+r5y1j5uSQNgQrNheA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-kimbie": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-kimbie/-/codemirror-theme-kimbie-4.22.2.tgz",
|
||||
"integrity": "sha512-dzXmOlgM8Ho6M4fzs95Zbttj9+VEFZtbS5nF98aoFqaqNeQU1iEk3EAtuNz9KRu9ogPvAeUsHqc76jnxB2J63g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-material": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-material/-/codemirror-theme-material-4.22.2.tgz",
|
||||
"integrity": "sha512-YJPNkNZo1RqtGgF3KNxFkSY7LDY8RqzJ7N5DR6o0d0IHCQSeTNk3TE14Gmc66GqfoPXfEQVLtPk/MiRZ/JQSpQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-monokai": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-monokai/-/codemirror-theme-monokai-4.22.2.tgz",
|
||||
"integrity": "sha512-lkpG9W2eDBylcqqD7w8zDXib9ydZOCnGOKRsZh651F4SN1iK4Za1hGrzx+g9PD+rpBBrGZ3UAomoAb2BZRV0og==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-monokai-dimmed": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-monokai-dimmed/-/codemirror-theme-monokai-dimmed-4.22.2.tgz",
|
||||
"integrity": "sha512-q/jopOSfttwh/uc04XMLXKKs2EsqRpbL6krBLQhQKahDXRR54G1UcLQNG+KglBLWSuCc5dYlQwcTjzwAFQJWgA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-noctis-lilac": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-noctis-lilac/-/codemirror-theme-noctis-lilac-4.22.2.tgz",
|
||||
"integrity": "sha512-nU+XC5NwbwZ+8X29OSMRV0e8eb1YCiwGkzuXN/cEnEnIcW5udNPydHalOwObOaDphC3dO+x8WSIf7LLycjpUsw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-nord": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-nord/-/codemirror-theme-nord-4.22.2.tgz",
|
||||
"integrity": "sha512-aqvS4WqFT7NWmWZ42m75SOfOGQE0n1+Hryb4ZxGpBweo9FQjxq7sswUACZMqH0gY8+JTUSCoRu7fFq0QqCykCQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-okaidia": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-okaidia/-/codemirror-theme-okaidia-4.22.2.tgz",
|
||||
"integrity": "sha512-X8QR4FB/GihU9Q/YTtpFGICLGQ7fY+zGJsmt7WAdvomBcfNe4grvj08MU+KoJ967iB1LvluH8cFVDRdu4Nh8sw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-quietlight": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-quietlight/-/codemirror-theme-quietlight-4.22.2.tgz",
|
||||
"integrity": "sha512-NtHUttXgnDE8F+lrJA6HfiTNjY8GVJjUwtpvOQywqgNoBDwBpuEfdpvZ/OI0EW0sqZpbVlWfmANT4H5oj3ODaw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-red": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-red/-/codemirror-theme-red-4.22.2.tgz",
|
||||
"integrity": "sha512-q+AZv6i9FrAXEFipcGsc754QPhWlLFIW/FEjcKz9fHXtmeSHR1e1ZONG/xzFcjRBor0rQizrZ/Buk3cFaCCNUQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-solarized": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-solarized/-/codemirror-theme-solarized-4.22.2.tgz",
|
||||
"integrity": "sha512-WSjLMzgXXUFxdDUmAyOyX1NmxdTdcLtQXZzZkgkJAm1e/F8OKlbPAkDcrNsTrMV4SGpcM2iwJiauNIxG48evJA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-sublime": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-sublime/-/codemirror-theme-sublime-4.22.2.tgz",
|
||||
"integrity": "sha512-9qcRyflyhc4J9veTVAY3JfXXgs3QOPvIIGm3YrZTwcx8s0OTD+iLUSUY/UMwyqEGCIHhyrNr6dr8qisdIL0Zvg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-tokyo-night": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-tokyo-night/-/codemirror-theme-tokyo-night-4.22.2.tgz",
|
||||
"integrity": "sha512-e6Z2r+TJsI+HY4vbozSOGkyoRQpcKb2BPY/7EHv+BRMzvUC62b8ZDbgYfctQBrEw50+vBRcs91slfMCWQ19AbQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-tokyo-night-day": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-tokyo-night-day/-/codemirror-theme-tokyo-night-day-4.22.2.tgz",
|
||||
"integrity": "sha512-bP48DXp+tmFhGoRVyBtntkZl2a7tNacHwE2fDgj/Le97pHfzxS/DQ3iHqcUq49I0ZefQnswCZEASfupApqucvQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-tokyo-night-storm": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-tokyo-night-storm/-/codemirror-theme-tokyo-night-storm-4.22.2.tgz",
|
||||
"integrity": "sha512-gnBxYrf0hVvE57yPaFX7esZsyRoDYWD3NBc6+YngBjGAq8CZ/JZphs13UBY3RNZq0ka9jJTkVanQOp+qb8cF1w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-tomorrow-night-blue": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-tomorrow-night-blue/-/codemirror-theme-tomorrow-night-blue-4.22.2.tgz",
|
||||
"integrity": "sha512-VFcqGpeXKS2laV4er9DiqnpOthmfMYQ85Jfmf44qe8T9iqFdE0YVyUNnKqH6vXrzaF17/PJgAxZFuohxAz381w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-vscode": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-vscode/-/codemirror-theme-vscode-4.22.2.tgz",
|
||||
"integrity": "sha512-wy+rd27Pz1f979QT8wHlBu7+XuwduSGDjqE972JRVf+Wqn2MbhXfTqD5YDx0lQJ+u05Y2IJKKbgPrWS+wt1a6A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-white": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-white/-/codemirror-theme-white-4.22.2.tgz",
|
||||
"integrity": "sha512-jFilUJLyNZkvMld+UFc/j27CHcMxxENiYHYrovBIO8lWN0qssvemvPNr/fKMFWuTHXwx6uGGUKP2MunxkrN0Fw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-theme-xcode": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-xcode/-/codemirror-theme-xcode-4.22.2.tgz",
|
||||
"integrity": "sha512-pHOeWHMK7lmxGjrwBnvaIsFppMaKjDbZ6fgWCItWUFI+JeO4/Orrn+q0r1tRbsbRAMPaVuxl+SUZUhPGuo8GCw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-themes": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-themes/-/codemirror-themes-4.22.2.tgz",
|
||||
"integrity": "sha512-gsLHn6SUuV5iboBvGrM7YimzLFHQmsNlkGIYs3UaVUJTo/A/ZrKoSJNyPziShLRjBXA2UwKdBTIU6VhHyyaChw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@codemirror/language": ">=6.0.0",
|
||||
"@codemirror/state": ">=6.0.0",
|
||||
"@codemirror/view": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/codemirror-themes-all": {
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/codemirror-themes-all/-/codemirror-themes-all-4.22.2.tgz",
|
||||
"integrity": "sha512-/57s1Pt8BUS+nBrFm8F4R1vpSs8FWhENL2PkfvO8opedTtFUzsIdV88jZHG8PDl7ydJta0ijO+w3qr4Z0IJ5ZQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/codemirror-theme-abcdef": "4.22.2",
|
||||
"@uiw/codemirror-theme-abyss": "4.22.2",
|
||||
"@uiw/codemirror-theme-androidstudio": "4.22.2",
|
||||
"@uiw/codemirror-theme-andromeda": "4.22.2",
|
||||
"@uiw/codemirror-theme-atomone": "4.22.2",
|
||||
"@uiw/codemirror-theme-aura": "4.22.2",
|
||||
"@uiw/codemirror-theme-basic": "4.22.2",
|
||||
"@uiw/codemirror-theme-bbedit": "4.22.2",
|
||||
"@uiw/codemirror-theme-bespin": "4.22.2",
|
||||
"@uiw/codemirror-theme-console": "4.22.2",
|
||||
"@uiw/codemirror-theme-copilot": "4.22.2",
|
||||
"@uiw/codemirror-theme-darcula": "4.22.2",
|
||||
"@uiw/codemirror-theme-dracula": "4.22.2",
|
||||
"@uiw/codemirror-theme-duotone": "4.22.2",
|
||||
"@uiw/codemirror-theme-eclipse": "4.22.2",
|
||||
"@uiw/codemirror-theme-github": "4.22.2",
|
||||
"@uiw/codemirror-theme-gruvbox-dark": "4.22.2",
|
||||
"@uiw/codemirror-theme-kimbie": "4.22.2",
|
||||
"@uiw/codemirror-theme-material": "4.22.2",
|
||||
"@uiw/codemirror-theme-monokai": "4.22.2",
|
||||
"@uiw/codemirror-theme-monokai-dimmed": "4.22.2",
|
||||
"@uiw/codemirror-theme-noctis-lilac": "4.22.2",
|
||||
"@uiw/codemirror-theme-nord": "4.22.2",
|
||||
"@uiw/codemirror-theme-okaidia": "4.22.2",
|
||||
"@uiw/codemirror-theme-quietlight": "4.22.2",
|
||||
"@uiw/codemirror-theme-red": "4.22.2",
|
||||
"@uiw/codemirror-theme-solarized": "4.22.2",
|
||||
"@uiw/codemirror-theme-sublime": "4.22.2",
|
||||
"@uiw/codemirror-theme-tokyo-night": "4.22.2",
|
||||
"@uiw/codemirror-theme-tokyo-night-day": "4.22.2",
|
||||
"@uiw/codemirror-theme-tokyo-night-storm": "4.22.2",
|
||||
"@uiw/codemirror-theme-tomorrow-night-blue": "4.22.2",
|
||||
"@uiw/codemirror-theme-vscode": "4.22.2",
|
||||
"@uiw/codemirror-theme-white": "4.22.2",
|
||||
"@uiw/codemirror-theme-xcode": "4.22.2",
|
||||
"@uiw/codemirror-themes": "4.22.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/@ungap/structured-clone": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
|
||||
@ -3565,6 +4185,21 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/codemirror": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz",
|
||||
"integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/commands": "^6.0.0",
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/lint": "^6.0.0",
|
||||
"@codemirror/search": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
@ -3629,6 +4264,12 @@
|
||||
"toggle-selection": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/crelt": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
|
||||
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
@ -7200,6 +7841,12 @@
|
||||
"integrity": "sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/style-mod": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
|
||||
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/sucrase": {
|
||||
"version": "3.34.0",
|
||||
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz",
|
||||
@ -8008,6 +8655,12 @@
|
||||
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz",
|
||||
"integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw=="
|
||||
},
|
||||
"node_modules/w3c-keyname": {
|
||||
"version": "2.2.8",
|
||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
|
||||
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/w3c-xmlserializer": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
|
||||
|
||||
@ -14,6 +14,9 @@
|
||||
"coverage": "vitest run --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codemirror/lang-yaml": "^6.1.1",
|
||||
"@codemirror/state": "^6.4.1",
|
||||
"@codemirror/view": "^6.28.1",
|
||||
"@cycjimmy/jsmpeg-player": "^6.0.5",
|
||||
"@hookform/resolvers": "^3.4.2",
|
||||
"@radix-ui/react-alert-dialog": "^1.0.5",
|
||||
@ -35,10 +38,12 @@
|
||||
"@radix-ui/react-toggle": "^1.0.3",
|
||||
"@radix-ui/react-toggle-group": "^1.0.4",
|
||||
"@radix-ui/react-tooltip": "^1.0.7",
|
||||
"@uiw/codemirror-themes-all": "^4.22.2",
|
||||
"apexcharts": "^3.49.1",
|
||||
"axios": "^1.7.2",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"codemirror": "^6.0.1",
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
"date-fns": "^3.6.0",
|
||||
"hls.js": "^1.5.8",
|
||||
|
||||
21
web/src/components/code_editor/CodeEditor.tsx
Normal file
21
web/src/components/code_editor/CodeEditor.tsx
Normal file
@ -0,0 +1,21 @@
|
||||
import { isDesktop } from "react-device-detect";
|
||||
import { MonacoEditor } from "./MonacoEditor";
|
||||
import { CodeMirrorEditor } from "./CodeMirrorEditor";
|
||||
|
||||
/**
|
||||
* Provides an interface for a Code Editor, to enable easy swapping between different implementations
|
||||
*/
|
||||
export type CodeEditorProps = {
|
||||
initialContent: string;
|
||||
yamlSchemaUrl: string;
|
||||
onDidChangeContent: (content: string) => void;
|
||||
};
|
||||
|
||||
/** Used to swap between the Monaco editor and the CodeMirror editor depending on device type.
|
||||
* The Monaco editor doesn't work well on mobile devices, see Github issue: https://github.com/microsoft/monaco-editor/issues/246
|
||||
*
|
||||
* A common solution is to switch to CodeMirror on mobile devices as they have invested significantly in touch support.
|
||||
*
|
||||
* It would be great to revisit this in in the future if/when Monaco improves mobile support.
|
||||
*/
|
||||
export const CodeEditor: (props: CodeEditorProps) => JSX.Element = isDesktop ? MonacoEditor : CodeMirrorEditor;
|
||||
109
web/src/components/code_editor/CodeMirrorEditor.tsx
Normal file
109
web/src/components/code_editor/CodeMirrorEditor.tsx
Normal file
@ -0,0 +1,109 @@
|
||||
import { EditorState } from "@codemirror/state";
|
||||
import { yaml } from "@codemirror/lang-yaml";
|
||||
import {
|
||||
EditorView,
|
||||
crosshairCursor,
|
||||
drawSelection,
|
||||
dropCursor,
|
||||
highlightActiveLine,
|
||||
highlightActiveLineGutter,
|
||||
highlightSpecialChars,
|
||||
keymap,
|
||||
lineNumbers,
|
||||
rectangularSelection,
|
||||
} from "@codemirror/view";
|
||||
import { useEffect, useRef } from "react";
|
||||
import type { CodeEditorProps } from "./CodeEditor";
|
||||
import {
|
||||
indentOnInput,
|
||||
bracketMatching,
|
||||
foldGutter,
|
||||
foldKeymap,
|
||||
} from "@codemirror/language";
|
||||
import {
|
||||
defaultKeymap,
|
||||
history,
|
||||
historyKeymap,
|
||||
indentWithTab,
|
||||
} from "@codemirror/commands";
|
||||
import { searchKeymap, highlightSelectionMatches } from "@codemirror/search";
|
||||
import {
|
||||
autocompletion,
|
||||
completionKeymap,
|
||||
closeBrackets,
|
||||
closeBracketsKeymap,
|
||||
} from "@codemirror/autocomplete";
|
||||
import { lintKeymap } from "@codemirror/lint";
|
||||
import { vscodeLight, githubDark } from "@uiw/codemirror-themes-all";
|
||||
import { useTheme } from "@/context/theme-provider";
|
||||
|
||||
/**
|
||||
* Uses `CodeMirror` as a code editor implementation.
|
||||
* Currently doesn't support yaml schema validation or linting.
|
||||
*/
|
||||
export function CodeMirrorEditor({
|
||||
initialContent,
|
||||
onDidChangeContent,
|
||||
}: Omit<CodeEditorProps, "schemaUrl">) {
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
const { theme, systemTheme } = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
if (containerRef.current == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const onChangeListener = EditorView.updateListener.of((update) => {
|
||||
if (update.docChanged) {
|
||||
onDidChangeContent(update.state.doc.toString());
|
||||
}
|
||||
});
|
||||
|
||||
const state = EditorState.create({
|
||||
doc: initialContent,
|
||||
extensions: [
|
||||
// vscodeDark isn't highlighting colors properly in yaml
|
||||
(systemTheme || theme) == "dark" ? githubDark : vscodeLight,
|
||||
lineNumbers(),
|
||||
highlightActiveLineGutter(),
|
||||
highlightSpecialChars(),
|
||||
history(),
|
||||
foldGutter(),
|
||||
drawSelection(),
|
||||
dropCursor(),
|
||||
EditorState.allowMultipleSelections.of(true),
|
||||
indentOnInput(),
|
||||
bracketMatching(),
|
||||
closeBrackets(),
|
||||
autocompletion(),
|
||||
rectangularSelection(),
|
||||
crosshairCursor(),
|
||||
highlightActiveLine(),
|
||||
highlightSelectionMatches(),
|
||||
keymap.of([
|
||||
...closeBracketsKeymap,
|
||||
...defaultKeymap,
|
||||
...searchKeymap,
|
||||
...historyKeymap,
|
||||
...foldKeymap,
|
||||
...completionKeymap,
|
||||
...lintKeymap,
|
||||
indentWithTab,
|
||||
]),
|
||||
yaml(),
|
||||
onChangeListener,
|
||||
],
|
||||
});
|
||||
|
||||
const view = new EditorView({
|
||||
state,
|
||||
parent: containerRef.current,
|
||||
});
|
||||
|
||||
return () => {
|
||||
view.destroy();
|
||||
};
|
||||
}, [initialContent, onDidChangeContent, systemTheme, theme]);
|
||||
|
||||
return <div ref={containerRef} className="h-full w-full overflow-y-scroll" />;
|
||||
}
|
||||
80
web/src/components/code_editor/MonacoEditor.tsx
Normal file
80
web/src/components/code_editor/MonacoEditor.tsx
Normal file
@ -0,0 +1,80 @@
|
||||
import { useTheme } from "@/context/theme-provider";
|
||||
import * as monaco from "monaco-editor";
|
||||
import { configureMonacoYaml } from "monaco-yaml";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import type { CodeEditorProps } from "./CodeEditor";
|
||||
|
||||
export function MonacoEditor({
|
||||
initialContent,
|
||||
yamlSchemaUrl,
|
||||
onDidChangeContent,
|
||||
}: CodeEditorProps) {
|
||||
const [editor, setEditor] =
|
||||
useState<monaco.editor.IStandaloneCodeEditor | null>(null);
|
||||
const [model, setModel] = useState<monaco.editor.ITextModel | null>(null);
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const { theme, systemTheme } = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
const disposeOnDidChangeContent = model?.onDidChangeContent(() => {
|
||||
onDidChangeContent(model.getValue());
|
||||
}).dispose;
|
||||
return () => {
|
||||
disposeOnDidChangeContent?.();
|
||||
};
|
||||
}, [model, onDidChangeContent]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!initialContent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (model != null && editor != null) {
|
||||
// we don't need to recreate the editor if it already exists
|
||||
editor.layout();
|
||||
return;
|
||||
}
|
||||
|
||||
const modelUri = monaco.Uri.parse("a://b/api/config/schema.json");
|
||||
|
||||
let tempModel: monaco.editor.ITextModel;
|
||||
if (monaco.editor.getModels().length > 0) {
|
||||
tempModel = monaco.editor.getModel(modelUri)!;
|
||||
} else {
|
||||
tempModel = monaco.editor.createModel(initialContent, "yaml", modelUri);
|
||||
}
|
||||
setModel(tempModel);
|
||||
|
||||
configureMonacoYaml(monaco, {
|
||||
enableSchemaRequest: true,
|
||||
hover: true,
|
||||
completion: true,
|
||||
validate: true,
|
||||
format: true,
|
||||
schemas: [
|
||||
{
|
||||
uri: yamlSchemaUrl,
|
||||
fileMatch: [String(modelUri)],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
if (containerRef.current != null) {
|
||||
setEditor(
|
||||
monaco.editor.create(containerRef.current, {
|
||||
language: "yaml",
|
||||
model: tempModel,
|
||||
scrollBeyondLastLine: false,
|
||||
theme: (systemTheme || theme) == "dark" ? "vs-dark" : "vs-light",
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return () => {
|
||||
containerRef.current = null;
|
||||
};
|
||||
}, [initialContent, model, editor, yamlSchemaUrl, systemTheme, theme]);
|
||||
|
||||
return <div ref={containerRef} className="h-full w-full" />;
|
||||
}
|
||||
@ -1,18 +1,16 @@
|
||||
import useSWR from "swr";
|
||||
import * as monaco from "monaco-editor";
|
||||
import { configureMonacoYaml } from "monaco-yaml";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useApiHost } from "@/api";
|
||||
import Heading from "@/components/ui/heading";
|
||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import axios from "axios";
|
||||
import copy from "copy-to-clipboard";
|
||||
import { useTheme } from "@/context/theme-provider";
|
||||
import { Toaster } from "@/components/ui/sonner";
|
||||
import { toast } from "sonner";
|
||||
import { LuCopy, LuSave } from "react-icons/lu";
|
||||
import { MdOutlineRestartAlt } from "react-icons/md";
|
||||
import { CodeEditor } from "@/components/code_editor/CodeEditor";
|
||||
|
||||
type SaveOptions = "saveonly" | "restart";
|
||||
|
||||
@ -25,27 +23,17 @@ function ConfigEditor() {
|
||||
|
||||
const { data: config } = useSWR<string>("config/raw");
|
||||
|
||||
const { theme, systemTheme } = useTheme();
|
||||
const [error, setError] = useState<string | undefined>();
|
||||
|
||||
const editorRef = useRef<monaco.editor.IStandaloneCodeEditor | null>(null);
|
||||
const modelRef = useRef<monaco.editor.ITextModel | null>(null);
|
||||
const configRef = useRef<HTMLDivElement | null>(null);
|
||||
/** Contains the config once touched by the user */
|
||||
const [dirtyConfig, setDirtyConfig] = useState<string | undefined>();
|
||||
|
||||
const onHandleSaveConfig = useCallback(
|
||||
async (save_option: SaveOptions) => {
|
||||
if (!editorRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
axios
|
||||
.post(
|
||||
`config/save?save_option=${save_option}`,
|
||||
editorRef.current.getValue(),
|
||||
{
|
||||
headers: { "Content-Type": "text/plain" },
|
||||
},
|
||||
)
|
||||
.post(`config/save?save_option=${save_option}`, dirtyConfig, {
|
||||
headers: { "Content-Type": "text/plain" },
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status === 200) {
|
||||
setError("");
|
||||
@ -62,73 +50,16 @@ function ConfigEditor() {
|
||||
}
|
||||
});
|
||||
},
|
||||
[editorRef],
|
||||
[dirtyConfig],
|
||||
);
|
||||
|
||||
const handleCopyConfig = useCallback(async () => {
|
||||
if (!editorRef.current) {
|
||||
if (!dirtyConfig) {
|
||||
return;
|
||||
}
|
||||
|
||||
copy(editorRef.current.getValue());
|
||||
copy(dirtyConfig);
|
||||
toast.success("Config copied to clipboard.", { position: "top-center" });
|
||||
}, [editorRef]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!config) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (modelRef.current != null) {
|
||||
// we don't need to recreate the editor if it already exists
|
||||
editorRef.current?.layout();
|
||||
return;
|
||||
}
|
||||
|
||||
const modelUri = monaco.Uri.parse("a://b/api/config/schema.json");
|
||||
|
||||
if (monaco.editor.getModels().length > 0) {
|
||||
modelRef.current = monaco.editor.getModel(modelUri);
|
||||
} else {
|
||||
modelRef.current = monaco.editor.createModel(config, "yaml", modelUri);
|
||||
}
|
||||
|
||||
configureMonacoYaml(monaco, {
|
||||
enableSchemaRequest: true,
|
||||
hover: true,
|
||||
completion: true,
|
||||
validate: true,
|
||||
format: true,
|
||||
schemas: [
|
||||
{
|
||||
uri: `${apiHost}api/config/schema.json`,
|
||||
fileMatch: [String(modelUri)],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const container = configRef.current;
|
||||
|
||||
if (container != null) {
|
||||
editorRef.current = monaco.editor.create(container, {
|
||||
language: "yaml",
|
||||
model: modelRef.current,
|
||||
scrollBeyondLastLine: false,
|
||||
theme: (systemTheme || theme) == "dark" ? "vs-dark" : "vs-light",
|
||||
});
|
||||
}
|
||||
|
||||
return () => {
|
||||
configRef.current = null;
|
||||
modelRef.current = null;
|
||||
};
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (config && modelRef.current) {
|
||||
modelRef.current.setValue(config);
|
||||
}
|
||||
}, [config]);
|
||||
}, [dirtyConfig]);
|
||||
|
||||
if (!config) {
|
||||
return <ActivityIndicator />;
|
||||
@ -178,7 +109,13 @@ function ConfigEditor() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div ref={configRef} className="mt-2 h-[calc(100%-2.75rem)]" />
|
||||
<div className="mt-2 h-[calc(100%-2.75rem)]">
|
||||
<CodeEditor
|
||||
initialContent={config}
|
||||
onDidChangeContent={setDirtyConfig}
|
||||
yamlSchemaUrl={`${apiHost}api/config/schema.json`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Toaster closeButton={true} />
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user