From 4a706c64a87630d6d326865f3058295f8a1d958b Mon Sep 17 00:00:00 2001 From: Murilo Polese Date: Mon, 20 Mar 2023 17:36:01 +0100 Subject: [PATCH 1/9] WIP FTP ui with React and Typescript --- .gitignore | 3 +- index.js | 14 +- ui/{arduino => editor}/about.css | 0 ui/{arduino => editor}/about.html | 0 ui/{arduino => editor}/app.js | 0 ui/{arduino => editor}/assets/about_image.png | Bin ui/{arduino => editor}/components/editor.js | 0 ui/{arduino => editor}/components/filename.js | 0 ui/{arduino => editor}/components/icon.js | 0 ui/{arduino => editor}/components/message.js | 0 .../components/newfiledialog.js | 0 ui/{arduino => editor}/components/panel.js | 0 .../components/panel_files.js | 0 .../components/panel_terminal.js | 0 .../components/portdialog.js | 0 ui/{arduino => editor}/components/toolbar.js | 0 .../components/toolbar_button.js | 0 ui/{arduino => editor}/icons/Connect.svg | 0 ui/{arduino => editor}/icons/Connect@3x.png | Bin ui/{arduino => editor}/icons/Copy-Left.svg | 0 ui/{arduino => editor}/icons/Copy-Left@3x.png | Bin ui/{arduino => editor}/icons/Copy-Right.svg | 0 .../icons/Copy-Right@3x.png | Bin ui/{arduino => editor}/icons/Copy.png | Bin ui/{arduino => editor}/icons/Copy.svg | 0 ui/{arduino => editor}/icons/Delete.svg | 0 ui/{arduino => editor}/icons/Delete@3x.png | Bin ui/{arduino => editor}/icons/Disconnect.svg | 0 .../icons/Disconnect@3x.png | Bin .../icons/File-Explorer.svg | 0 .../icons/File-Explorer@3x.png | Bin ui/{arduino => editor}/icons/New.svg | 0 ui/{arduino => editor}/icons/New@3x.png | Bin ui/{arduino => editor}/icons/Open.svg | 0 ui/{arduino => editor}/icons/Open@3x.png | Bin ui/{arduino => editor}/icons/Output.svg | 0 ui/{arduino => editor}/icons/Output@3x.png | Bin ui/{arduino => editor}/icons/Paste.png | Bin ui/{arduino => editor}/icons/Paste.svg | 0 ui/{arduino => editor}/icons/Reboot.svg | 0 ui/{arduino => editor}/icons/Reboot@3x.png | Bin ui/{arduino => editor}/icons/Run.svg | 0 ui/{arduino => editor}/icons/Run@3x.png | Bin ui/{arduino => editor}/icons/Save.svg | 0 ui/{arduino => editor}/icons/Save@3x.png | Bin ui/{arduino => editor}/icons/Stop.svg | 0 ui/{arduino => editor}/icons/Stop@3x.png | Bin ui/{arduino => editor}/index.html | 0 ui/{arduino => editor}/libs/FileSaver.js | 0 ui/{arduino => editor}/libs/ace/ace.js | 0 .../libs/ace/ext-beautify.js | 0 .../libs/ace/ext-code_lens.js | 0 .../libs/ace/ext-elastic_tabstops_lite.js | 0 ui/{arduino => editor}/libs/ace/ext-emmet.js | 0 .../libs/ace/ext-error_marker.js | 0 .../libs/ace/ext-keybinding_menu.js | 0 .../libs/ace/ext-language_tools.js | 0 .../libs/ace/ext-linking.js | 0 .../libs/ace/ext-modelist.js | 0 .../libs/ace/ext-options.js | 0 ui/{arduino => editor}/libs/ace/ext-prompt.js | 0 ui/{arduino => editor}/libs/ace/ext-rtl.js | 0 .../libs/ace/ext-searchbox.js | 0 .../libs/ace/ext-settings_menu.js | 0 .../libs/ace/ext-spellcheck.js | 0 ui/{arduino => editor}/libs/ace/ext-split.js | 0 .../libs/ace/ext-static_highlight.js | 0 .../libs/ace/ext-statusbar.js | 0 .../libs/ace/ext-textarea.js | 0 .../libs/ace/ext-themelist.js | 0 .../libs/ace/ext-whitespace.js | 0 .../libs/ace/keybinding-emacs.js | 0 .../libs/ace/keybinding-sublime.js | 0 .../libs/ace/keybinding-vim.js | 0 .../libs/ace/keybinding-vscode.js | 0 ui/{arduino => editor}/libs/ace/mode-abap.js | 0 ui/{arduino => editor}/libs/ace/mode-abc.js | 0 .../libs/ace/mode-actionscript.js | 0 ui/{arduino => editor}/libs/ace/mode-ada.js | 0 ui/{arduino => editor}/libs/ace/mode-alda.js | 0 .../libs/ace/mode-apache_conf.js | 0 ui/{arduino => editor}/libs/ace/mode-apex.js | 0 .../libs/ace/mode-applescript.js | 0 ui/{arduino => editor}/libs/ace/mode-aql.js | 0 .../libs/ace/mode-asciidoc.js | 0 ui/{arduino => editor}/libs/ace/mode-asl.js | 0 .../libs/ace/mode-assembly_x86.js | 0 .../libs/ace/mode-autohotkey.js | 0 .../libs/ace/mode-batchfile.js | 0 .../libs/ace/mode-c9search.js | 0 ui/{arduino => editor}/libs/ace/mode-c_cpp.js | 0 ui/{arduino => editor}/libs/ace/mode-cirru.js | 0 .../libs/ace/mode-clojure.js | 0 ui/{arduino => editor}/libs/ace/mode-cobol.js | 0 .../libs/ace/mode-coffee.js | 0 .../libs/ace/mode-coldfusion.js | 0 .../libs/ace/mode-crystal.js | 0 .../libs/ace/mode-csharp.js | 0 .../libs/ace/mode-csound_document.js | 0 .../libs/ace/mode-csound_orchestra.js | 0 .../libs/ace/mode-csound_score.js | 0 ui/{arduino => editor}/libs/ace/mode-csp.js | 0 ui/{arduino => editor}/libs/ace/mode-css.js | 0 ui/{arduino => editor}/libs/ace/mode-curly.js | 0 ui/{arduino => editor}/libs/ace/mode-d.js | 0 ui/{arduino => editor}/libs/ace/mode-dart.js | 0 ui/{arduino => editor}/libs/ace/mode-diff.js | 0 .../libs/ace/mode-django.js | 0 .../libs/ace/mode-dockerfile.js | 0 ui/{arduino => editor}/libs/ace/mode-dot.js | 0 .../libs/ace/mode-drools.js | 0 .../libs/ace/mode-edifact.js | 0 .../libs/ace/mode-eiffel.js | 0 ui/{arduino => editor}/libs/ace/mode-ejs.js | 0 .../libs/ace/mode-elixir.js | 0 ui/{arduino => editor}/libs/ace/mode-elm.js | 0 .../libs/ace/mode-erlang.js | 0 ui/{arduino => editor}/libs/ace/mode-forth.js | 0 .../libs/ace/mode-fortran.js | 0 .../libs/ace/mode-fsharp.js | 0 ui/{arduino => editor}/libs/ace/mode-fsl.js | 0 ui/{arduino => editor}/libs/ace/mode-ftl.js | 0 ui/{arduino => editor}/libs/ace/mode-gcode.js | 0 .../libs/ace/mode-gherkin.js | 0 .../libs/ace/mode-gitignore.js | 0 ui/{arduino => editor}/libs/ace/mode-glsl.js | 0 .../libs/ace/mode-gobstones.js | 0 .../libs/ace/mode-golang.js | 0 .../libs/ace/mode-graphqlschema.js | 0 .../libs/ace/mode-groovy.js | 0 ui/{arduino => editor}/libs/ace/mode-haml.js | 0 .../libs/ace/mode-handlebars.js | 0 .../libs/ace/mode-haskell.js | 0 .../libs/ace/mode-haskell_cabal.js | 0 ui/{arduino => editor}/libs/ace/mode-haxe.js | 0 ui/{arduino => editor}/libs/ace/mode-hjson.js | 0 ui/{arduino => editor}/libs/ace/mode-html.js | 0 .../libs/ace/mode-html_elixir.js | 0 .../libs/ace/mode-html_ruby.js | 0 ui/{arduino => editor}/libs/ace/mode-ini.js | 0 ui/{arduino => editor}/libs/ace/mode-io.js | 0 ui/{arduino => editor}/libs/ace/mode-jack.js | 0 ui/{arduino => editor}/libs/ace/mode-jade.js | 0 ui/{arduino => editor}/libs/ace/mode-java.js | 0 .../libs/ace/mode-javascript.js | 0 ui/{arduino => editor}/libs/ace/mode-json.js | 0 ui/{arduino => editor}/libs/ace/mode-json5.js | 0 .../libs/ace/mode-jsoniq.js | 0 ui/{arduino => editor}/libs/ace/mode-jsp.js | 0 ui/{arduino => editor}/libs/ace/mode-jssm.js | 0 ui/{arduino => editor}/libs/ace/mode-jsx.js | 0 ui/{arduino => editor}/libs/ace/mode-julia.js | 0 .../libs/ace/mode-kotlin.js | 0 ui/{arduino => editor}/libs/ace/mode-latex.js | 0 ui/{arduino => editor}/libs/ace/mode-less.js | 0 .../libs/ace/mode-liquid.js | 0 ui/{arduino => editor}/libs/ace/mode-lisp.js | 0 .../libs/ace/mode-livescript.js | 0 .../libs/ace/mode-logiql.js | 0 .../libs/ace/mode-logtalk.js | 0 ui/{arduino => editor}/libs/ace/mode-lsl.js | 0 ui/{arduino => editor}/libs/ace/mode-lua.js | 0 .../libs/ace/mode-luapage.js | 0 .../libs/ace/mode-lucene.js | 0 .../libs/ace/mode-makefile.js | 0 .../libs/ace/mode-markdown.js | 0 ui/{arduino => editor}/libs/ace/mode-mask.js | 0 .../libs/ace/mode-matlab.js | 0 ui/{arduino => editor}/libs/ace/mode-maze.js | 0 .../libs/ace/mode-mediawiki.js | 0 ui/{arduino => editor}/libs/ace/mode-mel.js | 0 ui/{arduino => editor}/libs/ace/mode-mixal.js | 0 .../libs/ace/mode-mushcode.js | 0 ui/{arduino => editor}/libs/ace/mode-mysql.js | 0 ui/{arduino => editor}/libs/ace/mode-nginx.js | 0 ui/{arduino => editor}/libs/ace/mode-nim.js | 0 ui/{arduino => editor}/libs/ace/mode-nix.js | 0 ui/{arduino => editor}/libs/ace/mode-nsis.js | 0 .../libs/ace/mode-nunjucks.js | 0 .../libs/ace/mode-objectivec.js | 0 ui/{arduino => editor}/libs/ace/mode-ocaml.js | 0 .../libs/ace/mode-pascal.js | 0 ui/{arduino => editor}/libs/ace/mode-perl.js | 0 ui/{arduino => editor}/libs/ace/mode-perl6.js | 0 ui/{arduino => editor}/libs/ace/mode-pgsql.js | 0 ui/{arduino => editor}/libs/ace/mode-php.js | 0 .../libs/ace/mode-php_laravel_blade.js | 0 ui/{arduino => editor}/libs/ace/mode-pig.js | 0 .../libs/ace/mode-plain_text.js | 0 .../libs/ace/mode-powershell.js | 0 ui/{arduino => editor}/libs/ace/mode-praat.js | 0 .../libs/ace/mode-prisma.js | 0 .../libs/ace/mode-prolog.js | 0 .../libs/ace/mode-properties.js | 0 .../libs/ace/mode-protobuf.js | 0 .../libs/ace/mode-puppet.js | 0 .../libs/ace/mode-python.js | 0 ui/{arduino => editor}/libs/ace/mode-qml.js | 0 ui/{arduino => editor}/libs/ace/mode-r.js | 0 ui/{arduino => editor}/libs/ace/mode-razor.js | 0 ui/{arduino => editor}/libs/ace/mode-rdoc.js | 0 ui/{arduino => editor}/libs/ace/mode-red.js | 0 .../libs/ace/mode-redshift.js | 0 ui/{arduino => editor}/libs/ace/mode-rhtml.js | 0 ui/{arduino => editor}/libs/ace/mode-rst.js | 0 ui/{arduino => editor}/libs/ace/mode-ruby.js | 0 ui/{arduino => editor}/libs/ace/mode-rust.js | 0 ui/{arduino => editor}/libs/ace/mode-sass.js | 0 ui/{arduino => editor}/libs/ace/mode-scad.js | 0 ui/{arduino => editor}/libs/ace/mode-scala.js | 0 .../libs/ace/mode-scheme.js | 0 ui/{arduino => editor}/libs/ace/mode-scss.js | 0 ui/{arduino => editor}/libs/ace/mode-sh.js | 0 ui/{arduino => editor}/libs/ace/mode-sjs.js | 0 ui/{arduino => editor}/libs/ace/mode-slim.js | 0 .../libs/ace/mode-smarty.js | 0 .../libs/ace/mode-snippets.js | 0 .../libs/ace/mode-soy_template.js | 0 ui/{arduino => editor}/libs/ace/mode-space.js | 0 .../libs/ace/mode-sparql.js | 0 ui/{arduino => editor}/libs/ace/mode-sql.js | 0 .../libs/ace/mode-sqlserver.js | 0 .../libs/ace/mode-stylus.js | 0 ui/{arduino => editor}/libs/ace/mode-svg.js | 0 ui/{arduino => editor}/libs/ace/mode-swift.js | 0 ui/{arduino => editor}/libs/ace/mode-tcl.js | 0 .../libs/ace/mode-terraform.js | 0 ui/{arduino => editor}/libs/ace/mode-tex.js | 0 ui/{arduino => editor}/libs/ace/mode-text.js | 0 .../libs/ace/mode-textile.js | 0 ui/{arduino => editor}/libs/ace/mode-toml.js | 0 ui/{arduino => editor}/libs/ace/mode-tsx.js | 0 .../libs/ace/mode-turtle.js | 0 ui/{arduino => editor}/libs/ace/mode-twig.js | 0 .../libs/ace/mode-typescript.js | 0 ui/{arduino => editor}/libs/ace/mode-vala.js | 0 .../libs/ace/mode-vbscript.js | 0 .../libs/ace/mode-velocity.js | 0 .../libs/ace/mode-verilog.js | 0 ui/{arduino => editor}/libs/ace/mode-vhdl.js | 0 .../libs/ace/mode-visualforce.js | 0 .../libs/ace/mode-wollok.js | 0 ui/{arduino => editor}/libs/ace/mode-xml.js | 0 .../libs/ace/mode-xquery.js | 0 ui/{arduino => editor}/libs/ace/mode-yaml.js | 0 ui/{arduino => editor}/libs/ace/mode-zeek.js | 0 .../libs/ace/snippets/abap.js | 0 .../libs/ace/snippets/abc.js | 0 .../libs/ace/snippets/actionscript.js | 0 .../libs/ace/snippets/ada.js | 0 .../libs/ace/snippets/alda.js | 0 .../libs/ace/snippets/apache_conf.js | 0 .../libs/ace/snippets/apex.js | 0 .../libs/ace/snippets/applescript.js | 0 .../libs/ace/snippets/aql.js | 0 .../libs/ace/snippets/asciidoc.js | 0 .../libs/ace/snippets/asl.js | 0 .../libs/ace/snippets/assembly_x86.js | 0 .../libs/ace/snippets/autohotkey.js | 0 .../libs/ace/snippets/batchfile.js | 0 .../libs/ace/snippets/c9search.js | 0 .../libs/ace/snippets/c_cpp.js | 0 .../libs/ace/snippets/cirru.js | 0 .../libs/ace/snippets/clojure.js | 0 .../libs/ace/snippets/cobol.js | 0 .../libs/ace/snippets/coffee.js | 0 .../libs/ace/snippets/coldfusion.js | 0 .../libs/ace/snippets/crystal.js | 0 .../libs/ace/snippets/csharp.js | 0 .../libs/ace/snippets/csound_document.js | 0 .../libs/ace/snippets/csound_orchestra.js | 0 .../libs/ace/snippets/csound_score.js | 0 .../libs/ace/snippets/csp.js | 0 .../libs/ace/snippets/css.js | 0 .../libs/ace/snippets/curly.js | 0 ui/{arduino => editor}/libs/ace/snippets/d.js | 0 .../libs/ace/snippets/dart.js | 0 .../libs/ace/snippets/diff.js | 0 .../libs/ace/snippets/django.js | 0 .../libs/ace/snippets/dockerfile.js | 0 .../libs/ace/snippets/dot.js | 0 .../libs/ace/snippets/drools.js | 0 .../libs/ace/snippets/edifact.js | 0 .../libs/ace/snippets/eiffel.js | 0 .../libs/ace/snippets/ejs.js | 0 .../libs/ace/snippets/elixir.js | 0 .../libs/ace/snippets/elm.js | 0 .../libs/ace/snippets/erlang.js | 0 .../libs/ace/snippets/forth.js | 0 .../libs/ace/snippets/fortran.js | 0 .../libs/ace/snippets/fsharp.js | 0 .../libs/ace/snippets/fsl.js | 0 .../libs/ace/snippets/ftl.js | 0 .../libs/ace/snippets/gcode.js | 0 .../libs/ace/snippets/gherkin.js | 0 .../libs/ace/snippets/gitignore.js | 0 .../libs/ace/snippets/glsl.js | 0 .../libs/ace/snippets/gobstones.js | 0 .../libs/ace/snippets/golang.js | 0 .../libs/ace/snippets/graphqlschema.js | 0 .../libs/ace/snippets/groovy.js | 0 .../libs/ace/snippets/haml.js | 0 .../libs/ace/snippets/handlebars.js | 0 .../libs/ace/snippets/haskell.js | 0 .../libs/ace/snippets/haskell_cabal.js | 0 .../libs/ace/snippets/haxe.js | 0 .../libs/ace/snippets/hjson.js | 0 .../libs/ace/snippets/html.js | 0 .../libs/ace/snippets/html_elixir.js | 0 .../libs/ace/snippets/html_ruby.js | 0 .../libs/ace/snippets/ini.js | 0 .../libs/ace/snippets/io.js | 0 .../libs/ace/snippets/jack.js | 0 .../libs/ace/snippets/jade.js | 0 .../libs/ace/snippets/java.js | 0 .../libs/ace/snippets/javascript.js | 0 .../libs/ace/snippets/json.js | 0 .../libs/ace/snippets/json5.js | 0 .../libs/ace/snippets/jsoniq.js | 0 .../libs/ace/snippets/jsp.js | 0 .../libs/ace/snippets/jssm.js | 0 .../libs/ace/snippets/jsx.js | 0 .../libs/ace/snippets/julia.js | 0 .../libs/ace/snippets/kotlin.js | 0 .../libs/ace/snippets/latex.js | 0 .../libs/ace/snippets/less.js | 0 .../libs/ace/snippets/liquid.js | 0 .../libs/ace/snippets/lisp.js | 0 .../libs/ace/snippets/livescript.js | 0 .../libs/ace/snippets/logiql.js | 0 .../libs/ace/snippets/logtalk.js | 0 .../libs/ace/snippets/lsl.js | 0 .../libs/ace/snippets/lua.js | 0 .../libs/ace/snippets/luapage.js | 0 .../libs/ace/snippets/lucene.js | 0 .../libs/ace/snippets/makefile.js | 0 .../libs/ace/snippets/markdown.js | 0 .../libs/ace/snippets/mask.js | 0 .../libs/ace/snippets/matlab.js | 0 .../libs/ace/snippets/maze.js | 0 .../libs/ace/snippets/mediawiki.js | 0 .../libs/ace/snippets/mel.js | 0 .../libs/ace/snippets/mixal.js | 0 .../libs/ace/snippets/mushcode.js | 0 .../libs/ace/snippets/mysql.js | 0 .../libs/ace/snippets/nginx.js | 0 .../libs/ace/snippets/nim.js | 0 .../libs/ace/snippets/nix.js | 0 .../libs/ace/snippets/nsis.js | 0 .../libs/ace/snippets/nunjucks.js | 0 .../libs/ace/snippets/objectivec.js | 0 .../libs/ace/snippets/ocaml.js | 0 .../libs/ace/snippets/pascal.js | 0 .../libs/ace/snippets/perl.js | 0 .../libs/ace/snippets/perl6.js | 0 .../libs/ace/snippets/pgsql.js | 0 .../libs/ace/snippets/php.js | 0 .../libs/ace/snippets/php_laravel_blade.js | 0 .../libs/ace/snippets/pig.js | 0 .../libs/ace/snippets/plain_text.js | 0 .../libs/ace/snippets/powershell.js | 0 .../libs/ace/snippets/praat.js | 0 .../libs/ace/snippets/prisma.js | 0 .../libs/ace/snippets/prolog.js | 0 .../libs/ace/snippets/properties.js | 0 .../libs/ace/snippets/protobuf.js | 0 .../libs/ace/snippets/puppet.js | 0 .../libs/ace/snippets/python.js | 0 .../libs/ace/snippets/qml.js | 0 ui/{arduino => editor}/libs/ace/snippets/r.js | 0 .../libs/ace/snippets/razor.js | 0 .../libs/ace/snippets/rdoc.js | 0 .../libs/ace/snippets/red.js | 0 .../libs/ace/snippets/redshift.js | 0 .../libs/ace/snippets/rhtml.js | 0 .../libs/ace/snippets/rst.js | 0 .../libs/ace/snippets/ruby.js | 0 .../libs/ace/snippets/rust.js | 0 .../libs/ace/snippets/sass.js | 0 .../libs/ace/snippets/scad.js | 0 .../libs/ace/snippets/scala.js | 0 .../libs/ace/snippets/scheme.js | 0 .../libs/ace/snippets/scss.js | 0 .../libs/ace/snippets/sh.js | 0 .../libs/ace/snippets/sjs.js | 0 .../libs/ace/snippets/slim.js | 0 .../libs/ace/snippets/smarty.js | 0 .../libs/ace/snippets/snippets.js | 0 .../libs/ace/snippets/soy_template.js | 0 .../libs/ace/snippets/space.js | 0 .../libs/ace/snippets/sparql.js | 0 .../libs/ace/snippets/sql.js | 0 .../libs/ace/snippets/sqlserver.js | 0 .../libs/ace/snippets/stylus.js | 0 .../libs/ace/snippets/svg.js | 0 .../libs/ace/snippets/swift.js | 0 .../libs/ace/snippets/tcl.js | 0 .../libs/ace/snippets/terraform.js | 0 .../libs/ace/snippets/tex.js | 0 .../libs/ace/snippets/text.js | 0 .../libs/ace/snippets/textile.js | 0 .../libs/ace/snippets/toml.js | 0 .../libs/ace/snippets/tsx.js | 0 .../libs/ace/snippets/turtle.js | 0 .../libs/ace/snippets/twig.js | 0 .../libs/ace/snippets/typescript.js | 0 .../libs/ace/snippets/vala.js | 0 .../libs/ace/snippets/vbscript.js | 0 .../libs/ace/snippets/velocity.js | 0 .../libs/ace/snippets/verilog.js | 0 .../libs/ace/snippets/vhdl.js | 0 .../libs/ace/snippets/visualforce.js | 0 .../libs/ace/snippets/wollok.js | 0 .../libs/ace/snippets/xml.js | 0 .../libs/ace/snippets/xquery.js | 0 .../libs/ace/snippets/yaml.js | 0 .../libs/ace/snippets/zeek.js | 0 .../libs/ace/theme-ambiance.js | 0 .../libs/ace/theme-chaos.js | 0 .../libs/ace/theme-chrome.js | 0 .../libs/ace/theme-clouds.js | 0 .../libs/ace/theme-clouds_midnight.js | 0 .../libs/ace/theme-cobalt.js | 0 .../libs/ace/theme-crimson_editor.js | 0 ui/{arduino => editor}/libs/ace/theme-dawn.js | 0 .../libs/ace/theme-dracula.js | 0 .../libs/ace/theme-dreamweaver.js | 0 .../libs/ace/theme-eclipse.js | 0 .../libs/ace/theme-github.js | 0 ui/{arduino => editor}/libs/ace/theme-gob.js | 0 .../libs/ace/theme-gruvbox.js | 0 .../libs/ace/theme-idle_fingers.js | 0 .../libs/ace/theme-iplastic.js | 0 .../libs/ace/theme-katzenmilch.js | 0 .../libs/ace/theme-kr_theme.js | 0 .../libs/ace/theme-kuroir.js | 0 .../libs/ace/theme-merbivore.js | 0 .../libs/ace/theme-merbivore_soft.js | 0 .../libs/ace/theme-mono_industrial.js | 0 .../libs/ace/theme-monokai.js | 0 .../libs/ace/theme-nord_dark.js | 0 .../libs/ace/theme-pastel_on_dark.js | 0 .../libs/ace/theme-solarized_dark.js | 0 .../libs/ace/theme-solarized_light.js | 0 .../libs/ace/theme-sqlserver.js | 0 .../libs/ace/theme-terminal.js | 0 .../libs/ace/theme-textmate.js | 0 .../libs/ace/theme-tomorrow.js | 0 .../libs/ace/theme-tomorrow_night.js | 0 .../libs/ace/theme-tomorrow_night_blue.js | 0 .../libs/ace/theme-tomorrow_night_bright.js | 0 .../libs/ace/theme-tomorrow_night_eighties.js | 0 .../libs/ace/theme-twilight.js | 0 .../libs/ace/theme-vibrant_ink.js | 0 .../libs/ace/theme-xcode.js | 0 .../libs/ace/worker-base.js | 0 .../libs/ace/worker-coffee.js | 0 ui/{arduino => editor}/libs/ace/worker-css.js | 0 .../libs/ace/worker-html.js | 0 .../libs/ace/worker-javascript.js | 0 .../libs/ace/worker-json.js | 0 ui/{arduino => editor}/libs/ace/worker-lua.js | 0 ui/{arduino => editor}/libs/ace/worker-php.js | 0 ui/{arduino => editor}/libs/ace/worker-xml.js | 0 .../libs/ace/worker-xquery.js | 0 ui/{arduino => editor}/libs/build_choo.js | 0 ui/{arduino => editor}/libs/choo.js | 0 .../libs/xterm-addon-fit.js | 0 ui/{arduino => editor}/libs/xterm.css | 0 ui/{arduino => editor}/libs/xterm.js | 0 ui/{arduino => editor}/package-lock.json | 0 ui/{arduino => editor}/package.json | 0 ui/{arduino => editor}/store.js | 0 ui/{arduino => editor}/theme.css | 0 ui/ftp/components/files/diskFiles.tsx | 16 + ui/ftp/components/files/diskFiles.type.ts | 8 + ui/ftp/components/files/management.type.ts | 7 + ui/ftp/components/files/serialFiles.tsx | 16 + ui/ftp/components/files/serialFiles.type.ts | 8 + .../components/navigation/diskNavigation.tsx | 9 + .../navigation/diskNavigation.type.ts | 6 + .../navigation/serialNavigation.tsx | 9 + .../navigation/serialNavigation.type.ts | 6 + .../components/shared/breadcrumbs.module.scss | 9 + ui/ftp/components/shared/breadcrumbs.tsx | 21 + ui/ftp/components/shared/button.module.scss | 12 + ui/ftp/components/shared/button.tsx | 8 + ui/ftp/components/toolbar/toolbar.module.scss | 8 + ui/ftp/components/toolbar/toolbar.tsx | 42 + ui/ftp/components/toolbar/toolbar.type.ts | 10 + ui/ftp/index.html | 14 + ui/ftp/main.logic.ts | 164 + ui/ftp/main.scss | 9 + ui/ftp/main.tsx | 46 + ui/ftp/main.type.ts | 6 + ui/ftp/package-lock.json | 2975 +++++++++++++++++ ui/ftp/package.json | 20 + 497 files changed, 3439 insertions(+), 7 deletions(-) rename ui/{arduino => editor}/about.css (100%) rename ui/{arduino => editor}/about.html (100%) rename ui/{arduino => editor}/app.js (100%) rename ui/{arduino => editor}/assets/about_image.png (100%) rename ui/{arduino => editor}/components/editor.js (100%) rename ui/{arduino => editor}/components/filename.js (100%) rename ui/{arduino => editor}/components/icon.js (100%) rename ui/{arduino => editor}/components/message.js (100%) rename ui/{arduino => editor}/components/newfiledialog.js (100%) rename ui/{arduino => editor}/components/panel.js (100%) rename ui/{arduino => editor}/components/panel_files.js (100%) rename ui/{arduino => editor}/components/panel_terminal.js (100%) rename ui/{arduino => editor}/components/portdialog.js (100%) rename ui/{arduino => editor}/components/toolbar.js (100%) rename ui/{arduino => editor}/components/toolbar_button.js (100%) rename ui/{arduino => editor}/icons/Connect.svg (100%) rename ui/{arduino => editor}/icons/Connect@3x.png (100%) rename ui/{arduino => editor}/icons/Copy-Left.svg (100%) rename ui/{arduino => editor}/icons/Copy-Left@3x.png (100%) rename ui/{arduino => editor}/icons/Copy-Right.svg (100%) rename ui/{arduino => editor}/icons/Copy-Right@3x.png (100%) rename ui/{arduino => editor}/icons/Copy.png (100%) rename ui/{arduino => editor}/icons/Copy.svg (100%) rename ui/{arduino => editor}/icons/Delete.svg (100%) rename ui/{arduino => editor}/icons/Delete@3x.png (100%) rename ui/{arduino => editor}/icons/Disconnect.svg (100%) rename ui/{arduino => editor}/icons/Disconnect@3x.png (100%) rename ui/{arduino => editor}/icons/File-Explorer.svg (100%) rename ui/{arduino => editor}/icons/File-Explorer@3x.png (100%) rename ui/{arduino => editor}/icons/New.svg (100%) rename ui/{arduino => editor}/icons/New@3x.png (100%) rename ui/{arduino => editor}/icons/Open.svg (100%) rename ui/{arduino => editor}/icons/Open@3x.png (100%) rename ui/{arduino => editor}/icons/Output.svg (100%) rename ui/{arduino => editor}/icons/Output@3x.png (100%) rename ui/{arduino => editor}/icons/Paste.png (100%) rename ui/{arduino => editor}/icons/Paste.svg (100%) rename ui/{arduino => editor}/icons/Reboot.svg (100%) rename ui/{arduino => editor}/icons/Reboot@3x.png (100%) rename ui/{arduino => editor}/icons/Run.svg (100%) rename ui/{arduino => editor}/icons/Run@3x.png (100%) rename ui/{arduino => editor}/icons/Save.svg (100%) rename ui/{arduino => editor}/icons/Save@3x.png (100%) rename ui/{arduino => editor}/icons/Stop.svg (100%) rename ui/{arduino => editor}/icons/Stop@3x.png (100%) rename ui/{arduino => editor}/index.html (100%) rename ui/{arduino => editor}/libs/FileSaver.js (100%) rename ui/{arduino => editor}/libs/ace/ace.js (100%) rename ui/{arduino => editor}/libs/ace/ext-beautify.js (100%) rename ui/{arduino => editor}/libs/ace/ext-code_lens.js (100%) rename ui/{arduino => editor}/libs/ace/ext-elastic_tabstops_lite.js (100%) rename ui/{arduino => editor}/libs/ace/ext-emmet.js (100%) rename ui/{arduino => editor}/libs/ace/ext-error_marker.js (100%) rename ui/{arduino => editor}/libs/ace/ext-keybinding_menu.js (100%) rename ui/{arduino => editor}/libs/ace/ext-language_tools.js (100%) rename ui/{arduino => editor}/libs/ace/ext-linking.js (100%) rename ui/{arduino => editor}/libs/ace/ext-modelist.js (100%) rename ui/{arduino => editor}/libs/ace/ext-options.js (100%) rename ui/{arduino => editor}/libs/ace/ext-prompt.js (100%) rename ui/{arduino => editor}/libs/ace/ext-rtl.js (100%) rename ui/{arduino => editor}/libs/ace/ext-searchbox.js (100%) rename ui/{arduino => editor}/libs/ace/ext-settings_menu.js (100%) rename ui/{arduino => editor}/libs/ace/ext-spellcheck.js (100%) rename ui/{arduino => editor}/libs/ace/ext-split.js (100%) rename ui/{arduino => editor}/libs/ace/ext-static_highlight.js (100%) rename ui/{arduino => editor}/libs/ace/ext-statusbar.js (100%) rename ui/{arduino => editor}/libs/ace/ext-textarea.js (100%) rename ui/{arduino => editor}/libs/ace/ext-themelist.js (100%) rename ui/{arduino => editor}/libs/ace/ext-whitespace.js (100%) rename ui/{arduino => editor}/libs/ace/keybinding-emacs.js (100%) rename ui/{arduino => editor}/libs/ace/keybinding-sublime.js (100%) rename ui/{arduino => editor}/libs/ace/keybinding-vim.js (100%) rename ui/{arduino => editor}/libs/ace/keybinding-vscode.js (100%) rename ui/{arduino => editor}/libs/ace/mode-abap.js (100%) rename ui/{arduino => editor}/libs/ace/mode-abc.js (100%) rename ui/{arduino => editor}/libs/ace/mode-actionscript.js (100%) rename ui/{arduino => editor}/libs/ace/mode-ada.js (100%) rename ui/{arduino => editor}/libs/ace/mode-alda.js (100%) rename ui/{arduino => editor}/libs/ace/mode-apache_conf.js (100%) rename ui/{arduino => editor}/libs/ace/mode-apex.js (100%) rename ui/{arduino => editor}/libs/ace/mode-applescript.js (100%) rename ui/{arduino => editor}/libs/ace/mode-aql.js (100%) rename ui/{arduino => editor}/libs/ace/mode-asciidoc.js (100%) rename ui/{arduino => editor}/libs/ace/mode-asl.js (100%) rename ui/{arduino => editor}/libs/ace/mode-assembly_x86.js (100%) rename ui/{arduino => editor}/libs/ace/mode-autohotkey.js (100%) rename ui/{arduino => editor}/libs/ace/mode-batchfile.js (100%) rename ui/{arduino => editor}/libs/ace/mode-c9search.js (100%) rename ui/{arduino => editor}/libs/ace/mode-c_cpp.js (100%) rename ui/{arduino => editor}/libs/ace/mode-cirru.js (100%) rename ui/{arduino => editor}/libs/ace/mode-clojure.js (100%) rename ui/{arduino => editor}/libs/ace/mode-cobol.js (100%) rename ui/{arduino => editor}/libs/ace/mode-coffee.js (100%) rename ui/{arduino => editor}/libs/ace/mode-coldfusion.js (100%) rename ui/{arduino => editor}/libs/ace/mode-crystal.js (100%) rename ui/{arduino => editor}/libs/ace/mode-csharp.js (100%) rename ui/{arduino => editor}/libs/ace/mode-csound_document.js (100%) rename ui/{arduino => editor}/libs/ace/mode-csound_orchestra.js (100%) rename ui/{arduino => editor}/libs/ace/mode-csound_score.js (100%) rename ui/{arduino => editor}/libs/ace/mode-csp.js (100%) rename ui/{arduino => editor}/libs/ace/mode-css.js (100%) rename ui/{arduino => editor}/libs/ace/mode-curly.js (100%) rename ui/{arduino => editor}/libs/ace/mode-d.js (100%) rename ui/{arduino => editor}/libs/ace/mode-dart.js (100%) rename ui/{arduino => editor}/libs/ace/mode-diff.js (100%) rename ui/{arduino => editor}/libs/ace/mode-django.js (100%) rename ui/{arduino => editor}/libs/ace/mode-dockerfile.js (100%) rename ui/{arduino => editor}/libs/ace/mode-dot.js (100%) rename ui/{arduino => editor}/libs/ace/mode-drools.js (100%) rename ui/{arduino => editor}/libs/ace/mode-edifact.js (100%) rename ui/{arduino => editor}/libs/ace/mode-eiffel.js (100%) rename ui/{arduino => editor}/libs/ace/mode-ejs.js (100%) rename ui/{arduino => editor}/libs/ace/mode-elixir.js (100%) rename ui/{arduino => editor}/libs/ace/mode-elm.js (100%) rename ui/{arduino => editor}/libs/ace/mode-erlang.js (100%) rename ui/{arduino => editor}/libs/ace/mode-forth.js (100%) rename ui/{arduino => editor}/libs/ace/mode-fortran.js (100%) rename ui/{arduino => editor}/libs/ace/mode-fsharp.js (100%) rename ui/{arduino => editor}/libs/ace/mode-fsl.js (100%) rename ui/{arduino => editor}/libs/ace/mode-ftl.js (100%) rename ui/{arduino => editor}/libs/ace/mode-gcode.js (100%) rename ui/{arduino => editor}/libs/ace/mode-gherkin.js (100%) rename ui/{arduino => editor}/libs/ace/mode-gitignore.js (100%) rename ui/{arduino => editor}/libs/ace/mode-glsl.js (100%) rename ui/{arduino => editor}/libs/ace/mode-gobstones.js (100%) rename ui/{arduino => editor}/libs/ace/mode-golang.js (100%) rename ui/{arduino => editor}/libs/ace/mode-graphqlschema.js (100%) rename ui/{arduino => editor}/libs/ace/mode-groovy.js (100%) rename ui/{arduino => editor}/libs/ace/mode-haml.js (100%) rename ui/{arduino => editor}/libs/ace/mode-handlebars.js (100%) rename ui/{arduino => editor}/libs/ace/mode-haskell.js (100%) rename ui/{arduino => editor}/libs/ace/mode-haskell_cabal.js (100%) rename ui/{arduino => editor}/libs/ace/mode-haxe.js (100%) rename ui/{arduino => editor}/libs/ace/mode-hjson.js (100%) rename ui/{arduino => editor}/libs/ace/mode-html.js (100%) rename ui/{arduino => editor}/libs/ace/mode-html_elixir.js (100%) rename ui/{arduino => editor}/libs/ace/mode-html_ruby.js (100%) rename ui/{arduino => editor}/libs/ace/mode-ini.js (100%) rename ui/{arduino => editor}/libs/ace/mode-io.js (100%) rename ui/{arduino => editor}/libs/ace/mode-jack.js (100%) rename ui/{arduino => editor}/libs/ace/mode-jade.js (100%) rename ui/{arduino => editor}/libs/ace/mode-java.js (100%) rename ui/{arduino => editor}/libs/ace/mode-javascript.js (100%) rename ui/{arduino => editor}/libs/ace/mode-json.js (100%) rename ui/{arduino => editor}/libs/ace/mode-json5.js (100%) rename ui/{arduino => editor}/libs/ace/mode-jsoniq.js (100%) rename ui/{arduino => editor}/libs/ace/mode-jsp.js (100%) rename ui/{arduino => editor}/libs/ace/mode-jssm.js (100%) rename ui/{arduino => editor}/libs/ace/mode-jsx.js (100%) rename ui/{arduino => editor}/libs/ace/mode-julia.js (100%) rename ui/{arduino => editor}/libs/ace/mode-kotlin.js (100%) rename ui/{arduino => editor}/libs/ace/mode-latex.js (100%) rename ui/{arduino => editor}/libs/ace/mode-less.js (100%) rename ui/{arduino => editor}/libs/ace/mode-liquid.js (100%) rename ui/{arduino => editor}/libs/ace/mode-lisp.js (100%) rename ui/{arduino => editor}/libs/ace/mode-livescript.js (100%) rename ui/{arduino => editor}/libs/ace/mode-logiql.js (100%) rename ui/{arduino => editor}/libs/ace/mode-logtalk.js (100%) rename ui/{arduino => editor}/libs/ace/mode-lsl.js (100%) rename ui/{arduino => editor}/libs/ace/mode-lua.js (100%) rename ui/{arduino => editor}/libs/ace/mode-luapage.js (100%) rename ui/{arduino => editor}/libs/ace/mode-lucene.js (100%) rename ui/{arduino => editor}/libs/ace/mode-makefile.js (100%) rename ui/{arduino => editor}/libs/ace/mode-markdown.js (100%) rename ui/{arduino => editor}/libs/ace/mode-mask.js (100%) rename ui/{arduino => editor}/libs/ace/mode-matlab.js (100%) rename ui/{arduino => editor}/libs/ace/mode-maze.js (100%) rename ui/{arduino => editor}/libs/ace/mode-mediawiki.js (100%) rename ui/{arduino => editor}/libs/ace/mode-mel.js (100%) rename ui/{arduino => editor}/libs/ace/mode-mixal.js (100%) rename ui/{arduino => editor}/libs/ace/mode-mushcode.js (100%) rename ui/{arduino => editor}/libs/ace/mode-mysql.js (100%) rename ui/{arduino => editor}/libs/ace/mode-nginx.js (100%) rename ui/{arduino => editor}/libs/ace/mode-nim.js (100%) rename ui/{arduino => editor}/libs/ace/mode-nix.js (100%) rename ui/{arduino => editor}/libs/ace/mode-nsis.js (100%) rename ui/{arduino => editor}/libs/ace/mode-nunjucks.js (100%) rename ui/{arduino => editor}/libs/ace/mode-objectivec.js (100%) rename ui/{arduino => editor}/libs/ace/mode-ocaml.js (100%) rename ui/{arduino => editor}/libs/ace/mode-pascal.js (100%) rename ui/{arduino => editor}/libs/ace/mode-perl.js (100%) rename ui/{arduino => editor}/libs/ace/mode-perl6.js (100%) rename ui/{arduino => editor}/libs/ace/mode-pgsql.js (100%) rename ui/{arduino => editor}/libs/ace/mode-php.js (100%) rename ui/{arduino => editor}/libs/ace/mode-php_laravel_blade.js (100%) rename ui/{arduino => editor}/libs/ace/mode-pig.js (100%) rename ui/{arduino => editor}/libs/ace/mode-plain_text.js (100%) rename ui/{arduino => editor}/libs/ace/mode-powershell.js (100%) rename ui/{arduino => editor}/libs/ace/mode-praat.js (100%) rename ui/{arduino => editor}/libs/ace/mode-prisma.js (100%) rename ui/{arduino => editor}/libs/ace/mode-prolog.js (100%) rename ui/{arduino => editor}/libs/ace/mode-properties.js (100%) rename ui/{arduino => editor}/libs/ace/mode-protobuf.js (100%) rename ui/{arduino => editor}/libs/ace/mode-puppet.js (100%) rename ui/{arduino => editor}/libs/ace/mode-python.js (100%) rename ui/{arduino => editor}/libs/ace/mode-qml.js (100%) rename ui/{arduino => editor}/libs/ace/mode-r.js (100%) rename ui/{arduino => editor}/libs/ace/mode-razor.js (100%) rename ui/{arduino => editor}/libs/ace/mode-rdoc.js (100%) rename ui/{arduino => editor}/libs/ace/mode-red.js (100%) rename ui/{arduino => editor}/libs/ace/mode-redshift.js (100%) rename ui/{arduino => editor}/libs/ace/mode-rhtml.js (100%) rename ui/{arduino => editor}/libs/ace/mode-rst.js (100%) rename ui/{arduino => editor}/libs/ace/mode-ruby.js (100%) rename ui/{arduino => editor}/libs/ace/mode-rust.js (100%) rename ui/{arduino => editor}/libs/ace/mode-sass.js (100%) rename ui/{arduino => editor}/libs/ace/mode-scad.js (100%) rename ui/{arduino => editor}/libs/ace/mode-scala.js (100%) rename ui/{arduino => editor}/libs/ace/mode-scheme.js (100%) rename ui/{arduino => editor}/libs/ace/mode-scss.js (100%) rename ui/{arduino => editor}/libs/ace/mode-sh.js (100%) rename ui/{arduino => editor}/libs/ace/mode-sjs.js (100%) rename ui/{arduino => editor}/libs/ace/mode-slim.js (100%) rename ui/{arduino => editor}/libs/ace/mode-smarty.js (100%) rename ui/{arduino => editor}/libs/ace/mode-snippets.js (100%) rename ui/{arduino => editor}/libs/ace/mode-soy_template.js (100%) rename ui/{arduino => editor}/libs/ace/mode-space.js (100%) rename ui/{arduino => editor}/libs/ace/mode-sparql.js (100%) rename ui/{arduino => editor}/libs/ace/mode-sql.js (100%) rename ui/{arduino => editor}/libs/ace/mode-sqlserver.js (100%) rename ui/{arduino => editor}/libs/ace/mode-stylus.js (100%) rename ui/{arduino => editor}/libs/ace/mode-svg.js (100%) rename ui/{arduino => editor}/libs/ace/mode-swift.js (100%) rename ui/{arduino => editor}/libs/ace/mode-tcl.js (100%) rename ui/{arduino => editor}/libs/ace/mode-terraform.js (100%) rename ui/{arduino => editor}/libs/ace/mode-tex.js (100%) rename ui/{arduino => editor}/libs/ace/mode-text.js (100%) rename ui/{arduino => editor}/libs/ace/mode-textile.js (100%) rename ui/{arduino => editor}/libs/ace/mode-toml.js (100%) rename ui/{arduino => editor}/libs/ace/mode-tsx.js (100%) rename ui/{arduino => editor}/libs/ace/mode-turtle.js (100%) rename ui/{arduino => editor}/libs/ace/mode-twig.js (100%) rename ui/{arduino => editor}/libs/ace/mode-typescript.js (100%) rename ui/{arduino => editor}/libs/ace/mode-vala.js (100%) rename ui/{arduino => editor}/libs/ace/mode-vbscript.js (100%) rename ui/{arduino => editor}/libs/ace/mode-velocity.js (100%) rename ui/{arduino => editor}/libs/ace/mode-verilog.js (100%) rename ui/{arduino => editor}/libs/ace/mode-vhdl.js (100%) rename ui/{arduino => editor}/libs/ace/mode-visualforce.js (100%) rename ui/{arduino => editor}/libs/ace/mode-wollok.js (100%) rename ui/{arduino => editor}/libs/ace/mode-xml.js (100%) rename ui/{arduino => editor}/libs/ace/mode-xquery.js (100%) rename ui/{arduino => editor}/libs/ace/mode-yaml.js (100%) rename ui/{arduino => editor}/libs/ace/mode-zeek.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/abap.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/abc.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/actionscript.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/ada.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/alda.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/apache_conf.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/apex.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/applescript.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/aql.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/asciidoc.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/asl.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/assembly_x86.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/autohotkey.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/batchfile.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/c9search.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/c_cpp.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/cirru.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/clojure.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/cobol.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/coffee.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/coldfusion.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/crystal.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/csharp.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/csound_document.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/csound_orchestra.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/csound_score.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/csp.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/css.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/curly.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/d.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/dart.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/diff.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/django.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/dockerfile.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/dot.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/drools.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/edifact.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/eiffel.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/ejs.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/elixir.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/elm.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/erlang.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/forth.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/fortran.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/fsharp.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/fsl.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/ftl.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/gcode.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/gherkin.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/gitignore.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/glsl.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/gobstones.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/golang.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/graphqlschema.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/groovy.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/haml.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/handlebars.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/haskell.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/haskell_cabal.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/haxe.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/hjson.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/html.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/html_elixir.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/html_ruby.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/ini.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/io.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/jack.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/jade.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/java.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/javascript.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/json.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/json5.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/jsoniq.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/jsp.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/jssm.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/jsx.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/julia.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/kotlin.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/latex.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/less.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/liquid.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/lisp.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/livescript.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/logiql.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/logtalk.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/lsl.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/lua.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/luapage.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/lucene.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/makefile.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/markdown.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/mask.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/matlab.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/maze.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/mediawiki.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/mel.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/mixal.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/mushcode.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/mysql.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/nginx.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/nim.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/nix.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/nsis.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/nunjucks.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/objectivec.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/ocaml.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/pascal.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/perl.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/perl6.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/pgsql.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/php.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/php_laravel_blade.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/pig.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/plain_text.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/powershell.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/praat.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/prisma.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/prolog.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/properties.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/protobuf.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/puppet.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/python.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/qml.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/r.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/razor.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/rdoc.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/red.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/redshift.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/rhtml.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/rst.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/ruby.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/rust.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/sass.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/scad.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/scala.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/scheme.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/scss.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/sh.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/sjs.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/slim.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/smarty.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/snippets.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/soy_template.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/space.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/sparql.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/sql.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/sqlserver.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/stylus.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/svg.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/swift.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/tcl.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/terraform.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/tex.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/text.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/textile.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/toml.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/tsx.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/turtle.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/twig.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/typescript.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/vala.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/vbscript.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/velocity.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/verilog.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/vhdl.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/visualforce.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/wollok.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/xml.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/xquery.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/yaml.js (100%) rename ui/{arduino => editor}/libs/ace/snippets/zeek.js (100%) rename ui/{arduino => editor}/libs/ace/theme-ambiance.js (100%) rename ui/{arduino => editor}/libs/ace/theme-chaos.js (100%) rename ui/{arduino => editor}/libs/ace/theme-chrome.js (100%) rename ui/{arduino => editor}/libs/ace/theme-clouds.js (100%) rename ui/{arduino => editor}/libs/ace/theme-clouds_midnight.js (100%) rename ui/{arduino => editor}/libs/ace/theme-cobalt.js (100%) rename ui/{arduino => editor}/libs/ace/theme-crimson_editor.js (100%) rename ui/{arduino => editor}/libs/ace/theme-dawn.js (100%) rename ui/{arduino => editor}/libs/ace/theme-dracula.js (100%) rename ui/{arduino => editor}/libs/ace/theme-dreamweaver.js (100%) rename ui/{arduino => editor}/libs/ace/theme-eclipse.js (100%) rename ui/{arduino => editor}/libs/ace/theme-github.js (100%) rename ui/{arduino => editor}/libs/ace/theme-gob.js (100%) rename ui/{arduino => editor}/libs/ace/theme-gruvbox.js (100%) rename ui/{arduino => editor}/libs/ace/theme-idle_fingers.js (100%) rename ui/{arduino => editor}/libs/ace/theme-iplastic.js (100%) rename ui/{arduino => editor}/libs/ace/theme-katzenmilch.js (100%) rename ui/{arduino => editor}/libs/ace/theme-kr_theme.js (100%) rename ui/{arduino => editor}/libs/ace/theme-kuroir.js (100%) rename ui/{arduino => editor}/libs/ace/theme-merbivore.js (100%) rename ui/{arduino => editor}/libs/ace/theme-merbivore_soft.js (100%) rename ui/{arduino => editor}/libs/ace/theme-mono_industrial.js (100%) rename ui/{arduino => editor}/libs/ace/theme-monokai.js (100%) rename ui/{arduino => editor}/libs/ace/theme-nord_dark.js (100%) rename ui/{arduino => editor}/libs/ace/theme-pastel_on_dark.js (100%) rename ui/{arduino => editor}/libs/ace/theme-solarized_dark.js (100%) rename ui/{arduino => editor}/libs/ace/theme-solarized_light.js (100%) rename ui/{arduino => editor}/libs/ace/theme-sqlserver.js (100%) rename ui/{arduino => editor}/libs/ace/theme-terminal.js (100%) rename ui/{arduino => editor}/libs/ace/theme-textmate.js (100%) rename ui/{arduino => editor}/libs/ace/theme-tomorrow.js (100%) rename ui/{arduino => editor}/libs/ace/theme-tomorrow_night.js (100%) rename ui/{arduino => editor}/libs/ace/theme-tomorrow_night_blue.js (100%) rename ui/{arduino => editor}/libs/ace/theme-tomorrow_night_bright.js (100%) rename ui/{arduino => editor}/libs/ace/theme-tomorrow_night_eighties.js (100%) rename ui/{arduino => editor}/libs/ace/theme-twilight.js (100%) rename ui/{arduino => editor}/libs/ace/theme-vibrant_ink.js (100%) rename ui/{arduino => editor}/libs/ace/theme-xcode.js (100%) rename ui/{arduino => editor}/libs/ace/worker-base.js (100%) rename ui/{arduino => editor}/libs/ace/worker-coffee.js (100%) rename ui/{arduino => editor}/libs/ace/worker-css.js (100%) rename ui/{arduino => editor}/libs/ace/worker-html.js (100%) rename ui/{arduino => editor}/libs/ace/worker-javascript.js (100%) rename ui/{arduino => editor}/libs/ace/worker-json.js (100%) rename ui/{arduino => editor}/libs/ace/worker-lua.js (100%) rename ui/{arduino => editor}/libs/ace/worker-php.js (100%) rename ui/{arduino => editor}/libs/ace/worker-xml.js (100%) rename ui/{arduino => editor}/libs/ace/worker-xquery.js (100%) rename ui/{arduino => editor}/libs/build_choo.js (100%) rename ui/{arduino => editor}/libs/choo.js (100%) rename ui/{arduino => editor}/libs/xterm-addon-fit.js (100%) rename ui/{arduino => editor}/libs/xterm.css (100%) rename ui/{arduino => editor}/libs/xterm.js (100%) rename ui/{arduino => editor}/package-lock.json (100%) rename ui/{arduino => editor}/package.json (100%) rename ui/{arduino => editor}/store.js (100%) rename ui/{arduino => editor}/theme.css (100%) create mode 100644 ui/ftp/components/files/diskFiles.tsx create mode 100644 ui/ftp/components/files/diskFiles.type.ts create mode 100644 ui/ftp/components/files/management.type.ts create mode 100644 ui/ftp/components/files/serialFiles.tsx create mode 100644 ui/ftp/components/files/serialFiles.type.ts create mode 100644 ui/ftp/components/navigation/diskNavigation.tsx create mode 100644 ui/ftp/components/navigation/diskNavigation.type.ts create mode 100644 ui/ftp/components/navigation/serialNavigation.tsx create mode 100644 ui/ftp/components/navigation/serialNavigation.type.ts create mode 100644 ui/ftp/components/shared/breadcrumbs.module.scss create mode 100644 ui/ftp/components/shared/breadcrumbs.tsx create mode 100644 ui/ftp/components/shared/button.module.scss create mode 100644 ui/ftp/components/shared/button.tsx create mode 100644 ui/ftp/components/toolbar/toolbar.module.scss create mode 100644 ui/ftp/components/toolbar/toolbar.tsx create mode 100644 ui/ftp/components/toolbar/toolbar.type.ts create mode 100644 ui/ftp/index.html create mode 100644 ui/ftp/main.logic.ts create mode 100644 ui/ftp/main.scss create mode 100644 ui/ftp/main.tsx create mode 100644 ui/ftp/main.type.ts create mode 100644 ui/ftp/package-lock.json create mode 100644 ui/ftp/package.json diff --git a/.gitignore b/.gitignore index c0320fa..a2220b2 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ dist dist/ .vscode Resources -temp \ No newline at end of file +temp +.parcel-cache \ No newline at end of file diff --git a/index.js b/index.js index bbf1df4..d49cd27 100644 --- a/index.js +++ b/index.js @@ -12,13 +12,15 @@ async function openFolderDialog() { return dir.filePaths[0] || null } -function listFolder(folder) { +function listFolder(folder, filesOnly) { files = fs.readdirSync(path.resolve(folder)) // Filter out directories - files = files.filter(f => { - let filePath = path.resolve(folder, f) - return !fs.lstatSync(filePath).isDirectory() - }) + if (filesOnly) { + files = files.filter(f => { + let filePath = path.resolve(folder, f) + return !fs.lstatSync(filePath).isDirectory() + }) + } // Filter out dot files files = files.filter(f => f.indexOf('.') !== 0) return files @@ -105,7 +107,7 @@ function createWindow () { } }) // and load the index.html of the app. - win.loadFile('ui/arduino/index.html') + win.loadFile('ui/ftp/dist/index.html') } // TODO: Loading splash screen diff --git a/ui/arduino/about.css b/ui/editor/about.css similarity index 100% rename from ui/arduino/about.css rename to ui/editor/about.css diff --git a/ui/arduino/about.html b/ui/editor/about.html similarity index 100% rename from ui/arduino/about.html rename to ui/editor/about.html diff --git a/ui/arduino/app.js b/ui/editor/app.js similarity index 100% rename from ui/arduino/app.js rename to ui/editor/app.js diff --git a/ui/arduino/assets/about_image.png b/ui/editor/assets/about_image.png similarity index 100% rename from ui/arduino/assets/about_image.png rename to ui/editor/assets/about_image.png diff --git a/ui/arduino/components/editor.js b/ui/editor/components/editor.js similarity index 100% rename from ui/arduino/components/editor.js rename to ui/editor/components/editor.js diff --git a/ui/arduino/components/filename.js b/ui/editor/components/filename.js similarity index 100% rename from ui/arduino/components/filename.js rename to ui/editor/components/filename.js diff --git a/ui/arduino/components/icon.js b/ui/editor/components/icon.js similarity index 100% rename from ui/arduino/components/icon.js rename to ui/editor/components/icon.js diff --git a/ui/arduino/components/message.js b/ui/editor/components/message.js similarity index 100% rename from ui/arduino/components/message.js rename to ui/editor/components/message.js diff --git a/ui/arduino/components/newfiledialog.js b/ui/editor/components/newfiledialog.js similarity index 100% rename from ui/arduino/components/newfiledialog.js rename to ui/editor/components/newfiledialog.js diff --git a/ui/arduino/components/panel.js b/ui/editor/components/panel.js similarity index 100% rename from ui/arduino/components/panel.js rename to ui/editor/components/panel.js diff --git a/ui/arduino/components/panel_files.js b/ui/editor/components/panel_files.js similarity index 100% rename from ui/arduino/components/panel_files.js rename to ui/editor/components/panel_files.js diff --git a/ui/arduino/components/panel_terminal.js b/ui/editor/components/panel_terminal.js similarity index 100% rename from ui/arduino/components/panel_terminal.js rename to ui/editor/components/panel_terminal.js diff --git a/ui/arduino/components/portdialog.js b/ui/editor/components/portdialog.js similarity index 100% rename from ui/arduino/components/portdialog.js rename to ui/editor/components/portdialog.js diff --git a/ui/arduino/components/toolbar.js b/ui/editor/components/toolbar.js similarity index 100% rename from ui/arduino/components/toolbar.js rename to ui/editor/components/toolbar.js diff --git a/ui/arduino/components/toolbar_button.js b/ui/editor/components/toolbar_button.js similarity index 100% rename from ui/arduino/components/toolbar_button.js rename to ui/editor/components/toolbar_button.js diff --git a/ui/arduino/icons/Connect.svg b/ui/editor/icons/Connect.svg similarity index 100% rename from ui/arduino/icons/Connect.svg rename to ui/editor/icons/Connect.svg diff --git a/ui/arduino/icons/Connect@3x.png b/ui/editor/icons/Connect@3x.png similarity index 100% rename from ui/arduino/icons/Connect@3x.png rename to ui/editor/icons/Connect@3x.png diff --git a/ui/arduino/icons/Copy-Left.svg b/ui/editor/icons/Copy-Left.svg similarity index 100% rename from ui/arduino/icons/Copy-Left.svg rename to ui/editor/icons/Copy-Left.svg diff --git a/ui/arduino/icons/Copy-Left@3x.png b/ui/editor/icons/Copy-Left@3x.png similarity index 100% rename from ui/arduino/icons/Copy-Left@3x.png rename to ui/editor/icons/Copy-Left@3x.png diff --git a/ui/arduino/icons/Copy-Right.svg b/ui/editor/icons/Copy-Right.svg similarity index 100% rename from ui/arduino/icons/Copy-Right.svg rename to ui/editor/icons/Copy-Right.svg diff --git a/ui/arduino/icons/Copy-Right@3x.png b/ui/editor/icons/Copy-Right@3x.png similarity index 100% rename from ui/arduino/icons/Copy-Right@3x.png rename to ui/editor/icons/Copy-Right@3x.png diff --git a/ui/arduino/icons/Copy.png b/ui/editor/icons/Copy.png similarity index 100% rename from ui/arduino/icons/Copy.png rename to ui/editor/icons/Copy.png diff --git a/ui/arduino/icons/Copy.svg b/ui/editor/icons/Copy.svg similarity index 100% rename from ui/arduino/icons/Copy.svg rename to ui/editor/icons/Copy.svg diff --git a/ui/arduino/icons/Delete.svg b/ui/editor/icons/Delete.svg similarity index 100% rename from ui/arduino/icons/Delete.svg rename to ui/editor/icons/Delete.svg diff --git a/ui/arduino/icons/Delete@3x.png b/ui/editor/icons/Delete@3x.png similarity index 100% rename from ui/arduino/icons/Delete@3x.png rename to ui/editor/icons/Delete@3x.png diff --git a/ui/arduino/icons/Disconnect.svg b/ui/editor/icons/Disconnect.svg similarity index 100% rename from ui/arduino/icons/Disconnect.svg rename to ui/editor/icons/Disconnect.svg diff --git a/ui/arduino/icons/Disconnect@3x.png b/ui/editor/icons/Disconnect@3x.png similarity index 100% rename from ui/arduino/icons/Disconnect@3x.png rename to ui/editor/icons/Disconnect@3x.png diff --git a/ui/arduino/icons/File-Explorer.svg b/ui/editor/icons/File-Explorer.svg similarity index 100% rename from ui/arduino/icons/File-Explorer.svg rename to ui/editor/icons/File-Explorer.svg diff --git a/ui/arduino/icons/File-Explorer@3x.png b/ui/editor/icons/File-Explorer@3x.png similarity index 100% rename from ui/arduino/icons/File-Explorer@3x.png rename to ui/editor/icons/File-Explorer@3x.png diff --git a/ui/arduino/icons/New.svg b/ui/editor/icons/New.svg similarity index 100% rename from ui/arduino/icons/New.svg rename to ui/editor/icons/New.svg diff --git a/ui/arduino/icons/New@3x.png b/ui/editor/icons/New@3x.png similarity index 100% rename from ui/arduino/icons/New@3x.png rename to ui/editor/icons/New@3x.png diff --git a/ui/arduino/icons/Open.svg b/ui/editor/icons/Open.svg similarity index 100% rename from ui/arduino/icons/Open.svg rename to ui/editor/icons/Open.svg diff --git a/ui/arduino/icons/Open@3x.png b/ui/editor/icons/Open@3x.png similarity index 100% rename from ui/arduino/icons/Open@3x.png rename to ui/editor/icons/Open@3x.png diff --git a/ui/arduino/icons/Output.svg b/ui/editor/icons/Output.svg similarity index 100% rename from ui/arduino/icons/Output.svg rename to ui/editor/icons/Output.svg diff --git a/ui/arduino/icons/Output@3x.png b/ui/editor/icons/Output@3x.png similarity index 100% rename from ui/arduino/icons/Output@3x.png rename to ui/editor/icons/Output@3x.png diff --git a/ui/arduino/icons/Paste.png b/ui/editor/icons/Paste.png similarity index 100% rename from ui/arduino/icons/Paste.png rename to ui/editor/icons/Paste.png diff --git a/ui/arduino/icons/Paste.svg b/ui/editor/icons/Paste.svg similarity index 100% rename from ui/arduino/icons/Paste.svg rename to ui/editor/icons/Paste.svg diff --git a/ui/arduino/icons/Reboot.svg b/ui/editor/icons/Reboot.svg similarity index 100% rename from ui/arduino/icons/Reboot.svg rename to ui/editor/icons/Reboot.svg diff --git a/ui/arduino/icons/Reboot@3x.png b/ui/editor/icons/Reboot@3x.png similarity index 100% rename from ui/arduino/icons/Reboot@3x.png rename to ui/editor/icons/Reboot@3x.png diff --git a/ui/arduino/icons/Run.svg b/ui/editor/icons/Run.svg similarity index 100% rename from ui/arduino/icons/Run.svg rename to ui/editor/icons/Run.svg diff --git a/ui/arduino/icons/Run@3x.png b/ui/editor/icons/Run@3x.png similarity index 100% rename from ui/arduino/icons/Run@3x.png rename to ui/editor/icons/Run@3x.png diff --git a/ui/arduino/icons/Save.svg b/ui/editor/icons/Save.svg similarity index 100% rename from ui/arduino/icons/Save.svg rename to ui/editor/icons/Save.svg diff --git a/ui/arduino/icons/Save@3x.png b/ui/editor/icons/Save@3x.png similarity index 100% rename from ui/arduino/icons/Save@3x.png rename to ui/editor/icons/Save@3x.png diff --git a/ui/arduino/icons/Stop.svg b/ui/editor/icons/Stop.svg similarity index 100% rename from ui/arduino/icons/Stop.svg rename to ui/editor/icons/Stop.svg diff --git a/ui/arduino/icons/Stop@3x.png b/ui/editor/icons/Stop@3x.png similarity index 100% rename from ui/arduino/icons/Stop@3x.png rename to ui/editor/icons/Stop@3x.png diff --git a/ui/arduino/index.html b/ui/editor/index.html similarity index 100% rename from ui/arduino/index.html rename to ui/editor/index.html diff --git a/ui/arduino/libs/FileSaver.js b/ui/editor/libs/FileSaver.js similarity index 100% rename from ui/arduino/libs/FileSaver.js rename to ui/editor/libs/FileSaver.js diff --git a/ui/arduino/libs/ace/ace.js b/ui/editor/libs/ace/ace.js similarity index 100% rename from ui/arduino/libs/ace/ace.js rename to ui/editor/libs/ace/ace.js diff --git a/ui/arduino/libs/ace/ext-beautify.js b/ui/editor/libs/ace/ext-beautify.js similarity index 100% rename from ui/arduino/libs/ace/ext-beautify.js rename to ui/editor/libs/ace/ext-beautify.js diff --git a/ui/arduino/libs/ace/ext-code_lens.js b/ui/editor/libs/ace/ext-code_lens.js similarity index 100% rename from ui/arduino/libs/ace/ext-code_lens.js rename to ui/editor/libs/ace/ext-code_lens.js diff --git a/ui/arduino/libs/ace/ext-elastic_tabstops_lite.js b/ui/editor/libs/ace/ext-elastic_tabstops_lite.js similarity index 100% rename from ui/arduino/libs/ace/ext-elastic_tabstops_lite.js rename to ui/editor/libs/ace/ext-elastic_tabstops_lite.js diff --git a/ui/arduino/libs/ace/ext-emmet.js b/ui/editor/libs/ace/ext-emmet.js similarity index 100% rename from ui/arduino/libs/ace/ext-emmet.js rename to ui/editor/libs/ace/ext-emmet.js diff --git a/ui/arduino/libs/ace/ext-error_marker.js b/ui/editor/libs/ace/ext-error_marker.js similarity index 100% rename from ui/arduino/libs/ace/ext-error_marker.js rename to ui/editor/libs/ace/ext-error_marker.js diff --git a/ui/arduino/libs/ace/ext-keybinding_menu.js b/ui/editor/libs/ace/ext-keybinding_menu.js similarity index 100% rename from ui/arduino/libs/ace/ext-keybinding_menu.js rename to ui/editor/libs/ace/ext-keybinding_menu.js diff --git a/ui/arduino/libs/ace/ext-language_tools.js b/ui/editor/libs/ace/ext-language_tools.js similarity index 100% rename from ui/arduino/libs/ace/ext-language_tools.js rename to ui/editor/libs/ace/ext-language_tools.js diff --git a/ui/arduino/libs/ace/ext-linking.js b/ui/editor/libs/ace/ext-linking.js similarity index 100% rename from ui/arduino/libs/ace/ext-linking.js rename to ui/editor/libs/ace/ext-linking.js diff --git a/ui/arduino/libs/ace/ext-modelist.js b/ui/editor/libs/ace/ext-modelist.js similarity index 100% rename from ui/arduino/libs/ace/ext-modelist.js rename to ui/editor/libs/ace/ext-modelist.js diff --git a/ui/arduino/libs/ace/ext-options.js b/ui/editor/libs/ace/ext-options.js similarity index 100% rename from ui/arduino/libs/ace/ext-options.js rename to ui/editor/libs/ace/ext-options.js diff --git a/ui/arduino/libs/ace/ext-prompt.js b/ui/editor/libs/ace/ext-prompt.js similarity index 100% rename from ui/arduino/libs/ace/ext-prompt.js rename to ui/editor/libs/ace/ext-prompt.js diff --git a/ui/arduino/libs/ace/ext-rtl.js b/ui/editor/libs/ace/ext-rtl.js similarity index 100% rename from ui/arduino/libs/ace/ext-rtl.js rename to ui/editor/libs/ace/ext-rtl.js diff --git a/ui/arduino/libs/ace/ext-searchbox.js b/ui/editor/libs/ace/ext-searchbox.js similarity index 100% rename from ui/arduino/libs/ace/ext-searchbox.js rename to ui/editor/libs/ace/ext-searchbox.js diff --git a/ui/arduino/libs/ace/ext-settings_menu.js b/ui/editor/libs/ace/ext-settings_menu.js similarity index 100% rename from ui/arduino/libs/ace/ext-settings_menu.js rename to ui/editor/libs/ace/ext-settings_menu.js diff --git a/ui/arduino/libs/ace/ext-spellcheck.js b/ui/editor/libs/ace/ext-spellcheck.js similarity index 100% rename from ui/arduino/libs/ace/ext-spellcheck.js rename to ui/editor/libs/ace/ext-spellcheck.js diff --git a/ui/arduino/libs/ace/ext-split.js b/ui/editor/libs/ace/ext-split.js similarity index 100% rename from ui/arduino/libs/ace/ext-split.js rename to ui/editor/libs/ace/ext-split.js diff --git a/ui/arduino/libs/ace/ext-static_highlight.js b/ui/editor/libs/ace/ext-static_highlight.js similarity index 100% rename from ui/arduino/libs/ace/ext-static_highlight.js rename to ui/editor/libs/ace/ext-static_highlight.js diff --git a/ui/arduino/libs/ace/ext-statusbar.js b/ui/editor/libs/ace/ext-statusbar.js similarity index 100% rename from ui/arduino/libs/ace/ext-statusbar.js rename to ui/editor/libs/ace/ext-statusbar.js diff --git a/ui/arduino/libs/ace/ext-textarea.js b/ui/editor/libs/ace/ext-textarea.js similarity index 100% rename from ui/arduino/libs/ace/ext-textarea.js rename to ui/editor/libs/ace/ext-textarea.js diff --git a/ui/arduino/libs/ace/ext-themelist.js b/ui/editor/libs/ace/ext-themelist.js similarity index 100% rename from ui/arduino/libs/ace/ext-themelist.js rename to ui/editor/libs/ace/ext-themelist.js diff --git a/ui/arduino/libs/ace/ext-whitespace.js b/ui/editor/libs/ace/ext-whitespace.js similarity index 100% rename from ui/arduino/libs/ace/ext-whitespace.js rename to ui/editor/libs/ace/ext-whitespace.js diff --git a/ui/arduino/libs/ace/keybinding-emacs.js b/ui/editor/libs/ace/keybinding-emacs.js similarity index 100% rename from ui/arduino/libs/ace/keybinding-emacs.js rename to ui/editor/libs/ace/keybinding-emacs.js diff --git a/ui/arduino/libs/ace/keybinding-sublime.js b/ui/editor/libs/ace/keybinding-sublime.js similarity index 100% rename from ui/arduino/libs/ace/keybinding-sublime.js rename to ui/editor/libs/ace/keybinding-sublime.js diff --git a/ui/arduino/libs/ace/keybinding-vim.js b/ui/editor/libs/ace/keybinding-vim.js similarity index 100% rename from ui/arduino/libs/ace/keybinding-vim.js rename to ui/editor/libs/ace/keybinding-vim.js diff --git a/ui/arduino/libs/ace/keybinding-vscode.js b/ui/editor/libs/ace/keybinding-vscode.js similarity index 100% rename from ui/arduino/libs/ace/keybinding-vscode.js rename to ui/editor/libs/ace/keybinding-vscode.js diff --git a/ui/arduino/libs/ace/mode-abap.js b/ui/editor/libs/ace/mode-abap.js similarity index 100% rename from ui/arduino/libs/ace/mode-abap.js rename to ui/editor/libs/ace/mode-abap.js diff --git a/ui/arduino/libs/ace/mode-abc.js b/ui/editor/libs/ace/mode-abc.js similarity index 100% rename from ui/arduino/libs/ace/mode-abc.js rename to ui/editor/libs/ace/mode-abc.js diff --git a/ui/arduino/libs/ace/mode-actionscript.js b/ui/editor/libs/ace/mode-actionscript.js similarity index 100% rename from ui/arduino/libs/ace/mode-actionscript.js rename to ui/editor/libs/ace/mode-actionscript.js diff --git a/ui/arduino/libs/ace/mode-ada.js b/ui/editor/libs/ace/mode-ada.js similarity index 100% rename from ui/arduino/libs/ace/mode-ada.js rename to ui/editor/libs/ace/mode-ada.js diff --git a/ui/arduino/libs/ace/mode-alda.js b/ui/editor/libs/ace/mode-alda.js similarity index 100% rename from ui/arduino/libs/ace/mode-alda.js rename to ui/editor/libs/ace/mode-alda.js diff --git a/ui/arduino/libs/ace/mode-apache_conf.js b/ui/editor/libs/ace/mode-apache_conf.js similarity index 100% rename from ui/arduino/libs/ace/mode-apache_conf.js rename to ui/editor/libs/ace/mode-apache_conf.js diff --git a/ui/arduino/libs/ace/mode-apex.js b/ui/editor/libs/ace/mode-apex.js similarity index 100% rename from ui/arduino/libs/ace/mode-apex.js rename to ui/editor/libs/ace/mode-apex.js diff --git a/ui/arduino/libs/ace/mode-applescript.js b/ui/editor/libs/ace/mode-applescript.js similarity index 100% rename from ui/arduino/libs/ace/mode-applescript.js rename to ui/editor/libs/ace/mode-applescript.js diff --git a/ui/arduino/libs/ace/mode-aql.js b/ui/editor/libs/ace/mode-aql.js similarity index 100% rename from ui/arduino/libs/ace/mode-aql.js rename to ui/editor/libs/ace/mode-aql.js diff --git a/ui/arduino/libs/ace/mode-asciidoc.js b/ui/editor/libs/ace/mode-asciidoc.js similarity index 100% rename from ui/arduino/libs/ace/mode-asciidoc.js rename to ui/editor/libs/ace/mode-asciidoc.js diff --git a/ui/arduino/libs/ace/mode-asl.js b/ui/editor/libs/ace/mode-asl.js similarity index 100% rename from ui/arduino/libs/ace/mode-asl.js rename to ui/editor/libs/ace/mode-asl.js diff --git a/ui/arduino/libs/ace/mode-assembly_x86.js b/ui/editor/libs/ace/mode-assembly_x86.js similarity index 100% rename from ui/arduino/libs/ace/mode-assembly_x86.js rename to ui/editor/libs/ace/mode-assembly_x86.js diff --git a/ui/arduino/libs/ace/mode-autohotkey.js b/ui/editor/libs/ace/mode-autohotkey.js similarity index 100% rename from ui/arduino/libs/ace/mode-autohotkey.js rename to ui/editor/libs/ace/mode-autohotkey.js diff --git a/ui/arduino/libs/ace/mode-batchfile.js b/ui/editor/libs/ace/mode-batchfile.js similarity index 100% rename from ui/arduino/libs/ace/mode-batchfile.js rename to ui/editor/libs/ace/mode-batchfile.js diff --git a/ui/arduino/libs/ace/mode-c9search.js b/ui/editor/libs/ace/mode-c9search.js similarity index 100% rename from ui/arduino/libs/ace/mode-c9search.js rename to ui/editor/libs/ace/mode-c9search.js diff --git a/ui/arduino/libs/ace/mode-c_cpp.js b/ui/editor/libs/ace/mode-c_cpp.js similarity index 100% rename from ui/arduino/libs/ace/mode-c_cpp.js rename to ui/editor/libs/ace/mode-c_cpp.js diff --git a/ui/arduino/libs/ace/mode-cirru.js b/ui/editor/libs/ace/mode-cirru.js similarity index 100% rename from ui/arduino/libs/ace/mode-cirru.js rename to ui/editor/libs/ace/mode-cirru.js diff --git a/ui/arduino/libs/ace/mode-clojure.js b/ui/editor/libs/ace/mode-clojure.js similarity index 100% rename from ui/arduino/libs/ace/mode-clojure.js rename to ui/editor/libs/ace/mode-clojure.js diff --git a/ui/arduino/libs/ace/mode-cobol.js b/ui/editor/libs/ace/mode-cobol.js similarity index 100% rename from ui/arduino/libs/ace/mode-cobol.js rename to ui/editor/libs/ace/mode-cobol.js diff --git a/ui/arduino/libs/ace/mode-coffee.js b/ui/editor/libs/ace/mode-coffee.js similarity index 100% rename from ui/arduino/libs/ace/mode-coffee.js rename to ui/editor/libs/ace/mode-coffee.js diff --git a/ui/arduino/libs/ace/mode-coldfusion.js b/ui/editor/libs/ace/mode-coldfusion.js similarity index 100% rename from ui/arduino/libs/ace/mode-coldfusion.js rename to ui/editor/libs/ace/mode-coldfusion.js diff --git a/ui/arduino/libs/ace/mode-crystal.js b/ui/editor/libs/ace/mode-crystal.js similarity index 100% rename from ui/arduino/libs/ace/mode-crystal.js rename to ui/editor/libs/ace/mode-crystal.js diff --git a/ui/arduino/libs/ace/mode-csharp.js b/ui/editor/libs/ace/mode-csharp.js similarity index 100% rename from ui/arduino/libs/ace/mode-csharp.js rename to ui/editor/libs/ace/mode-csharp.js diff --git a/ui/arduino/libs/ace/mode-csound_document.js b/ui/editor/libs/ace/mode-csound_document.js similarity index 100% rename from ui/arduino/libs/ace/mode-csound_document.js rename to ui/editor/libs/ace/mode-csound_document.js diff --git a/ui/arduino/libs/ace/mode-csound_orchestra.js b/ui/editor/libs/ace/mode-csound_orchestra.js similarity index 100% rename from ui/arduino/libs/ace/mode-csound_orchestra.js rename to ui/editor/libs/ace/mode-csound_orchestra.js diff --git a/ui/arduino/libs/ace/mode-csound_score.js b/ui/editor/libs/ace/mode-csound_score.js similarity index 100% rename from ui/arduino/libs/ace/mode-csound_score.js rename to ui/editor/libs/ace/mode-csound_score.js diff --git a/ui/arduino/libs/ace/mode-csp.js b/ui/editor/libs/ace/mode-csp.js similarity index 100% rename from ui/arduino/libs/ace/mode-csp.js rename to ui/editor/libs/ace/mode-csp.js diff --git a/ui/arduino/libs/ace/mode-css.js b/ui/editor/libs/ace/mode-css.js similarity index 100% rename from ui/arduino/libs/ace/mode-css.js rename to ui/editor/libs/ace/mode-css.js diff --git a/ui/arduino/libs/ace/mode-curly.js b/ui/editor/libs/ace/mode-curly.js similarity index 100% rename from ui/arduino/libs/ace/mode-curly.js rename to ui/editor/libs/ace/mode-curly.js diff --git a/ui/arduino/libs/ace/mode-d.js b/ui/editor/libs/ace/mode-d.js similarity index 100% rename from ui/arduino/libs/ace/mode-d.js rename to ui/editor/libs/ace/mode-d.js diff --git a/ui/arduino/libs/ace/mode-dart.js b/ui/editor/libs/ace/mode-dart.js similarity index 100% rename from ui/arduino/libs/ace/mode-dart.js rename to ui/editor/libs/ace/mode-dart.js diff --git a/ui/arduino/libs/ace/mode-diff.js b/ui/editor/libs/ace/mode-diff.js similarity index 100% rename from ui/arduino/libs/ace/mode-diff.js rename to ui/editor/libs/ace/mode-diff.js diff --git a/ui/arduino/libs/ace/mode-django.js b/ui/editor/libs/ace/mode-django.js similarity index 100% rename from ui/arduino/libs/ace/mode-django.js rename to ui/editor/libs/ace/mode-django.js diff --git a/ui/arduino/libs/ace/mode-dockerfile.js b/ui/editor/libs/ace/mode-dockerfile.js similarity index 100% rename from ui/arduino/libs/ace/mode-dockerfile.js rename to ui/editor/libs/ace/mode-dockerfile.js diff --git a/ui/arduino/libs/ace/mode-dot.js b/ui/editor/libs/ace/mode-dot.js similarity index 100% rename from ui/arduino/libs/ace/mode-dot.js rename to ui/editor/libs/ace/mode-dot.js diff --git a/ui/arduino/libs/ace/mode-drools.js b/ui/editor/libs/ace/mode-drools.js similarity index 100% rename from ui/arduino/libs/ace/mode-drools.js rename to ui/editor/libs/ace/mode-drools.js diff --git a/ui/arduino/libs/ace/mode-edifact.js b/ui/editor/libs/ace/mode-edifact.js similarity index 100% rename from ui/arduino/libs/ace/mode-edifact.js rename to ui/editor/libs/ace/mode-edifact.js diff --git a/ui/arduino/libs/ace/mode-eiffel.js b/ui/editor/libs/ace/mode-eiffel.js similarity index 100% rename from ui/arduino/libs/ace/mode-eiffel.js rename to ui/editor/libs/ace/mode-eiffel.js diff --git a/ui/arduino/libs/ace/mode-ejs.js b/ui/editor/libs/ace/mode-ejs.js similarity index 100% rename from ui/arduino/libs/ace/mode-ejs.js rename to ui/editor/libs/ace/mode-ejs.js diff --git a/ui/arduino/libs/ace/mode-elixir.js b/ui/editor/libs/ace/mode-elixir.js similarity index 100% rename from ui/arduino/libs/ace/mode-elixir.js rename to ui/editor/libs/ace/mode-elixir.js diff --git a/ui/arduino/libs/ace/mode-elm.js b/ui/editor/libs/ace/mode-elm.js similarity index 100% rename from ui/arduino/libs/ace/mode-elm.js rename to ui/editor/libs/ace/mode-elm.js diff --git a/ui/arduino/libs/ace/mode-erlang.js b/ui/editor/libs/ace/mode-erlang.js similarity index 100% rename from ui/arduino/libs/ace/mode-erlang.js rename to ui/editor/libs/ace/mode-erlang.js diff --git a/ui/arduino/libs/ace/mode-forth.js b/ui/editor/libs/ace/mode-forth.js similarity index 100% rename from ui/arduino/libs/ace/mode-forth.js rename to ui/editor/libs/ace/mode-forth.js diff --git a/ui/arduino/libs/ace/mode-fortran.js b/ui/editor/libs/ace/mode-fortran.js similarity index 100% rename from ui/arduino/libs/ace/mode-fortran.js rename to ui/editor/libs/ace/mode-fortran.js diff --git a/ui/arduino/libs/ace/mode-fsharp.js b/ui/editor/libs/ace/mode-fsharp.js similarity index 100% rename from ui/arduino/libs/ace/mode-fsharp.js rename to ui/editor/libs/ace/mode-fsharp.js diff --git a/ui/arduino/libs/ace/mode-fsl.js b/ui/editor/libs/ace/mode-fsl.js similarity index 100% rename from ui/arduino/libs/ace/mode-fsl.js rename to ui/editor/libs/ace/mode-fsl.js diff --git a/ui/arduino/libs/ace/mode-ftl.js b/ui/editor/libs/ace/mode-ftl.js similarity index 100% rename from ui/arduino/libs/ace/mode-ftl.js rename to ui/editor/libs/ace/mode-ftl.js diff --git a/ui/arduino/libs/ace/mode-gcode.js b/ui/editor/libs/ace/mode-gcode.js similarity index 100% rename from ui/arduino/libs/ace/mode-gcode.js rename to ui/editor/libs/ace/mode-gcode.js diff --git a/ui/arduino/libs/ace/mode-gherkin.js b/ui/editor/libs/ace/mode-gherkin.js similarity index 100% rename from ui/arduino/libs/ace/mode-gherkin.js rename to ui/editor/libs/ace/mode-gherkin.js diff --git a/ui/arduino/libs/ace/mode-gitignore.js b/ui/editor/libs/ace/mode-gitignore.js similarity index 100% rename from ui/arduino/libs/ace/mode-gitignore.js rename to ui/editor/libs/ace/mode-gitignore.js diff --git a/ui/arduino/libs/ace/mode-glsl.js b/ui/editor/libs/ace/mode-glsl.js similarity index 100% rename from ui/arduino/libs/ace/mode-glsl.js rename to ui/editor/libs/ace/mode-glsl.js diff --git a/ui/arduino/libs/ace/mode-gobstones.js b/ui/editor/libs/ace/mode-gobstones.js similarity index 100% rename from ui/arduino/libs/ace/mode-gobstones.js rename to ui/editor/libs/ace/mode-gobstones.js diff --git a/ui/arduino/libs/ace/mode-golang.js b/ui/editor/libs/ace/mode-golang.js similarity index 100% rename from ui/arduino/libs/ace/mode-golang.js rename to ui/editor/libs/ace/mode-golang.js diff --git a/ui/arduino/libs/ace/mode-graphqlschema.js b/ui/editor/libs/ace/mode-graphqlschema.js similarity index 100% rename from ui/arduino/libs/ace/mode-graphqlschema.js rename to ui/editor/libs/ace/mode-graphqlschema.js diff --git a/ui/arduino/libs/ace/mode-groovy.js b/ui/editor/libs/ace/mode-groovy.js similarity index 100% rename from ui/arduino/libs/ace/mode-groovy.js rename to ui/editor/libs/ace/mode-groovy.js diff --git a/ui/arduino/libs/ace/mode-haml.js b/ui/editor/libs/ace/mode-haml.js similarity index 100% rename from ui/arduino/libs/ace/mode-haml.js rename to ui/editor/libs/ace/mode-haml.js diff --git a/ui/arduino/libs/ace/mode-handlebars.js b/ui/editor/libs/ace/mode-handlebars.js similarity index 100% rename from ui/arduino/libs/ace/mode-handlebars.js rename to ui/editor/libs/ace/mode-handlebars.js diff --git a/ui/arduino/libs/ace/mode-haskell.js b/ui/editor/libs/ace/mode-haskell.js similarity index 100% rename from ui/arduino/libs/ace/mode-haskell.js rename to ui/editor/libs/ace/mode-haskell.js diff --git a/ui/arduino/libs/ace/mode-haskell_cabal.js b/ui/editor/libs/ace/mode-haskell_cabal.js similarity index 100% rename from ui/arduino/libs/ace/mode-haskell_cabal.js rename to ui/editor/libs/ace/mode-haskell_cabal.js diff --git a/ui/arduino/libs/ace/mode-haxe.js b/ui/editor/libs/ace/mode-haxe.js similarity index 100% rename from ui/arduino/libs/ace/mode-haxe.js rename to ui/editor/libs/ace/mode-haxe.js diff --git a/ui/arduino/libs/ace/mode-hjson.js b/ui/editor/libs/ace/mode-hjson.js similarity index 100% rename from ui/arduino/libs/ace/mode-hjson.js rename to ui/editor/libs/ace/mode-hjson.js diff --git a/ui/arduino/libs/ace/mode-html.js b/ui/editor/libs/ace/mode-html.js similarity index 100% rename from ui/arduino/libs/ace/mode-html.js rename to ui/editor/libs/ace/mode-html.js diff --git a/ui/arduino/libs/ace/mode-html_elixir.js b/ui/editor/libs/ace/mode-html_elixir.js similarity index 100% rename from ui/arduino/libs/ace/mode-html_elixir.js rename to ui/editor/libs/ace/mode-html_elixir.js diff --git a/ui/arduino/libs/ace/mode-html_ruby.js b/ui/editor/libs/ace/mode-html_ruby.js similarity index 100% rename from ui/arduino/libs/ace/mode-html_ruby.js rename to ui/editor/libs/ace/mode-html_ruby.js diff --git a/ui/arduino/libs/ace/mode-ini.js b/ui/editor/libs/ace/mode-ini.js similarity index 100% rename from ui/arduino/libs/ace/mode-ini.js rename to ui/editor/libs/ace/mode-ini.js diff --git a/ui/arduino/libs/ace/mode-io.js b/ui/editor/libs/ace/mode-io.js similarity index 100% rename from ui/arduino/libs/ace/mode-io.js rename to ui/editor/libs/ace/mode-io.js diff --git a/ui/arduino/libs/ace/mode-jack.js b/ui/editor/libs/ace/mode-jack.js similarity index 100% rename from ui/arduino/libs/ace/mode-jack.js rename to ui/editor/libs/ace/mode-jack.js diff --git a/ui/arduino/libs/ace/mode-jade.js b/ui/editor/libs/ace/mode-jade.js similarity index 100% rename from ui/arduino/libs/ace/mode-jade.js rename to ui/editor/libs/ace/mode-jade.js diff --git a/ui/arduino/libs/ace/mode-java.js b/ui/editor/libs/ace/mode-java.js similarity index 100% rename from ui/arduino/libs/ace/mode-java.js rename to ui/editor/libs/ace/mode-java.js diff --git a/ui/arduino/libs/ace/mode-javascript.js b/ui/editor/libs/ace/mode-javascript.js similarity index 100% rename from ui/arduino/libs/ace/mode-javascript.js rename to ui/editor/libs/ace/mode-javascript.js diff --git a/ui/arduino/libs/ace/mode-json.js b/ui/editor/libs/ace/mode-json.js similarity index 100% rename from ui/arduino/libs/ace/mode-json.js rename to ui/editor/libs/ace/mode-json.js diff --git a/ui/arduino/libs/ace/mode-json5.js b/ui/editor/libs/ace/mode-json5.js similarity index 100% rename from ui/arduino/libs/ace/mode-json5.js rename to ui/editor/libs/ace/mode-json5.js diff --git a/ui/arduino/libs/ace/mode-jsoniq.js b/ui/editor/libs/ace/mode-jsoniq.js similarity index 100% rename from ui/arduino/libs/ace/mode-jsoniq.js rename to ui/editor/libs/ace/mode-jsoniq.js diff --git a/ui/arduino/libs/ace/mode-jsp.js b/ui/editor/libs/ace/mode-jsp.js similarity index 100% rename from ui/arduino/libs/ace/mode-jsp.js rename to ui/editor/libs/ace/mode-jsp.js diff --git a/ui/arduino/libs/ace/mode-jssm.js b/ui/editor/libs/ace/mode-jssm.js similarity index 100% rename from ui/arduino/libs/ace/mode-jssm.js rename to ui/editor/libs/ace/mode-jssm.js diff --git a/ui/arduino/libs/ace/mode-jsx.js b/ui/editor/libs/ace/mode-jsx.js similarity index 100% rename from ui/arduino/libs/ace/mode-jsx.js rename to ui/editor/libs/ace/mode-jsx.js diff --git a/ui/arduino/libs/ace/mode-julia.js b/ui/editor/libs/ace/mode-julia.js similarity index 100% rename from ui/arduino/libs/ace/mode-julia.js rename to ui/editor/libs/ace/mode-julia.js diff --git a/ui/arduino/libs/ace/mode-kotlin.js b/ui/editor/libs/ace/mode-kotlin.js similarity index 100% rename from ui/arduino/libs/ace/mode-kotlin.js rename to ui/editor/libs/ace/mode-kotlin.js diff --git a/ui/arduino/libs/ace/mode-latex.js b/ui/editor/libs/ace/mode-latex.js similarity index 100% rename from ui/arduino/libs/ace/mode-latex.js rename to ui/editor/libs/ace/mode-latex.js diff --git a/ui/arduino/libs/ace/mode-less.js b/ui/editor/libs/ace/mode-less.js similarity index 100% rename from ui/arduino/libs/ace/mode-less.js rename to ui/editor/libs/ace/mode-less.js diff --git a/ui/arduino/libs/ace/mode-liquid.js b/ui/editor/libs/ace/mode-liquid.js similarity index 100% rename from ui/arduino/libs/ace/mode-liquid.js rename to ui/editor/libs/ace/mode-liquid.js diff --git a/ui/arduino/libs/ace/mode-lisp.js b/ui/editor/libs/ace/mode-lisp.js similarity index 100% rename from ui/arduino/libs/ace/mode-lisp.js rename to ui/editor/libs/ace/mode-lisp.js diff --git a/ui/arduino/libs/ace/mode-livescript.js b/ui/editor/libs/ace/mode-livescript.js similarity index 100% rename from ui/arduino/libs/ace/mode-livescript.js rename to ui/editor/libs/ace/mode-livescript.js diff --git a/ui/arduino/libs/ace/mode-logiql.js b/ui/editor/libs/ace/mode-logiql.js similarity index 100% rename from ui/arduino/libs/ace/mode-logiql.js rename to ui/editor/libs/ace/mode-logiql.js diff --git a/ui/arduino/libs/ace/mode-logtalk.js b/ui/editor/libs/ace/mode-logtalk.js similarity index 100% rename from ui/arduino/libs/ace/mode-logtalk.js rename to ui/editor/libs/ace/mode-logtalk.js diff --git a/ui/arduino/libs/ace/mode-lsl.js b/ui/editor/libs/ace/mode-lsl.js similarity index 100% rename from ui/arduino/libs/ace/mode-lsl.js rename to ui/editor/libs/ace/mode-lsl.js diff --git a/ui/arduino/libs/ace/mode-lua.js b/ui/editor/libs/ace/mode-lua.js similarity index 100% rename from ui/arduino/libs/ace/mode-lua.js rename to ui/editor/libs/ace/mode-lua.js diff --git a/ui/arduino/libs/ace/mode-luapage.js b/ui/editor/libs/ace/mode-luapage.js similarity index 100% rename from ui/arduino/libs/ace/mode-luapage.js rename to ui/editor/libs/ace/mode-luapage.js diff --git a/ui/arduino/libs/ace/mode-lucene.js b/ui/editor/libs/ace/mode-lucene.js similarity index 100% rename from ui/arduino/libs/ace/mode-lucene.js rename to ui/editor/libs/ace/mode-lucene.js diff --git a/ui/arduino/libs/ace/mode-makefile.js b/ui/editor/libs/ace/mode-makefile.js similarity index 100% rename from ui/arduino/libs/ace/mode-makefile.js rename to ui/editor/libs/ace/mode-makefile.js diff --git a/ui/arduino/libs/ace/mode-markdown.js b/ui/editor/libs/ace/mode-markdown.js similarity index 100% rename from ui/arduino/libs/ace/mode-markdown.js rename to ui/editor/libs/ace/mode-markdown.js diff --git a/ui/arduino/libs/ace/mode-mask.js b/ui/editor/libs/ace/mode-mask.js similarity index 100% rename from ui/arduino/libs/ace/mode-mask.js rename to ui/editor/libs/ace/mode-mask.js diff --git a/ui/arduino/libs/ace/mode-matlab.js b/ui/editor/libs/ace/mode-matlab.js similarity index 100% rename from ui/arduino/libs/ace/mode-matlab.js rename to ui/editor/libs/ace/mode-matlab.js diff --git a/ui/arduino/libs/ace/mode-maze.js b/ui/editor/libs/ace/mode-maze.js similarity index 100% rename from ui/arduino/libs/ace/mode-maze.js rename to ui/editor/libs/ace/mode-maze.js diff --git a/ui/arduino/libs/ace/mode-mediawiki.js b/ui/editor/libs/ace/mode-mediawiki.js similarity index 100% rename from ui/arduino/libs/ace/mode-mediawiki.js rename to ui/editor/libs/ace/mode-mediawiki.js diff --git a/ui/arduino/libs/ace/mode-mel.js b/ui/editor/libs/ace/mode-mel.js similarity index 100% rename from ui/arduino/libs/ace/mode-mel.js rename to ui/editor/libs/ace/mode-mel.js diff --git a/ui/arduino/libs/ace/mode-mixal.js b/ui/editor/libs/ace/mode-mixal.js similarity index 100% rename from ui/arduino/libs/ace/mode-mixal.js rename to ui/editor/libs/ace/mode-mixal.js diff --git a/ui/arduino/libs/ace/mode-mushcode.js b/ui/editor/libs/ace/mode-mushcode.js similarity index 100% rename from ui/arduino/libs/ace/mode-mushcode.js rename to ui/editor/libs/ace/mode-mushcode.js diff --git a/ui/arduino/libs/ace/mode-mysql.js b/ui/editor/libs/ace/mode-mysql.js similarity index 100% rename from ui/arduino/libs/ace/mode-mysql.js rename to ui/editor/libs/ace/mode-mysql.js diff --git a/ui/arduino/libs/ace/mode-nginx.js b/ui/editor/libs/ace/mode-nginx.js similarity index 100% rename from ui/arduino/libs/ace/mode-nginx.js rename to ui/editor/libs/ace/mode-nginx.js diff --git a/ui/arduino/libs/ace/mode-nim.js b/ui/editor/libs/ace/mode-nim.js similarity index 100% rename from ui/arduino/libs/ace/mode-nim.js rename to ui/editor/libs/ace/mode-nim.js diff --git a/ui/arduino/libs/ace/mode-nix.js b/ui/editor/libs/ace/mode-nix.js similarity index 100% rename from ui/arduino/libs/ace/mode-nix.js rename to ui/editor/libs/ace/mode-nix.js diff --git a/ui/arduino/libs/ace/mode-nsis.js b/ui/editor/libs/ace/mode-nsis.js similarity index 100% rename from ui/arduino/libs/ace/mode-nsis.js rename to ui/editor/libs/ace/mode-nsis.js diff --git a/ui/arduino/libs/ace/mode-nunjucks.js b/ui/editor/libs/ace/mode-nunjucks.js similarity index 100% rename from ui/arduino/libs/ace/mode-nunjucks.js rename to ui/editor/libs/ace/mode-nunjucks.js diff --git a/ui/arduino/libs/ace/mode-objectivec.js b/ui/editor/libs/ace/mode-objectivec.js similarity index 100% rename from ui/arduino/libs/ace/mode-objectivec.js rename to ui/editor/libs/ace/mode-objectivec.js diff --git a/ui/arduino/libs/ace/mode-ocaml.js b/ui/editor/libs/ace/mode-ocaml.js similarity index 100% rename from ui/arduino/libs/ace/mode-ocaml.js rename to ui/editor/libs/ace/mode-ocaml.js diff --git a/ui/arduino/libs/ace/mode-pascal.js b/ui/editor/libs/ace/mode-pascal.js similarity index 100% rename from ui/arduino/libs/ace/mode-pascal.js rename to ui/editor/libs/ace/mode-pascal.js diff --git a/ui/arduino/libs/ace/mode-perl.js b/ui/editor/libs/ace/mode-perl.js similarity index 100% rename from ui/arduino/libs/ace/mode-perl.js rename to ui/editor/libs/ace/mode-perl.js diff --git a/ui/arduino/libs/ace/mode-perl6.js b/ui/editor/libs/ace/mode-perl6.js similarity index 100% rename from ui/arduino/libs/ace/mode-perl6.js rename to ui/editor/libs/ace/mode-perl6.js diff --git a/ui/arduino/libs/ace/mode-pgsql.js b/ui/editor/libs/ace/mode-pgsql.js similarity index 100% rename from ui/arduino/libs/ace/mode-pgsql.js rename to ui/editor/libs/ace/mode-pgsql.js diff --git a/ui/arduino/libs/ace/mode-php.js b/ui/editor/libs/ace/mode-php.js similarity index 100% rename from ui/arduino/libs/ace/mode-php.js rename to ui/editor/libs/ace/mode-php.js diff --git a/ui/arduino/libs/ace/mode-php_laravel_blade.js b/ui/editor/libs/ace/mode-php_laravel_blade.js similarity index 100% rename from ui/arduino/libs/ace/mode-php_laravel_blade.js rename to ui/editor/libs/ace/mode-php_laravel_blade.js diff --git a/ui/arduino/libs/ace/mode-pig.js b/ui/editor/libs/ace/mode-pig.js similarity index 100% rename from ui/arduino/libs/ace/mode-pig.js rename to ui/editor/libs/ace/mode-pig.js diff --git a/ui/arduino/libs/ace/mode-plain_text.js b/ui/editor/libs/ace/mode-plain_text.js similarity index 100% rename from ui/arduino/libs/ace/mode-plain_text.js rename to ui/editor/libs/ace/mode-plain_text.js diff --git a/ui/arduino/libs/ace/mode-powershell.js b/ui/editor/libs/ace/mode-powershell.js similarity index 100% rename from ui/arduino/libs/ace/mode-powershell.js rename to ui/editor/libs/ace/mode-powershell.js diff --git a/ui/arduino/libs/ace/mode-praat.js b/ui/editor/libs/ace/mode-praat.js similarity index 100% rename from ui/arduino/libs/ace/mode-praat.js rename to ui/editor/libs/ace/mode-praat.js diff --git a/ui/arduino/libs/ace/mode-prisma.js b/ui/editor/libs/ace/mode-prisma.js similarity index 100% rename from ui/arduino/libs/ace/mode-prisma.js rename to ui/editor/libs/ace/mode-prisma.js diff --git a/ui/arduino/libs/ace/mode-prolog.js b/ui/editor/libs/ace/mode-prolog.js similarity index 100% rename from ui/arduino/libs/ace/mode-prolog.js rename to ui/editor/libs/ace/mode-prolog.js diff --git a/ui/arduino/libs/ace/mode-properties.js b/ui/editor/libs/ace/mode-properties.js similarity index 100% rename from ui/arduino/libs/ace/mode-properties.js rename to ui/editor/libs/ace/mode-properties.js diff --git a/ui/arduino/libs/ace/mode-protobuf.js b/ui/editor/libs/ace/mode-protobuf.js similarity index 100% rename from ui/arduino/libs/ace/mode-protobuf.js rename to ui/editor/libs/ace/mode-protobuf.js diff --git a/ui/arduino/libs/ace/mode-puppet.js b/ui/editor/libs/ace/mode-puppet.js similarity index 100% rename from ui/arduino/libs/ace/mode-puppet.js rename to ui/editor/libs/ace/mode-puppet.js diff --git a/ui/arduino/libs/ace/mode-python.js b/ui/editor/libs/ace/mode-python.js similarity index 100% rename from ui/arduino/libs/ace/mode-python.js rename to ui/editor/libs/ace/mode-python.js diff --git a/ui/arduino/libs/ace/mode-qml.js b/ui/editor/libs/ace/mode-qml.js similarity index 100% rename from ui/arduino/libs/ace/mode-qml.js rename to ui/editor/libs/ace/mode-qml.js diff --git a/ui/arduino/libs/ace/mode-r.js b/ui/editor/libs/ace/mode-r.js similarity index 100% rename from ui/arduino/libs/ace/mode-r.js rename to ui/editor/libs/ace/mode-r.js diff --git a/ui/arduino/libs/ace/mode-razor.js b/ui/editor/libs/ace/mode-razor.js similarity index 100% rename from ui/arduino/libs/ace/mode-razor.js rename to ui/editor/libs/ace/mode-razor.js diff --git a/ui/arduino/libs/ace/mode-rdoc.js b/ui/editor/libs/ace/mode-rdoc.js similarity index 100% rename from ui/arduino/libs/ace/mode-rdoc.js rename to ui/editor/libs/ace/mode-rdoc.js diff --git a/ui/arduino/libs/ace/mode-red.js b/ui/editor/libs/ace/mode-red.js similarity index 100% rename from ui/arduino/libs/ace/mode-red.js rename to ui/editor/libs/ace/mode-red.js diff --git a/ui/arduino/libs/ace/mode-redshift.js b/ui/editor/libs/ace/mode-redshift.js similarity index 100% rename from ui/arduino/libs/ace/mode-redshift.js rename to ui/editor/libs/ace/mode-redshift.js diff --git a/ui/arduino/libs/ace/mode-rhtml.js b/ui/editor/libs/ace/mode-rhtml.js similarity index 100% rename from ui/arduino/libs/ace/mode-rhtml.js rename to ui/editor/libs/ace/mode-rhtml.js diff --git a/ui/arduino/libs/ace/mode-rst.js b/ui/editor/libs/ace/mode-rst.js similarity index 100% rename from ui/arduino/libs/ace/mode-rst.js rename to ui/editor/libs/ace/mode-rst.js diff --git a/ui/arduino/libs/ace/mode-ruby.js b/ui/editor/libs/ace/mode-ruby.js similarity index 100% rename from ui/arduino/libs/ace/mode-ruby.js rename to ui/editor/libs/ace/mode-ruby.js diff --git a/ui/arduino/libs/ace/mode-rust.js b/ui/editor/libs/ace/mode-rust.js similarity index 100% rename from ui/arduino/libs/ace/mode-rust.js rename to ui/editor/libs/ace/mode-rust.js diff --git a/ui/arduino/libs/ace/mode-sass.js b/ui/editor/libs/ace/mode-sass.js similarity index 100% rename from ui/arduino/libs/ace/mode-sass.js rename to ui/editor/libs/ace/mode-sass.js diff --git a/ui/arduino/libs/ace/mode-scad.js b/ui/editor/libs/ace/mode-scad.js similarity index 100% rename from ui/arduino/libs/ace/mode-scad.js rename to ui/editor/libs/ace/mode-scad.js diff --git a/ui/arduino/libs/ace/mode-scala.js b/ui/editor/libs/ace/mode-scala.js similarity index 100% rename from ui/arduino/libs/ace/mode-scala.js rename to ui/editor/libs/ace/mode-scala.js diff --git a/ui/arduino/libs/ace/mode-scheme.js b/ui/editor/libs/ace/mode-scheme.js similarity index 100% rename from ui/arduino/libs/ace/mode-scheme.js rename to ui/editor/libs/ace/mode-scheme.js diff --git a/ui/arduino/libs/ace/mode-scss.js b/ui/editor/libs/ace/mode-scss.js similarity index 100% rename from ui/arduino/libs/ace/mode-scss.js rename to ui/editor/libs/ace/mode-scss.js diff --git a/ui/arduino/libs/ace/mode-sh.js b/ui/editor/libs/ace/mode-sh.js similarity index 100% rename from ui/arduino/libs/ace/mode-sh.js rename to ui/editor/libs/ace/mode-sh.js diff --git a/ui/arduino/libs/ace/mode-sjs.js b/ui/editor/libs/ace/mode-sjs.js similarity index 100% rename from ui/arduino/libs/ace/mode-sjs.js rename to ui/editor/libs/ace/mode-sjs.js diff --git a/ui/arduino/libs/ace/mode-slim.js b/ui/editor/libs/ace/mode-slim.js similarity index 100% rename from ui/arduino/libs/ace/mode-slim.js rename to ui/editor/libs/ace/mode-slim.js diff --git a/ui/arduino/libs/ace/mode-smarty.js b/ui/editor/libs/ace/mode-smarty.js similarity index 100% rename from ui/arduino/libs/ace/mode-smarty.js rename to ui/editor/libs/ace/mode-smarty.js diff --git a/ui/arduino/libs/ace/mode-snippets.js b/ui/editor/libs/ace/mode-snippets.js similarity index 100% rename from ui/arduino/libs/ace/mode-snippets.js rename to ui/editor/libs/ace/mode-snippets.js diff --git a/ui/arduino/libs/ace/mode-soy_template.js b/ui/editor/libs/ace/mode-soy_template.js similarity index 100% rename from ui/arduino/libs/ace/mode-soy_template.js rename to ui/editor/libs/ace/mode-soy_template.js diff --git a/ui/arduino/libs/ace/mode-space.js b/ui/editor/libs/ace/mode-space.js similarity index 100% rename from ui/arduino/libs/ace/mode-space.js rename to ui/editor/libs/ace/mode-space.js diff --git a/ui/arduino/libs/ace/mode-sparql.js b/ui/editor/libs/ace/mode-sparql.js similarity index 100% rename from ui/arduino/libs/ace/mode-sparql.js rename to ui/editor/libs/ace/mode-sparql.js diff --git a/ui/arduino/libs/ace/mode-sql.js b/ui/editor/libs/ace/mode-sql.js similarity index 100% rename from ui/arduino/libs/ace/mode-sql.js rename to ui/editor/libs/ace/mode-sql.js diff --git a/ui/arduino/libs/ace/mode-sqlserver.js b/ui/editor/libs/ace/mode-sqlserver.js similarity index 100% rename from ui/arduino/libs/ace/mode-sqlserver.js rename to ui/editor/libs/ace/mode-sqlserver.js diff --git a/ui/arduino/libs/ace/mode-stylus.js b/ui/editor/libs/ace/mode-stylus.js similarity index 100% rename from ui/arduino/libs/ace/mode-stylus.js rename to ui/editor/libs/ace/mode-stylus.js diff --git a/ui/arduino/libs/ace/mode-svg.js b/ui/editor/libs/ace/mode-svg.js similarity index 100% rename from ui/arduino/libs/ace/mode-svg.js rename to ui/editor/libs/ace/mode-svg.js diff --git a/ui/arduino/libs/ace/mode-swift.js b/ui/editor/libs/ace/mode-swift.js similarity index 100% rename from ui/arduino/libs/ace/mode-swift.js rename to ui/editor/libs/ace/mode-swift.js diff --git a/ui/arduino/libs/ace/mode-tcl.js b/ui/editor/libs/ace/mode-tcl.js similarity index 100% rename from ui/arduino/libs/ace/mode-tcl.js rename to ui/editor/libs/ace/mode-tcl.js diff --git a/ui/arduino/libs/ace/mode-terraform.js b/ui/editor/libs/ace/mode-terraform.js similarity index 100% rename from ui/arduino/libs/ace/mode-terraform.js rename to ui/editor/libs/ace/mode-terraform.js diff --git a/ui/arduino/libs/ace/mode-tex.js b/ui/editor/libs/ace/mode-tex.js similarity index 100% rename from ui/arduino/libs/ace/mode-tex.js rename to ui/editor/libs/ace/mode-tex.js diff --git a/ui/arduino/libs/ace/mode-text.js b/ui/editor/libs/ace/mode-text.js similarity index 100% rename from ui/arduino/libs/ace/mode-text.js rename to ui/editor/libs/ace/mode-text.js diff --git a/ui/arduino/libs/ace/mode-textile.js b/ui/editor/libs/ace/mode-textile.js similarity index 100% rename from ui/arduino/libs/ace/mode-textile.js rename to ui/editor/libs/ace/mode-textile.js diff --git a/ui/arduino/libs/ace/mode-toml.js b/ui/editor/libs/ace/mode-toml.js similarity index 100% rename from ui/arduino/libs/ace/mode-toml.js rename to ui/editor/libs/ace/mode-toml.js diff --git a/ui/arduino/libs/ace/mode-tsx.js b/ui/editor/libs/ace/mode-tsx.js similarity index 100% rename from ui/arduino/libs/ace/mode-tsx.js rename to ui/editor/libs/ace/mode-tsx.js diff --git a/ui/arduino/libs/ace/mode-turtle.js b/ui/editor/libs/ace/mode-turtle.js similarity index 100% rename from ui/arduino/libs/ace/mode-turtle.js rename to ui/editor/libs/ace/mode-turtle.js diff --git a/ui/arduino/libs/ace/mode-twig.js b/ui/editor/libs/ace/mode-twig.js similarity index 100% rename from ui/arduino/libs/ace/mode-twig.js rename to ui/editor/libs/ace/mode-twig.js diff --git a/ui/arduino/libs/ace/mode-typescript.js b/ui/editor/libs/ace/mode-typescript.js similarity index 100% rename from ui/arduino/libs/ace/mode-typescript.js rename to ui/editor/libs/ace/mode-typescript.js diff --git a/ui/arduino/libs/ace/mode-vala.js b/ui/editor/libs/ace/mode-vala.js similarity index 100% rename from ui/arduino/libs/ace/mode-vala.js rename to ui/editor/libs/ace/mode-vala.js diff --git a/ui/arduino/libs/ace/mode-vbscript.js b/ui/editor/libs/ace/mode-vbscript.js similarity index 100% rename from ui/arduino/libs/ace/mode-vbscript.js rename to ui/editor/libs/ace/mode-vbscript.js diff --git a/ui/arduino/libs/ace/mode-velocity.js b/ui/editor/libs/ace/mode-velocity.js similarity index 100% rename from ui/arduino/libs/ace/mode-velocity.js rename to ui/editor/libs/ace/mode-velocity.js diff --git a/ui/arduino/libs/ace/mode-verilog.js b/ui/editor/libs/ace/mode-verilog.js similarity index 100% rename from ui/arduino/libs/ace/mode-verilog.js rename to ui/editor/libs/ace/mode-verilog.js diff --git a/ui/arduino/libs/ace/mode-vhdl.js b/ui/editor/libs/ace/mode-vhdl.js similarity index 100% rename from ui/arduino/libs/ace/mode-vhdl.js rename to ui/editor/libs/ace/mode-vhdl.js diff --git a/ui/arduino/libs/ace/mode-visualforce.js b/ui/editor/libs/ace/mode-visualforce.js similarity index 100% rename from ui/arduino/libs/ace/mode-visualforce.js rename to ui/editor/libs/ace/mode-visualforce.js diff --git a/ui/arduino/libs/ace/mode-wollok.js b/ui/editor/libs/ace/mode-wollok.js similarity index 100% rename from ui/arduino/libs/ace/mode-wollok.js rename to ui/editor/libs/ace/mode-wollok.js diff --git a/ui/arduino/libs/ace/mode-xml.js b/ui/editor/libs/ace/mode-xml.js similarity index 100% rename from ui/arduino/libs/ace/mode-xml.js rename to ui/editor/libs/ace/mode-xml.js diff --git a/ui/arduino/libs/ace/mode-xquery.js b/ui/editor/libs/ace/mode-xquery.js similarity index 100% rename from ui/arduino/libs/ace/mode-xquery.js rename to ui/editor/libs/ace/mode-xquery.js diff --git a/ui/arduino/libs/ace/mode-yaml.js b/ui/editor/libs/ace/mode-yaml.js similarity index 100% rename from ui/arduino/libs/ace/mode-yaml.js rename to ui/editor/libs/ace/mode-yaml.js diff --git a/ui/arduino/libs/ace/mode-zeek.js b/ui/editor/libs/ace/mode-zeek.js similarity index 100% rename from ui/arduino/libs/ace/mode-zeek.js rename to ui/editor/libs/ace/mode-zeek.js diff --git a/ui/arduino/libs/ace/snippets/abap.js b/ui/editor/libs/ace/snippets/abap.js similarity index 100% rename from ui/arduino/libs/ace/snippets/abap.js rename to ui/editor/libs/ace/snippets/abap.js diff --git a/ui/arduino/libs/ace/snippets/abc.js b/ui/editor/libs/ace/snippets/abc.js similarity index 100% rename from ui/arduino/libs/ace/snippets/abc.js rename to ui/editor/libs/ace/snippets/abc.js diff --git a/ui/arduino/libs/ace/snippets/actionscript.js b/ui/editor/libs/ace/snippets/actionscript.js similarity index 100% rename from ui/arduino/libs/ace/snippets/actionscript.js rename to ui/editor/libs/ace/snippets/actionscript.js diff --git a/ui/arduino/libs/ace/snippets/ada.js b/ui/editor/libs/ace/snippets/ada.js similarity index 100% rename from ui/arduino/libs/ace/snippets/ada.js rename to ui/editor/libs/ace/snippets/ada.js diff --git a/ui/arduino/libs/ace/snippets/alda.js b/ui/editor/libs/ace/snippets/alda.js similarity index 100% rename from ui/arduino/libs/ace/snippets/alda.js rename to ui/editor/libs/ace/snippets/alda.js diff --git a/ui/arduino/libs/ace/snippets/apache_conf.js b/ui/editor/libs/ace/snippets/apache_conf.js similarity index 100% rename from ui/arduino/libs/ace/snippets/apache_conf.js rename to ui/editor/libs/ace/snippets/apache_conf.js diff --git a/ui/arduino/libs/ace/snippets/apex.js b/ui/editor/libs/ace/snippets/apex.js similarity index 100% rename from ui/arduino/libs/ace/snippets/apex.js rename to ui/editor/libs/ace/snippets/apex.js diff --git a/ui/arduino/libs/ace/snippets/applescript.js b/ui/editor/libs/ace/snippets/applescript.js similarity index 100% rename from ui/arduino/libs/ace/snippets/applescript.js rename to ui/editor/libs/ace/snippets/applescript.js diff --git a/ui/arduino/libs/ace/snippets/aql.js b/ui/editor/libs/ace/snippets/aql.js similarity index 100% rename from ui/arduino/libs/ace/snippets/aql.js rename to ui/editor/libs/ace/snippets/aql.js diff --git a/ui/arduino/libs/ace/snippets/asciidoc.js b/ui/editor/libs/ace/snippets/asciidoc.js similarity index 100% rename from ui/arduino/libs/ace/snippets/asciidoc.js rename to ui/editor/libs/ace/snippets/asciidoc.js diff --git a/ui/arduino/libs/ace/snippets/asl.js b/ui/editor/libs/ace/snippets/asl.js similarity index 100% rename from ui/arduino/libs/ace/snippets/asl.js rename to ui/editor/libs/ace/snippets/asl.js diff --git a/ui/arduino/libs/ace/snippets/assembly_x86.js b/ui/editor/libs/ace/snippets/assembly_x86.js similarity index 100% rename from ui/arduino/libs/ace/snippets/assembly_x86.js rename to ui/editor/libs/ace/snippets/assembly_x86.js diff --git a/ui/arduino/libs/ace/snippets/autohotkey.js b/ui/editor/libs/ace/snippets/autohotkey.js similarity index 100% rename from ui/arduino/libs/ace/snippets/autohotkey.js rename to ui/editor/libs/ace/snippets/autohotkey.js diff --git a/ui/arduino/libs/ace/snippets/batchfile.js b/ui/editor/libs/ace/snippets/batchfile.js similarity index 100% rename from ui/arduino/libs/ace/snippets/batchfile.js rename to ui/editor/libs/ace/snippets/batchfile.js diff --git a/ui/arduino/libs/ace/snippets/c9search.js b/ui/editor/libs/ace/snippets/c9search.js similarity index 100% rename from ui/arduino/libs/ace/snippets/c9search.js rename to ui/editor/libs/ace/snippets/c9search.js diff --git a/ui/arduino/libs/ace/snippets/c_cpp.js b/ui/editor/libs/ace/snippets/c_cpp.js similarity index 100% rename from ui/arduino/libs/ace/snippets/c_cpp.js rename to ui/editor/libs/ace/snippets/c_cpp.js diff --git a/ui/arduino/libs/ace/snippets/cirru.js b/ui/editor/libs/ace/snippets/cirru.js similarity index 100% rename from ui/arduino/libs/ace/snippets/cirru.js rename to ui/editor/libs/ace/snippets/cirru.js diff --git a/ui/arduino/libs/ace/snippets/clojure.js b/ui/editor/libs/ace/snippets/clojure.js similarity index 100% rename from ui/arduino/libs/ace/snippets/clojure.js rename to ui/editor/libs/ace/snippets/clojure.js diff --git a/ui/arduino/libs/ace/snippets/cobol.js b/ui/editor/libs/ace/snippets/cobol.js similarity index 100% rename from ui/arduino/libs/ace/snippets/cobol.js rename to ui/editor/libs/ace/snippets/cobol.js diff --git a/ui/arduino/libs/ace/snippets/coffee.js b/ui/editor/libs/ace/snippets/coffee.js similarity index 100% rename from ui/arduino/libs/ace/snippets/coffee.js rename to ui/editor/libs/ace/snippets/coffee.js diff --git a/ui/arduino/libs/ace/snippets/coldfusion.js b/ui/editor/libs/ace/snippets/coldfusion.js similarity index 100% rename from ui/arduino/libs/ace/snippets/coldfusion.js rename to ui/editor/libs/ace/snippets/coldfusion.js diff --git a/ui/arduino/libs/ace/snippets/crystal.js b/ui/editor/libs/ace/snippets/crystal.js similarity index 100% rename from ui/arduino/libs/ace/snippets/crystal.js rename to ui/editor/libs/ace/snippets/crystal.js diff --git a/ui/arduino/libs/ace/snippets/csharp.js b/ui/editor/libs/ace/snippets/csharp.js similarity index 100% rename from ui/arduino/libs/ace/snippets/csharp.js rename to ui/editor/libs/ace/snippets/csharp.js diff --git a/ui/arduino/libs/ace/snippets/csound_document.js b/ui/editor/libs/ace/snippets/csound_document.js similarity index 100% rename from ui/arduino/libs/ace/snippets/csound_document.js rename to ui/editor/libs/ace/snippets/csound_document.js diff --git a/ui/arduino/libs/ace/snippets/csound_orchestra.js b/ui/editor/libs/ace/snippets/csound_orchestra.js similarity index 100% rename from ui/arduino/libs/ace/snippets/csound_orchestra.js rename to ui/editor/libs/ace/snippets/csound_orchestra.js diff --git a/ui/arduino/libs/ace/snippets/csound_score.js b/ui/editor/libs/ace/snippets/csound_score.js similarity index 100% rename from ui/arduino/libs/ace/snippets/csound_score.js rename to ui/editor/libs/ace/snippets/csound_score.js diff --git a/ui/arduino/libs/ace/snippets/csp.js b/ui/editor/libs/ace/snippets/csp.js similarity index 100% rename from ui/arduino/libs/ace/snippets/csp.js rename to ui/editor/libs/ace/snippets/csp.js diff --git a/ui/arduino/libs/ace/snippets/css.js b/ui/editor/libs/ace/snippets/css.js similarity index 100% rename from ui/arduino/libs/ace/snippets/css.js rename to ui/editor/libs/ace/snippets/css.js diff --git a/ui/arduino/libs/ace/snippets/curly.js b/ui/editor/libs/ace/snippets/curly.js similarity index 100% rename from ui/arduino/libs/ace/snippets/curly.js rename to ui/editor/libs/ace/snippets/curly.js diff --git a/ui/arduino/libs/ace/snippets/d.js b/ui/editor/libs/ace/snippets/d.js similarity index 100% rename from ui/arduino/libs/ace/snippets/d.js rename to ui/editor/libs/ace/snippets/d.js diff --git a/ui/arduino/libs/ace/snippets/dart.js b/ui/editor/libs/ace/snippets/dart.js similarity index 100% rename from ui/arduino/libs/ace/snippets/dart.js rename to ui/editor/libs/ace/snippets/dart.js diff --git a/ui/arduino/libs/ace/snippets/diff.js b/ui/editor/libs/ace/snippets/diff.js similarity index 100% rename from ui/arduino/libs/ace/snippets/diff.js rename to ui/editor/libs/ace/snippets/diff.js diff --git a/ui/arduino/libs/ace/snippets/django.js b/ui/editor/libs/ace/snippets/django.js similarity index 100% rename from ui/arduino/libs/ace/snippets/django.js rename to ui/editor/libs/ace/snippets/django.js diff --git a/ui/arduino/libs/ace/snippets/dockerfile.js b/ui/editor/libs/ace/snippets/dockerfile.js similarity index 100% rename from ui/arduino/libs/ace/snippets/dockerfile.js rename to ui/editor/libs/ace/snippets/dockerfile.js diff --git a/ui/arduino/libs/ace/snippets/dot.js b/ui/editor/libs/ace/snippets/dot.js similarity index 100% rename from ui/arduino/libs/ace/snippets/dot.js rename to ui/editor/libs/ace/snippets/dot.js diff --git a/ui/arduino/libs/ace/snippets/drools.js b/ui/editor/libs/ace/snippets/drools.js similarity index 100% rename from ui/arduino/libs/ace/snippets/drools.js rename to ui/editor/libs/ace/snippets/drools.js diff --git a/ui/arduino/libs/ace/snippets/edifact.js b/ui/editor/libs/ace/snippets/edifact.js similarity index 100% rename from ui/arduino/libs/ace/snippets/edifact.js rename to ui/editor/libs/ace/snippets/edifact.js diff --git a/ui/arduino/libs/ace/snippets/eiffel.js b/ui/editor/libs/ace/snippets/eiffel.js similarity index 100% rename from ui/arduino/libs/ace/snippets/eiffel.js rename to ui/editor/libs/ace/snippets/eiffel.js diff --git a/ui/arduino/libs/ace/snippets/ejs.js b/ui/editor/libs/ace/snippets/ejs.js similarity index 100% rename from ui/arduino/libs/ace/snippets/ejs.js rename to ui/editor/libs/ace/snippets/ejs.js diff --git a/ui/arduino/libs/ace/snippets/elixir.js b/ui/editor/libs/ace/snippets/elixir.js similarity index 100% rename from ui/arduino/libs/ace/snippets/elixir.js rename to ui/editor/libs/ace/snippets/elixir.js diff --git a/ui/arduino/libs/ace/snippets/elm.js b/ui/editor/libs/ace/snippets/elm.js similarity index 100% rename from ui/arduino/libs/ace/snippets/elm.js rename to ui/editor/libs/ace/snippets/elm.js diff --git a/ui/arduino/libs/ace/snippets/erlang.js b/ui/editor/libs/ace/snippets/erlang.js similarity index 100% rename from ui/arduino/libs/ace/snippets/erlang.js rename to ui/editor/libs/ace/snippets/erlang.js diff --git a/ui/arduino/libs/ace/snippets/forth.js b/ui/editor/libs/ace/snippets/forth.js similarity index 100% rename from ui/arduino/libs/ace/snippets/forth.js rename to ui/editor/libs/ace/snippets/forth.js diff --git a/ui/arduino/libs/ace/snippets/fortran.js b/ui/editor/libs/ace/snippets/fortran.js similarity index 100% rename from ui/arduino/libs/ace/snippets/fortran.js rename to ui/editor/libs/ace/snippets/fortran.js diff --git a/ui/arduino/libs/ace/snippets/fsharp.js b/ui/editor/libs/ace/snippets/fsharp.js similarity index 100% rename from ui/arduino/libs/ace/snippets/fsharp.js rename to ui/editor/libs/ace/snippets/fsharp.js diff --git a/ui/arduino/libs/ace/snippets/fsl.js b/ui/editor/libs/ace/snippets/fsl.js similarity index 100% rename from ui/arduino/libs/ace/snippets/fsl.js rename to ui/editor/libs/ace/snippets/fsl.js diff --git a/ui/arduino/libs/ace/snippets/ftl.js b/ui/editor/libs/ace/snippets/ftl.js similarity index 100% rename from ui/arduino/libs/ace/snippets/ftl.js rename to ui/editor/libs/ace/snippets/ftl.js diff --git a/ui/arduino/libs/ace/snippets/gcode.js b/ui/editor/libs/ace/snippets/gcode.js similarity index 100% rename from ui/arduino/libs/ace/snippets/gcode.js rename to ui/editor/libs/ace/snippets/gcode.js diff --git a/ui/arduino/libs/ace/snippets/gherkin.js b/ui/editor/libs/ace/snippets/gherkin.js similarity index 100% rename from ui/arduino/libs/ace/snippets/gherkin.js rename to ui/editor/libs/ace/snippets/gherkin.js diff --git a/ui/arduino/libs/ace/snippets/gitignore.js b/ui/editor/libs/ace/snippets/gitignore.js similarity index 100% rename from ui/arduino/libs/ace/snippets/gitignore.js rename to ui/editor/libs/ace/snippets/gitignore.js diff --git a/ui/arduino/libs/ace/snippets/glsl.js b/ui/editor/libs/ace/snippets/glsl.js similarity index 100% rename from ui/arduino/libs/ace/snippets/glsl.js rename to ui/editor/libs/ace/snippets/glsl.js diff --git a/ui/arduino/libs/ace/snippets/gobstones.js b/ui/editor/libs/ace/snippets/gobstones.js similarity index 100% rename from ui/arduino/libs/ace/snippets/gobstones.js rename to ui/editor/libs/ace/snippets/gobstones.js diff --git a/ui/arduino/libs/ace/snippets/golang.js b/ui/editor/libs/ace/snippets/golang.js similarity index 100% rename from ui/arduino/libs/ace/snippets/golang.js rename to ui/editor/libs/ace/snippets/golang.js diff --git a/ui/arduino/libs/ace/snippets/graphqlschema.js b/ui/editor/libs/ace/snippets/graphqlschema.js similarity index 100% rename from ui/arduino/libs/ace/snippets/graphqlschema.js rename to ui/editor/libs/ace/snippets/graphqlschema.js diff --git a/ui/arduino/libs/ace/snippets/groovy.js b/ui/editor/libs/ace/snippets/groovy.js similarity index 100% rename from ui/arduino/libs/ace/snippets/groovy.js rename to ui/editor/libs/ace/snippets/groovy.js diff --git a/ui/arduino/libs/ace/snippets/haml.js b/ui/editor/libs/ace/snippets/haml.js similarity index 100% rename from ui/arduino/libs/ace/snippets/haml.js rename to ui/editor/libs/ace/snippets/haml.js diff --git a/ui/arduino/libs/ace/snippets/handlebars.js b/ui/editor/libs/ace/snippets/handlebars.js similarity index 100% rename from ui/arduino/libs/ace/snippets/handlebars.js rename to ui/editor/libs/ace/snippets/handlebars.js diff --git a/ui/arduino/libs/ace/snippets/haskell.js b/ui/editor/libs/ace/snippets/haskell.js similarity index 100% rename from ui/arduino/libs/ace/snippets/haskell.js rename to ui/editor/libs/ace/snippets/haskell.js diff --git a/ui/arduino/libs/ace/snippets/haskell_cabal.js b/ui/editor/libs/ace/snippets/haskell_cabal.js similarity index 100% rename from ui/arduino/libs/ace/snippets/haskell_cabal.js rename to ui/editor/libs/ace/snippets/haskell_cabal.js diff --git a/ui/arduino/libs/ace/snippets/haxe.js b/ui/editor/libs/ace/snippets/haxe.js similarity index 100% rename from ui/arduino/libs/ace/snippets/haxe.js rename to ui/editor/libs/ace/snippets/haxe.js diff --git a/ui/arduino/libs/ace/snippets/hjson.js b/ui/editor/libs/ace/snippets/hjson.js similarity index 100% rename from ui/arduino/libs/ace/snippets/hjson.js rename to ui/editor/libs/ace/snippets/hjson.js diff --git a/ui/arduino/libs/ace/snippets/html.js b/ui/editor/libs/ace/snippets/html.js similarity index 100% rename from ui/arduino/libs/ace/snippets/html.js rename to ui/editor/libs/ace/snippets/html.js diff --git a/ui/arduino/libs/ace/snippets/html_elixir.js b/ui/editor/libs/ace/snippets/html_elixir.js similarity index 100% rename from ui/arduino/libs/ace/snippets/html_elixir.js rename to ui/editor/libs/ace/snippets/html_elixir.js diff --git a/ui/arduino/libs/ace/snippets/html_ruby.js b/ui/editor/libs/ace/snippets/html_ruby.js similarity index 100% rename from ui/arduino/libs/ace/snippets/html_ruby.js rename to ui/editor/libs/ace/snippets/html_ruby.js diff --git a/ui/arduino/libs/ace/snippets/ini.js b/ui/editor/libs/ace/snippets/ini.js similarity index 100% rename from ui/arduino/libs/ace/snippets/ini.js rename to ui/editor/libs/ace/snippets/ini.js diff --git a/ui/arduino/libs/ace/snippets/io.js b/ui/editor/libs/ace/snippets/io.js similarity index 100% rename from ui/arduino/libs/ace/snippets/io.js rename to ui/editor/libs/ace/snippets/io.js diff --git a/ui/arduino/libs/ace/snippets/jack.js b/ui/editor/libs/ace/snippets/jack.js similarity index 100% rename from ui/arduino/libs/ace/snippets/jack.js rename to ui/editor/libs/ace/snippets/jack.js diff --git a/ui/arduino/libs/ace/snippets/jade.js b/ui/editor/libs/ace/snippets/jade.js similarity index 100% rename from ui/arduino/libs/ace/snippets/jade.js rename to ui/editor/libs/ace/snippets/jade.js diff --git a/ui/arduino/libs/ace/snippets/java.js b/ui/editor/libs/ace/snippets/java.js similarity index 100% rename from ui/arduino/libs/ace/snippets/java.js rename to ui/editor/libs/ace/snippets/java.js diff --git a/ui/arduino/libs/ace/snippets/javascript.js b/ui/editor/libs/ace/snippets/javascript.js similarity index 100% rename from ui/arduino/libs/ace/snippets/javascript.js rename to ui/editor/libs/ace/snippets/javascript.js diff --git a/ui/arduino/libs/ace/snippets/json.js b/ui/editor/libs/ace/snippets/json.js similarity index 100% rename from ui/arduino/libs/ace/snippets/json.js rename to ui/editor/libs/ace/snippets/json.js diff --git a/ui/arduino/libs/ace/snippets/json5.js b/ui/editor/libs/ace/snippets/json5.js similarity index 100% rename from ui/arduino/libs/ace/snippets/json5.js rename to ui/editor/libs/ace/snippets/json5.js diff --git a/ui/arduino/libs/ace/snippets/jsoniq.js b/ui/editor/libs/ace/snippets/jsoniq.js similarity index 100% rename from ui/arduino/libs/ace/snippets/jsoniq.js rename to ui/editor/libs/ace/snippets/jsoniq.js diff --git a/ui/arduino/libs/ace/snippets/jsp.js b/ui/editor/libs/ace/snippets/jsp.js similarity index 100% rename from ui/arduino/libs/ace/snippets/jsp.js rename to ui/editor/libs/ace/snippets/jsp.js diff --git a/ui/arduino/libs/ace/snippets/jssm.js b/ui/editor/libs/ace/snippets/jssm.js similarity index 100% rename from ui/arduino/libs/ace/snippets/jssm.js rename to ui/editor/libs/ace/snippets/jssm.js diff --git a/ui/arduino/libs/ace/snippets/jsx.js b/ui/editor/libs/ace/snippets/jsx.js similarity index 100% rename from ui/arduino/libs/ace/snippets/jsx.js rename to ui/editor/libs/ace/snippets/jsx.js diff --git a/ui/arduino/libs/ace/snippets/julia.js b/ui/editor/libs/ace/snippets/julia.js similarity index 100% rename from ui/arduino/libs/ace/snippets/julia.js rename to ui/editor/libs/ace/snippets/julia.js diff --git a/ui/arduino/libs/ace/snippets/kotlin.js b/ui/editor/libs/ace/snippets/kotlin.js similarity index 100% rename from ui/arduino/libs/ace/snippets/kotlin.js rename to ui/editor/libs/ace/snippets/kotlin.js diff --git a/ui/arduino/libs/ace/snippets/latex.js b/ui/editor/libs/ace/snippets/latex.js similarity index 100% rename from ui/arduino/libs/ace/snippets/latex.js rename to ui/editor/libs/ace/snippets/latex.js diff --git a/ui/arduino/libs/ace/snippets/less.js b/ui/editor/libs/ace/snippets/less.js similarity index 100% rename from ui/arduino/libs/ace/snippets/less.js rename to ui/editor/libs/ace/snippets/less.js diff --git a/ui/arduino/libs/ace/snippets/liquid.js b/ui/editor/libs/ace/snippets/liquid.js similarity index 100% rename from ui/arduino/libs/ace/snippets/liquid.js rename to ui/editor/libs/ace/snippets/liquid.js diff --git a/ui/arduino/libs/ace/snippets/lisp.js b/ui/editor/libs/ace/snippets/lisp.js similarity index 100% rename from ui/arduino/libs/ace/snippets/lisp.js rename to ui/editor/libs/ace/snippets/lisp.js diff --git a/ui/arduino/libs/ace/snippets/livescript.js b/ui/editor/libs/ace/snippets/livescript.js similarity index 100% rename from ui/arduino/libs/ace/snippets/livescript.js rename to ui/editor/libs/ace/snippets/livescript.js diff --git a/ui/arduino/libs/ace/snippets/logiql.js b/ui/editor/libs/ace/snippets/logiql.js similarity index 100% rename from ui/arduino/libs/ace/snippets/logiql.js rename to ui/editor/libs/ace/snippets/logiql.js diff --git a/ui/arduino/libs/ace/snippets/logtalk.js b/ui/editor/libs/ace/snippets/logtalk.js similarity index 100% rename from ui/arduino/libs/ace/snippets/logtalk.js rename to ui/editor/libs/ace/snippets/logtalk.js diff --git a/ui/arduino/libs/ace/snippets/lsl.js b/ui/editor/libs/ace/snippets/lsl.js similarity index 100% rename from ui/arduino/libs/ace/snippets/lsl.js rename to ui/editor/libs/ace/snippets/lsl.js diff --git a/ui/arduino/libs/ace/snippets/lua.js b/ui/editor/libs/ace/snippets/lua.js similarity index 100% rename from ui/arduino/libs/ace/snippets/lua.js rename to ui/editor/libs/ace/snippets/lua.js diff --git a/ui/arduino/libs/ace/snippets/luapage.js b/ui/editor/libs/ace/snippets/luapage.js similarity index 100% rename from ui/arduino/libs/ace/snippets/luapage.js rename to ui/editor/libs/ace/snippets/luapage.js diff --git a/ui/arduino/libs/ace/snippets/lucene.js b/ui/editor/libs/ace/snippets/lucene.js similarity index 100% rename from ui/arduino/libs/ace/snippets/lucene.js rename to ui/editor/libs/ace/snippets/lucene.js diff --git a/ui/arduino/libs/ace/snippets/makefile.js b/ui/editor/libs/ace/snippets/makefile.js similarity index 100% rename from ui/arduino/libs/ace/snippets/makefile.js rename to ui/editor/libs/ace/snippets/makefile.js diff --git a/ui/arduino/libs/ace/snippets/markdown.js b/ui/editor/libs/ace/snippets/markdown.js similarity index 100% rename from ui/arduino/libs/ace/snippets/markdown.js rename to ui/editor/libs/ace/snippets/markdown.js diff --git a/ui/arduino/libs/ace/snippets/mask.js b/ui/editor/libs/ace/snippets/mask.js similarity index 100% rename from ui/arduino/libs/ace/snippets/mask.js rename to ui/editor/libs/ace/snippets/mask.js diff --git a/ui/arduino/libs/ace/snippets/matlab.js b/ui/editor/libs/ace/snippets/matlab.js similarity index 100% rename from ui/arduino/libs/ace/snippets/matlab.js rename to ui/editor/libs/ace/snippets/matlab.js diff --git a/ui/arduino/libs/ace/snippets/maze.js b/ui/editor/libs/ace/snippets/maze.js similarity index 100% rename from ui/arduino/libs/ace/snippets/maze.js rename to ui/editor/libs/ace/snippets/maze.js diff --git a/ui/arduino/libs/ace/snippets/mediawiki.js b/ui/editor/libs/ace/snippets/mediawiki.js similarity index 100% rename from ui/arduino/libs/ace/snippets/mediawiki.js rename to ui/editor/libs/ace/snippets/mediawiki.js diff --git a/ui/arduino/libs/ace/snippets/mel.js b/ui/editor/libs/ace/snippets/mel.js similarity index 100% rename from ui/arduino/libs/ace/snippets/mel.js rename to ui/editor/libs/ace/snippets/mel.js diff --git a/ui/arduino/libs/ace/snippets/mixal.js b/ui/editor/libs/ace/snippets/mixal.js similarity index 100% rename from ui/arduino/libs/ace/snippets/mixal.js rename to ui/editor/libs/ace/snippets/mixal.js diff --git a/ui/arduino/libs/ace/snippets/mushcode.js b/ui/editor/libs/ace/snippets/mushcode.js similarity index 100% rename from ui/arduino/libs/ace/snippets/mushcode.js rename to ui/editor/libs/ace/snippets/mushcode.js diff --git a/ui/arduino/libs/ace/snippets/mysql.js b/ui/editor/libs/ace/snippets/mysql.js similarity index 100% rename from ui/arduino/libs/ace/snippets/mysql.js rename to ui/editor/libs/ace/snippets/mysql.js diff --git a/ui/arduino/libs/ace/snippets/nginx.js b/ui/editor/libs/ace/snippets/nginx.js similarity index 100% rename from ui/arduino/libs/ace/snippets/nginx.js rename to ui/editor/libs/ace/snippets/nginx.js diff --git a/ui/arduino/libs/ace/snippets/nim.js b/ui/editor/libs/ace/snippets/nim.js similarity index 100% rename from ui/arduino/libs/ace/snippets/nim.js rename to ui/editor/libs/ace/snippets/nim.js diff --git a/ui/arduino/libs/ace/snippets/nix.js b/ui/editor/libs/ace/snippets/nix.js similarity index 100% rename from ui/arduino/libs/ace/snippets/nix.js rename to ui/editor/libs/ace/snippets/nix.js diff --git a/ui/arduino/libs/ace/snippets/nsis.js b/ui/editor/libs/ace/snippets/nsis.js similarity index 100% rename from ui/arduino/libs/ace/snippets/nsis.js rename to ui/editor/libs/ace/snippets/nsis.js diff --git a/ui/arduino/libs/ace/snippets/nunjucks.js b/ui/editor/libs/ace/snippets/nunjucks.js similarity index 100% rename from ui/arduino/libs/ace/snippets/nunjucks.js rename to ui/editor/libs/ace/snippets/nunjucks.js diff --git a/ui/arduino/libs/ace/snippets/objectivec.js b/ui/editor/libs/ace/snippets/objectivec.js similarity index 100% rename from ui/arduino/libs/ace/snippets/objectivec.js rename to ui/editor/libs/ace/snippets/objectivec.js diff --git a/ui/arduino/libs/ace/snippets/ocaml.js b/ui/editor/libs/ace/snippets/ocaml.js similarity index 100% rename from ui/arduino/libs/ace/snippets/ocaml.js rename to ui/editor/libs/ace/snippets/ocaml.js diff --git a/ui/arduino/libs/ace/snippets/pascal.js b/ui/editor/libs/ace/snippets/pascal.js similarity index 100% rename from ui/arduino/libs/ace/snippets/pascal.js rename to ui/editor/libs/ace/snippets/pascal.js diff --git a/ui/arduino/libs/ace/snippets/perl.js b/ui/editor/libs/ace/snippets/perl.js similarity index 100% rename from ui/arduino/libs/ace/snippets/perl.js rename to ui/editor/libs/ace/snippets/perl.js diff --git a/ui/arduino/libs/ace/snippets/perl6.js b/ui/editor/libs/ace/snippets/perl6.js similarity index 100% rename from ui/arduino/libs/ace/snippets/perl6.js rename to ui/editor/libs/ace/snippets/perl6.js diff --git a/ui/arduino/libs/ace/snippets/pgsql.js b/ui/editor/libs/ace/snippets/pgsql.js similarity index 100% rename from ui/arduino/libs/ace/snippets/pgsql.js rename to ui/editor/libs/ace/snippets/pgsql.js diff --git a/ui/arduino/libs/ace/snippets/php.js b/ui/editor/libs/ace/snippets/php.js similarity index 100% rename from ui/arduino/libs/ace/snippets/php.js rename to ui/editor/libs/ace/snippets/php.js diff --git a/ui/arduino/libs/ace/snippets/php_laravel_blade.js b/ui/editor/libs/ace/snippets/php_laravel_blade.js similarity index 100% rename from ui/arduino/libs/ace/snippets/php_laravel_blade.js rename to ui/editor/libs/ace/snippets/php_laravel_blade.js diff --git a/ui/arduino/libs/ace/snippets/pig.js b/ui/editor/libs/ace/snippets/pig.js similarity index 100% rename from ui/arduino/libs/ace/snippets/pig.js rename to ui/editor/libs/ace/snippets/pig.js diff --git a/ui/arduino/libs/ace/snippets/plain_text.js b/ui/editor/libs/ace/snippets/plain_text.js similarity index 100% rename from ui/arduino/libs/ace/snippets/plain_text.js rename to ui/editor/libs/ace/snippets/plain_text.js diff --git a/ui/arduino/libs/ace/snippets/powershell.js b/ui/editor/libs/ace/snippets/powershell.js similarity index 100% rename from ui/arduino/libs/ace/snippets/powershell.js rename to ui/editor/libs/ace/snippets/powershell.js diff --git a/ui/arduino/libs/ace/snippets/praat.js b/ui/editor/libs/ace/snippets/praat.js similarity index 100% rename from ui/arduino/libs/ace/snippets/praat.js rename to ui/editor/libs/ace/snippets/praat.js diff --git a/ui/arduino/libs/ace/snippets/prisma.js b/ui/editor/libs/ace/snippets/prisma.js similarity index 100% rename from ui/arduino/libs/ace/snippets/prisma.js rename to ui/editor/libs/ace/snippets/prisma.js diff --git a/ui/arduino/libs/ace/snippets/prolog.js b/ui/editor/libs/ace/snippets/prolog.js similarity index 100% rename from ui/arduino/libs/ace/snippets/prolog.js rename to ui/editor/libs/ace/snippets/prolog.js diff --git a/ui/arduino/libs/ace/snippets/properties.js b/ui/editor/libs/ace/snippets/properties.js similarity index 100% rename from ui/arduino/libs/ace/snippets/properties.js rename to ui/editor/libs/ace/snippets/properties.js diff --git a/ui/arduino/libs/ace/snippets/protobuf.js b/ui/editor/libs/ace/snippets/protobuf.js similarity index 100% rename from ui/arduino/libs/ace/snippets/protobuf.js rename to ui/editor/libs/ace/snippets/protobuf.js diff --git a/ui/arduino/libs/ace/snippets/puppet.js b/ui/editor/libs/ace/snippets/puppet.js similarity index 100% rename from ui/arduino/libs/ace/snippets/puppet.js rename to ui/editor/libs/ace/snippets/puppet.js diff --git a/ui/arduino/libs/ace/snippets/python.js b/ui/editor/libs/ace/snippets/python.js similarity index 100% rename from ui/arduino/libs/ace/snippets/python.js rename to ui/editor/libs/ace/snippets/python.js diff --git a/ui/arduino/libs/ace/snippets/qml.js b/ui/editor/libs/ace/snippets/qml.js similarity index 100% rename from ui/arduino/libs/ace/snippets/qml.js rename to ui/editor/libs/ace/snippets/qml.js diff --git a/ui/arduino/libs/ace/snippets/r.js b/ui/editor/libs/ace/snippets/r.js similarity index 100% rename from ui/arduino/libs/ace/snippets/r.js rename to ui/editor/libs/ace/snippets/r.js diff --git a/ui/arduino/libs/ace/snippets/razor.js b/ui/editor/libs/ace/snippets/razor.js similarity index 100% rename from ui/arduino/libs/ace/snippets/razor.js rename to ui/editor/libs/ace/snippets/razor.js diff --git a/ui/arduino/libs/ace/snippets/rdoc.js b/ui/editor/libs/ace/snippets/rdoc.js similarity index 100% rename from ui/arduino/libs/ace/snippets/rdoc.js rename to ui/editor/libs/ace/snippets/rdoc.js diff --git a/ui/arduino/libs/ace/snippets/red.js b/ui/editor/libs/ace/snippets/red.js similarity index 100% rename from ui/arduino/libs/ace/snippets/red.js rename to ui/editor/libs/ace/snippets/red.js diff --git a/ui/arduino/libs/ace/snippets/redshift.js b/ui/editor/libs/ace/snippets/redshift.js similarity index 100% rename from ui/arduino/libs/ace/snippets/redshift.js rename to ui/editor/libs/ace/snippets/redshift.js diff --git a/ui/arduino/libs/ace/snippets/rhtml.js b/ui/editor/libs/ace/snippets/rhtml.js similarity index 100% rename from ui/arduino/libs/ace/snippets/rhtml.js rename to ui/editor/libs/ace/snippets/rhtml.js diff --git a/ui/arduino/libs/ace/snippets/rst.js b/ui/editor/libs/ace/snippets/rst.js similarity index 100% rename from ui/arduino/libs/ace/snippets/rst.js rename to ui/editor/libs/ace/snippets/rst.js diff --git a/ui/arduino/libs/ace/snippets/ruby.js b/ui/editor/libs/ace/snippets/ruby.js similarity index 100% rename from ui/arduino/libs/ace/snippets/ruby.js rename to ui/editor/libs/ace/snippets/ruby.js diff --git a/ui/arduino/libs/ace/snippets/rust.js b/ui/editor/libs/ace/snippets/rust.js similarity index 100% rename from ui/arduino/libs/ace/snippets/rust.js rename to ui/editor/libs/ace/snippets/rust.js diff --git a/ui/arduino/libs/ace/snippets/sass.js b/ui/editor/libs/ace/snippets/sass.js similarity index 100% rename from ui/arduino/libs/ace/snippets/sass.js rename to ui/editor/libs/ace/snippets/sass.js diff --git a/ui/arduino/libs/ace/snippets/scad.js b/ui/editor/libs/ace/snippets/scad.js similarity index 100% rename from ui/arduino/libs/ace/snippets/scad.js rename to ui/editor/libs/ace/snippets/scad.js diff --git a/ui/arduino/libs/ace/snippets/scala.js b/ui/editor/libs/ace/snippets/scala.js similarity index 100% rename from ui/arduino/libs/ace/snippets/scala.js rename to ui/editor/libs/ace/snippets/scala.js diff --git a/ui/arduino/libs/ace/snippets/scheme.js b/ui/editor/libs/ace/snippets/scheme.js similarity index 100% rename from ui/arduino/libs/ace/snippets/scheme.js rename to ui/editor/libs/ace/snippets/scheme.js diff --git a/ui/arduino/libs/ace/snippets/scss.js b/ui/editor/libs/ace/snippets/scss.js similarity index 100% rename from ui/arduino/libs/ace/snippets/scss.js rename to ui/editor/libs/ace/snippets/scss.js diff --git a/ui/arduino/libs/ace/snippets/sh.js b/ui/editor/libs/ace/snippets/sh.js similarity index 100% rename from ui/arduino/libs/ace/snippets/sh.js rename to ui/editor/libs/ace/snippets/sh.js diff --git a/ui/arduino/libs/ace/snippets/sjs.js b/ui/editor/libs/ace/snippets/sjs.js similarity index 100% rename from ui/arduino/libs/ace/snippets/sjs.js rename to ui/editor/libs/ace/snippets/sjs.js diff --git a/ui/arduino/libs/ace/snippets/slim.js b/ui/editor/libs/ace/snippets/slim.js similarity index 100% rename from ui/arduino/libs/ace/snippets/slim.js rename to ui/editor/libs/ace/snippets/slim.js diff --git a/ui/arduino/libs/ace/snippets/smarty.js b/ui/editor/libs/ace/snippets/smarty.js similarity index 100% rename from ui/arduino/libs/ace/snippets/smarty.js rename to ui/editor/libs/ace/snippets/smarty.js diff --git a/ui/arduino/libs/ace/snippets/snippets.js b/ui/editor/libs/ace/snippets/snippets.js similarity index 100% rename from ui/arduino/libs/ace/snippets/snippets.js rename to ui/editor/libs/ace/snippets/snippets.js diff --git a/ui/arduino/libs/ace/snippets/soy_template.js b/ui/editor/libs/ace/snippets/soy_template.js similarity index 100% rename from ui/arduino/libs/ace/snippets/soy_template.js rename to ui/editor/libs/ace/snippets/soy_template.js diff --git a/ui/arduino/libs/ace/snippets/space.js b/ui/editor/libs/ace/snippets/space.js similarity index 100% rename from ui/arduino/libs/ace/snippets/space.js rename to ui/editor/libs/ace/snippets/space.js diff --git a/ui/arduino/libs/ace/snippets/sparql.js b/ui/editor/libs/ace/snippets/sparql.js similarity index 100% rename from ui/arduino/libs/ace/snippets/sparql.js rename to ui/editor/libs/ace/snippets/sparql.js diff --git a/ui/arduino/libs/ace/snippets/sql.js b/ui/editor/libs/ace/snippets/sql.js similarity index 100% rename from ui/arduino/libs/ace/snippets/sql.js rename to ui/editor/libs/ace/snippets/sql.js diff --git a/ui/arduino/libs/ace/snippets/sqlserver.js b/ui/editor/libs/ace/snippets/sqlserver.js similarity index 100% rename from ui/arduino/libs/ace/snippets/sqlserver.js rename to ui/editor/libs/ace/snippets/sqlserver.js diff --git a/ui/arduino/libs/ace/snippets/stylus.js b/ui/editor/libs/ace/snippets/stylus.js similarity index 100% rename from ui/arduino/libs/ace/snippets/stylus.js rename to ui/editor/libs/ace/snippets/stylus.js diff --git a/ui/arduino/libs/ace/snippets/svg.js b/ui/editor/libs/ace/snippets/svg.js similarity index 100% rename from ui/arduino/libs/ace/snippets/svg.js rename to ui/editor/libs/ace/snippets/svg.js diff --git a/ui/arduino/libs/ace/snippets/swift.js b/ui/editor/libs/ace/snippets/swift.js similarity index 100% rename from ui/arduino/libs/ace/snippets/swift.js rename to ui/editor/libs/ace/snippets/swift.js diff --git a/ui/arduino/libs/ace/snippets/tcl.js b/ui/editor/libs/ace/snippets/tcl.js similarity index 100% rename from ui/arduino/libs/ace/snippets/tcl.js rename to ui/editor/libs/ace/snippets/tcl.js diff --git a/ui/arduino/libs/ace/snippets/terraform.js b/ui/editor/libs/ace/snippets/terraform.js similarity index 100% rename from ui/arduino/libs/ace/snippets/terraform.js rename to ui/editor/libs/ace/snippets/terraform.js diff --git a/ui/arduino/libs/ace/snippets/tex.js b/ui/editor/libs/ace/snippets/tex.js similarity index 100% rename from ui/arduino/libs/ace/snippets/tex.js rename to ui/editor/libs/ace/snippets/tex.js diff --git a/ui/arduino/libs/ace/snippets/text.js b/ui/editor/libs/ace/snippets/text.js similarity index 100% rename from ui/arduino/libs/ace/snippets/text.js rename to ui/editor/libs/ace/snippets/text.js diff --git a/ui/arduino/libs/ace/snippets/textile.js b/ui/editor/libs/ace/snippets/textile.js similarity index 100% rename from ui/arduino/libs/ace/snippets/textile.js rename to ui/editor/libs/ace/snippets/textile.js diff --git a/ui/arduino/libs/ace/snippets/toml.js b/ui/editor/libs/ace/snippets/toml.js similarity index 100% rename from ui/arduino/libs/ace/snippets/toml.js rename to ui/editor/libs/ace/snippets/toml.js diff --git a/ui/arduino/libs/ace/snippets/tsx.js b/ui/editor/libs/ace/snippets/tsx.js similarity index 100% rename from ui/arduino/libs/ace/snippets/tsx.js rename to ui/editor/libs/ace/snippets/tsx.js diff --git a/ui/arduino/libs/ace/snippets/turtle.js b/ui/editor/libs/ace/snippets/turtle.js similarity index 100% rename from ui/arduino/libs/ace/snippets/turtle.js rename to ui/editor/libs/ace/snippets/turtle.js diff --git a/ui/arduino/libs/ace/snippets/twig.js b/ui/editor/libs/ace/snippets/twig.js similarity index 100% rename from ui/arduino/libs/ace/snippets/twig.js rename to ui/editor/libs/ace/snippets/twig.js diff --git a/ui/arduino/libs/ace/snippets/typescript.js b/ui/editor/libs/ace/snippets/typescript.js similarity index 100% rename from ui/arduino/libs/ace/snippets/typescript.js rename to ui/editor/libs/ace/snippets/typescript.js diff --git a/ui/arduino/libs/ace/snippets/vala.js b/ui/editor/libs/ace/snippets/vala.js similarity index 100% rename from ui/arduino/libs/ace/snippets/vala.js rename to ui/editor/libs/ace/snippets/vala.js diff --git a/ui/arduino/libs/ace/snippets/vbscript.js b/ui/editor/libs/ace/snippets/vbscript.js similarity index 100% rename from ui/arduino/libs/ace/snippets/vbscript.js rename to ui/editor/libs/ace/snippets/vbscript.js diff --git a/ui/arduino/libs/ace/snippets/velocity.js b/ui/editor/libs/ace/snippets/velocity.js similarity index 100% rename from ui/arduino/libs/ace/snippets/velocity.js rename to ui/editor/libs/ace/snippets/velocity.js diff --git a/ui/arduino/libs/ace/snippets/verilog.js b/ui/editor/libs/ace/snippets/verilog.js similarity index 100% rename from ui/arduino/libs/ace/snippets/verilog.js rename to ui/editor/libs/ace/snippets/verilog.js diff --git a/ui/arduino/libs/ace/snippets/vhdl.js b/ui/editor/libs/ace/snippets/vhdl.js similarity index 100% rename from ui/arduino/libs/ace/snippets/vhdl.js rename to ui/editor/libs/ace/snippets/vhdl.js diff --git a/ui/arduino/libs/ace/snippets/visualforce.js b/ui/editor/libs/ace/snippets/visualforce.js similarity index 100% rename from ui/arduino/libs/ace/snippets/visualforce.js rename to ui/editor/libs/ace/snippets/visualforce.js diff --git a/ui/arduino/libs/ace/snippets/wollok.js b/ui/editor/libs/ace/snippets/wollok.js similarity index 100% rename from ui/arduino/libs/ace/snippets/wollok.js rename to ui/editor/libs/ace/snippets/wollok.js diff --git a/ui/arduino/libs/ace/snippets/xml.js b/ui/editor/libs/ace/snippets/xml.js similarity index 100% rename from ui/arduino/libs/ace/snippets/xml.js rename to ui/editor/libs/ace/snippets/xml.js diff --git a/ui/arduino/libs/ace/snippets/xquery.js b/ui/editor/libs/ace/snippets/xquery.js similarity index 100% rename from ui/arduino/libs/ace/snippets/xquery.js rename to ui/editor/libs/ace/snippets/xquery.js diff --git a/ui/arduino/libs/ace/snippets/yaml.js b/ui/editor/libs/ace/snippets/yaml.js similarity index 100% rename from ui/arduino/libs/ace/snippets/yaml.js rename to ui/editor/libs/ace/snippets/yaml.js diff --git a/ui/arduino/libs/ace/snippets/zeek.js b/ui/editor/libs/ace/snippets/zeek.js similarity index 100% rename from ui/arduino/libs/ace/snippets/zeek.js rename to ui/editor/libs/ace/snippets/zeek.js diff --git a/ui/arduino/libs/ace/theme-ambiance.js b/ui/editor/libs/ace/theme-ambiance.js similarity index 100% rename from ui/arduino/libs/ace/theme-ambiance.js rename to ui/editor/libs/ace/theme-ambiance.js diff --git a/ui/arduino/libs/ace/theme-chaos.js b/ui/editor/libs/ace/theme-chaos.js similarity index 100% rename from ui/arduino/libs/ace/theme-chaos.js rename to ui/editor/libs/ace/theme-chaos.js diff --git a/ui/arduino/libs/ace/theme-chrome.js b/ui/editor/libs/ace/theme-chrome.js similarity index 100% rename from ui/arduino/libs/ace/theme-chrome.js rename to ui/editor/libs/ace/theme-chrome.js diff --git a/ui/arduino/libs/ace/theme-clouds.js b/ui/editor/libs/ace/theme-clouds.js similarity index 100% rename from ui/arduino/libs/ace/theme-clouds.js rename to ui/editor/libs/ace/theme-clouds.js diff --git a/ui/arduino/libs/ace/theme-clouds_midnight.js b/ui/editor/libs/ace/theme-clouds_midnight.js similarity index 100% rename from ui/arduino/libs/ace/theme-clouds_midnight.js rename to ui/editor/libs/ace/theme-clouds_midnight.js diff --git a/ui/arduino/libs/ace/theme-cobalt.js b/ui/editor/libs/ace/theme-cobalt.js similarity index 100% rename from ui/arduino/libs/ace/theme-cobalt.js rename to ui/editor/libs/ace/theme-cobalt.js diff --git a/ui/arduino/libs/ace/theme-crimson_editor.js b/ui/editor/libs/ace/theme-crimson_editor.js similarity index 100% rename from ui/arduino/libs/ace/theme-crimson_editor.js rename to ui/editor/libs/ace/theme-crimson_editor.js diff --git a/ui/arduino/libs/ace/theme-dawn.js b/ui/editor/libs/ace/theme-dawn.js similarity index 100% rename from ui/arduino/libs/ace/theme-dawn.js rename to ui/editor/libs/ace/theme-dawn.js diff --git a/ui/arduino/libs/ace/theme-dracula.js b/ui/editor/libs/ace/theme-dracula.js similarity index 100% rename from ui/arduino/libs/ace/theme-dracula.js rename to ui/editor/libs/ace/theme-dracula.js diff --git a/ui/arduino/libs/ace/theme-dreamweaver.js b/ui/editor/libs/ace/theme-dreamweaver.js similarity index 100% rename from ui/arduino/libs/ace/theme-dreamweaver.js rename to ui/editor/libs/ace/theme-dreamweaver.js diff --git a/ui/arduino/libs/ace/theme-eclipse.js b/ui/editor/libs/ace/theme-eclipse.js similarity index 100% rename from ui/arduino/libs/ace/theme-eclipse.js rename to ui/editor/libs/ace/theme-eclipse.js diff --git a/ui/arduino/libs/ace/theme-github.js b/ui/editor/libs/ace/theme-github.js similarity index 100% rename from ui/arduino/libs/ace/theme-github.js rename to ui/editor/libs/ace/theme-github.js diff --git a/ui/arduino/libs/ace/theme-gob.js b/ui/editor/libs/ace/theme-gob.js similarity index 100% rename from ui/arduino/libs/ace/theme-gob.js rename to ui/editor/libs/ace/theme-gob.js diff --git a/ui/arduino/libs/ace/theme-gruvbox.js b/ui/editor/libs/ace/theme-gruvbox.js similarity index 100% rename from ui/arduino/libs/ace/theme-gruvbox.js rename to ui/editor/libs/ace/theme-gruvbox.js diff --git a/ui/arduino/libs/ace/theme-idle_fingers.js b/ui/editor/libs/ace/theme-idle_fingers.js similarity index 100% rename from ui/arduino/libs/ace/theme-idle_fingers.js rename to ui/editor/libs/ace/theme-idle_fingers.js diff --git a/ui/arduino/libs/ace/theme-iplastic.js b/ui/editor/libs/ace/theme-iplastic.js similarity index 100% rename from ui/arduino/libs/ace/theme-iplastic.js rename to ui/editor/libs/ace/theme-iplastic.js diff --git a/ui/arduino/libs/ace/theme-katzenmilch.js b/ui/editor/libs/ace/theme-katzenmilch.js similarity index 100% rename from ui/arduino/libs/ace/theme-katzenmilch.js rename to ui/editor/libs/ace/theme-katzenmilch.js diff --git a/ui/arduino/libs/ace/theme-kr_theme.js b/ui/editor/libs/ace/theme-kr_theme.js similarity index 100% rename from ui/arduino/libs/ace/theme-kr_theme.js rename to ui/editor/libs/ace/theme-kr_theme.js diff --git a/ui/arduino/libs/ace/theme-kuroir.js b/ui/editor/libs/ace/theme-kuroir.js similarity index 100% rename from ui/arduino/libs/ace/theme-kuroir.js rename to ui/editor/libs/ace/theme-kuroir.js diff --git a/ui/arduino/libs/ace/theme-merbivore.js b/ui/editor/libs/ace/theme-merbivore.js similarity index 100% rename from ui/arduino/libs/ace/theme-merbivore.js rename to ui/editor/libs/ace/theme-merbivore.js diff --git a/ui/arduino/libs/ace/theme-merbivore_soft.js b/ui/editor/libs/ace/theme-merbivore_soft.js similarity index 100% rename from ui/arduino/libs/ace/theme-merbivore_soft.js rename to ui/editor/libs/ace/theme-merbivore_soft.js diff --git a/ui/arduino/libs/ace/theme-mono_industrial.js b/ui/editor/libs/ace/theme-mono_industrial.js similarity index 100% rename from ui/arduino/libs/ace/theme-mono_industrial.js rename to ui/editor/libs/ace/theme-mono_industrial.js diff --git a/ui/arduino/libs/ace/theme-monokai.js b/ui/editor/libs/ace/theme-monokai.js similarity index 100% rename from ui/arduino/libs/ace/theme-monokai.js rename to ui/editor/libs/ace/theme-monokai.js diff --git a/ui/arduino/libs/ace/theme-nord_dark.js b/ui/editor/libs/ace/theme-nord_dark.js similarity index 100% rename from ui/arduino/libs/ace/theme-nord_dark.js rename to ui/editor/libs/ace/theme-nord_dark.js diff --git a/ui/arduino/libs/ace/theme-pastel_on_dark.js b/ui/editor/libs/ace/theme-pastel_on_dark.js similarity index 100% rename from ui/arduino/libs/ace/theme-pastel_on_dark.js rename to ui/editor/libs/ace/theme-pastel_on_dark.js diff --git a/ui/arduino/libs/ace/theme-solarized_dark.js b/ui/editor/libs/ace/theme-solarized_dark.js similarity index 100% rename from ui/arduino/libs/ace/theme-solarized_dark.js rename to ui/editor/libs/ace/theme-solarized_dark.js diff --git a/ui/arduino/libs/ace/theme-solarized_light.js b/ui/editor/libs/ace/theme-solarized_light.js similarity index 100% rename from ui/arduino/libs/ace/theme-solarized_light.js rename to ui/editor/libs/ace/theme-solarized_light.js diff --git a/ui/arduino/libs/ace/theme-sqlserver.js b/ui/editor/libs/ace/theme-sqlserver.js similarity index 100% rename from ui/arduino/libs/ace/theme-sqlserver.js rename to ui/editor/libs/ace/theme-sqlserver.js diff --git a/ui/arduino/libs/ace/theme-terminal.js b/ui/editor/libs/ace/theme-terminal.js similarity index 100% rename from ui/arduino/libs/ace/theme-terminal.js rename to ui/editor/libs/ace/theme-terminal.js diff --git a/ui/arduino/libs/ace/theme-textmate.js b/ui/editor/libs/ace/theme-textmate.js similarity index 100% rename from ui/arduino/libs/ace/theme-textmate.js rename to ui/editor/libs/ace/theme-textmate.js diff --git a/ui/arduino/libs/ace/theme-tomorrow.js b/ui/editor/libs/ace/theme-tomorrow.js similarity index 100% rename from ui/arduino/libs/ace/theme-tomorrow.js rename to ui/editor/libs/ace/theme-tomorrow.js diff --git a/ui/arduino/libs/ace/theme-tomorrow_night.js b/ui/editor/libs/ace/theme-tomorrow_night.js similarity index 100% rename from ui/arduino/libs/ace/theme-tomorrow_night.js rename to ui/editor/libs/ace/theme-tomorrow_night.js diff --git a/ui/arduino/libs/ace/theme-tomorrow_night_blue.js b/ui/editor/libs/ace/theme-tomorrow_night_blue.js similarity index 100% rename from ui/arduino/libs/ace/theme-tomorrow_night_blue.js rename to ui/editor/libs/ace/theme-tomorrow_night_blue.js diff --git a/ui/arduino/libs/ace/theme-tomorrow_night_bright.js b/ui/editor/libs/ace/theme-tomorrow_night_bright.js similarity index 100% rename from ui/arduino/libs/ace/theme-tomorrow_night_bright.js rename to ui/editor/libs/ace/theme-tomorrow_night_bright.js diff --git a/ui/arduino/libs/ace/theme-tomorrow_night_eighties.js b/ui/editor/libs/ace/theme-tomorrow_night_eighties.js similarity index 100% rename from ui/arduino/libs/ace/theme-tomorrow_night_eighties.js rename to ui/editor/libs/ace/theme-tomorrow_night_eighties.js diff --git a/ui/arduino/libs/ace/theme-twilight.js b/ui/editor/libs/ace/theme-twilight.js similarity index 100% rename from ui/arduino/libs/ace/theme-twilight.js rename to ui/editor/libs/ace/theme-twilight.js diff --git a/ui/arduino/libs/ace/theme-vibrant_ink.js b/ui/editor/libs/ace/theme-vibrant_ink.js similarity index 100% rename from ui/arduino/libs/ace/theme-vibrant_ink.js rename to ui/editor/libs/ace/theme-vibrant_ink.js diff --git a/ui/arduino/libs/ace/theme-xcode.js b/ui/editor/libs/ace/theme-xcode.js similarity index 100% rename from ui/arduino/libs/ace/theme-xcode.js rename to ui/editor/libs/ace/theme-xcode.js diff --git a/ui/arduino/libs/ace/worker-base.js b/ui/editor/libs/ace/worker-base.js similarity index 100% rename from ui/arduino/libs/ace/worker-base.js rename to ui/editor/libs/ace/worker-base.js diff --git a/ui/arduino/libs/ace/worker-coffee.js b/ui/editor/libs/ace/worker-coffee.js similarity index 100% rename from ui/arduino/libs/ace/worker-coffee.js rename to ui/editor/libs/ace/worker-coffee.js diff --git a/ui/arduino/libs/ace/worker-css.js b/ui/editor/libs/ace/worker-css.js similarity index 100% rename from ui/arduino/libs/ace/worker-css.js rename to ui/editor/libs/ace/worker-css.js diff --git a/ui/arduino/libs/ace/worker-html.js b/ui/editor/libs/ace/worker-html.js similarity index 100% rename from ui/arduino/libs/ace/worker-html.js rename to ui/editor/libs/ace/worker-html.js diff --git a/ui/arduino/libs/ace/worker-javascript.js b/ui/editor/libs/ace/worker-javascript.js similarity index 100% rename from ui/arduino/libs/ace/worker-javascript.js rename to ui/editor/libs/ace/worker-javascript.js diff --git a/ui/arduino/libs/ace/worker-json.js b/ui/editor/libs/ace/worker-json.js similarity index 100% rename from ui/arduino/libs/ace/worker-json.js rename to ui/editor/libs/ace/worker-json.js diff --git a/ui/arduino/libs/ace/worker-lua.js b/ui/editor/libs/ace/worker-lua.js similarity index 100% rename from ui/arduino/libs/ace/worker-lua.js rename to ui/editor/libs/ace/worker-lua.js diff --git a/ui/arduino/libs/ace/worker-php.js b/ui/editor/libs/ace/worker-php.js similarity index 100% rename from ui/arduino/libs/ace/worker-php.js rename to ui/editor/libs/ace/worker-php.js diff --git a/ui/arduino/libs/ace/worker-xml.js b/ui/editor/libs/ace/worker-xml.js similarity index 100% rename from ui/arduino/libs/ace/worker-xml.js rename to ui/editor/libs/ace/worker-xml.js diff --git a/ui/arduino/libs/ace/worker-xquery.js b/ui/editor/libs/ace/worker-xquery.js similarity index 100% rename from ui/arduino/libs/ace/worker-xquery.js rename to ui/editor/libs/ace/worker-xquery.js diff --git a/ui/arduino/libs/build_choo.js b/ui/editor/libs/build_choo.js similarity index 100% rename from ui/arduino/libs/build_choo.js rename to ui/editor/libs/build_choo.js diff --git a/ui/arduino/libs/choo.js b/ui/editor/libs/choo.js similarity index 100% rename from ui/arduino/libs/choo.js rename to ui/editor/libs/choo.js diff --git a/ui/arduino/libs/xterm-addon-fit.js b/ui/editor/libs/xterm-addon-fit.js similarity index 100% rename from ui/arduino/libs/xterm-addon-fit.js rename to ui/editor/libs/xterm-addon-fit.js diff --git a/ui/arduino/libs/xterm.css b/ui/editor/libs/xterm.css similarity index 100% rename from ui/arduino/libs/xterm.css rename to ui/editor/libs/xterm.css diff --git a/ui/arduino/libs/xterm.js b/ui/editor/libs/xterm.js similarity index 100% rename from ui/arduino/libs/xterm.js rename to ui/editor/libs/xterm.js diff --git a/ui/arduino/package-lock.json b/ui/editor/package-lock.json similarity index 100% rename from ui/arduino/package-lock.json rename to ui/editor/package-lock.json diff --git a/ui/arduino/package.json b/ui/editor/package.json similarity index 100% rename from ui/arduino/package.json rename to ui/editor/package.json diff --git a/ui/arduino/store.js b/ui/editor/store.js similarity index 100% rename from ui/arduino/store.js rename to ui/editor/store.js diff --git a/ui/arduino/theme.css b/ui/editor/theme.css similarity index 100% rename from ui/arduino/theme.css rename to ui/editor/theme.css diff --git a/ui/ftp/components/files/diskFiles.tsx b/ui/ftp/components/files/diskFiles.tsx new file mode 100644 index 0000000..682840d --- /dev/null +++ b/ui/ftp/components/files/diskFiles.tsx @@ -0,0 +1,16 @@ +import React from 'react' +import DiskFilesType from './diskFiles.type.ts' +import Button from '../shared/button.tsx' + +const DiskFiles: React.FC = ({ diskFilesLogic }) => { + const { diskFiles = [], navigate }: DiskFilesType = diskFilesLogic() + const onClick = (folder) => () => { + navigate(folder) + } + const files = diskFiles.map((folder, i) => { + return
  • + }) + return +} + +export default DiskFiles \ No newline at end of file diff --git a/ui/ftp/components/files/diskFiles.type.ts b/ui/ftp/components/files/diskFiles.type.ts new file mode 100644 index 0000000..cf38a69 --- /dev/null +++ b/ui/ftp/components/files/diskFiles.type.ts @@ -0,0 +1,8 @@ +type DiskFilesType = () => { + diskFiles: String[] + // selectedFile: File + navigate: (folder : String) => void + selectFile: (path: String) => void +} + +export default DiskFilesType \ No newline at end of file diff --git a/ui/ftp/components/files/management.type.ts b/ui/ftp/components/files/management.type.ts new file mode 100644 index 0000000..5dd88ff --- /dev/null +++ b/ui/ftp/components/files/management.type.ts @@ -0,0 +1,7 @@ +type FileManagementType = () => { + upload: (diskPath: String, serialPath: String) => void + download: (serialPath: String, diskPath: String) => void + remove: () => void +} + +export default FileManagementType \ No newline at end of file diff --git a/ui/ftp/components/files/serialFiles.tsx b/ui/ftp/components/files/serialFiles.tsx new file mode 100644 index 0000000..23c9724 --- /dev/null +++ b/ui/ftp/components/files/serialFiles.tsx @@ -0,0 +1,16 @@ +import React from 'react' +import SerialFilesType from './serialFiles.type.ts' +import Button from '../shared/button.tsx' + +const SerialFiles: React.FC = ({ serialFilesLogic }) => { + const { serialFiles = [], navigate }: SerialFilesType = serialFilesLogic() + const onClick = (folder) => () => { + navigate(folder) + } + const files = serialFiles.map((folder, i) => { + return
  • + }) + return +} + +export default SerialFiles \ No newline at end of file diff --git a/ui/ftp/components/files/serialFiles.type.ts b/ui/ftp/components/files/serialFiles.type.ts new file mode 100644 index 0000000..93bc68b --- /dev/null +++ b/ui/ftp/components/files/serialFiles.type.ts @@ -0,0 +1,8 @@ +type SerialFilesType = () => { + serialFiles: String[] + selectedFile: File + navigate: (folder : String) => void + selectFile: (path: String) => void +} + +export default SerialFilesType \ No newline at end of file diff --git a/ui/ftp/components/navigation/diskNavigation.tsx b/ui/ftp/components/navigation/diskNavigation.tsx new file mode 100644 index 0000000..beab208 --- /dev/null +++ b/ui/ftp/components/navigation/diskNavigation.tsx @@ -0,0 +1,9 @@ +import React from 'react' +import BreadCrumbs from '../shared/breadcrumbs' + +const DiskNavigation: React.FC = ({ navigationLogic }) => { + const { diskPath = '', navigate } = navigationLogic() + return +} + +export default DiskNavigation \ No newline at end of file diff --git a/ui/ftp/components/navigation/diskNavigation.type.ts b/ui/ftp/components/navigation/diskNavigation.type.ts new file mode 100644 index 0000000..fb8364b --- /dev/null +++ b/ui/ftp/components/navigation/diskNavigation.type.ts @@ -0,0 +1,6 @@ +type DiskNavigationType = () => { + diskPath: String + navigate: (folder : String) => void +} + +export default DiskNavigationType \ No newline at end of file diff --git a/ui/ftp/components/navigation/serialNavigation.tsx b/ui/ftp/components/navigation/serialNavigation.tsx new file mode 100644 index 0000000..98b8314 --- /dev/null +++ b/ui/ftp/components/navigation/serialNavigation.tsx @@ -0,0 +1,9 @@ +import React from 'react' +import BreadCrumbs from '../shared/breadcrumbs' + +const SerialNavigation: React.FC = ({ navigationLogic }) => { + const { serialPath = '', navigate } = navigationLogic() + return +} + +export default SerialNavigation \ No newline at end of file diff --git a/ui/ftp/components/navigation/serialNavigation.type.ts b/ui/ftp/components/navigation/serialNavigation.type.ts new file mode 100644 index 0000000..1d057c0 --- /dev/null +++ b/ui/ftp/components/navigation/serialNavigation.type.ts @@ -0,0 +1,6 @@ +type SerialNavigationType = () => { + serialPath: String + navigate: (folder: String) => void +} + +export default SerialNavigationType \ No newline at end of file diff --git a/ui/ftp/components/shared/breadcrumbs.module.scss b/ui/ftp/components/shared/breadcrumbs.module.scss new file mode 100644 index 0000000..822400d --- /dev/null +++ b/ui/ftp/components/shared/breadcrumbs.module.scss @@ -0,0 +1,9 @@ +.body { + display: flex; + flex-direction: row; + align-items: center; + padding: 1rem; + > * { + margin: 0 0.5rem 0 0; + } +} \ No newline at end of file diff --git a/ui/ftp/components/shared/breadcrumbs.tsx b/ui/ftp/components/shared/breadcrumbs.tsx new file mode 100644 index 0000000..f42d966 --- /dev/null +++ b/ui/ftp/components/shared/breadcrumbs.tsx @@ -0,0 +1,21 @@ +import React from 'react' +import Button from './button.tsx' +import styles from './breadcrumbs.module.scss' + +const BreadCrumbs: React.FC = ({ path, navigate }) => { + if (!path) return <> + const pathArray = path.split('/') + const onClick = (folder) => () => { + navigate(folder) + } + const items = pathArray.map( + (folder, i) => ( + + / + + ) + ) + return
    {items}
    +} + +export default BreadCrumbs \ No newline at end of file diff --git a/ui/ftp/components/shared/button.module.scss b/ui/ftp/components/shared/button.module.scss new file mode 100644 index 0000000..ce0e3f6 --- /dev/null +++ b/ui/ftp/components/shared/button.module.scss @@ -0,0 +1,12 @@ +.button { + padding: 1rem; + border: none; + cursor: pointer; + background: #ddd; + &:hover { + opacity: 0.8; + } + &:active { + opacity: 1.0; + } +} \ No newline at end of file diff --git a/ui/ftp/components/shared/button.tsx b/ui/ftp/components/shared/button.tsx new file mode 100644 index 0000000..47e5c29 --- /dev/null +++ b/ui/ftp/components/shared/button.tsx @@ -0,0 +1,8 @@ +import React from 'react' +import styles from './button.module.scss' + +const Button: React.FC = (attr) => { + return +} + +export default Button \ No newline at end of file diff --git a/ui/ftp/components/toolbar/toolbar.module.scss b/ui/ftp/components/toolbar/toolbar.module.scss new file mode 100644 index 0000000..6d41740 --- /dev/null +++ b/ui/ftp/components/toolbar/toolbar.module.scss @@ -0,0 +1,8 @@ +.body { + display: flex; + flex-direction: row; + padding: 1rem; + > * { + margin: 0 0.5rem 0 0; + } +} diff --git a/ui/ftp/components/toolbar/toolbar.tsx b/ui/ftp/components/toolbar/toolbar.tsx new file mode 100644 index 0000000..46bc943 --- /dev/null +++ b/ui/ftp/components/toolbar/toolbar.tsx @@ -0,0 +1,42 @@ +import React, { useState } from 'react' +import styles from './toolbar.module.scss' +import Button from '../shared/button.tsx' + + +const Toolbar: React.FC = ({ toolbarLogic }) => { + const { + openFolder, + refresh, + connect, + disconnect, + connectedDevice, + availableDevices = [] + } = toolbarLogic() + const [ selectedDevice, setSelectedDevice ] = useState() + const onChange = (e) => setSelectedDevice(e.target.value) + const onConnect = () => connect(selectedDevice) + + const deviceSelector = ( + + ) + const deviceDisplay = ( + {connectedDevice} + ) + + return ( +
    + {connectedDevice ? deviceDisplay : deviceSelector} + + + + {connectedDevice ? Connected : Disconnected} +
    + ) +} + +export default Toolbar \ No newline at end of file diff --git a/ui/ftp/components/toolbar/toolbar.type.ts b/ui/ftp/components/toolbar/toolbar.type.ts new file mode 100644 index 0000000..01a653b --- /dev/null +++ b/ui/ftp/components/toolbar/toolbar.type.ts @@ -0,0 +1,10 @@ +type ToolbarType = () => { + availableDevices: String[] + connectedDevice: String | null + connect: (devicePath: String) => void + disconnect: () => void + openFolder: () => void + refresh: () => void +} + +export default ToolbarType \ No newline at end of file diff --git a/ui/ftp/index.html b/ui/ftp/index.html new file mode 100644 index 0000000..4a7d0ad --- /dev/null +++ b/ui/ftp/index.html @@ -0,0 +1,14 @@ + + + + + + + Document + + + + +
    + + \ No newline at end of file diff --git a/ui/ftp/main.logic.ts b/ui/ftp/main.logic.ts new file mode 100644 index 0000000..5c511d7 --- /dev/null +++ b/ui/ftp/main.logic.ts @@ -0,0 +1,164 @@ +import { useState } from 'react'; + +import ToolbarType from './components/toolbar/toolbar.type' +import DiskNavigationType from './components/navigation/diskNavigation.type' +import DiskFilesType from './components/files/diskFiles.type' +import SerialNavigationType from './components/navigation/serialNavigation.type' +import SerialFilesType from './components/files/serialFiles.type' +import FileManagementType from './components/files/management.type' + +import { Device, File } from './main.type' + +export type UseMainLogic = () => { + toolbarLogic: ToolbarType + diskNavigationLogic: DiskNavigationType + diskFilesLogic: DiskFilesType + serialNavigationLogic: SerialNavigationType + serialFilesLogic: SerialFilesType + fileManagementLogic: FileManagementType +} + +export const useMainLogic : UseMainLogic = function() : ReturnType { + const { BridgeSerial, BridgeDisk } = window + // List and connect to serial devices + const [ availableDevices, setAvailableDevices ] = useState() + const [ connectedDevice, setConnectedDevice ] = useState() + // Navigation paths + const [ serialPath, setSerialPath ] = useState() + const [ diskPath, setDiskPath ] = useState() + // Available files (listed) + const [ diskFiles, setDiskFiles ] = useState() + const [ serialFiles, setSerialFiles ] = useState() + // Selected file + const [ selectedFile, setSelectedFile ] = useState() + // Progress + const [ waiting, setWaiting ] = useState() + + // HELPERS + const navigateDisk = async (folder) => { + const pathArray = diskPath.split('/') + const folderIndex = pathArray.indexOf(folder) + let newPathArray = [] + if (folderIndex === -1) { + newPathArray = pathArray.concat(folder) + } else { + newPathArray = pathArray.slice(0, folderIndex+1) + } + const newPath = newPathArray.join('/') + const files = await BridgeDisk.listFiles(newPath) + setDiskPath(newPath) + setDiskFiles(files) + } + + const navigateSerial = async (folder) => { + const pathArray = serialPath.split('/') + const folderIndex = pathArray.indexOf(folder) + let newPathArray = [] + if (folderIndex === -1) { + newPathArray = pathArray.concat(folder) + } else { + newPathArray = pathArray.slice(0, folderIndex+1) + } + const newPath = newPathArray.join('/') + const files = await BridgeSerial.listFiles(newPath) + setSerialPath(newPath) + setSerialFiles(files) + } + + // LOGIC + const toolbarLogic = () : ReturnType => { + return { + availableDevices: availableDevices, + connectedDevice: connectedDevice, + connect: async (devicePath: String) => { + await BridgeSerial.connect(devicePath) + setConnectedDevice(devicePath) + setSerialPath('/') + }, + disconnect: () => { + setConnectedDevice(null) + setSerialPath(null) + }, + openFolder: async () => { + const { folder, files } = await BridgeDisk.openFolder() + setDiskPath(folder) + setDiskFiles(files) + }, + refresh: async () => { + // list available devices + const devices = await BridgeSerial.loadPorts() + setAvailableDevices(devices) + // list serial files + if (connectedDevice) { + const files = await BridgeSerial.listFiles(serialPath) + setSerialFiles(files) + } + // list disk files + if (diskPath) { + const files = await BridgeDisk.listFiles(diskPath) + setDiskFiles(files) + } + } + } + } + + const diskNavigationLogic = () : ReturnType => { + return { + diskPath: diskPath, + navigate: navigateDisk + } + } + + const diskFilesLogic = () : ReturnType => { + return { + diskFiles: diskFiles, + // selectedFile: selectedFile, + navigate: navigateDisk, + selectFile: (path) => { + setSelectedFile({ + path: path, + device: Device.disk + }) + } + } + } + + const serialNavigationLogic = () : ReturnType => { + return { + serialPath: serialPath, + navigate: navigateSerial + } + } + + const serialFilesLogic = () : ReturnType => { + return { + serialFiles: serialFiles, + selectedFile: selectedFile, + navigate: navigateSerial, + selectFile: (path) => { + setSelectedFile({ + path: path, + device: Device.serial + }) + } + } + } + + const fileManagementLogic = () : ReturnType => { + return { + upload: (diskPath, serialPath) => {}, + download: (serialPath, diskPath) => {}, + remove: () => {} + } + } + + return { + toolbarLogic, + diskNavigationLogic, + diskFilesLogic, + serialNavigationLogic, + serialFilesLogic, + fileManagementLogic + } +} + diff --git a/ui/ftp/main.scss b/ui/ftp/main.scss new file mode 100644 index 0000000..dee2604 --- /dev/null +++ b/ui/ftp/main.scss @@ -0,0 +1,9 @@ +* { + box-sizing: border-box; +} +html, +body { + margin: 0; + width: 100%; + height: 100%; +} \ No newline at end of file diff --git a/ui/ftp/main.tsx b/ui/ftp/main.tsx new file mode 100644 index 0000000..be3b1de --- /dev/null +++ b/ui/ftp/main.tsx @@ -0,0 +1,46 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' + +import Toolbar from './components/toolbar/toolbar' +import DiskNavigation from './components/navigation/diskNavigation' +import DiskFiles from './components/files/diskFiles' +import SerialNavigation from './components/navigation/serialNavigation' +import SerialFiles from './components/files/serialFiles' + +import { useMainLogic } from './main.logic.ts' + +const App: React.FC = () => { + const { + toolbarLogic, + diskNavigationLogic, + diskFilesLogic, + serialNavigationLogic, + serialFilesLogic + } = useMainLogic() + return ( + <> + +
    +
    + + +
    +
    + + +
    +
    + + ) +} + +window.addEventListener('load', () => { + window.BridgeWindow.setWindowSize(900, 600) + const container : HTMLElement | null = document.querySelector('main') + const root = ReactDOM.createRoot(container) + root.render( + + + + ) +}) diff --git a/ui/ftp/main.type.ts b/ui/ftp/main.type.ts new file mode 100644 index 0000000..3516891 --- /dev/null +++ b/ui/ftp/main.type.ts @@ -0,0 +1,6 @@ +export enum Device { serial, disk } + +export type File = { + path: String + device: Device +} \ No newline at end of file diff --git a/ui/ftp/package-lock.json b/ui/ftp/package-lock.json new file mode 100644 index 0000000..f66a792 --- /dev/null +++ b/ui/ftp/package-lock.json @@ -0,0 +1,2975 @@ +{ + "name": "ftp", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "ftp", + "version": "1.0.0", + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@parcel/transformer-sass": "^2.8.3", + "parcel": "latest", + "process": "^0.11.10" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@lezer/common": { + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.15.12.tgz", + "integrity": "sha512-edfwCxNLnzq5pBA/yaIhwJ3U3Kz8VAUOTRg0hhxaizaI1N+qxV7EXDv/kLCkLeq2RzSFvxexlaj5Mzfn2kY0Ig==", + "dev": true + }, + "node_modules/@lezer/lr": { + "version": "0.15.8", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.15.8.tgz", + "integrity": "sha512-bM6oE6VQZ6hIFxDNKk8bKPa14hqFrV07J/vHGOeiAbJReIaQXmkVb6xQu4MR+JBTLa5arGRyAAjJe1qaQt3Uvg==", + "dev": true, + "dependencies": { + "@lezer/common": "^0.15.0" + } + }, + "node_modules/@lmdb/lmdb-darwin-arm64": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-2.5.2.tgz", + "integrity": "sha512-+F8ioQIUN68B4UFiIBYu0QQvgb9FmlKw2ctQMSBfW2QBrZIxz9vD9jCGqTCPqZBRbPHAS/vG1zSXnKqnS2ch/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@lmdb/lmdb-darwin-x64": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-2.5.2.tgz", + "integrity": "sha512-KvPH56KRLLx4KSfKBx0m1r7GGGUMXm0jrKmNE7plbHlesZMuPJICtn07HYgQhj1LNsK7Yqwuvnqh1QxhJnF1EA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@lmdb/lmdb-linux-arm": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-2.5.2.tgz", + "integrity": "sha512-5kQAP21hAkfW5Bl+e0P57dV4dGYnkNIpR7f/GAh6QHlgXx+vp/teVj4PGRZaKAvt0GX6++N6hF8NnGElLDuIDw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@lmdb/lmdb-linux-arm64": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-2.5.2.tgz", + "integrity": "sha512-aLl89VHL/wjhievEOlPocoefUyWdvzVrcQ/MHQYZm2JfV1jUsrbr/ZfkPPUFvZBf+VSE+Q0clWs9l29PCX1hTQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@lmdb/lmdb-linux-x64": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-2.5.2.tgz", + "integrity": "sha512-xUdUfwDJLGjOUPH3BuPBt0NlIrR7f/QHKgu3GZIXswMMIihAekj2i97oI0iWG5Bok/b+OBjHPfa8IU9velnP/Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@lmdb/lmdb-win32-x64": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-2.5.2.tgz", + "integrity": "sha512-zrBczSbXKxEyK2ijtbRdICDygRqWSRPpZMN5dD1T8VMEW5RIhIbwFWw2phDRXuBQdVDpSjalCIUMWMV2h3JaZA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@mischnic/json-sourcemap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@mischnic/json-sourcemap/-/json-sourcemap-0.1.0.tgz", + "integrity": "sha512-dQb3QnfNqmQNYA4nFSN/uLaByIic58gOXq4Y4XqLOWmOrw73KmJPt/HLyG0wvn1bnR6mBKs/Uwvkh+Hns1T0XA==", + "dev": true, + "dependencies": { + "@lezer/common": "^0.15.7", + "@lezer/lr": "^0.15.4", + "json5": "^2.2.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz", + "integrity": "sha512-9bfjwDxIDWmmOKusUcqdS4Rw+SETlp9Dy39Xui9BEGEk19dDwH0jhipwFzEff/pFg95NKymc6TOTbRKcWeRqyQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.2.tgz", + "integrity": "sha512-lwriRAHm1Yg4iDf23Oxm9n/t5Zpw1lVnxYU3HnJPTi2lJRkKTrps1KVgvL6m7WvmhYVt/FIsssWay+k45QHeuw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.2.tgz", + "integrity": "sha512-MOI9Dlfrpi2Cuc7i5dXdxPbFIgbDBGgKR5F2yWEa6FVEtSWncfVNKW5AKjImAQ6CZlBK9tympdsZJ2xThBiWWA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.2.tgz", + "integrity": "sha512-FU20Bo66/f7He9Fp9sP2zaJ1Q8L9uLPZQDub/WlUip78JlPeMbVL8546HbZfcW9LNciEXc8d+tThSJjSC+tmsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.2.tgz", + "integrity": "sha512-gsWNDCklNy7Ajk0vBBf9jEx04RUxuDQfBse918Ww+Qb9HCPoGzS+XJTLe96iN3BVK7grnLiYghP/M4L8VsaHeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.2.tgz", + "integrity": "sha512-O+6Gs8UeDbyFpbSh2CPEz/UOrrdWPTBYNblZK5CxxLisYt4kGX3Sc+czffFonyjiGSq3jWLwJS/CCJc7tBr4sQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@parcel/bundler-default": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.8.3.tgz", + "integrity": "sha512-yJvRsNWWu5fVydsWk3O2L4yIy3UZiKWO2cPDukGOIWMgp/Vbpp+2Ct5IygVRtE22bnseW/E/oe0PV3d2IkEJGg==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/graph": "2.8.3", + "@parcel/hash": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/cache": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/cache/-/cache-2.8.3.tgz", + "integrity": "sha512-k7xv5vSQrJLdXuglo+Hv3yF4BCSs1tQ/8Vbd6CHTkOhf7LcGg6CPtLw053R/KdMpd/4GPn0QrAsOLdATm1ELtQ==", + "dev": true, + "dependencies": { + "@parcel/fs": "2.8.3", + "@parcel/logger": "2.8.3", + "@parcel/utils": "2.8.3", + "lmdb": "2.5.2" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.8.3" + } + }, + "node_modules/@parcel/codeframe": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/codeframe/-/codeframe-2.8.3.tgz", + "integrity": "sha512-FE7sY53D6n/+2Pgg6M9iuEC6F5fvmyBkRE4d9VdnOoxhTXtkEqpqYgX7RJ12FAQwNlxKq4suBJQMgQHMF2Kjeg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/compressor-raw": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/compressor-raw/-/compressor-raw-2.8.3.tgz", + "integrity": "sha512-bVDsqleBUxRdKMakWSlWC9ZjOcqDKE60BE+Gh3JSN6WJrycJ02P5wxjTVF4CStNP/G7X17U+nkENxSlMG77ySg==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/config-default": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/config-default/-/config-default-2.8.3.tgz", + "integrity": "sha512-o/A/mbrO6X/BfGS65Sib8d6SSG45NYrNooNBkH/o7zbOBSRQxwyTlysleK1/3Wa35YpvFyLOwgfakqCtbGy4fw==", + "dev": true, + "dependencies": { + "@parcel/bundler-default": "2.8.3", + "@parcel/compressor-raw": "2.8.3", + "@parcel/namer-default": "2.8.3", + "@parcel/optimizer-css": "2.8.3", + "@parcel/optimizer-htmlnano": "2.8.3", + "@parcel/optimizer-image": "2.8.3", + "@parcel/optimizer-svgo": "2.8.3", + "@parcel/optimizer-terser": "2.8.3", + "@parcel/packager-css": "2.8.3", + "@parcel/packager-html": "2.8.3", + "@parcel/packager-js": "2.8.3", + "@parcel/packager-raw": "2.8.3", + "@parcel/packager-svg": "2.8.3", + "@parcel/reporter-dev-server": "2.8.3", + "@parcel/resolver-default": "2.8.3", + "@parcel/runtime-browser-hmr": "2.8.3", + "@parcel/runtime-js": "2.8.3", + "@parcel/runtime-react-refresh": "2.8.3", + "@parcel/runtime-service-worker": "2.8.3", + "@parcel/transformer-babel": "2.8.3", + "@parcel/transformer-css": "2.8.3", + "@parcel/transformer-html": "2.8.3", + "@parcel/transformer-image": "2.8.3", + "@parcel/transformer-js": "2.8.3", + "@parcel/transformer-json": "2.8.3", + "@parcel/transformer-postcss": "2.8.3", + "@parcel/transformer-posthtml": "2.8.3", + "@parcel/transformer-raw": "2.8.3", + "@parcel/transformer-react-refresh-wrap": "2.8.3", + "@parcel/transformer-svg": "2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.8.3" + } + }, + "node_modules/@parcel/core": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/core/-/core-2.8.3.tgz", + "integrity": "sha512-Euf/un4ZAiClnlUXqPB9phQlKbveU+2CotZv7m7i+qkgvFn5nAGnrV4h1OzQU42j9dpgOxWi7AttUDMrvkbhCQ==", + "dev": true, + "dependencies": { + "@mischnic/json-sourcemap": "^0.1.0", + "@parcel/cache": "2.8.3", + "@parcel/diagnostic": "2.8.3", + "@parcel/events": "2.8.3", + "@parcel/fs": "2.8.3", + "@parcel/graph": "2.8.3", + "@parcel/hash": "2.8.3", + "@parcel/logger": "2.8.3", + "@parcel/package-manager": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/types": "2.8.3", + "@parcel/utils": "2.8.3", + "@parcel/workers": "2.8.3", + "abortcontroller-polyfill": "^1.1.9", + "base-x": "^3.0.8", + "browserslist": "^4.6.6", + "clone": "^2.1.1", + "dotenv": "^7.0.0", + "dotenv-expand": "^5.1.0", + "json5": "^2.2.0", + "msgpackr": "^1.5.4", + "nullthrows": "^1.1.1", + "semver": "^5.7.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/diagnostic": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/diagnostic/-/diagnostic-2.8.3.tgz", + "integrity": "sha512-u7wSzuMhLGWZjVNYJZq/SOViS3uFG0xwIcqXw12w54Uozd6BH8JlhVtVyAsq9kqnn7YFkw6pXHqAo5Tzh4FqsQ==", + "dev": true, + "dependencies": { + "@mischnic/json-sourcemap": "^0.1.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/events": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/events/-/events-2.8.3.tgz", + "integrity": "sha512-hoIS4tAxWp8FJk3628bsgKxEvR7bq2scCVYHSqZ4fTi/s0+VymEATrRCUqf+12e5H47uw1/ZjoqrGtBI02pz4w==", + "dev": true, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/fs": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/fs/-/fs-2.8.3.tgz", + "integrity": "sha512-y+i+oXbT7lP0e0pJZi/YSm1vg0LDsbycFuHZIL80pNwdEppUAtibfJZCp606B7HOjMAlNZOBo48e3hPG3d8jgQ==", + "dev": true, + "dependencies": { + "@parcel/fs-search": "2.8.3", + "@parcel/types": "2.8.3", + "@parcel/utils": "2.8.3", + "@parcel/watcher": "^2.0.7", + "@parcel/workers": "2.8.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.8.3" + } + }, + "node_modules/@parcel/fs-search": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/fs-search/-/fs-search-2.8.3.tgz", + "integrity": "sha512-DJBT2N8knfN7Na6PP2mett3spQLTqxFrvl0gv+TJRp61T8Ljc4VuUTb0hqBj+belaASIp3Q+e8+SgaFQu7wLiQ==", + "dev": true, + "dependencies": { + "detect-libc": "^1.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/graph": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/graph/-/graph-2.8.3.tgz", + "integrity": "sha512-26GL8fYZPdsRhSXCZ0ZWliloK6DHlMJPWh6Z+3VVZ5mnDSbYg/rRKWmrkhnr99ZWmL9rJsv4G74ZwvDEXTMPBg==", + "dev": true, + "dependencies": { + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/hash": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/hash/-/hash-2.8.3.tgz", + "integrity": "sha512-FVItqzjWmnyP4ZsVgX+G00+6U2IzOvqDtdwQIWisCcVoXJFCqZJDy6oa2qDDFz96xCCCynjRjPdQx2jYBCpfYw==", + "dev": true, + "dependencies": { + "detect-libc": "^1.0.3", + "xxhash-wasm": "^0.4.2" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/logger": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/logger/-/logger-2.8.3.tgz", + "integrity": "sha512-Kpxd3O/Vs7nYJIzkdmB6Bvp3l/85ydIxaZaPfGSGTYOfaffSOTkhcW9l6WemsxUrlts4za6CaEWcc4DOvaMOPA==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/events": "2.8.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/markdown-ansi": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/markdown-ansi/-/markdown-ansi-2.8.3.tgz", + "integrity": "sha512-4v+pjyoh9f5zuU/gJlNvNFGEAb6J90sOBwpKJYJhdWXLZMNFCVzSigxrYO+vCsi8G4rl6/B2c0LcwIMjGPHmFQ==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/namer-default": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/namer-default/-/namer-default-2.8.3.tgz", + "integrity": "sha512-tJ7JehZviS5QwnxbARd8Uh63rkikZdZs1QOyivUhEvhN+DddSAVEdQLHGPzkl3YRk0tjFhbqo+Jci7TpezuAMw==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/plugin": "2.8.3", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/node-resolver-core": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/node-resolver-core/-/node-resolver-core-2.8.3.tgz", + "integrity": "sha512-12YryWcA5Iw2WNoEVr/t2HDjYR1iEzbjEcxfh1vaVDdZ020PiGw67g5hyIE/tsnG7SRJ0xdRx1fQ2hDgED+0Ww==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/utils": "2.8.3", + "nullthrows": "^1.1.1", + "semver": "^5.7.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/optimizer-css": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-css/-/optimizer-css-2.8.3.tgz", + "integrity": "sha512-JotGAWo8JhuXsQDK0UkzeQB0UR5hDAKvAviXrjqB4KM9wZNLhLleeEAW4Hk8R9smCeQFP6Xg/N/NkLDpqMwT3g==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.3", + "browserslist": "^4.6.6", + "lightningcss": "^1.16.1", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/optimizer-htmlnano": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-htmlnano/-/optimizer-htmlnano-2.8.3.tgz", + "integrity": "sha512-L8/fHbEy8Id2a2E0fwR5eKGlv9VYDjrH9PwdJE9Za9v1O/vEsfl/0T/79/x129l5O0yB6EFQkFa20MiK3b+vOg==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3", + "htmlnano": "^2.0.0", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "svgo": "^2.4.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/optimizer-image": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-image/-/optimizer-image-2.8.3.tgz", + "integrity": "sha512-SD71sSH27SkCDNUNx9A3jizqB/WIJr3dsfp+JZGZC42tpD/Siim6Rqy9M4To/BpMMQIIiEXa5ofwS+DgTEiEHQ==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "@parcel/workers": "2.8.3", + "detect-libc": "^1.0.3" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/optimizer-svgo": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-svgo/-/optimizer-svgo-2.8.3.tgz", + "integrity": "sha512-9KQed99NZnQw3/W4qBYVQ7212rzA9EqrQG019TIWJzkA9tjGBMIm2c/nXpK1tc3hQ3e7KkXkFCQ3C+ibVUnHNA==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "svgo": "^2.4.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/optimizer-terser": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/optimizer-terser/-/optimizer-terser-2.8.3.tgz", + "integrity": "sha512-9EeQlN6zIeUWwzrzu6Q2pQSaYsYGah8MtiQ/hog9KEPlYTP60hBv/+utDyYEHSQhL7y5ym08tPX5GzBvwAD/dA==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.3", + "nullthrows": "^1.1.1", + "terser": "^5.2.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/package-manager": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/package-manager/-/package-manager-2.8.3.tgz", + "integrity": "sha512-tIpY5pD2lH53p9hpi++GsODy6V3khSTX4pLEGuMpeSYbHthnOViobqIlFLsjni+QA1pfc8NNNIQwSNdGjYflVA==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/fs": "2.8.3", + "@parcel/logger": "2.8.3", + "@parcel/types": "2.8.3", + "@parcel/utils": "2.8.3", + "@parcel/workers": "2.8.3", + "semver": "^5.7.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.8.3" + } + }, + "node_modules/@parcel/packager-css": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/packager-css/-/packager-css-2.8.3.tgz", + "integrity": "sha512-WyvkMmsurlHG8d8oUVm7S+D+cC/T3qGeqogb7sTI52gB6uiywU7lRCizLNqGFyFGIxcVTVHWnSHqItBcLN76lA==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.3", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/packager-html": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/packager-html/-/packager-html-2.8.3.tgz", + "integrity": "sha512-OhPu1Hx1RRKJodpiu86ZqL8el2Aa4uhBHF6RAL1Pcrh2EhRRlPf70Sk0tC22zUpYL7es+iNKZ/n0Rl+OWSHWEw==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3", + "@parcel/types": "2.8.3", + "@parcel/utils": "2.8.3", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/packager-js": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/packager-js/-/packager-js-2.8.3.tgz", + "integrity": "sha512-0pGKC3Ax5vFuxuZCRB+nBucRfFRz4ioie19BbDxYnvBxrd4M3FIu45njf6zbBYsI9eXqaDnL1b3DcZJfYqtIzw==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/hash": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.3", + "globals": "^13.2.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/packager-raw": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/packager-raw/-/packager-raw-2.8.3.tgz", + "integrity": "sha512-BA6enNQo1RCnco9MhkxGrjOk59O71IZ9DPKu3lCtqqYEVd823tXff2clDKHK25i6cChmeHu6oB1Rb73hlPqhUA==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/packager-svg": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/packager-svg/-/packager-svg-2.8.3.tgz", + "integrity": "sha512-mvIoHpmv5yzl36OjrklTDFShLUfPFTwrmp1eIwiszGdEBuQaX7JVI3Oo2jbVQgcN4W7J6SENzGQ3Q5hPTW3pMw==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3", + "@parcel/types": "2.8.3", + "@parcel/utils": "2.8.3", + "posthtml": "^0.16.4" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/plugin": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/plugin/-/plugin-2.8.3.tgz", + "integrity": "sha512-jZ6mnsS4D9X9GaNnvrixDQwlUQJCohDX2hGyM0U0bY2NWU8Km97SjtoCpWjq+XBCx/gpC4g58+fk9VQeZq2vlw==", + "dev": true, + "dependencies": { + "@parcel/types": "2.8.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/reporter-cli": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/reporter-cli/-/reporter-cli-2.8.3.tgz", + "integrity": "sha512-3sJkS6tFFzgIOz3u3IpD/RsmRxvOKKiQHOTkiiqRt1l44mMDGKS7zANRnJYsQzdCsgwc9SOP30XFgJwtoVlMbw==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3", + "@parcel/types": "2.8.3", + "@parcel/utils": "2.8.3", + "chalk": "^4.1.0", + "term-size": "^2.2.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/reporter-dev-server": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/reporter-dev-server/-/reporter-dev-server-2.8.3.tgz", + "integrity": "sha512-Y8C8hzgzTd13IoWTj+COYXEyCkXfmVJs3//GDBsH22pbtSFMuzAZd+8J9qsCo0EWpiDow7V9f1LischvEh3FbQ==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/resolver-default": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/resolver-default/-/resolver-default-2.8.3.tgz", + "integrity": "sha512-k0B5M/PJ+3rFbNj4xZSBr6d6HVIe6DH/P3dClLcgBYSXAvElNDfXgtIimbjCyItFkW9/BfcgOVKEEIZOeySH/A==", + "dev": true, + "dependencies": { + "@parcel/node-resolver-core": "2.8.3", + "@parcel/plugin": "2.8.3" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/runtime-browser-hmr": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/runtime-browser-hmr/-/runtime-browser-hmr-2.8.3.tgz", + "integrity": "sha512-2O1PYi2j/Q0lTyGNV3JdBYwg4rKo6TEVFlYGdd5wCYU9ZIN9RRuoCnWWH2qCPj3pjIVtBeppYxzfVjPEHINWVg==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/runtime-js": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/runtime-js/-/runtime-js-2.8.3.tgz", + "integrity": "sha512-IRja0vNKwvMtPgIqkBQh0QtRn0XcxNC8HU1jrgWGRckzu10qJWO+5ULgtOeR4pv9krffmMPqywGXw6l/gvJKYQ==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/runtime-react-refresh": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/runtime-react-refresh/-/runtime-react-refresh-2.8.3.tgz", + "integrity": "sha512-2v/qFKp00MfG0234OdOgQNAo6TLENpFYZMbVbAsPMY9ITiqG73MrEsrGXVoGbYiGTMB/Toer/lSWlJxtacOCuA==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "react-error-overlay": "6.0.9", + "react-refresh": "^0.9.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/runtime-service-worker": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/runtime-service-worker/-/runtime-service-worker-2.8.3.tgz", + "integrity": "sha512-/Skkw+EeRiwzOJso5fQtK8c9b452uWLNhQH1ISTodbmlcyB4YalAiSsyHCtMYD0c3/t5Sx4ZS7vxBAtQd0RvOw==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/source-map": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@parcel/source-map/-/source-map-2.1.1.tgz", + "integrity": "sha512-Ejx1P/mj+kMjQb8/y5XxDUn4reGdr+WyKYloBljpppUy8gs42T+BNoEOuRYqDVdgPc6NxduzIDoJS9pOFfV5Ew==", + "dev": true, + "dependencies": { + "detect-libc": "^1.0.3" + }, + "engines": { + "node": "^12.18.3 || >=14" + } + }, + "node_modules/@parcel/transformer-babel": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-babel/-/transformer-babel-2.8.3.tgz", + "integrity": "sha512-L6lExfpvvC7T/g3pxf3CIJRouQl+sgrSzuWQ0fD4PemUDHvHchSP4SNUVnd6gOytF3Y1KpnEZIunQGi5xVqQCQ==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.3", + "browserslist": "^4.6.6", + "json5": "^2.2.0", + "nullthrows": "^1.1.1", + "semver": "^5.7.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-css": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-css/-/transformer-css-2.8.3.tgz", + "integrity": "sha512-xTqFwlSXtnaYen9ivAgz+xPW7yRl/u4QxtnDyDpz5dr8gSeOpQYRcjkd4RsYzKsWzZcGtB5EofEk8ayUbWKEUg==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.3", + "browserslist": "^4.6.6", + "lightningcss": "^1.16.1", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-html": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-html/-/transformer-html-2.8.3.tgz", + "integrity": "sha512-kIZO3qsMYTbSnSpl9cnZog+SwL517ffWH54JeB410OSAYF1ouf4n5v9qBnALZbuCCmPwJRGs4jUtE452hxwN4g==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/hash": "2.8.3", + "@parcel/plugin": "2.8.3", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", + "semver": "^5.7.1", + "srcset": "4" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-image": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-image/-/transformer-image-2.8.3.tgz", + "integrity": "sha512-cO4uptcCGTi5H6bvTrAWEFUsTNhA4kCo8BSvRSCHA2sf/4C5tGQPHt3JhdO0GQLPwZRCh/R41EkJs5HZ8A8DAg==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "@parcel/workers": "2.8.3", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "peerDependencies": { + "@parcel/core": "^2.8.3" + } + }, + "node_modules/@parcel/transformer-js": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-js/-/transformer-js-2.8.3.tgz", + "integrity": "sha512-9Qd6bib+sWRcpovvzvxwy/PdFrLUXGfmSW9XcVVG8pvgXsZPFaNjnNT8stzGQj1pQiougCoxMY4aTM5p1lGHEQ==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/utils": "2.8.3", + "@parcel/workers": "2.8.3", + "@swc/helpers": "^0.4.12", + "browserslist": "^4.6.6", + "detect-libc": "^1.0.3", + "nullthrows": "^1.1.1", + "regenerator-runtime": "^0.13.7", + "semver": "^5.7.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.8.3" + } + }, + "node_modules/@parcel/transformer-json": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-json/-/transformer-json-2.8.3.tgz", + "integrity": "sha512-B7LmVq5Q7bZO4ERb6NHtRuUKWGysEeaj9H4zelnyBv+wLgpo4f5FCxSE1/rTNmP9u1qHvQ3scGdK6EdSSokGPg==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3", + "json5": "^2.2.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-postcss": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-postcss/-/transformer-postcss-2.8.3.tgz", + "integrity": "sha512-e8luB/poIlz6jBsD1Izms+6ElbyzuoFVa4lFVLZnTAChI3UxPdt9p/uTsIO46HyBps/Bk8ocvt3J4YF84jzmvg==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/hash": "2.8.3", + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "clone": "^2.1.1", + "nullthrows": "^1.1.1", + "postcss-value-parser": "^4.2.0", + "semver": "^5.7.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-posthtml": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-posthtml/-/transformer-posthtml-2.8.3.tgz", + "integrity": "sha512-pkzf9Smyeaw4uaRLsT41RGrPLT5Aip8ZPcntawAfIo+KivBQUV0erY1IvHYjyfFzq1ld/Fo2Ith9He6mxpPifA==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", + "semver": "^5.7.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-raw": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-raw/-/transformer-raw-2.8.3.tgz", + "integrity": "sha512-G+5cXnd2/1O3nV/pgRxVKZY/HcGSseuhAe71gQdSQftb8uJEURyUHoQ9Eh0JUD3MgWh9V+nIKoyFEZdf9T0sUQ==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-react-refresh-wrap": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-react-refresh-wrap/-/transformer-react-refresh-wrap-2.8.3.tgz", + "integrity": "sha512-q8AAoEvBnCf/nPvgOwFwKZfEl/thwq7c2duxXkhl+tTLDRN2vGmyz4355IxCkavSX+pLWSQ5MexklSEeMkgthg==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3", + "@parcel/utils": "2.8.3", + "react-refresh": "^0.9.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-sass": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-sass/-/transformer-sass-2.8.3.tgz", + "integrity": "sha512-ak196rjvXdsBOGi5aTkBEKv6i4LKQgOkHuaKEjeT8g2a3CU6Z36J+j2GbZzsznfws/hH+CRTf8bAsbkxtKlkjQ==", + "dev": true, + "dependencies": { + "@parcel/plugin": "2.8.3", + "@parcel/source-map": "^2.1.1", + "sass": "^1.38.0" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/transformer-svg": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/transformer-svg/-/transformer-svg-2.8.3.tgz", + "integrity": "sha512-3Zr/gBzxi1ZH1fftH/+KsZU7w5GqkmxlB0ZM8ovS5E/Pl1lq1t0xvGJue9m2VuQqP8Mxfpl5qLFmsKlhaZdMIQ==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/hash": "2.8.3", + "@parcel/plugin": "2.8.3", + "nullthrows": "^1.1.1", + "posthtml": "^0.16.5", + "posthtml-parser": "^0.10.1", + "posthtml-render": "^3.0.0", + "semver": "^5.7.1" + }, + "engines": { + "node": ">= 12.0.0", + "parcel": "^2.8.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/types": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/types/-/types-2.8.3.tgz", + "integrity": "sha512-FECA1FB7+0UpITKU0D6TgGBpGxYpVSMNEENZbSJxFSajNy3wrko+zwBKQmFOLOiPcEtnGikxNs+jkFWbPlUAtw==", + "dev": true, + "dependencies": { + "@parcel/cache": "2.8.3", + "@parcel/diagnostic": "2.8.3", + "@parcel/fs": "2.8.3", + "@parcel/package-manager": "2.8.3", + "@parcel/source-map": "^2.1.1", + "@parcel/workers": "2.8.3", + "utility-types": "^3.10.0" + } + }, + "node_modules/@parcel/utils": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/utils/-/utils-2.8.3.tgz", + "integrity": "sha512-IhVrmNiJ+LOKHcCivG5dnuLGjhPYxQ/IzbnF2DKNQXWBTsYlHkJZpmz7THoeLtLliGmSOZ3ZCsbR8/tJJKmxjA==", + "dev": true, + "dependencies": { + "@parcel/codeframe": "2.8.3", + "@parcel/diagnostic": "2.8.3", + "@parcel/hash": "2.8.3", + "@parcel/logger": "2.8.3", + "@parcel/markdown-ansi": "2.8.3", + "@parcel/source-map": "^2.1.1", + "chalk": "^4.1.0" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.1.0.tgz", + "integrity": "sha512-8s8yYjd19pDSsBpbkOHnT6Z2+UJSuLQx61pCFM0s5wSRvKCEMDjd/cHY3/GI1szHIWbpXpsJdg3V6ISGGx9xDw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^3.2.1", + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/workers": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@parcel/workers/-/workers-2.8.3.tgz", + "integrity": "sha512-+AxBnKgjqVpUHBcHLWIHcjYgKIvHIpZjN33mG5LG9XXvrZiqdWvouEzqEXlVLq5VzzVbKIQQcmsvRy138YErkg==", + "dev": true, + "dependencies": { + "@parcel/diagnostic": "2.8.3", + "@parcel/logger": "2.8.3", + "@parcel/types": "2.8.3", + "@parcel/utils": "2.8.3", + "chrome-trace-event": "^1.0.2", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "peerDependencies": { + "@parcel/core": "^2.8.3" + } + }, + "node_modules/@swc/helpers": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "dev": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/abortcontroller-polyfill": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz", + "integrity": "sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001460", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001460.tgz", + "integrity": "sha512-Bud7abqjvEjipUkpLs4D7gR0l8hBYBHoa+tGtKJHvT2AYzLp1z7EmVkUT4ERpVUfca8S2HGIVs883D8pUH1ZzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dev": true, + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dotenv": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz", + "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.320", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.320.tgz", + "integrity": "sha512-h70iRscrNluMZPVICXYl5SSB+rBKo22XfuIS1ER0OQxQZpKTnFpuS6coj7wY9M/3trv7OR88rRMOlKmRvDty7Q==", + "dev": true + }, + "node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-port": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-4.2.0.tgz", + "integrity": "sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/htmlnano": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/htmlnano/-/htmlnano-2.0.3.tgz", + "integrity": "sha512-S4PGGj9RbdgW8LhbILNK7W9JhmYP8zmDY7KDV/8eCiJBQJlbmltp5I0gv8c5ntLljfdxxfmJ+UJVSqyH4mb41A==", + "dev": true, + "dependencies": { + "cosmiconfig": "^7.0.1", + "posthtml": "^0.16.5", + "timsort": "^0.3.0" + }, + "peerDependencies": { + "cssnano": "^5.0.11", + "postcss": "^8.3.11", + "purgecss": "^5.0.0", + "relateurl": "^0.2.7", + "srcset": "4.0.0", + "svgo": "^2.8.0", + "terser": "^5.10.0", + "uncss": "^0.17.3" + }, + "peerDependenciesMeta": { + "cssnano": { + "optional": true + }, + "postcss": { + "optional": true + }, + "purgecss": { + "optional": true + }, + "relateurl": { + "optional": true + }, + "srcset": { + "optional": true + }, + "svgo": { + "optional": true + }, + "terser": { + "optional": true + }, + "uncss": { + "optional": true + } + } + }, + "node_modules/htmlparser2": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", + "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.2", + "domutils": "^2.8.0", + "entities": "^3.0.1" + } + }, + "node_modules/immutable": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.4.tgz", + "integrity": "sha512-WDxL3Hheb1JkRN3sQkyujNlL/xRjAo3rJtaU5xeufUauG66JdMr32bLj4gF+vWl84DIA3Zxw7tiAjneYzRRw+w==", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-json": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-json/-/is-json-2.0.1.tgz", + "integrity": "sha512-6BEnpVn1rcf3ngfmViLM6vjUjGErbdrL4rwlv+u1NO1XO8kqT4YGL8+19Q+Z/bas8tY90BTWMk2+fW1g6hQjbA==", + "dev": true + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lightningcss": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.19.0.tgz", + "integrity": "sha512-yV5UR7og+Og7lQC+70DA7a8ta1uiOPnWPJfxa0wnxylev5qfo4P+4iMpzWAdYWOca4jdNQZii+bDL/l+4hUXIA==", + "dev": true, + "dependencies": { + "detect-libc": "^1.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.19.0", + "lightningcss-darwin-x64": "1.19.0", + "lightningcss-linux-arm-gnueabihf": "1.19.0", + "lightningcss-linux-arm64-gnu": "1.19.0", + "lightningcss-linux-arm64-musl": "1.19.0", + "lightningcss-linux-x64-gnu": "1.19.0", + "lightningcss-linux-x64-musl": "1.19.0", + "lightningcss-win32-x64-msvc": "1.19.0" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.19.0.tgz", + "integrity": "sha512-wIJmFtYX0rXHsXHSr4+sC5clwblEMji7HHQ4Ub1/CznVRxtCFha6JIt5JZaNf8vQrfdZnBxLLC6R8pC818jXqg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.19.0.tgz", + "integrity": "sha512-Lif1wD6P4poaw9c/4Uh2z+gmrWhw/HtXFoeZ3bEsv6Ia4tt8rOJBdkfVaUJ6VXmpKHALve+iTyP2+50xY1wKPw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.19.0.tgz", + "integrity": "sha512-P15VXY5682mTXaiDtbnLYQflc8BYb774j2R84FgDLJTN6Qp0ZjWEFyN1SPqyfTj2B2TFjRHRUvQSSZ7qN4Weig==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.19.0.tgz", + "integrity": "sha512-zwXRjWqpev8wqO0sv0M1aM1PpjHz6RVIsBcxKszIG83Befuh4yNysjgHVplF9RTU7eozGe3Ts7r6we1+Qkqsww==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.19.0.tgz", + "integrity": "sha512-vSCKO7SDnZaFN9zEloKSZM5/kC5gbzUjoJQ43BvUpyTFUX7ACs/mDfl2Eq6fdz2+uWhUh7vf92c4EaaP4udEtA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.19.0.tgz", + "integrity": "sha512-0AFQKvVzXf9byrXUq9z0anMGLdZJS+XSDqidyijI5njIwj6MdbvX2UZK/c4FfNmeRa2N/8ngTffoIuOUit5eIQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.19.0.tgz", + "integrity": "sha512-SJoM8CLPt6ECCgSuWe+g0qo8dqQYVcPiW2s19dxkmSI5+Uu1GIRzyKA0b7QqmEXolA+oSJhQqCmJpzjY4CuZAg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.19.0.tgz", + "integrity": "sha512-C+VuUTeSUOAaBZZOPT7Etn/agx/MatzJzGRkeV+zEABmPuntv1zihncsi+AyGmjkkzq3wVedEy7h0/4S84mUtg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/lmdb": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-2.5.2.tgz", + "integrity": "sha512-V5V5Xa2Hp9i2XsbDALkBTeHXnBXh/lEmk9p22zdr7jtuOIY9TGhjK6vAvTpOOx9IKU4hJkRWZxn/HsvR1ELLtA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "msgpackr": "^1.5.4", + "node-addon-api": "^4.3.0", + "node-gyp-build-optional-packages": "5.0.3", + "ordered-binary": "^1.2.4", + "weak-lru-cache": "^1.2.2" + }, + "optionalDependencies": { + "@lmdb/lmdb-darwin-arm64": "2.5.2", + "@lmdb/lmdb-darwin-x64": "2.5.2", + "@lmdb/lmdb-linux-arm": "2.5.2", + "@lmdb/lmdb-linux-arm64": "2.5.2", + "@lmdb/lmdb-linux-x64": "2.5.2", + "@lmdb/lmdb-win32-x64": "2.5.2" + } + }, + "node_modules/lmdb/node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "dev": true + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/msgpackr": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.8.4.tgz", + "integrity": "sha512-BE3hD3PqV7jsNaV022uq0jMW+ZVc32wSYyQmwAoJUc+vPtCeyro2MOtAW61Fd9ZKNySM6y913E9fBY0mG+hKXg==", + "dev": true, + "optionalDependencies": { + "msgpackr-extract": "^3.0.1" + } + }, + "node_modules/msgpackr-extract": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.2.tgz", + "integrity": "sha512-SdzXp4kD/Qf8agZ9+iTu6eql0m3kWm1A2y1hkpTeVNENutaB0BwHlSvAIaMxwntmRUAUjon2V4L8Z/njd0Ct8A==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.0.7" + }, + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.2", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.2" + } + }, + "node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz", + "integrity": "sha512-YlCCc6Wffkx0kHkmam79GKvDQ6x+QZkMjFGrIMxgFNILFvGSbCp2fCBC55pGTT9gVaz8Na5CLmxt/urtzRv36w==", + "dev": true, + "optional": true, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, + "node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true + }, + "node_modules/node-gyp-build": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", + "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-gyp-build-optional-packages": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.3.tgz", + "integrity": "sha512-k75jcVzk5wnnc/FMxsf4udAoTEUv2jY3ycfdSd3yWu6Cnd1oee6/CfZJApyscA4FJOmdoixWwiwOyf16RzD5JA==", + "dev": true, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, + "node_modules/node-releases": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", + "dev": true + }, + "node_modules/ordered-binary": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.4.0.tgz", + "integrity": "sha512-EHQ/jk4/a9hLupIKxTfUsQRej1Yd/0QLQs3vGvIqg5ZtCYSzNhkzHoZc7Zf4e4kUlDaC3Uw8Q/1opOLNN2OKRQ==", + "dev": true + }, + "node_modules/parcel": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/parcel/-/parcel-2.8.3.tgz", + "integrity": "sha512-5rMBpbNE72g6jZvkdR5gS2nyhwIXaJy8i65osOqs/+5b7zgf3eMKgjSsDrv6bhz3gzifsba6MBJiZdBckl+vnA==", + "dev": true, + "dependencies": { + "@parcel/config-default": "2.8.3", + "@parcel/core": "2.8.3", + "@parcel/diagnostic": "2.8.3", + "@parcel/events": "2.8.3", + "@parcel/fs": "2.8.3", + "@parcel/logger": "2.8.3", + "@parcel/package-manager": "2.8.3", + "@parcel/reporter-cli": "2.8.3", + "@parcel/reporter-dev-server": "2.8.3", + "@parcel/utils": "2.8.3", + "chalk": "^4.1.0", + "commander": "^7.0.0", + "get-port": "^4.2.0", + "v8-compile-cache": "^2.0.0" + }, + "bin": { + "parcel": "lib/bin.js" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/posthtml": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.16.6.tgz", + "integrity": "sha512-JcEmHlyLK/o0uGAlj65vgg+7LIms0xKXe60lcDOTU7oVX/3LuEuLwrQpW3VJ7de5TaFKiW4kWkaIpJL42FEgxQ==", + "dev": true, + "dependencies": { + "posthtml-parser": "^0.11.0", + "posthtml-render": "^3.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/posthtml-parser": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.10.2.tgz", + "integrity": "sha512-PId6zZ/2lyJi9LiKfe+i2xv57oEjJgWbsHGGANwos5AvdQp98i6AtamAl8gzSVFGfQ43Glb5D614cvZf012VKg==", + "dev": true, + "dependencies": { + "htmlparser2": "^7.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/posthtml-render": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-3.0.0.tgz", + "integrity": "sha512-z+16RoxK3fUPgwaIgH9NGnK1HKY9XIDpydky5eQGgAFVXTCSezalv9U2jQuNV+Z9qV1fDWNzldcw4eK0SSbqKA==", + "dev": true, + "dependencies": { + "is-json": "^2.0.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/posthtml/node_modules/posthtml-parser": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.11.0.tgz", + "integrity": "sha512-QecJtfLekJbWVo/dMAA+OSwY79wpRmbqS5TeXvXSX+f0c6pW4/SE6inzZ2qkU7oAMCPqIDkZDvd/bQsSFUnKyw==", + "dev": true, + "dependencies": { + "htmlparser2": "^7.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-error-overlay": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz", + "integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==", + "dev": true + }, + "node_modules/react-refresh": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.9.0.tgz", + "integrity": "sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "dev": true + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/sass": { + "version": "1.58.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.3.tgz", + "integrity": "sha512-Q7RaEtYf6BflYrQ+buPudKR26/lH+10EmO9bBqbmPh/KeLqv8bjpTNqxe71ocONqXq+jYiCbpPUmQMS+JJPk4A==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/srcset": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz", + "integrity": "sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", + "dev": true + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dev": true, + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/term-size": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", + "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.5.tgz", + "integrity": "sha512-qcwfg4+RZa3YvlFh0qjifnzBHjKGNbtDo9yivMqMFDy9Q6FSaQWSB/j1xKhsoUFJIqDOM3TsN6D5xbrMrFcHbg==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/utility-types": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", + "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/weak-lru-cache": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", + "integrity": "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==", + "dev": true + }, + "node_modules/xxhash-wasm": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-0.4.2.tgz", + "integrity": "sha512-/eyHVRJQCirEkSZ1agRSCwriMhwlyUcFkXD5TPVSLP+IPzjsqMVzZwdoczLp1SoQU0R3dxz1RpIK+4YNQbCVOA==", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + } + } +} diff --git a/ui/ftp/package.json b/ui/ftp/package.json new file mode 100644 index 0000000..cb1692f --- /dev/null +++ b/ui/ftp/package.json @@ -0,0 +1,20 @@ +{ + "name": "ftp", + "version": "1.0.0", + "description": "FTP Frontend for MPYLAB", + "source": "index.html", + "scripts": { + "start": "parcel", + "dev": "parcel watch --public-url ./", + "build": "parcel build --public-url ./" + }, + "devDependencies": { + "@parcel/transformer-sass": "^2.8.3", + "parcel": "latest", + "process": "^0.11.10" + }, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + } +} From 8dc5027380c93842aeda066a81ebc8bb64040d9d Mon Sep 17 00:00:00 2001 From: Murilo Polese Date: Tue, 4 Apr 2023 00:21:21 +0200 Subject: [PATCH 2/9] Navigating, selecting multiple files and file management --- preload.js | 17 +- ui/ftp/components/files/diskFiles.tsx | 28 +- ui/ftp/components/files/diskFiles.type.ts | 11 +- ui/ftp/components/files/fileManagement.tsx | 16 + .../components/files/fileManagement.type.ts | 7 + ui/ftp/components/files/management.type.ts | 7 - ui/ftp/components/files/serialFiles.tsx | 34 +- ui/ftp/components/files/serialFiles.type.ts | 4 +- ui/ftp/components/shared/breadcrumbs.tsx | 34 +- ui/ftp/main.logic.ts | 311 ++++++++++-------- ui/ftp/main.scss | 43 ++- ui/ftp/main.tsx | 36 +- 12 files changed, 353 insertions(+), 195 deletions(-) create mode 100644 ui/ftp/components/files/fileManagement.tsx create mode 100644 ui/ftp/components/files/fileManagement.type.ts delete mode 100644 ui/ftp/components/files/management.type.ts diff --git a/preload.js b/preload.js index b1ef2fd..1e413f5 100644 --- a/preload.js +++ b/preload.js @@ -47,9 +47,8 @@ const Serial = { onData: (fn) => { board.serial.on('data', fn) }, - listFiles: async () => { - const output = await board.fs_ls() - return output + listFiles: async (folder) => { + return await board.fs_ls(folder) }, loadFile: async (file) => { const output = await board.fs_cat(file) @@ -61,14 +60,14 @@ const Serial = { saveFileContent: async (filename, content) => { return board.fs_save(content || ' ', filename) }, - uploadFile: async (folder, filename) => { - let src = `${folder}/${filename}` - let dest = filename + uploadFile: async (diskPath, serialPath, filename) => { + let src = `${diskPath}/${filename}` + let dest = `${serialPath}/${filename}` return board.fs_put(src, dest) }, - downloadFile: async (folder, filename) => { - let contents = await Serial.loadFile(filename) - return ipcRenderer.invoke('save-file', folder, filename, contents) + downloadFile: async (serialPath, diskPath, filename) => { + let contents = await Serial.loadFile(serialPath + '/' + filename) + return ipcRenderer.invoke('save-file', diskPath, filename, contents) }, renameFile: async (oldName, newName) => { return board.fs_rename(oldName, newName) diff --git a/ui/ftp/components/files/diskFiles.tsx b/ui/ftp/components/files/diskFiles.tsx index 682840d..0a43d32 100644 --- a/ui/ftp/components/files/diskFiles.tsx +++ b/ui/ftp/components/files/diskFiles.tsx @@ -1,16 +1,30 @@ import React from 'react' import DiskFilesType from './diskFiles.type.ts' import Button from '../shared/button.tsx' +import { Device } from '../../main.type' -const DiskFiles: React.FC = ({ diskFilesLogic }) => { - const { diskFiles = [], navigate }: DiskFilesType = diskFilesLogic() - const onClick = (folder) => () => { - navigate(folder) - } +const DiskFiles: React.FC = ({ diskFilesLogic }) => { + const { + diskPath, + selectedFiles = [], + diskFiles = [], + navigate, + selectFile + } : DiskFilesType = diskFilesLogic() + const onNavigate = (folder) => () => navigate([diskPath,folder].join('/')) + const onSelect = (folder) => () => selectFile([diskPath,folder].join('/')) const files = diskFiles.map((folder, i) => { - return
  • + const checked = selectedFiles + .filter(f => f.device === Device.disk) + .find(f => f.path === [diskPath,folder].join('/')) + return ( +
  • + + +
  • + ) }) return
      {files}
    } -export default DiskFiles \ No newline at end of file +export default DiskFiles diff --git a/ui/ftp/components/files/diskFiles.type.ts b/ui/ftp/components/files/diskFiles.type.ts index cf38a69..2f09c16 100644 --- a/ui/ftp/components/files/diskFiles.type.ts +++ b/ui/ftp/components/files/diskFiles.type.ts @@ -1,8 +1,9 @@ type DiskFilesType = () => { - diskFiles: String[] - // selectedFile: File - navigate: (folder : String) => void - selectFile: (path: String) => void + diskPath: string, + diskFiles: string[] + selectedFiles: File[] + navigate: (folder : string) => void + selectFile: (path: string) => void } -export default DiskFilesType \ No newline at end of file +export default DiskFilesType diff --git a/ui/ftp/components/files/fileManagement.tsx b/ui/ftp/components/files/fileManagement.tsx new file mode 100644 index 0000000..e80d1cc --- /dev/null +++ b/ui/ftp/components/files/fileManagement.tsx @@ -0,0 +1,16 @@ +import React from 'react' +import FileManagementType from './fileManagement.type' +import Button from '../shared/button.tsx' + +const FileManagement: React.FC = ({ fileManagementLogic }) => { + const { upload, download, remove }: FileManagementType = fileManagementLogic() + return ( +
      +
    • +
    • +
    • +
    + ) +} + +export default FileManagement diff --git a/ui/ftp/components/files/fileManagement.type.ts b/ui/ftp/components/files/fileManagement.type.ts new file mode 100644 index 0000000..f1200d0 --- /dev/null +++ b/ui/ftp/components/files/fileManagement.type.ts @@ -0,0 +1,7 @@ +type FileManagementType = () => { + upload: () => void + download: () => void + remove: () => void +} + +export default FileManagementType diff --git a/ui/ftp/components/files/management.type.ts b/ui/ftp/components/files/management.type.ts deleted file mode 100644 index 5dd88ff..0000000 --- a/ui/ftp/components/files/management.type.ts +++ /dev/null @@ -1,7 +0,0 @@ -type FileManagementType = () => { - upload: (diskPath: String, serialPath: String) => void - download: (serialPath: String, diskPath: String) => void - remove: () => void -} - -export default FileManagementType \ No newline at end of file diff --git a/ui/ftp/components/files/serialFiles.tsx b/ui/ftp/components/files/serialFiles.tsx index 23c9724..5ff8d9f 100644 --- a/ui/ftp/components/files/serialFiles.tsx +++ b/ui/ftp/components/files/serialFiles.tsx @@ -1,16 +1,30 @@ import React from 'react' import SerialFilesType from './serialFiles.type.ts' import Button from '../shared/button.tsx' +import { Device } from '../../main.type' -const SerialFiles: React.FC = ({ serialFilesLogic }) => { - const { serialFiles = [], navigate }: SerialFilesType = serialFilesLogic() - const onClick = (folder) => () => { - navigate(folder) - } - const files = serialFiles.map((folder, i) => { - return
  • - }) - return
      {files}
    +const SerialFiles: React.FC = ({ serialFilesLogic }) => { + const { + serialPath, + selectedFiles = [], + serialFiles = [], + navigate, + selectFile + } : SerialFilesType = serialFilesLogic() + const onNavigate = (folder) => () => navigate([serialPath,folder].join('/')) + const onSelect = (folder) => () => selectFile([serialPath,folder].join('/')) + const files = serialFiles.map((folder, i) => { + const checked = selectedFiles + .filter(f => f.device === Device.serial) + .find(f => f.path === [serialPath,folder].join('/')) + return ( +
  • + + +
  • + ) + }) + return
      {files}
    } -export default SerialFiles \ No newline at end of file +export default SerialFiles diff --git a/ui/ftp/components/files/serialFiles.type.ts b/ui/ftp/components/files/serialFiles.type.ts index 93bc68b..74809c0 100644 --- a/ui/ftp/components/files/serialFiles.type.ts +++ b/ui/ftp/components/files/serialFiles.type.ts @@ -1,8 +1,8 @@ type SerialFilesType = () => { serialFiles: String[] - selectedFile: File + selectedFiles: File[] navigate: (folder : String) => void selectFile: (path: String) => void } -export default SerialFilesType \ No newline at end of file +export default SerialFilesType diff --git a/ui/ftp/components/shared/breadcrumbs.tsx b/ui/ftp/components/shared/breadcrumbs.tsx index f42d966..1ae240d 100644 --- a/ui/ftp/components/shared/breadcrumbs.tsx +++ b/ui/ftp/components/shared/breadcrumbs.tsx @@ -3,19 +3,27 @@ import Button from './button.tsx' import styles from './breadcrumbs.module.scss' const BreadCrumbs: React.FC = ({ path, navigate }) => { - if (!path) return <> - const pathArray = path.split('/') - const onClick = (folder) => () => { - navigate(folder) - } - const items = pathArray.map( - (folder, i) => ( - - / - - ) + if (!path) return <> + const pathArray = path.split('/') + const crumbs = pathArray.filter(crumb => crumb != '') + + const onClick = (i) => () => { + const newPath = '/' + crumbs.slice(0, i+1).join('/') + navigate(newPath) + } + const items = crumbs.map( + (folder, i) => ( + + + ) - return
    {items}
    + ) + return ( +
    + + {items} +
    + ) } -export default BreadCrumbs \ No newline at end of file +export default BreadCrumbs diff --git a/ui/ftp/main.logic.ts b/ui/ftp/main.logic.ts index 5c511d7..b54962f 100644 --- a/ui/ftp/main.logic.ts +++ b/ui/ftp/main.logic.ts @@ -5,160 +5,211 @@ import DiskNavigationType from './components/navigation/diskNavigation.type' import DiskFilesType from './components/files/diskFiles.type' import SerialNavigationType from './components/navigation/serialNavigation.type' import SerialFilesType from './components/files/serialFiles.type' -import FileManagementType from './components/files/management.type' +import FileManagementType from './components/files/fileManagement.type' import { Device, File } from './main.type' export type UseMainLogic = () => { - toolbarLogic: ToolbarType - diskNavigationLogic: DiskNavigationType - diskFilesLogic: DiskFilesType - serialNavigationLogic: SerialNavigationType - serialFilesLogic: SerialFilesType - fileManagementLogic: FileManagementType + toolbarLogic: ToolbarType + diskNavigationLogic: DiskNavigationType + diskFilesLogic: DiskFilesType + serialNavigationLogic: SerialNavigationType + serialFilesLogic: SerialFilesType + fileManagementLogic: FileManagementType } export const useMainLogic : UseMainLogic = function() : ReturnType { - const { BridgeSerial, BridgeDisk } = window - // List and connect to serial devices - const [ availableDevices, setAvailableDevices ] = useState() - const [ connectedDevice, setConnectedDevice ] = useState() - // Navigation paths - const [ serialPath, setSerialPath ] = useState() - const [ diskPath, setDiskPath ] = useState() - // Available files (listed) - const [ diskFiles, setDiskFiles ] = useState() - const [ serialFiles, setSerialFiles ] = useState() - // Selected file - const [ selectedFile, setSelectedFile ] = useState() - // Progress - const [ waiting, setWaiting ] = useState() + const { BridgeSerial, BridgeDisk } = window + // List and connect to serial devices + const [ availableDevices, setAvailableDevices ] = useState() + const [ connectedDevice, setConnectedDevice ] = useState() + // Navigation paths + const [ serialPath, setSerialPath ] = useState() + const [ diskPath, setDiskPath ] = useState() + // Available files (listed) + const [ diskFiles, setDiskFiles ] = useState() + const [ serialFiles, setSerialFiles ] = useState() + // Selected files + const [ selectedFiles = [], setSelectedFiles ] = useState() + // Progress + const [ waiting, setWaiting ] = useState() - // HELPERS - const navigateDisk = async (folder) => { - const pathArray = diskPath.split('/') - const folderIndex = pathArray.indexOf(folder) - let newPathArray = [] - if (folderIndex === -1) { - newPathArray = pathArray.concat(folder) - } else { - newPathArray = pathArray.slice(0, folderIndex+1) - } - const newPath = newPathArray.join('/') - const files = await BridgeDisk.listFiles(newPath) - setDiskPath(newPath) - setDiskFiles(files) - } + // HELPERS + const navigateDisk = async (newPath) => { + const files = await BridgeDisk.listFiles(newPath) + setDiskPath(newPath) + setDiskFiles(files) + const newSelection = selectedFiles.filter(f => f.device !== Device.disk) + setSelectedFiles(newSelection) + } - const navigateSerial = async (folder) => { - const pathArray = serialPath.split('/') - const folderIndex = pathArray.indexOf(folder) - let newPathArray = [] - if (folderIndex === -1) { - newPathArray = pathArray.concat(folder) - } else { - newPathArray = pathArray.slice(0, folderIndex+1) - } - const newPath = newPathArray.join('/') - const files = await BridgeSerial.listFiles(newPath) - setSerialPath(newPath) + const navigateSerial = async (newPath) => { + const files = await BridgeSerial.listFiles(newPath) + setSerialPath(newPath) + setSerialFiles(files) + const newSelection = selectedFiles.filter(f => f.device !== Device.serial) + setSelectedFiles(newSelection) + } + + // LOGIC + const refresh = async () => { + // list available devices + const devices = await BridgeSerial.loadPorts() + setAvailableDevices(devices) + // list serial files + if (connectedDevice) { + const files = await BridgeSerial.listFiles(serialPath) + setSerialFiles(files) + } + // list disk files + if (diskPath) { + const files = await BridgeDisk.listFiles(diskPath) + setDiskFiles(files) + } + } + const toolbarLogic = () : ReturnType => { + return { + availableDevices: availableDevices, + connectedDevice: connectedDevice, + connect: async (devicePath: String) => { + await BridgeSerial.connect(devicePath) + setConnectedDevice(devicePath) + setSerialPath('/') + const files = await BridgeSerial.listFiles('/') setSerialFiles(files) + }, + disconnect: () => { + setConnectedDevice(null) + setSerialPath(null) + }, + openFolder: async () => { + const { folder, files } = await BridgeDisk.openFolder() + setDiskPath(folder) + setDiskFiles(files) + }, + refresh: refresh } + } - // LOGIC - const toolbarLogic = () : ReturnType => { - return { - availableDevices: availableDevices, - connectedDevice: connectedDevice, - connect: async (devicePath: String) => { - await BridgeSerial.connect(devicePath) - setConnectedDevice(devicePath) - setSerialPath('/') - }, - disconnect: () => { - setConnectedDevice(null) - setSerialPath(null) - }, - openFolder: async () => { - const { folder, files } = await BridgeDisk.openFolder() - setDiskPath(folder) - setDiskFiles(files) - }, - refresh: async () => { - // list available devices - const devices = await BridgeSerial.loadPorts() - setAvailableDevices(devices) - // list serial files - if (connectedDevice) { - const files = await BridgeSerial.listFiles(serialPath) - setSerialFiles(files) - } - // list disk files - if (diskPath) { - const files = await BridgeDisk.listFiles(diskPath) - setDiskFiles(files) - } - } - } + const diskNavigationLogic = () : ReturnType => { + return { + diskPath: diskPath, + navigate: navigateDisk } + } - const diskNavigationLogic = () : ReturnType => { - return { - diskPath: diskPath, - navigate: navigateDisk + const diskFilesLogic = () : ReturnType => { + return { + diskPath: diskPath, + diskFiles: diskFiles, + selectedFiles: selectedFiles, + navigate: navigateDisk, + selectFile: (path) => { + const diskFilesOnly = selectedFiles.filter(f => f.device === Device.disk) + const selected = diskFilesOnly.find(f => f.path === path) + if (selected) { + let newSelection = diskFilesOnly.filter(f => f.path !== path) + setSelectedFiles(newSelection) + } else { + let file = { + path: path, + device: Device.disk + } + diskFilesOnly.push(file) + setSelectedFiles(diskFilesOnly.slice()) } + } } + } - const diskFilesLogic = () : ReturnType => { - return { - diskFiles: diskFiles, - // selectedFile: selectedFile, - navigate: navigateDisk, - selectFile: (path) => { - setSelectedFile({ - path: path, - device: Device.disk - }) - } - } + const serialNavigationLogic = () : ReturnType => { + return { + serialPath: serialPath, + navigate: navigateSerial } + } - const serialNavigationLogic = () : ReturnType => { - return { - serialPath: serialPath, - navigate: navigateSerial + const serialFilesLogic = () : ReturnType => { + return { + serialPath: serialPath, + serialFiles: serialFiles, + selectedFiles: selectedFiles, + navigate: navigateSerial, + selectFile: (path) => { + const serialFilesOnly = selectedFiles.filter(f => f.device === Device.serial) + const selected = serialFilesOnly.find(f => f.path === path) + if (selected) { + let newSelection = serialFilesOnly.filter(f => f.path !== path) + setSelectedFiles(newSelection) + } else { + let file = { + path: path, + device: Device.serial + } + serialFilesOnly.push(file) + setSelectedFiles(serialFilesOnly.slice()) } + } } + } - const serialFilesLogic = () : ReturnType => { - return { - serialFiles: serialFiles, - selectedFile: selectedFile, - navigate: navigateSerial, - selectFile: (path) => { - setSelectedFile({ - path: path, - device: Device.serial - }) - } + const fileManagementLogic = () : ReturnType => { + return { + upload: async () => { + setWaiting(true) + try { + for (let i = 0; i < selectedFiles.length; i++) { + const filename = selectedFiles[i].path.split('/').pop() + await BridgeSerial.uploadFile(diskPath, serialPath, filename) + } + refresh() + } catch (e) { + console.log('error', e) } - } - - const fileManagementLogic = () : ReturnType => { - return { - upload: (diskPath, serialPath) => {}, - download: (serialPath, diskPath) => {}, - remove: () => {} + setWaiting(false) + }, + download: async () => { + setWaiting(true) + try { + for (let i = 0; i < selectedFiles.length; i++) { + const filename = selectedFiles[i].path.split('/').pop() + await BridgeSerial.downloadFile(serialPath, diskPath, filename) + } + refresh() + } catch (e) { + console.log('error', e) + } + setWaiting(false) + }, + remove: async () => { + setWaiting(true) + try { + for (let i = 0; i < selectedFiles.length; i++) { + const f = selectedFiles[i] + const filename = f.path.split('/').pop() + if (f.device === Device.disk) { + await BridgeDisk.removeFile(diskPath, filename) + } + if (f.device === Device.serial) { + await BridgeSerial.removeFile(f.path) + } + } + refresh() + } catch (e) { + console.log('error', e) } + setWaiting(false) + } } + } - return { - toolbarLogic, - diskNavigationLogic, - diskFilesLogic, - serialNavigationLogic, - serialFilesLogic, - fileManagementLogic - } + return { + toolbarLogic, + diskNavigationLogic, + diskFilesLogic, + serialNavigationLogic, + serialFilesLogic, + fileManagementLogic, + waiting + } } - diff --git a/ui/ftp/main.scss b/ui/ftp/main.scss index dee2604..3791c39 100644 --- a/ui/ftp/main.scss +++ b/ui/ftp/main.scss @@ -1,9 +1,46 @@ -* { - box-sizing: border-box; +* { + box-sizing: border-box; } html, body { margin: 0; width: 100%; height: 100%; -} \ No newline at end of file +} + +.row { + display: flex; + flex-direction: row; + height: 100%; +} + +.column { + display: flex; + flex-direction: column; + width: 100%; +} + +.justify-center { + justify-content: center; +} + +.align-center { + align-items: center; +} + +ul { + list-style: none; + padding: 0; +} + +.file-panel { + width: 100%; + overflow: scroll; + height: 70vh; +} + +.file-management { + width: 10%; + justify-content: center; + align-items: center; +} diff --git a/ui/ftp/main.tsx b/ui/ftp/main.tsx index be3b1de..82109da 100644 --- a/ui/ftp/main.tsx +++ b/ui/ftp/main.tsx @@ -6,28 +6,46 @@ import DiskNavigation from './components/navigation/diskNavigation' import DiskFiles from './components/files/diskFiles' import SerialNavigation from './components/navigation/serialNavigation' import SerialFiles from './components/files/serialFiles' +import FileManagement from './components/files/fileManagement' import { useMainLogic } from './main.logic.ts' const App: React.FC = () => { - const { + const { + waiting, toolbarLogic, diskNavigationLogic, diskFilesLogic, serialNavigationLogic, - serialFilesLogic + serialFilesLogic, + fileManagementLogic } = useMainLogic() + if (waiting) { + return ( + <> + + WAIT! + + ) + } return ( <> -
    -
    - - -
    -
    +
    +
    - +
    + +
    +
    +
    + +
    +
    + +
    + +
    From 88b35a4557a7a5336ca9c134e64f2efd21ec71c6 Mon Sep 17 00:00:00 2001 From: Murilo Polese Date: Tue, 18 Apr 2023 16:49:31 +0200 Subject: [PATCH 3/9] WIP FTP ui bindings --- ui/ftp/components/diskView.tsx | 84 +++++++ ui/ftp/components/fileManagementView.tsx | 22 ++ ui/ftp/components/files/diskFiles.tsx | 2 +- ui/ftp/components/files/serialFiles.tsx | 2 +- ui/ftp/components/loadinbView.tsx | 9 + ui/ftp/components/serialView.tsx | 74 ++++++ ui/ftp/components/toolbar/toolbar.tsx | 70 +++--- ui/ftp/main.logic.ts | 277 ++++++++++------------- ui/ftp/main.scss | 113 ++++++++- ui/ftp/main.tsx | 59 ++--- ui/ftp/main.type.ts | 14 +- 11 files changed, 490 insertions(+), 236 deletions(-) create mode 100644 ui/ftp/components/diskView.tsx create mode 100644 ui/ftp/components/fileManagementView.tsx create mode 100644 ui/ftp/components/loadinbView.tsx create mode 100644 ui/ftp/components/serialView.tsx diff --git a/ui/ftp/components/diskView.tsx b/ui/ftp/components/diskView.tsx new file mode 100644 index 0000000..5a2c3f5 --- /dev/null +++ b/ui/ftp/components/diskView.tsx @@ -0,0 +1,84 @@ +import React from 'react' + +const DiskView: React.FC = ({ logic }) => { + const { waiting } = logic() + return ( +
    +
    + +
    +
    + + + + + + +
    +
    +
    +
    📁
    + lib +
    +
    + + boot.py +
    +
    + + main.py +
    +
    + + turing_machine.py +
    +
    + + README.md +
    +
    +
    📁
    + lib +
    +
    + + boot.py +
    +
    + + main.py +
    +
    + + turing_machine.py +
    +
    + + README.md +
    +
    +
    📁
    + lib +
    +
    + + boot.py +
    +
    + + main.py +
    +
    + + turing_machine.py +
    +
    + + README.md +
    +
    +
    + ) +} + +export default DiskView diff --git a/ui/ftp/components/fileManagementView.tsx b/ui/ftp/components/fileManagementView.tsx new file mode 100644 index 0000000..9251e94 --- /dev/null +++ b/ui/ftp/components/fileManagementView.tsx @@ -0,0 +1,22 @@ +import React from 'react' + +type FileManagementParams = () => { + upload: () => void + download: () => void + remove: () => void + refresh: () => void +} + +const FileManagementView: React.FC = ({ logic }) => { + const { refresh } : FileManagementParams = logic() + return ( +
    + + + + +
    + ) +} + +export default FileManagementView diff --git a/ui/ftp/components/files/diskFiles.tsx b/ui/ftp/components/files/diskFiles.tsx index 0a43d32..40b6b6e 100644 --- a/ui/ftp/components/files/diskFiles.tsx +++ b/ui/ftp/components/files/diskFiles.tsx @@ -15,7 +15,7 @@ const DiskFiles: React.FC = ({ diskFilesLogic }) => { const onSelect = (folder) => () => selectFile([diskPath,folder].join('/')) const files = diskFiles.map((folder, i) => { const checked = selectedFiles - .filter(f => f.device === Device.disk) + .filter(f => f.device === DeviceType.disk) .find(f => f.path === [diskPath,folder].join('/')) return (
  • diff --git a/ui/ftp/components/files/serialFiles.tsx b/ui/ftp/components/files/serialFiles.tsx index 5ff8d9f..ff047cc 100644 --- a/ui/ftp/components/files/serialFiles.tsx +++ b/ui/ftp/components/files/serialFiles.tsx @@ -15,7 +15,7 @@ const SerialFiles: React.FC = ({ serialFilesLogic }) => { const onSelect = (folder) => () => selectFile([serialPath,folder].join('/')) const files = serialFiles.map((folder, i) => { const checked = selectedFiles - .filter(f => f.device === Device.serial) + .filter(f => f.device === DeviceType.serial) .find(f => f.path === [serialPath,folder].join('/')) return (
  • diff --git a/ui/ftp/components/loadinbView.tsx b/ui/ftp/components/loadinbView.tsx new file mode 100644 index 0000000..8abeef4 --- /dev/null +++ b/ui/ftp/components/loadinbView.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +const LoadingView: React.FC = ({ logic }) => { + const { waiting } = logic() + if (waiting) return
    Wait
    + return <> +} + +export default LoadingView diff --git a/ui/ftp/components/serialView.tsx b/ui/ftp/components/serialView.tsx new file mode 100644 index 0000000..1bd406c --- /dev/null +++ b/ui/ftp/components/serialView.tsx @@ -0,0 +1,74 @@ +import { React } from 'react' + +import { + File, + AvailableDevice +} from '../main.type.ts' + +type SerialParams = () => { + availableDevices: AvailableDevices[] + connectedDevice: string + serialPath: string + serialFiles: String[] + selectedFiles: File[] + connect: (path: string) => void + disconnect: () => void + selectFile: (path: string) => void + refresh: () => void + navigate: (path: string) => void +} + +const SerialView: React.FC = ({ logic }) => { + const { + availableDevices = [], + serialFiles = [], + serialPath = '', + connect, + disconnect + } : SerialParams = logic() + + const onSelectDevice = (e) => { + const value = e.target.value + if (value === "null") { + disconnect() + } else { + connect(value) + } + } + + const ListItem = (file: File, i: number) => ( +
    + + {file} +
    + ) + + const NavigationItem = (name: string, i:number) => ( + + ) + let serialPathArray = [] + if (serialPath) { + serialPathArray = ['/'].concat( + serialPath.split('/').filter(s => s !== '') + ) + } + + return ( +
    +
    + +
    +
    + {serialPathArray.map(NavigationItem)} +
    +
    + {serialFiles.map(ListItem)} +
    +
    + ) +} + +export default SerialView diff --git a/ui/ftp/components/toolbar/toolbar.tsx b/ui/ftp/components/toolbar/toolbar.tsx index 46bc943..5c6fcce 100644 --- a/ui/ftp/components/toolbar/toolbar.tsx +++ b/ui/ftp/components/toolbar/toolbar.tsx @@ -3,40 +3,44 @@ import styles from './toolbar.module.scss' import Button from '../shared/button.tsx' -const Toolbar: React.FC = ({ toolbarLogic }) => { - const { - openFolder, - refresh, - connect, - disconnect, - connectedDevice, - availableDevices = [] - } = toolbarLogic() - const [ selectedDevice, setSelectedDevice ] = useState() - const onChange = (e) => setSelectedDevice(e.target.value) - const onConnect = () => connect(selectedDevice) +const Toolbar: React.FC = ({ toolbarLogic }) => { + const { + openFolder, + refresh, + connect, + disconnect, + connectedDevice, + availableDevices = [] + } = toolbarLogic() + const [ selectedDevice, setSelectedDevice ] = useState() + const onChange = (e) => setSelectedDevice(e.target.value) + const onConnect = () => { + if (connectedDevice) { + disconnect() + } else { + connect(selectedDevice) + } + } - const deviceSelector = ( - - ) - const deviceDisplay = ( - {connectedDevice} - ) + const deviceSelector = ( + + ) + const deviceDisplay = {connectedDevice} - return ( -
    - {connectedDevice ? deviceDisplay : deviceSelector} - - - - {connectedDevice ? Connected : Disconnected} -
    - ) + return ( +
    + + {connectedDevice ? deviceDisplay : deviceSelector} + {connectedDevice ? : } + + +
    + ) } -export default Toolbar \ No newline at end of file +export default Toolbar diff --git a/ui/ftp/main.logic.ts b/ui/ftp/main.logic.ts index b54962f..8e93668 100644 --- a/ui/ftp/main.logic.ts +++ b/ui/ftp/main.logic.ts @@ -1,27 +1,11 @@ import { useState } from 'react'; -import ToolbarType from './components/toolbar/toolbar.type' -import DiskNavigationType from './components/navigation/diskNavigation.type' -import DiskFilesType from './components/files/diskFiles.type' -import SerialNavigationType from './components/navigation/serialNavigation.type' -import SerialFilesType from './components/files/serialFiles.type' -import FileManagementType from './components/files/fileManagement.type' +import { Device, File, AvailableDevices } from './main.type' -import { Device, File } from './main.type' - -export type UseMainLogic = () => { - toolbarLogic: ToolbarType - diskNavigationLogic: DiskNavigationType - diskFilesLogic: DiskFilesType - serialNavigationLogic: SerialNavigationType - serialFilesLogic: SerialFilesType - fileManagementLogic: FileManagementType -} - -export const useMainLogic : UseMainLogic = function() : ReturnType { +export const useMainLogic = function() { const { BridgeSerial, BridgeDisk } = window // List and connect to serial devices - const [ availableDevices, setAvailableDevices ] = useState() + const [ availableDevices, setAvailableDevices ] = useState() const [ connectedDevice, setConnectedDevice ] = useState() // Navigation paths const [ serialPath, setSerialPath ] = useState() @@ -39,7 +23,7 @@ export const useMainLogic : UseMainLogic = function() : ReturnType const files = await BridgeDisk.listFiles(newPath) setDiskPath(newPath) setDiskFiles(files) - const newSelection = selectedFiles.filter(f => f.device !== Device.disk) + const newSelection = selectedFiles.filter(f => f.device !== DeviceType.disk) setSelectedFiles(newSelection) } @@ -47,12 +31,12 @@ export const useMainLogic : UseMainLogic = function() : ReturnType const files = await BridgeSerial.listFiles(newPath) setSerialPath(newPath) setSerialFiles(files) - const newSelection = selectedFiles.filter(f => f.device !== Device.serial) + const newSelection = selectedFiles.filter(f => f.device !== DeviceType.serial) setSelectedFiles(newSelection) } - // LOGIC const refresh = async () => { + setWaiting(true) // list available devices const devices = await BridgeSerial.loadPorts() setAvailableDevices(devices) @@ -60,156 +44,143 @@ export const useMainLogic : UseMainLogic = function() : ReturnType if (connectedDevice) { const files = await BridgeSerial.listFiles(serialPath) setSerialFiles(files) + } else { + setSerialFiles([]) } // list disk files if (diskPath) { const files = await BridgeDisk.listFiles(diskPath) setDiskFiles(files) + } else { + setDiskFiles([]) } - } - const toolbarLogic = () : ReturnType => { - return { - availableDevices: availableDevices, - connectedDevice: connectedDevice, - connect: async (devicePath: String) => { - await BridgeSerial.connect(devicePath) - setConnectedDevice(devicePath) - setSerialPath('/') - const files = await BridgeSerial.listFiles('/') - setSerialFiles(files) - }, - disconnect: () => { - setConnectedDevice(null) - setSerialPath(null) - }, - openFolder: async () => { - const { folder, files } = await BridgeDisk.openFolder() - setDiskPath(folder) - setDiskFiles(files) - }, - refresh: refresh - } - } - - const diskNavigationLogic = () : ReturnType => { - return { - diskPath: diskPath, - navigate: navigateDisk - } + setWaiting(false) } - const diskFilesLogic = () : ReturnType => { - return { - diskPath: diskPath, - diskFiles: diskFiles, - selectedFiles: selectedFiles, - navigate: navigateDisk, - selectFile: (path) => { - const diskFilesOnly = selectedFiles.filter(f => f.device === Device.disk) - const selected = diskFilesOnly.find(f => f.path === path) - if (selected) { - let newSelection = diskFilesOnly.filter(f => f.path !== path) - setSelectedFiles(newSelection) - } else { - let file = { - path: path, - device: Device.disk - } - diskFilesOnly.push(file) - setSelectedFiles(diskFilesOnly.slice()) + const serialLogic = () => ({ + availableDevices: availableDevices, + connectedDevice: connectedDevice, + serialPath: serialPath, + serialFiles: serialFiles, + selectedFiles: selectedFiles, + connect: async (devicePath: String) => { + setWaiting(true) + await BridgeSerial.connect(devicePath) + setConnectedDevice(devicePath) + setSerialPath('/') + const files = await BridgeSerial.listFiles('/') + setSerialFiles(files) + setWaiting(false) + }, + disconnect: async () => { + setWaiting(true) + await BridgeSerial.disconnect() + setConnectedDevice(null) + setSerialPath(null) + setSerialFiles([]) + setWaiting(false) + }, + selectFile: (path) => { + const serialFilesOnly = selectedFiles.filter(f => f.device === DeviceType.serial) + const selected = serialFilesOnly.find(f => f.path === path) + if (selected) { + let newSelection = serialFilesOnly.filter(f => f.path !== path) + setSelectedFiles(newSelection) + } else { + let file = { + path: path, + device: DeviceType.serial } + serialFilesOnly.push(file) + setSelectedFiles(serialFilesOnly.slice()) } - } - } - - const serialNavigationLogic = () : ReturnType => { - return { - serialPath: serialPath, - navigate: navigateSerial - } - } - - const serialFilesLogic = () : ReturnType => { - return { - serialPath: serialPath, - serialFiles: serialFiles, - selectedFiles: selectedFiles, - navigate: navigateSerial, - selectFile: (path) => { - const serialFilesOnly = selectedFiles.filter(f => f.device === Device.serial) - const selected = serialFilesOnly.find(f => f.path === path) - if (selected) { - let newSelection = serialFilesOnly.filter(f => f.path !== path) - setSelectedFiles(newSelection) - } else { - let file = { - path: path, - device: Device.serial - } - serialFilesOnly.push(file) - setSelectedFiles(serialFilesOnly.slice()) + }, + refresh: refresh, + navigate: navigateSerial, + }) + const diskLogic = () => ({ + diskPath: diskPath, + diskFiles: diskFiles, + selectedFiles: selectedFiles, + openFolder: async () => { + const { folder, files } = await BridgeDisk.openFolder() + setDiskPath(folder) + setDiskFiles(files) + }, + selectFile: (path) => { + const diskFilesOnly = selectedFiles.filter(f => f.device === DeviceType.disk) + const selected = diskFilesOnly.find(f => f.path === path) + if (selected) { + let newSelection = diskFilesOnly.filter(f => f.path !== path) + setSelectedFiles(newSelection) + } else { + let file = { + path: path, + device: DeviceType.disk } + diskFilesOnly.push(file) + setSelectedFiles(diskFilesOnly.slice()) } - } - } - - const fileManagementLogic = () : ReturnType => { - return { - upload: async () => { - setWaiting(true) - try { - for (let i = 0; i < selectedFiles.length; i++) { - const filename = selectedFiles[i].path.split('/').pop() - await BridgeSerial.uploadFile(diskPath, serialPath, filename) - } - refresh() - } catch (e) { - console.log('error', e) + }, + navigate: navigateDisk + }) + const fileManagementLogic = () => ({ + upload: async () => { + setWaiting(true) + try { + for (let i = 0; i < selectedFiles.length; i++) { + const filename = selectedFiles[i].path.split('/').pop() + await BridgeSerial.uploadFile(diskPath, serialPath, filename) } - setWaiting(false) - }, - download: async () => { - setWaiting(true) - try { - for (let i = 0; i < selectedFiles.length; i++) { - const filename = selectedFiles[i].path.split('/').pop() - await BridgeSerial.downloadFile(serialPath, diskPath, filename) - } - refresh() - } catch (e) { - console.log('error', e) + refresh() + } catch (e) { + console.log('error', e) + } + setWaiting(false) + }, + download: async () => { + setWaiting(true) + try { + for (let i = 0; i < selectedFiles.length; i++) { + const filename = selectedFiles[i].path.split('/').pop() + await BridgeSerial.downloadFile(serialPath, diskPath, filename) } - setWaiting(false) - }, - remove: async () => { - setWaiting(true) - try { - for (let i = 0; i < selectedFiles.length; i++) { - const f = selectedFiles[i] - const filename = f.path.split('/').pop() - if (f.device === Device.disk) { - await BridgeDisk.removeFile(diskPath, filename) - } - if (f.device === Device.serial) { - await BridgeSerial.removeFile(f.path) - } + refresh() + } catch (e) { + console.log('error', e) + } + setWaiting(false) + }, + remove: async () => { + setWaiting(true) + try { + for (let i = 0; i < selectedFiles.length; i++) { + const f = selectedFiles[i] + const filename = f.path.split('/').pop() + if (f.device === DeviceType.disk) { + await BridgeDisk.removeFile(diskPath, filename) + } + if (f.device === DeviceType.serial) { + await BridgeSerial.removeFile(f.path) } - refresh() - } catch (e) { - console.log('error', e) } - setWaiting(false) + refresh() + } catch (e) { + console.log('error', e) } - } - } + setWaiting(false) + }, + refresh: refresh + }) + const loadingLogic = async () => ({ + waiting + }) return { - toolbarLogic, - diskNavigationLogic, - diskFilesLogic, - serialNavigationLogic, - serialFilesLogic, + waiting, + serialLogic, + diskLogic, fileManagementLogic, - waiting + loadingLogic } } diff --git a/ui/ftp/main.scss b/ui/ftp/main.scss index 3791c39..c30528e 100644 --- a/ui/ftp/main.scss +++ b/ui/ftp/main.scss @@ -1,11 +1,32 @@ * { box-sizing: border-box; + font-family: sans-serif; + font-size: var(--base-size); } html, body { margin: 0; width: 100%; height: 100%; + + --base-size: 18px; + --brand-color: #008184; + --light-color: #FFFFFF; + --dark-color: #005C5F; + --dark-tone: #DAE3E3; + --light-tone: #ECF1F1; + --highlight-color: #F26727; + + background: var(--light-tone); +} + +main { + width: 100vw; + height: 100vh; +} +.window-wrapper { + width: 100%; + height: 100%; } .row { @@ -28,19 +49,95 @@ body { align-items: center; } -ul { - list-style: none; - padding: 0; +.full-width { + width: 100%; +} +.full-height { + height: 100%; +} + +.toolbar { + height: 100px; + padding-bottom: var(--base-size); + + select { + width: 100%; + } + + button { + width: 100%; + } } .file-panel { - width: 100%; - overflow: scroll; - height: 70vh; + padding: 40px; + width: calc(50% - 25px); +} + +.list { + background: var(--light-color); + overflow: overlay; +} + +.list-item { + padding: var(--base-size) 5px; + cursor: pointer; + .checkbox, input[type="checkbox"] { + display: inline-block; + width: 50px; + cursor: pointer; + text-align: center; + } + &:hover { + background: var(--dark-tone); + } +} + +.navigation { + height: 100px; + background: var(--dark-tone); + padding: var(--base-size); + padding-bottom: var(--base-size); + overflow: overlay; + & > * { + margin-right: 10px; + } } .file-management { - width: 10%; + width: 50px; + button { + padding: 0; + width: 50px; + height: 50px; + margin: 5px 0; + } +} + + +select { + padding: 5px 30px; + border: none; + cursor: pointer; + background: var(--light-color); +} + +button { + background: var(--brand-color); + color: var(--light-color); + border: none; + padding: 5px 30px; + cursor: pointer; +} + +.window-overlay { + width: 100vw; + height: 100vh; + top: 0; + left: 0; + position: fixed; + z-index: 9999; + background: rgba(255, 255, 255, 0.5); + display: flex; justify-content: center; - align-items: center; } diff --git a/ui/ftp/main.tsx b/ui/ftp/main.tsx index 82109da..389494d 100644 --- a/ui/ftp/main.tsx +++ b/ui/ftp/main.tsx @@ -1,53 +1,35 @@ import React from 'react' import ReactDOM from 'react-dom/client' -import Toolbar from './components/toolbar/toolbar' -import DiskNavigation from './components/navigation/diskNavigation' -import DiskFiles from './components/files/diskFiles' -import SerialNavigation from './components/navigation/serialNavigation' -import SerialFiles from './components/files/serialFiles' -import FileManagement from './components/files/fileManagement' +import SerialView from './components/serialView.tsx' +import FileManagementView from './components/fileManagementView.tsx' +import DiskView from './components/diskView.tsx' +import LoadingView from './components/loadingView.tsx' import { useMainLogic } from './main.logic.ts' const App: React.FC = () => { const { waiting, - toolbarLogic, - diskNavigationLogic, - diskFilesLogic, - serialNavigationLogic, - serialFilesLogic, - fileManagementLogic + serialLogic, + diskLogic, + fileManagementLogic, + loadingLogic } = useMainLogic() - if (waiting) { - return ( - <> - - WAIT! - - ) - } + + const overlay = ( +
    +
    Waiting
    +
    + ) return ( <> - -
    -
    - -
    - -
    -
    -
    - -
    -
    - -
    - -
    -
    -
    +
    + + + +
    + {waiting ? overlay : null} ) } @@ -56,6 +38,7 @@ window.addEventListener('load', () => { window.BridgeWindow.setWindowSize(900, 600) const container : HTMLElement | null = document.querySelector('main') const root = ReactDOM.createRoot(container) + root.render( diff --git a/ui/ftp/main.type.ts b/ui/ftp/main.type.ts index 3516891..4468173 100644 --- a/ui/ftp/main.type.ts +++ b/ui/ftp/main.type.ts @@ -1,6 +1,16 @@ -export enum Device { serial, disk } +export enum DeviceType { serial, disk } export type File = { path: String device: Device -} \ No newline at end of file +} + +export type AvailableDevice = { + locationId: undefined | string + manufacturer: string + path: string + pnpId: string + productId: string + serialNumber: string + vendorId: string +} From 63cc09949ec8c2ceae6e3c098083e603367839cb Mon Sep 17 00:00:00 2001 From: Murilo Polese Date: Wed, 19 Apr 2023 15:47:03 +0200 Subject: [PATCH 4/9] Serial view plugged --- index.js | 1 + package-lock.json | 9 +++-- package.json | 5 ++- preload.js | 3 ++ ui/ftp/components/serialView.tsx | 42 ++++++++++++++++------ ui/ftp/main.logic.ts | 62 ++++++++++++++++++-------------- ui/ftp/main.scss | 5 +++ ui/ftp/main.type.ts | 3 ++ 8 files changed, 85 insertions(+), 45 deletions(-) diff --git a/index.js b/index.js index d49cd27..69befd9 100644 --- a/index.js +++ b/index.js @@ -107,6 +107,7 @@ function createWindow () { } }) // and load the index.html of the app. + // win.loadFile('ui/editor/index.html') win.loadFile('ui/ftp/dist/index.html') } diff --git a/package-lock.json b/package-lock.json index 5cb6cdb..fdc6798 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,9 +11,8 @@ "license": "MIT", "dependencies": { "about-window": "^1.15.2", - "micropython.js": "github:murilopolese/micropython.js#v1.2.2", - "mkdirp": "^1.0.3", - "serialport": "^10.4.0" + "micropython.js": "github:arduino/micropython.js#1.3.0", + "mkdirp": "^1.0.3" }, "devDependencies": { "electron": "^19.0.10", @@ -3143,8 +3142,8 @@ } }, "node_modules/micropython.js": { - "version": "1.2.2", - "resolved": "git+ssh://git@github.com/murilopolese/micropython.js.git#1f630d21f6ee18a901dc5a1ebe4ce5b92f05943a", + "version": "1.3.0", + "resolved": "git+ssh://git@github.com/arduino/micropython.js.git#418c81147d547a5cac9f51cba9700800811803f7", "dependencies": { "serialport": "^10.4.0" }, diff --git a/package.json b/package.json index 670bcc5..de76002 100644 --- a/package.json +++ b/package.json @@ -38,9 +38,8 @@ "license": "MIT", "dependencies": { "about-window": "^1.15.2", - "micropython.js": "github:murilopolese/micropython.js#v1.2.2", - "mkdirp": "^1.0.3", - "serialport": "^10.4.0" + "micropython.js": "github:arduino/micropython.js#1.3.0", + "mkdirp": "^1.0.3" }, "engines": { "node": "18" diff --git a/preload.js b/preload.js index 1e413f5..34e616c 100644 --- a/preload.js +++ b/preload.js @@ -50,6 +50,9 @@ const Serial = { listFiles: async (folder) => { return await board.fs_ls(folder) }, + ilistFiles: async (folder) => { + return await board.fs_ils(folder) + }, loadFile: async (file) => { const output = await board.fs_cat(file) return output || '' diff --git a/ui/ftp/components/serialView.tsx b/ui/ftp/components/serialView.tsx index 1bd406c..ed0af6a 100644 --- a/ui/ftp/components/serialView.tsx +++ b/ui/ftp/components/serialView.tsx @@ -2,6 +2,7 @@ import { React } from 'react' import { File, + DeviceType, AvailableDevice } from '../main.type.ts' @@ -22,9 +23,12 @@ const SerialView: React.FC = ({ logic }) => { const { availableDevices = [], serialFiles = [], + selectedFiles = [], serialPath = '', connect, - disconnect + disconnect, + navigate, + selectFile } : SerialParams = logic() const onSelectDevice = (e) => { @@ -36,16 +40,34 @@ const SerialView: React.FC = ({ logic }) => { } } - const ListItem = (file: File, i: number) => ( -
    - - {file} -
    - ) + const ListItem = (file: File, i: number) => { + const onClick = () => { + if (file.type === 'file') { + selectFile(file) + } else { + navigate(serialPath + '/' + file.path) + } + } + const checked = selectedFiles + .filter(f => f.device === DeviceType.serial) + .find(f => f.path === file.path) + const icon = file.type === 'file' + ?
    📄
    + :
    📁
    + return ( +
    + {icon}{file.path} +
    + ) + } - const NavigationItem = (name: string, i:number) => ( - - ) + const NavigationItem = (name: string, i:number) => { + const crumbs = serialPath.split('/').filter(c => c !== '') + const path = '/' + crumbs.slice(0, i).join('/') + return ( + + ) + } let serialPathArray = [] if (serialPath) { serialPathArray = ['/'].concat( diff --git a/ui/ftp/main.logic.ts b/ui/ftp/main.logic.ts index 8e93668..06b7fb4 100644 --- a/ui/ftp/main.logic.ts +++ b/ui/ftp/main.logic.ts @@ -1,6 +1,6 @@ import { useState } from 'react'; -import { Device, File, AvailableDevices } from './main.type' +import { DeviceType, File, FileType, AvailableDevices } from './main.type' export const useMainLogic = function() { const { BridgeSerial, BridgeDisk } = window @@ -28,11 +28,31 @@ export const useMainLogic = function() { } const navigateSerial = async (newPath) => { - const files = await BridgeSerial.listFiles(newPath) + setWaiting(true) setSerialPath(newPath) - setSerialFiles(files) + await refreshSerialFiles(newPath) const newSelection = selectedFiles.filter(f => f.device !== DeviceType.serial) setSelectedFiles(newSelection) + setWaiting(false) + } + + const refreshSerialFiles = async (path) => { + const detailedFiles = await BridgeSerial.ilistFiles(path) + const folders = detailedFiles.filter(f => f[1] === FileType.folder) || [] + const files = detailedFiles.filter(f => f[1] === FileType.file) || [] + const sortedFiles = folders.concat(files) + .map(f => ({ + path: f[0], + type: (f[1] === FileType.folder) ? 'folder' : 'file', + size: f[3], + device: DeviceType.serial + })) || [] + setSerialFiles(sortedFiles) + } + + const refreshDiskFiles = async () => { + const files = await BridgeDisk.listFiles(diskPath) + setDiskFiles(files) } const refresh = async () => { @@ -41,19 +61,12 @@ export const useMainLogic = function() { const devices = await BridgeSerial.loadPorts() setAvailableDevices(devices) // list serial files - if (connectedDevice) { - const files = await BridgeSerial.listFiles(serialPath) - setSerialFiles(files) - } else { - setSerialFiles([]) - } + if (connectedDevice) await refreshSerialFiles(serialPath) + else setSerialFiles([]) // list disk files - if (diskPath) { - const files = await BridgeDisk.listFiles(diskPath) - setDiskFiles(files) - } else { - setDiskFiles([]) - } + if (diskPath) await refreshDiskFiles() + else setDiskFiles([]) + setWaiting(false) } @@ -63,13 +76,12 @@ export const useMainLogic = function() { serialPath: serialPath, serialFiles: serialFiles, selectedFiles: selectedFiles, - connect: async (devicePath: String) => { + connect: async (port: String) => { setWaiting(true) - await BridgeSerial.connect(devicePath) - setConnectedDevice(devicePath) + await BridgeSerial.connect(port) + setConnectedDevice(port) setSerialPath('/') - const files = await BridgeSerial.listFiles('/') - setSerialFiles(files) + refreshSerialFiles(serialPath) setWaiting(false) }, disconnect: async () => { @@ -80,17 +92,13 @@ export const useMainLogic = function() { setSerialFiles([]) setWaiting(false) }, - selectFile: (path) => { + selectFile: (file: File) => { const serialFilesOnly = selectedFiles.filter(f => f.device === DeviceType.serial) - const selected = serialFilesOnly.find(f => f.path === path) + const selected = serialFilesOnly.find(f => f.path === file.path) if (selected) { - let newSelection = serialFilesOnly.filter(f => f.path !== path) + let newSelection = serialFilesOnly.filter(f => f.path !== file.path) setSelectedFiles(newSelection) } else { - let file = { - path: path, - device: DeviceType.serial - } serialFilesOnly.push(file) setSelectedFiles(serialFilesOnly.slice()) } diff --git a/ui/ftp/main.scss b/ui/ftp/main.scss index c30528e..ad1766a 100644 --- a/ui/ftp/main.scss +++ b/ui/ftp/main.scss @@ -91,6 +91,11 @@ main { &:hover { background: var(--dark-tone); } + &.checked { + background: var(--highlight-color); + color: var(--light-color); + font-weight: bold; + } } .navigation { diff --git a/ui/ftp/main.type.ts b/ui/ftp/main.type.ts index 4468173..7712173 100644 --- a/ui/ftp/main.type.ts +++ b/ui/ftp/main.type.ts @@ -1,8 +1,11 @@ export enum DeviceType { serial, disk } +export enum FileType { file = 0x8000, folder = 0x4000 } export type File = { path: String + type: FileType device: Device + size: Number } export type AvailableDevice = { From ce9c5dc723ea693b1d48a94e958a31f374e79027 Mon Sep 17 00:00:00 2001 From: Murilo Polese Date: Wed, 19 Apr 2023 16:29:40 +0200 Subject: [PATCH 5/9] Disk view plugged --- index.js | 26 ++++++- preload.js | 3 + ui/ftp/components/diskView.tsx | 130 +++++++++++++++---------------- ui/ftp/components/serialView.tsx | 1 - ui/ftp/main.logic.ts | 43 ++++++---- ui/ftp/main.scss | 5 ++ ui/ftp/main.type.ts | 2 +- 7 files changed, 123 insertions(+), 87 deletions(-) diff --git a/index.js b/index.js index 69befd9..341c3ea 100644 --- a/index.js +++ b/index.js @@ -26,13 +26,31 @@ function listFolder(folder, filesOnly) { return files } +function ilistFolder(folder, filesOnly) { + let files = fs.readdirSync(path.resolve(folder)) + files = files.map(f => { + let filePath = path.resolve(folder, f) + return { + path: f, + type: fs.lstatSync(filePath).isDirectory() ? 'folder' : 'file' + } + }) + // Filter out directories + if (filesOnly) { + files = files.filter(f => f.type === 'file') + } + // Filter out dot files + files = files.filter(f => f.path.indexOf('.') !== 0) + return files +} + // LOCAL FILE SYSTEM ACCESS ipcMain.handle('open-folder', async (event) => { console.log('ipcMain', 'open-folder') const folder = await openFolderDialog() let files = [] if (folder) { - files = listFolder(folder) + files = ilistFolder(folder) } return { folder, files } }) @@ -43,6 +61,12 @@ ipcMain.handle('list-files', async (event, folder) => { return listFolder(folder) }) +ipcMain.handle('ilist-files', async (event, folder) => { + console.log('ipcMain', 'ilist-files', folder) + if (!folder) return [] + return ilistFolder(folder) +}) + ipcMain.handle('load-file', (event, folder, filename) => { console.log('ipcMain', 'load-file', folder, filename ) let filePath = path.resolve(folder, filename) diff --git a/preload.js b/preload.js index 34e616c..0b5db21 100644 --- a/preload.js +++ b/preload.js @@ -87,6 +87,9 @@ const Disk = { listFiles: async (folder) => { return ipcRenderer.invoke('list-files', folder) }, + ilistFiles: async (folder) => { + return ipcRenderer.invoke('ilist-files', folder) + }, loadFile: async (folder, file) => { let content = await ipcRenderer.invoke('load-file', folder, file) return new TextDecoder().decode(content) diff --git a/ui/ftp/components/diskView.tsx b/ui/ftp/components/diskView.tsx index 5a2c3f5..334d324 100644 --- a/ui/ftp/components/diskView.tsx +++ b/ui/ftp/components/diskView.tsx @@ -1,81 +1,75 @@ import React from 'react' +import { + File, + DeviceType +} from '../main.type.ts' + +type DiskViewParams = { + waiting: Boolean, + diskPath: String + diskFiles: File[] + selectedFiles: File[] + openFolder: () => void + selectFile: (file: File) => void + navigate: (path: String) => void +} + const DiskView: React.FC = ({ logic }) => { - const { waiting } = logic() + const { + waiting = true, + diskPath, + diskFiles = [], + selectedFiles = [], + openFolder, + selectFile, + navigate + } : DiskViewParams = logic() + + const ListItem = (file: File, i: number) => { + const onClick = () => { + if (file.type === 'file') { + selectFile(file) + } else { + navigate(diskPath + '/' + file.path) + } + } + const checked = selectedFiles + .filter(f => f.device === DeviceType.disk) + .find(f => f.path === file.path) + const icon = file.type === 'file' + ?
    📄
    + :
    📁
    + return ( +
    + {icon}{file.path} +
    + ) + } + + const NavigationItem = (name: string, i:number) => { + const crumbs = diskPath.split('/').filter(c => c !== '') + const path = '/' + crumbs.slice(0, i).join('/') + return ( + + ) + } + let diskPathArray = [] + if (diskPath) { + diskPathArray = ['/'].concat( + diskPath.split('/').filter(s => s !== '') + ) + } return (
    - +
    - - - - - - + {diskPathArray.map(NavigationItem)}
    -
    -
    📁
    - lib -
    -
    - - boot.py -
    -
    - - main.py -
    -
    - - turing_machine.py -
    -
    - - README.md -
    -
    -
    📁
    - lib -
    -
    - - boot.py -
    -
    - - main.py -
    -
    - - turing_machine.py -
    -
    - - README.md -
    -
    -
    📁
    - lib -
    -
    - - boot.py -
    -
    - - main.py -
    -
    - - turing_machine.py -
    -
    - - README.md -
    + {diskFiles.map(ListItem)}
    ) diff --git a/ui/ftp/components/serialView.tsx b/ui/ftp/components/serialView.tsx index ed0af6a..5e8646f 100644 --- a/ui/ftp/components/serialView.tsx +++ b/ui/ftp/components/serialView.tsx @@ -15,7 +15,6 @@ type SerialParams = () => { connect: (path: string) => void disconnect: () => void selectFile: (path: string) => void - refresh: () => void navigate: (path: string) => void } diff --git a/ui/ftp/main.logic.ts b/ui/ftp/main.logic.ts index 06b7fb4..29c27fa 100644 --- a/ui/ftp/main.logic.ts +++ b/ui/ftp/main.logic.ts @@ -20,11 +20,12 @@ export const useMainLogic = function() { // HELPERS const navigateDisk = async (newPath) => { - const files = await BridgeDisk.listFiles(newPath) + setWaiting(true) setDiskPath(newPath) - setDiskFiles(files) + await refreshDiskFiles(newPath) const newSelection = selectedFiles.filter(f => f.device !== DeviceType.disk) setSelectedFiles(newSelection) + setWaiting(false) } const navigateSerial = async (newPath) => { @@ -36,11 +37,12 @@ export const useMainLogic = function() { setWaiting(false) } - const refreshSerialFiles = async (path) => { + const refreshSerialFiles = async (path: String) => { const detailedFiles = await BridgeSerial.ilistFiles(path) const folders = detailedFiles.filter(f => f[1] === FileType.folder) || [] const files = detailedFiles.filter(f => f[1] === FileType.file) || [] - const sortedFiles = folders.concat(files) + const sortedFiles = folders + .concat(files) .map(f => ({ path: f[0], type: (f[1] === FileType.folder) ? 'folder' : 'file', @@ -50,9 +52,18 @@ export const useMainLogic = function() { setSerialFiles(sortedFiles) } - const refreshDiskFiles = async () => { - const files = await BridgeDisk.listFiles(diskPath) - setDiskFiles(files) + const refreshDiskFiles = async (path: String) => { + const detailedFiles = await BridgeDisk.ilistFiles(path) + const folders = detailedFiles.filter(f => f.type === 'folder') || [] + const files = detailedFiles.filter(f => f.type === 'file') || [] + const sortedFiles = folders + .concat(files) + .map(f => ({ + path: f.path, + type: f.type, + device: DeviceType.disk + })) + setDiskFiles(sortedFiles) } const refresh = async () => { @@ -64,7 +75,7 @@ export const useMainLogic = function() { if (connectedDevice) await refreshSerialFiles(serialPath) else setSerialFiles([]) // list disk files - if (diskPath) await refreshDiskFiles() + if (diskPath) await refreshDiskFiles(diskPath) else setDiskFiles([]) setWaiting(false) @@ -103,7 +114,6 @@ export const useMainLogic = function() { setSelectedFiles(serialFilesOnly.slice()) } }, - refresh: refresh, navigate: navigateSerial, }) const diskLogic = () => ({ @@ -113,20 +123,21 @@ export const useMainLogic = function() { openFolder: async () => { const { folder, files } = await BridgeDisk.openFolder() setDiskPath(folder) - setDiskFiles(files) + await refreshDiskFiles(folder) }, - selectFile: (path) => { + selectFile: (file: File) => { const diskFilesOnly = selectedFiles.filter(f => f.device === DeviceType.disk) - const selected = diskFilesOnly.find(f => f.path === path) + const selected = diskFilesOnly.find(f => f.path === file.path) if (selected) { - let newSelection = diskFilesOnly.filter(f => f.path !== path) + let newSelection = diskFilesOnly.filter(f => f.path !== file.path) setSelectedFiles(newSelection) } else { - let file = { - path: path, + let f = { + path: file.path, + type: file.type, device: DeviceType.disk } - diskFilesOnly.push(file) + diskFilesOnly.push(f) setSelectedFiles(diskFilesOnly.slice()) } }, diff --git a/ui/ftp/main.scss b/ui/ftp/main.scss index ad1766a..1552c0d 100644 --- a/ui/ftp/main.scss +++ b/ui/ftp/main.scss @@ -82,6 +82,7 @@ main { .list-item { padding: var(--base-size) 5px; cursor: pointer; + display: flex; .checkbox, input[type="checkbox"] { display: inline-block; width: 50px; @@ -95,6 +96,10 @@ main { background: var(--highlight-color); color: var(--light-color); font-weight: bold; + + &:hover { + opacity: 0.85; + } } } diff --git a/ui/ftp/main.type.ts b/ui/ftp/main.type.ts index 7712173..7bbcc4e 100644 --- a/ui/ftp/main.type.ts +++ b/ui/ftp/main.type.ts @@ -5,7 +5,7 @@ export type File = { path: String type: FileType device: Device - size: Number + size?: Number } export type AvailableDevice = { From f05c5bbe5c268e2e5316c57262079a8966f0cd76 Mon Sep 17 00:00:00 2001 From: Murilo Polese Date: Wed, 19 Apr 2023 18:13:37 +0200 Subject: [PATCH 6/9] File management plugged --- ui/ftp/components/fileManagementView.tsx | 21 +++++++++++++++++---- ui/ftp/main.logic.ts | 4 +++- ui/ftp/main.scss | 4 ++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/ui/ftp/components/fileManagementView.tsx b/ui/ftp/components/fileManagementView.tsx index 9251e94..35e883d 100644 --- a/ui/ftp/components/fileManagementView.tsx +++ b/ui/ftp/components/fileManagementView.tsx @@ -1,20 +1,33 @@ import React from 'react' +import { File, DeviceType } from '../main.type.ts' + type FileManagementParams = () => { upload: () => void download: () => void remove: () => void refresh: () => void + canDownload: Boolean, + canUpload: Boolean, + selectedFiles: File[] } const FileManagementView: React.FC = ({ logic }) => { - const { refresh } : FileManagementParams = logic() + const { + refresh, + download, + upload, + remove, + canUpload, + canDownload, + selectedFiles = [] + } : FileManagementParams = logic() return (
    - - - + + +
    ) } diff --git a/ui/ftp/main.logic.ts b/ui/ftp/main.logic.ts index 29c27fa..7dc3ab4 100644 --- a/ui/ftp/main.logic.ts +++ b/ui/ftp/main.logic.ts @@ -144,6 +144,8 @@ export const useMainLogic = function() { navigate: navigateDisk }) const fileManagementLogic = () => ({ + canUpload: selectedFiles.find(f => f.device === DeviceType.disk) && serialPath, + canDownload: selectedFiles.find(f => f.device === DeviceType.serial) && diskPath, upload: async () => { setWaiting(true) try { @@ -180,7 +182,7 @@ export const useMainLogic = function() { await BridgeDisk.removeFile(diskPath, filename) } if (f.device === DeviceType.serial) { - await BridgeSerial.removeFile(f.path) + await BridgeSerial.removeFile(serialPath + '/' + f.path) } } refresh() diff --git a/ui/ftp/main.scss b/ui/ftp/main.scss index 1552c0d..38ae44d 100644 --- a/ui/ftp/main.scss +++ b/ui/ftp/main.scss @@ -139,6 +139,10 @@ button { padding: 5px 30px; cursor: pointer; } +button[disabled] { + opacity: 0.5; + cursor: not-allowed; +} .window-overlay { width: 100vw; From bf98398afa5df9910a8767b238b7d21c3f06a2bc Mon Sep 17 00:00:00 2001 From: Murilo Polese Date: Fri, 28 Apr 2023 15:14:30 +0200 Subject: [PATCH 7/9] Cleanup and wip breadcrumb --- ui/ftp/components/diskView.tsx | 17 ++----- ui/ftp/components/files/diskFiles.tsx | 30 ------------ ui/ftp/components/files/diskFiles.type.ts | 9 ---- ui/ftp/components/files/fileManagement.tsx | 16 ------- .../components/files/fileManagement.type.ts | 7 --- ui/ftp/components/files/serialFiles.tsx | 30 ------------ ui/ftp/components/files/serialFiles.type.ts | 8 ---- .../components/navigation/diskNavigation.tsx | 9 ---- .../navigation/diskNavigation.type.ts | 6 --- .../navigation/serialNavigation.tsx | 9 ---- .../navigation/serialNavigation.type.ts | 6 --- ui/ftp/components/serialView.tsx | 18 ++------ .../components/shared/breadcrumbs.module.scss | 9 ---- ui/ftp/components/shared/breadcrumbs.tsx | 29 ------------ ui/ftp/components/shared/button.module.scss | 12 ----- ui/ftp/components/shared/button.tsx | 8 ---- ui/ftp/components/toolbar/toolbar.module.scss | 8 ---- ui/ftp/components/toolbar/toolbar.tsx | 46 ------------------- ui/ftp/components/toolbar/toolbar.type.ts | 10 ---- ui/ftp/components/ui/BreadCrumb.tsx | 21 +++++++++ ui/ftp/main.logic.ts | 3 +- ui/ftp/main.scss | 13 +++++- ui/ftp/main.tsx | 8 +++- ui/ftp/main.type.ts | 1 + 24 files changed, 48 insertions(+), 285 deletions(-) delete mode 100644 ui/ftp/components/files/diskFiles.tsx delete mode 100644 ui/ftp/components/files/diskFiles.type.ts delete mode 100644 ui/ftp/components/files/fileManagement.tsx delete mode 100644 ui/ftp/components/files/fileManagement.type.ts delete mode 100644 ui/ftp/components/files/serialFiles.tsx delete mode 100644 ui/ftp/components/files/serialFiles.type.ts delete mode 100644 ui/ftp/components/navigation/diskNavigation.tsx delete mode 100644 ui/ftp/components/navigation/diskNavigation.type.ts delete mode 100644 ui/ftp/components/navigation/serialNavigation.tsx delete mode 100644 ui/ftp/components/navigation/serialNavigation.type.ts delete mode 100644 ui/ftp/components/shared/breadcrumbs.module.scss delete mode 100644 ui/ftp/components/shared/breadcrumbs.tsx delete mode 100644 ui/ftp/components/shared/button.module.scss delete mode 100644 ui/ftp/components/shared/button.tsx delete mode 100644 ui/ftp/components/toolbar/toolbar.module.scss delete mode 100644 ui/ftp/components/toolbar/toolbar.tsx delete mode 100644 ui/ftp/components/toolbar/toolbar.type.ts create mode 100644 ui/ftp/components/ui/BreadCrumb.tsx diff --git a/ui/ftp/components/diskView.tsx b/ui/ftp/components/diskView.tsx index 334d324..57ac8f6 100644 --- a/ui/ftp/components/diskView.tsx +++ b/ui/ftp/components/diskView.tsx @@ -5,6 +5,8 @@ import { DeviceType } from '../main.type.ts' +import BreadCrumb from './ui/BreadCrumb' + type DiskViewParams = { waiting: Boolean, diskPath: String @@ -47,26 +49,13 @@ const DiskView: React.FC = ({ logic }) => { ) } - const NavigationItem = (name: string, i:number) => { - const crumbs = diskPath.split('/').filter(c => c !== '') - const path = '/' + crumbs.slice(0, i).join('/') - return ( - - ) - } - let diskPathArray = [] - if (diskPath) { - diskPathArray = ['/'].concat( - diskPath.split('/').filter(s => s !== '') - ) - } return (
    - {diskPathArray.map(NavigationItem)} + {BreadCrumb(diskPath, navigate)}
    {diskFiles.map(ListItem)} diff --git a/ui/ftp/components/files/diskFiles.tsx b/ui/ftp/components/files/diskFiles.tsx deleted file mode 100644 index 40b6b6e..0000000 --- a/ui/ftp/components/files/diskFiles.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import React from 'react' -import DiskFilesType from './diskFiles.type.ts' -import Button from '../shared/button.tsx' -import { Device } from '../../main.type' - -const DiskFiles: React.FC = ({ diskFilesLogic }) => { - const { - diskPath, - selectedFiles = [], - diskFiles = [], - navigate, - selectFile - } : DiskFilesType = diskFilesLogic() - const onNavigate = (folder) => () => navigate([diskPath,folder].join('/')) - const onSelect = (folder) => () => selectFile([diskPath,folder].join('/')) - const files = diskFiles.map((folder, i) => { - const checked = selectedFiles - .filter(f => f.device === DeviceType.disk) - .find(f => f.path === [diskPath,folder].join('/')) - return ( -
  • - - -
  • - ) - }) - return
      {files}
    -} - -export default DiskFiles diff --git a/ui/ftp/components/files/diskFiles.type.ts b/ui/ftp/components/files/diskFiles.type.ts deleted file mode 100644 index 2f09c16..0000000 --- a/ui/ftp/components/files/diskFiles.type.ts +++ /dev/null @@ -1,9 +0,0 @@ -type DiskFilesType = () => { - diskPath: string, - diskFiles: string[] - selectedFiles: File[] - navigate: (folder : string) => void - selectFile: (path: string) => void -} - -export default DiskFilesType diff --git a/ui/ftp/components/files/fileManagement.tsx b/ui/ftp/components/files/fileManagement.tsx deleted file mode 100644 index e80d1cc..0000000 --- a/ui/ftp/components/files/fileManagement.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react' -import FileManagementType from './fileManagement.type' -import Button from '../shared/button.tsx' - -const FileManagement: React.FC = ({ fileManagementLogic }) => { - const { upload, download, remove }: FileManagementType = fileManagementLogic() - return ( -
      -
    • -
    • -
    • -
    - ) -} - -export default FileManagement diff --git a/ui/ftp/components/files/fileManagement.type.ts b/ui/ftp/components/files/fileManagement.type.ts deleted file mode 100644 index f1200d0..0000000 --- a/ui/ftp/components/files/fileManagement.type.ts +++ /dev/null @@ -1,7 +0,0 @@ -type FileManagementType = () => { - upload: () => void - download: () => void - remove: () => void -} - -export default FileManagementType diff --git a/ui/ftp/components/files/serialFiles.tsx b/ui/ftp/components/files/serialFiles.tsx deleted file mode 100644 index ff047cc..0000000 --- a/ui/ftp/components/files/serialFiles.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import React from 'react' -import SerialFilesType from './serialFiles.type.ts' -import Button from '../shared/button.tsx' -import { Device } from '../../main.type' - -const SerialFiles: React.FC = ({ serialFilesLogic }) => { - const { - serialPath, - selectedFiles = [], - serialFiles = [], - navigate, - selectFile - } : SerialFilesType = serialFilesLogic() - const onNavigate = (folder) => () => navigate([serialPath,folder].join('/')) - const onSelect = (folder) => () => selectFile([serialPath,folder].join('/')) - const files = serialFiles.map((folder, i) => { - const checked = selectedFiles - .filter(f => f.device === DeviceType.serial) - .find(f => f.path === [serialPath,folder].join('/')) - return ( -
  • - - -
  • - ) - }) - return
      {files}
    -} - -export default SerialFiles diff --git a/ui/ftp/components/files/serialFiles.type.ts b/ui/ftp/components/files/serialFiles.type.ts deleted file mode 100644 index 74809c0..0000000 --- a/ui/ftp/components/files/serialFiles.type.ts +++ /dev/null @@ -1,8 +0,0 @@ -type SerialFilesType = () => { - serialFiles: String[] - selectedFiles: File[] - navigate: (folder : String) => void - selectFile: (path: String) => void -} - -export default SerialFilesType diff --git a/ui/ftp/components/navigation/diskNavigation.tsx b/ui/ftp/components/navigation/diskNavigation.tsx deleted file mode 100644 index beab208..0000000 --- a/ui/ftp/components/navigation/diskNavigation.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react' -import BreadCrumbs from '../shared/breadcrumbs' - -const DiskNavigation: React.FC = ({ navigationLogic }) => { - const { diskPath = '', navigate } = navigationLogic() - return -} - -export default DiskNavigation \ No newline at end of file diff --git a/ui/ftp/components/navigation/diskNavigation.type.ts b/ui/ftp/components/navigation/diskNavigation.type.ts deleted file mode 100644 index fb8364b..0000000 --- a/ui/ftp/components/navigation/diskNavigation.type.ts +++ /dev/null @@ -1,6 +0,0 @@ -type DiskNavigationType = () => { - diskPath: String - navigate: (folder : String) => void -} - -export default DiskNavigationType \ No newline at end of file diff --git a/ui/ftp/components/navigation/serialNavigation.tsx b/ui/ftp/components/navigation/serialNavigation.tsx deleted file mode 100644 index 98b8314..0000000 --- a/ui/ftp/components/navigation/serialNavigation.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react' -import BreadCrumbs from '../shared/breadcrumbs' - -const SerialNavigation: React.FC = ({ navigationLogic }) => { - const { serialPath = '', navigate } = navigationLogic() - return -} - -export default SerialNavigation \ No newline at end of file diff --git a/ui/ftp/components/navigation/serialNavigation.type.ts b/ui/ftp/components/navigation/serialNavigation.type.ts deleted file mode 100644 index 1d057c0..0000000 --- a/ui/ftp/components/navigation/serialNavigation.type.ts +++ /dev/null @@ -1,6 +0,0 @@ -type SerialNavigationType = () => { - serialPath: String - navigate: (folder: String) => void -} - -export default SerialNavigationType \ No newline at end of file diff --git a/ui/ftp/components/serialView.tsx b/ui/ftp/components/serialView.tsx index 5e8646f..52ee8e4 100644 --- a/ui/ftp/components/serialView.tsx +++ b/ui/ftp/components/serialView.tsx @@ -6,6 +6,8 @@ import { AvailableDevice } from '../main.type.ts' +import BreadCrumb from './ui/BreadCrumb' + type SerialParams = () => { availableDevices: AvailableDevices[] connectedDevice: string @@ -60,20 +62,6 @@ const SerialView: React.FC = ({ logic }) => { ) } - const NavigationItem = (name: string, i:number) => { - const crumbs = serialPath.split('/').filter(c => c !== '') - const path = '/' + crumbs.slice(0, i).join('/') - return ( - - ) - } - let serialPathArray = [] - if (serialPath) { - serialPathArray = ['/'].concat( - serialPath.split('/').filter(s => s !== '') - ) - } - return (
    @@ -83,7 +71,7 @@ const SerialView: React.FC = ({ logic }) => {
    - {serialPathArray.map(NavigationItem)} + {BreadCrumb(serialPath, navigate)}
    {serialFiles.map(ListItem)} diff --git a/ui/ftp/components/shared/breadcrumbs.module.scss b/ui/ftp/components/shared/breadcrumbs.module.scss deleted file mode 100644 index 822400d..0000000 --- a/ui/ftp/components/shared/breadcrumbs.module.scss +++ /dev/null @@ -1,9 +0,0 @@ -.body { - display: flex; - flex-direction: row; - align-items: center; - padding: 1rem; - > * { - margin: 0 0.5rem 0 0; - } -} \ No newline at end of file diff --git a/ui/ftp/components/shared/breadcrumbs.tsx b/ui/ftp/components/shared/breadcrumbs.tsx deleted file mode 100644 index 1ae240d..0000000 --- a/ui/ftp/components/shared/breadcrumbs.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react' -import Button from './button.tsx' -import styles from './breadcrumbs.module.scss' - -const BreadCrumbs: React.FC = ({ path, navigate }) => { - if (!path) return <> - const pathArray = path.split('/') - const crumbs = pathArray.filter(crumb => crumb != '') - - const onClick = (i) => () => { - const newPath = '/' + crumbs.slice(0, i+1).join('/') - navigate(newPath) - } - const items = crumbs.map( - (folder, i) => ( - - - - ) - ) - return ( -
    - - {items} -
    - ) -} - -export default BreadCrumbs diff --git a/ui/ftp/components/shared/button.module.scss b/ui/ftp/components/shared/button.module.scss deleted file mode 100644 index ce0e3f6..0000000 --- a/ui/ftp/components/shared/button.module.scss +++ /dev/null @@ -1,12 +0,0 @@ -.button { - padding: 1rem; - border: none; - cursor: pointer; - background: #ddd; - &:hover { - opacity: 0.8; - } - &:active { - opacity: 1.0; - } -} \ No newline at end of file diff --git a/ui/ftp/components/shared/button.tsx b/ui/ftp/components/shared/button.tsx deleted file mode 100644 index 47e5c29..0000000 --- a/ui/ftp/components/shared/button.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react' -import styles from './button.module.scss' - -const Button: React.FC = (attr) => { - return -} - -export default Button \ No newline at end of file diff --git a/ui/ftp/components/toolbar/toolbar.module.scss b/ui/ftp/components/toolbar/toolbar.module.scss deleted file mode 100644 index 6d41740..0000000 --- a/ui/ftp/components/toolbar/toolbar.module.scss +++ /dev/null @@ -1,8 +0,0 @@ -.body { - display: flex; - flex-direction: row; - padding: 1rem; - > * { - margin: 0 0.5rem 0 0; - } -} diff --git a/ui/ftp/components/toolbar/toolbar.tsx b/ui/ftp/components/toolbar/toolbar.tsx deleted file mode 100644 index 5c6fcce..0000000 --- a/ui/ftp/components/toolbar/toolbar.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React, { useState } from 'react' -import styles from './toolbar.module.scss' -import Button from '../shared/button.tsx' - - -const Toolbar: React.FC = ({ toolbarLogic }) => { - const { - openFolder, - refresh, - connect, - disconnect, - connectedDevice, - availableDevices = [] - } = toolbarLogic() - const [ selectedDevice, setSelectedDevice ] = useState() - const onChange = (e) => setSelectedDevice(e.target.value) - const onConnect = () => { - if (connectedDevice) { - disconnect() - } else { - connect(selectedDevice) - } - } - - const deviceSelector = ( - - ) - const deviceDisplay = {connectedDevice} - - return ( -
    - - {connectedDevice ? deviceDisplay : deviceSelector} - {connectedDevice ? : } - - -
    - ) -} - -export default Toolbar diff --git a/ui/ftp/components/toolbar/toolbar.type.ts b/ui/ftp/components/toolbar/toolbar.type.ts deleted file mode 100644 index 01a653b..0000000 --- a/ui/ftp/components/toolbar/toolbar.type.ts +++ /dev/null @@ -1,10 +0,0 @@ -type ToolbarType = () => { - availableDevices: String[] - connectedDevice: String | null - connect: (devicePath: String) => void - disconnect: () => void - openFolder: () => void - refresh: () => void -} - -export default ToolbarType \ No newline at end of file diff --git a/ui/ftp/components/ui/BreadCrumb.tsx b/ui/ftp/components/ui/BreadCrumb.tsx new file mode 100644 index 0000000..6e66016 --- /dev/null +++ b/ui/ftp/components/ui/BreadCrumb.tsx @@ -0,0 +1,21 @@ + +const BreadCrumb = (path: string, navigate: (p: string) => void) => { + let pathArray = [] + if (path) { + pathArray = ['/'].concat( + path.split('/').filter(s => s !== '') + ) + } + if (pathArray.length > 2) { + pathArray = pathArray.slice(-3) + } + return pathArray.map((name, i) => { + const crumbs = path.split('/').filter(c => c !== '') + const p = '/' + crumbs.slice(0, i).join('/') + return ( + navigate(p)}>{name} + ) + }) +} + +export default BreadCrumb diff --git a/ui/ftp/main.logic.ts b/ui/ftp/main.logic.ts index 7dc3ab4..0174f99 100644 --- a/ui/ftp/main.logic.ts +++ b/ui/ftp/main.logic.ts @@ -202,6 +202,7 @@ export const useMainLogic = function() { serialLogic, diskLogic, fileManagementLogic, - loadingLogic + loadingLogic, + refresh } } diff --git a/ui/ftp/main.scss b/ui/ftp/main.scss index 38ae44d..e3ad1fe 100644 --- a/ui/ftp/main.scss +++ b/ui/ftp/main.scss @@ -104,16 +104,25 @@ main { } .navigation { - height: 100px; + display: flex; + flex-direction: row; + justify-content: flex-start; + height: calc(var(--base-size) * 5); background: var(--dark-tone); padding: var(--base-size); padding-bottom: var(--base-size); - overflow: overlay; + overflow: hidden; & > * { margin-right: 10px; } } +.breadcrumb { + padding: 0.5em; + background: var(--light-tone); + cursor: pointer; +} + .file-management { width: 50px; button { diff --git a/ui/ftp/main.tsx b/ui/ftp/main.tsx index 389494d..8247b83 100644 --- a/ui/ftp/main.tsx +++ b/ui/ftp/main.tsx @@ -1,4 +1,5 @@ import React from 'react' +import { useEffect } from 'react' import ReactDOM from 'react-dom/client' import SerialView from './components/serialView.tsx' @@ -14,9 +15,14 @@ const App: React.FC = () => { serialLogic, diskLogic, fileManagementLogic, - loadingLogic + loadingLogic, + refresh } = useMainLogic() + useEffect(() => { + refresh() + }, []) + const overlay = (
    Waiting
    diff --git a/ui/ftp/main.type.ts b/ui/ftp/main.type.ts index 7bbcc4e..e1f3c73 100644 --- a/ui/ftp/main.type.ts +++ b/ui/ftp/main.type.ts @@ -1,4 +1,5 @@ export enum DeviceType { serial, disk } + export enum FileType { file = 0x8000, folder = 0x4000 } export type File = { From b1dde2e38522810d6e44f774a33e3705e0942548 Mon Sep 17 00:00:00 2001 From: Murilo Polese Date: Tue, 2 May 2023 15:19:17 +0200 Subject: [PATCH 8/9] WIP --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 341c3ea..db37855 100644 --- a/index.js +++ b/index.js @@ -131,8 +131,8 @@ function createWindow () { } }) // and load the index.html of the app. - // win.loadFile('ui/editor/index.html') - win.loadFile('ui/ftp/dist/index.html') + win.loadFile('ui/editor/index.html') + // win.loadFile('ui/ftp/dist/index.html') } // TODO: Loading splash screen From 90aa58f7bdc072cc4a1738ad5db849e9fb3ad005 Mon Sep 17 00:00:00 2001 From: Murilo Polese Date: Tue, 2 May 2023 20:06:47 +0200 Subject: [PATCH 9/9] Use back button instead of breadcrumb for navigation --- index.js | 4 ++-- ui/ftp/components/diskView.tsx | 5 ++--- ui/ftp/components/serialView.tsx | 6 +++--- ui/ftp/components/ui/BreadCrumb.tsx | 3 --- ui/ftp/components/ui/NavigateUp.tsx | 16 ++++++++++++++++ ui/ftp/main.scss | 15 ++++++++++++++- 6 files changed, 37 insertions(+), 12 deletions(-) create mode 100644 ui/ftp/components/ui/NavigateUp.tsx diff --git a/index.js b/index.js index db37855..341c3ea 100644 --- a/index.js +++ b/index.js @@ -131,8 +131,8 @@ function createWindow () { } }) // and load the index.html of the app. - win.loadFile('ui/editor/index.html') - // win.loadFile('ui/ftp/dist/index.html') + // win.loadFile('ui/editor/index.html') + win.loadFile('ui/ftp/dist/index.html') } // TODO: Loading splash screen diff --git a/ui/ftp/components/diskView.tsx b/ui/ftp/components/diskView.tsx index 57ac8f6..fe7262f 100644 --- a/ui/ftp/components/diskView.tsx +++ b/ui/ftp/components/diskView.tsx @@ -6,6 +6,7 @@ import { } from '../main.type.ts' import BreadCrumb from './ui/BreadCrumb' +import NavigateUp from './ui/NavigateUp' type DiskViewParams = { waiting: Boolean, @@ -54,10 +55,8 @@ const DiskView: React.FC = ({ logic }) => {
    -
    - {BreadCrumb(diskPath, navigate)} -
    + {NavigateUp(diskPath, navigate)} {diskFiles.map(ListItem)}
    diff --git a/ui/ftp/components/serialView.tsx b/ui/ftp/components/serialView.tsx index 52ee8e4..f9648fe 100644 --- a/ui/ftp/components/serialView.tsx +++ b/ui/ftp/components/serialView.tsx @@ -7,6 +7,7 @@ import { } from '../main.type.ts' import BreadCrumb from './ui/BreadCrumb' +import NavigateUp from './ui/NavigateUp' type SerialParams = () => { availableDevices: AvailableDevices[] @@ -62,6 +63,7 @@ const SerialView: React.FC = ({ logic }) => { ) } + return (
    @@ -70,10 +72,8 @@ const SerialView: React.FC = ({ logic }) => { {availableDevices.map((d, i) => )}
    -
    - {BreadCrumb(serialPath, navigate)} -
    + {NavigateUp(serialPath, navigate)} {serialFiles.map(ListItem)}
    diff --git a/ui/ftp/components/ui/BreadCrumb.tsx b/ui/ftp/components/ui/BreadCrumb.tsx index 6e66016..f2380d2 100644 --- a/ui/ftp/components/ui/BreadCrumb.tsx +++ b/ui/ftp/components/ui/BreadCrumb.tsx @@ -6,9 +6,6 @@ const BreadCrumb = (path: string, navigate: (p: string) => void) => { path.split('/').filter(s => s !== '') ) } - if (pathArray.length > 2) { - pathArray = pathArray.slice(-3) - } return pathArray.map((name, i) => { const crumbs = path.split('/').filter(c => c !== '') const p = '/' + crumbs.slice(0, i).join('/') diff --git a/ui/ftp/components/ui/NavigateUp.tsx b/ui/ftp/components/ui/NavigateUp.tsx new file mode 100644 index 0000000..a533aa1 --- /dev/null +++ b/ui/ftp/components/ui/NavigateUp.tsx @@ -0,0 +1,16 @@ + +const NavigateUp = (path: string, navigate: (p: string) => void) => { + if (!path || path === '/') return null + const navigateUp = () => { + const pathArray = path.split('/').filter(p => p) + pathArray.pop() + navigate('/'+pathArray.join('/')) + } + return ( +
    +
    Back +
    + ) +} + +export default NavigateUp diff --git a/ui/ftp/main.scss b/ui/ftp/main.scss index e3ad1fe..8d873e0 100644 --- a/ui/ftp/main.scss +++ b/ui/ftp/main.scss @@ -111,16 +111,29 @@ main { background: var(--dark-tone); padding: var(--base-size); padding-bottom: var(--base-size); - overflow: hidden; + overflow: overlay; & > * { margin-right: 10px; } } .breadcrumb { + position: relative; padding: 0.5em; + padding-left: 2.5rem; background: var(--light-tone); cursor: pointer; + overflow: hidden; + height: 2rem; + text-overflow: ellipsis; +} + +.breadcrumb::after { + content: '📁'; + position: absolute; + left: 0.5rem; + top: 50%; + transform: translateY(-50%); } .file-management {