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 { pFad - Phonifier reborn

    Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

    Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


    Alternative Proxies:

    Alternative Proxy

    pFad Proxy

    pFad v3 Proxy

    pFad v4 Proxy