diff --git a/assets/css/_phx-liveview.scss b/assets/css/_phx-liveview.scss index 8bb19bf..4dadcd4 100644 --- a/assets/css/_phx-liveview.scss +++ b/assets/css/_phx-liveview.scss @@ -1,9 +1,32 @@ /* LiveView specific classes for your customizations */ + +/* hides the feedback field help if liveview indicates field not touched yet */ .phx-no-feedback.invalid-feedback, .phx-no-feedback .invalid-feedback { display: none; } +/* sets default bootstrap form-control styles if field not touched yet */ +.phx-no-feedback .form-control.is-valid, +.phx-no-feedback .form-control.is-invalid { + padding: $input-padding-y $input-padding-x; + border: $input-border-width solid $input-border-color; + background-image: none; + + &:focus { + color: $input-focus-color; + background-color: $input-focus-bg; + border-color: $input-focus-border-color; + outline: 0; + @if $enable-shadows { + @include box-shadow($input-box-shadow, $input-focus-box-shadow); + } @else { + // Avoid using mixin so we can pass custom focus shadow properly + box-shadow: $input-focus-box-shadow; + } + } +} + .phx-click-loading { opacity: 0.5; transition: opacity 1s ease-out; @@ -15,38 +38,3 @@ .phx-disconnected * { pointer-events: none; } - -.phx-modal { - opacity: 1 !important; - position: fixed; - z-index: 1; - left: 0; - top: 0; - width: 100%; - height: 100%; - overflow: auto; - background-color: rgb(0, 0, 0); - background-color: rgba(0, 0, 0, 0.4); -} - -.phx-modal-content { - background-color: #fefefe; - margin: 15% auto; - padding: 20px; - border: 1px solid #888; - width: 80%; -} - -.phx-modal-close { - color: #aaa; - float: right; - font-size: 28px; - font-weight: bold; -} - -.phx-modal-close:hover, -.phx-modal-close:focus { - color: black; - text-decoration: none; - cursor: pointer; -} diff --git a/assets/js/_bs_modal.js b/assets/js/_bs_modal.js new file mode 100644 index 0000000..981b3bc --- /dev/null +++ b/assets/js/_bs_modal.js @@ -0,0 +1,34 @@ +// Helping bootstrap modals work with liveview +// preserving animations +import Modal from "bootstrap/js/dist/modal"; +// import { Modal } from "bootstrap"; + +export const BsModal = { + mounted() { + // when the liveview mounts, create the BS modal + const modal = new Modal(this.el); + // and trigger BS modal to show + modal.show(); + + // when the BS modal hides, send 'close' to the liveview + this.el.addEventListener("hidden.bs.modal", (event) => { + this.pushEventTo(`#${this.el.getAttribute("id")}`, "close", {}); + modal.dispose(); + }); + + // liveview can send this event to tell BS modal to close + // ex.: on successful form save, instead of immediate redirect + // this event hides the BS modal, which triggers the above, + // which sends 'close' to liveview and disposes the BS modal + this.handleEvent("modal-please-hide", (payload) => { + modal.hide(); + }); + }, + + destroyed() { + // when the liveview is destroyed, + // modal-backdrop must be forcibly removed + const backdrop = document.querySelector(".modal-backdrop"); + if (backdrop) backdrop.parentElement.removeChild(backdrop); + }, +}; diff --git a/assets/js/app.js b/assets/js/app.js index b9765da..a337a46 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -37,17 +37,20 @@ import topbar from "topbar"; import { LiveSocket } from "phoenix_live_view"; // Bootstrap v5 js imports +import "bootstrap/js/dist/alert"; import "bootstrap/js/dist/collapse"; import "bootstrap/js/dist/dropdown"; -import "bootstrap/js/dist/alert"; -// Boostrap helpers +// Bootstrap helpers import "./_hamburger-helper"; import "./_form-validity"; +// Bootstrap-liveview helpers import { AlertRemover } from "./_alert-remover"; +import { BsModal } from "./_bs_modal"; // LiveSocket setup let Hooks = {}; Hooks.AlertRemover = AlertRemover; +Hooks.BsModal = BsModal; let csrfToken = document .querySelector("meta[name='csrf-token']") .getAttribute("content"); diff --git a/assets/package-lock.json b/assets/package-lock.json index 9814230..f0137bf 100644 --- a/assets/package-lock.json +++ b/assets/package-lock.json @@ -9,6 +9,7 @@ "@fontsource/lato": "^4.2.1", "@mdi/svg": "^5.9.55", "@popperjs/core": "^2.8.4", + "alpinejs": "^2.8.1", "bootstrap": "^5.0.0-beta2", "bootstrap-icons": "^1.4.0", "hamburgers": "^1.1.3", @@ -61,23 +62,23 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.13.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.13.6.tgz", - "integrity": "sha512-VhgqKOWYVm7lQXlvbJnWOzwfAQATd2nV52koT0HZ/LdDH0m4DUDwkKYsH+IwpXb+bKPyBJzawA4I6nBKqZcpQw==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.13.8.tgz", + "integrity": "sha512-EaI33z19T4qN3xLXsGf48M2cDqa6ei9tPZlfLdb2HC+e/cFtREiRd8hdSqDbwdLB0/+gLwqJmCYASH0z2bUdog==", "dev": true }, "node_modules/@babel/core": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.13.1.tgz", - "integrity": "sha512-FzeKfFBG2rmFtGiiMdXZPFt/5R5DXubVi82uYhjGX4Msf+pgYQMCFIqFXZWs5vbIYbf14VeBIgdGI03CDOOM1w==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.13.8.tgz", + "integrity": "sha512-oYapIySGw1zGhEFRd6lzWNLWFX2s5dA/jm+Pw/+59ZdXtjyIuwlXbrId22Md0rgZVop+aVoqow2riXhBLNyuQg==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", "@babel/generator": "^7.13.0", - "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-compilation-targets": "^7.13.8", "@babel/helper-module-transforms": "^7.13.0", "@babel/helpers": "^7.13.0", - "@babel/parser": "^7.13.0", + "@babel/parser": "^7.13.4", "@babel/template": "^7.12.13", "@babel/traverse": "^7.13.0", "@babel/types": "^7.13.0", @@ -86,7 +87,7 @@ "gensync": "^1.0.0-beta.2", "json5": "^2.1.2", "lodash": "^4.17.19", - "semver": "7.0.0", + "semver": "^6.3.0", "source-map": "^0.5.0" }, "engines": { @@ -97,6 +98,15 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/generator": { "version": "7.13.0", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.0.tgz", @@ -128,20 +138,29 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.0.tgz", - "integrity": "sha512-SOWD0JK9+MMIhTQiUVd4ng8f3NXhPVQvTv7D3UN4wbp/6cAHnB2EmMaU1zZA2Hh1gwme+THBrVSqTFxHczTh0Q==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.8.tgz", + "integrity": "sha512-pBljUGC1y3xKLn1nrx2eAhurLMA8OqBtBP/JwG4U8skN7kf8/aqwwxpV1N6T0e7r6+7uNitIa/fUxPFagSXp3A==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.13.0", + "@babel/compat-data": "^7.13.8", "@babel/helper-validator-option": "^7.12.17", "browserslist": "^4.14.5", - "semver": "7.0.0" + "semver": "^6.3.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.13.0", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.0.tgz", @@ -397,14 +416,14 @@ } }, "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.13.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.13.5.tgz", - "integrity": "sha512-8cErJEDzhZgNKzYyjCKsHuyPqtWxG8gc9h4OFSUDJu0vCAOsObPU2LcECnW0kJwh/b+uUz46lObVzIXw0fzAbA==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.13.8.tgz", + "integrity": "sha512-rPBnhj+WgoSmgq+4gQUtXx/vOcU+UYtjy1AA/aeD61Hwj410fwYyqfUcRP3lR8ucgliVJL/G7sXcNUecC75IXA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.13.0", "@babel/helper-remap-async-to-generator": "^7.13.0", - "@babel/plugin-syntax-async-generators": "^7.8.0" + "@babel/plugin-syntax-async-generators": "^7.8.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" @@ -424,13 +443,13 @@ } }, "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.17.tgz", - "integrity": "sha512-ZNGoFZqrnuy9H2izB2jLlnNDAfVPlGl5NhFEiFe4D84ix9GQGygF+CWMGHKuE+bpyS/AOuDQCnkiRNqW2IzS1Q==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.13.8.tgz", + "integrity": "sha512-ONWKj0H6+wIRCkZi9zSbZtE/r73uOhMVHh256ys0UzfM7I3d4n+spZNWjOnJv2gzopumP2Wxi186vI8N0Y2JyQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13", - "@babel/plugin-syntax-dynamic-import": "^7.8.0" + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" }, "peerDependencies": { "@babel/core": "^7.0.0-0" @@ -450,25 +469,25 @@ } }, "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.13.tgz", - "integrity": "sha512-v9eEi4GiORDg8x+Dmi5r8ibOe0VXoKDeNPYcTTxdGN4eOWikrJfDJCJrr1l5gKGvsNyGJbrfMftC2dTL6oz7pg==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.13.8.tgz", + "integrity": "sha512-w4zOPKUFPX1mgvTmL/fcEqy34hrQ1CRcGxdphBc6snDnnqJ47EZDIyop6IwXzAC8G916hsIuXB2ZMBCExC5k7Q==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13", - "@babel/plugin-syntax-json-strings": "^7.8.0" + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/plugin-syntax-json-strings": "^7.8.3" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.13.tgz", - "integrity": "sha512-fqmiD3Lz7jVdK6kabeSr1PZlWSUVqSitmHEe3Z00dtGTKieWnX9beafvavc32kjORa5Bai4QNHgFDwWJP+WtSQ==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.13.8.tgz", + "integrity": "sha512-aul6znYB4N4HGweImqKn59Su9RS8lbUIqxtXTOcAGtNIDczoEFv+l1EhmX8rUBp3G1jMjKJm8m0jXVp63ZpS4A==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "peerDependencies": { @@ -476,13 +495,13 @@ } }, "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.13.0.tgz", - "integrity": "sha512-UkAvFA/9+lBBL015gjA68NvKiCReNxqFLm3SdNKaM3XXoDisA7tMAIX4PmIwatFoFqMxxT3WyG9sK3MO0Kting==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.13.8.tgz", + "integrity": "sha512-iePlDPBn//UhxExyS9KyeYU7RM9WScAG+D3Hhno0PLJebAEpDZMocbDe64eqynhNAnwz/vZoL/q/QB2T1OH39A==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.13.0", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "peerDependencies": { "@babel/core": "^7.0.0-0" @@ -502,13 +521,15 @@ } }, "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.13.0.tgz", - "integrity": "sha512-B4qphdSTp0nLsWcuei07JPKeZej4+Hd22MdnulJXQa1nCcGSBlk8FiqenGERaPZ+PuYhz4Li2Wjc8yfJvHgUMw==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.13.8.tgz", + "integrity": "sha512-DhB2EuB1Ih7S3/IRX5AFVgZ16k3EzfRbq97CxAVI1KSYcW+lexV8VZb7G7L8zuPVSdQMRn0kiBpf/Yzu9ZKH0g==", "dev": true, "dependencies": { + "@babel/compat-data": "^7.13.8", + "@babel/helper-compilation-targets": "^7.13.8", "@babel/helper-plugin-utils": "^7.13.0", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-transform-parameters": "^7.13.0" }, "peerDependencies": { @@ -516,27 +537,27 @@ } }, "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.13.tgz", - "integrity": "sha512-9+MIm6msl9sHWg58NvqpNpLtuFbmpFYk37x8kgnGzAHvX35E1FyAwSUt5hIkSoWJFSAH+iwU8bJ4fcD1zKXOzg==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.13.8.tgz", + "integrity": "sha512-0wS/4DUF1CuTmGo+NiaHfHcVSeSLj5S3e6RivPTg/2k3wOv3jO35tZ6/ZWsQhQMvdgI7CwphjQa/ccarLymHVA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.13.0.tgz", - "integrity": "sha512-OVRQOZEBP2luZrvEbNSX5FfWDousthhdEoAOpej+Tpe58HFLvqRClT89RauIvBuCDFEip7GW1eT86/5lMy2RNA==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.13.8.tgz", + "integrity": "sha512-hpbBwbTgd7Cz1QryvwJZRo1U0k1q8uyBmeXOSQUjdg/A2TASkhR/rz7AyqZ/kS8kbpsNA80rOYbxySBJAqmhhQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.13.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1", - "@babel/plugin-syntax-optional-chaining": "^7.8.0" + "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "peerDependencies": { "@babel/core": "^7.0.0-0" @@ -909,9 +930,9 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.13.0.tgz", - "integrity": "sha512-j7397PkIB4lcn25U2dClK6VLC6pr2s3q+wbE8R3vJvY6U1UTBBj0n6F+5v6+Fd/UwfDPAorMOs2TV+T4M+owpQ==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.13.8.tgz", + "integrity": "sha512-9QiOx4MEGglfYZ4XOnU79OHr6vIWUakIj9b4mioN8eQIoEh+pf5p/zEB36JpDFWA12nNMiRf7bfoRvl9Rn79Bw==", "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.13.0", @@ -924,14 +945,14 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.13.tgz", - "integrity": "sha512-aHfVjhZ8QekaNF/5aNdStCGzwTbU7SI5hUybBKlMzqIMC7w7Ho8hx5a4R/DkTHfRfLwHGGxSpFt9BfxKCoXKoA==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.13.8.tgz", + "integrity": "sha512-hwqctPYjhM6cWvVIlOIe27jCIBgHCsdH2xCJVAYQm7V5yTMoilbVMi9f6wKg0rpQAOn6ZG4AOyvCqFF/hUh6+A==", "dev": true, "dependencies": { - "@babel/helper-hoist-variables": "^7.12.13", - "@babel/helper-module-transforms": "^7.12.13", - "@babel/helper-plugin-utils": "^7.12.13", + "@babel/helper-hoist-variables": "^7.13.0", + "@babel/helper-module-transforms": "^7.13.0", + "@babel/helper-plugin-utils": "^7.13.0", "@babel/helper-validator-identifier": "^7.12.11", "babel-plugin-dynamic-import-node": "^2.3.3" }, @@ -1124,39 +1145,39 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.13.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.13.5.tgz", - "integrity": "sha512-xUeKBIIcbwxGevyWMSWZOW98W1lp7toITvVsMxSddCEQy932yYiF4fCB+CG3E/MXzFX3KbefgvCqEQ7TDoE6UQ==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.13.9.tgz", + "integrity": "sha512-mcsHUlh2rIhViqMG823JpscLMesRt3QbMsv1+jhopXEb3W2wXvQ9QoiOlZI9ZbR3XqPtaFpZwEZKYqGJnGMZTQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.13.5", - "@babel/helper-compilation-targets": "^7.13.0", + "@babel/compat-data": "^7.13.8", + "@babel/helper-compilation-targets": "^7.13.8", "@babel/helper-plugin-utils": "^7.13.0", "@babel/helper-validator-option": "^7.12.17", - "@babel/plugin-proposal-async-generator-functions": "^7.13.5", + "@babel/plugin-proposal-async-generator-functions": "^7.13.8", "@babel/plugin-proposal-class-properties": "^7.13.0", - "@babel/plugin-proposal-dynamic-import": "^7.12.17", + "@babel/plugin-proposal-dynamic-import": "^7.13.8", "@babel/plugin-proposal-export-namespace-from": "^7.12.13", - "@babel/plugin-proposal-json-strings": "^7.12.13", - "@babel/plugin-proposal-logical-assignment-operators": "^7.12.13", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.0", + "@babel/plugin-proposal-json-strings": "^7.13.8", + "@babel/plugin-proposal-logical-assignment-operators": "^7.13.8", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", "@babel/plugin-proposal-numeric-separator": "^7.12.13", - "@babel/plugin-proposal-object-rest-spread": "^7.13.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.12.13", - "@babel/plugin-proposal-optional-chaining": "^7.13.0", + "@babel/plugin-proposal-object-rest-spread": "^7.13.8", + "@babel/plugin-proposal-optional-catch-binding": "^7.13.8", + "@babel/plugin-proposal-optional-chaining": "^7.13.8", "@babel/plugin-proposal-private-methods": "^7.13.0", "@babel/plugin-proposal-unicode-property-regex": "^7.12.13", - "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-top-level-await": "^7.12.13", "@babel/plugin-transform-arrow-functions": "^7.13.0", "@babel/plugin-transform-async-to-generator": "^7.13.0", @@ -1173,8 +1194,8 @@ "@babel/plugin-transform-literals": "^7.12.13", "@babel/plugin-transform-member-expression-literals": "^7.12.13", "@babel/plugin-transform-modules-amd": "^7.13.0", - "@babel/plugin-transform-modules-commonjs": "^7.13.0", - "@babel/plugin-transform-modules-systemjs": "^7.12.13", + "@babel/plugin-transform-modules-commonjs": "^7.13.8", + "@babel/plugin-transform-modules-systemjs": "^7.13.8", "@babel/plugin-transform-modules-umd": "^7.13.0", "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.13", "@babel/plugin-transform-new-target": "^7.12.13", @@ -1190,18 +1211,27 @@ "@babel/plugin-transform-typeof-symbol": "^7.12.13", "@babel/plugin-transform-unicode-escapes": "^7.12.13", "@babel/plugin-transform-unicode-regex": "^7.12.13", - "@babel/preset-modules": "^0.1.3", + "@babel/preset-modules": "^0.1.4", "@babel/types": "^7.13.0", "babel-plugin-polyfill-corejs2": "^0.1.4", "babel-plugin-polyfill-corejs3": "^0.1.3", "babel-plugin-polyfill-regenerator": "^0.1.2", "core-js-compat": "^3.9.0", - "semver": "7.0.0" + "semver": "^6.3.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/preset-modules": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", @@ -1334,9 +1364,9 @@ } }, "node_modules/@popperjs/core": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.8.4.tgz", - "integrity": "sha512-h0lY7g36rhjNV8KVHKS3/BEOgfsxu0AiRI8+ry5IFBGEsQFkpjxtcpVc9ndN8zrKUeMZXAWMc7eQMepfgykpxQ==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.0.tgz", + "integrity": "sha512-wjtKehFAIARq2OxK8j3JrggNlEslJfNuSm2ArteIbKyRMts2g0a7KzTxfRVNUM+O0gnBJ2hNV8nWPOYBgI1sew==", "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" @@ -1642,6 +1672,11 @@ "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", "dev": true }, + "node_modules/alpinejs": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-2.8.1.tgz", + "integrity": "sha512-ETJ/k0fbiBeP+OSd5Fhj70c+zb+YRzcVbyh5DVeLT3FBWMUeUvjOSWLi53IVLPSehaT2SKmB7w08WGF2jYTqNA==" + }, "node_modules/ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -2583,9 +2618,9 @@ } }, "node_modules/css-loader": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.1.0.tgz", - "integrity": "sha512-mFs3Xe2UrzRzL0+ML6e7Q2e/Ozp/WpDcam0l1X+rXgkuFjjsNSrjiyimG6malUOZGVuEjzKp1NqEqN3exG7ZqQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.1.1.tgz", + "integrity": "sha512-5FfhpjwtuRgxqmusDidowqmLlcb+1HgnEDMsi2JhiUrZUcoc+cqw+mUtMIF/+OfeMYaaFCLYp1TaIt9H6I/fKA==", "dev": true, "dependencies": { "camelcase": "^6.2.0", @@ -4856,9 +4891,9 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.3.8.tgz", - "integrity": "sha512-u+2kVov/Gcs74iz+x3phEBWMAGw2djjnKfYez+Pl/b5dyXL7aM4Lp5QQtIq16CDwRHT/woUJki49gBNMhfm1eA==", + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.3.9.tgz", + "integrity": "sha512-Ac4s+xhVbqlyhXS5J/Vh/QXUz3ycXlCqoCPpg0vdfhsIBH9eg/It/9L1r1XhSCH737M1lqcWnMuWL13zcygn5A==", "dev": true, "dependencies": { "loader-utils": "^2.0.0", @@ -9798,23 +9833,23 @@ } }, "@babel/compat-data": { - "version": "7.13.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.13.6.tgz", - "integrity": "sha512-VhgqKOWYVm7lQXlvbJnWOzwfAQATd2nV52koT0HZ/LdDH0m4DUDwkKYsH+IwpXb+bKPyBJzawA4I6nBKqZcpQw==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.13.8.tgz", + "integrity": "sha512-EaI33z19T4qN3xLXsGf48M2cDqa6ei9tPZlfLdb2HC+e/cFtREiRd8hdSqDbwdLB0/+gLwqJmCYASH0z2bUdog==", "dev": true }, "@babel/core": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.13.1.tgz", - "integrity": "sha512-FzeKfFBG2rmFtGiiMdXZPFt/5R5DXubVi82uYhjGX4Msf+pgYQMCFIqFXZWs5vbIYbf14VeBIgdGI03CDOOM1w==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.13.8.tgz", + "integrity": "sha512-oYapIySGw1zGhEFRd6lzWNLWFX2s5dA/jm+Pw/+59ZdXtjyIuwlXbrId22Md0rgZVop+aVoqow2riXhBLNyuQg==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", "@babel/generator": "^7.13.0", - "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-compilation-targets": "^7.13.8", "@babel/helper-module-transforms": "^7.13.0", "@babel/helpers": "^7.13.0", - "@babel/parser": "^7.13.0", + "@babel/parser": "^7.13.4", "@babel/template": "^7.12.13", "@babel/traverse": "^7.13.0", "@babel/types": "^7.13.0", @@ -9823,8 +9858,16 @@ "gensync": "^1.0.0-beta.2", "json5": "^2.1.2", "lodash": "^4.17.19", - "semver": "7.0.0", + "semver": "^6.3.0", "source-map": "^0.5.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "@babel/generator": { @@ -9858,15 +9901,23 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.0.tgz", - "integrity": "sha512-SOWD0JK9+MMIhTQiUVd4ng8f3NXhPVQvTv7D3UN4wbp/6cAHnB2EmMaU1zZA2Hh1gwme+THBrVSqTFxHczTh0Q==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.8.tgz", + "integrity": "sha512-pBljUGC1y3xKLn1nrx2eAhurLMA8OqBtBP/JwG4U8skN7kf8/aqwwxpV1N6T0e7r6+7uNitIa/fUxPFagSXp3A==", "dev": true, "requires": { - "@babel/compat-data": "^7.13.0", + "@babel/compat-data": "^7.13.8", "@babel/helper-validator-option": "^7.12.17", "browserslist": "^4.14.5", - "semver": "7.0.0" + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "@babel/helper-create-class-features-plugin": { @@ -10108,14 +10159,14 @@ "dev": true }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.13.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.13.5.tgz", - "integrity": "sha512-8cErJEDzhZgNKzYyjCKsHuyPqtWxG8gc9h4OFSUDJu0vCAOsObPU2LcECnW0kJwh/b+uUz46lObVzIXw0fzAbA==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.13.8.tgz", + "integrity": "sha512-rPBnhj+WgoSmgq+4gQUtXx/vOcU+UYtjy1AA/aeD61Hwj410fwYyqfUcRP3lR8ucgliVJL/G7sXcNUecC75IXA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.13.0", "@babel/helper-remap-async-to-generator": "^7.13.0", - "@babel/plugin-syntax-async-generators": "^7.8.0" + "@babel/plugin-syntax-async-generators": "^7.8.4" } }, "@babel/plugin-proposal-class-properties": { @@ -10129,13 +10180,13 @@ } }, "@babel/plugin-proposal-dynamic-import": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.17.tgz", - "integrity": "sha512-ZNGoFZqrnuy9H2izB2jLlnNDAfVPlGl5NhFEiFe4D84ix9GQGygF+CWMGHKuE+bpyS/AOuDQCnkiRNqW2IzS1Q==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.13.8.tgz", + "integrity": "sha512-ONWKj0H6+wIRCkZi9zSbZtE/r73uOhMVHh256ys0UzfM7I3d4n+spZNWjOnJv2gzopumP2Wxi186vI8N0Y2JyQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13", - "@babel/plugin-syntax-dynamic-import": "^7.8.0" + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" } }, "@babel/plugin-proposal-export-namespace-from": { @@ -10149,33 +10200,33 @@ } }, "@babel/plugin-proposal-json-strings": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.13.tgz", - "integrity": "sha512-v9eEi4GiORDg8x+Dmi5r8ibOe0VXoKDeNPYcTTxdGN4eOWikrJfDJCJrr1l5gKGvsNyGJbrfMftC2dTL6oz7pg==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.13.8.tgz", + "integrity": "sha512-w4zOPKUFPX1mgvTmL/fcEqy34hrQ1CRcGxdphBc6snDnnqJ47EZDIyop6IwXzAC8G916hsIuXB2ZMBCExC5k7Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13", - "@babel/plugin-syntax-json-strings": "^7.8.0" + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/plugin-syntax-json-strings": "^7.8.3" } }, "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.13.tgz", - "integrity": "sha512-fqmiD3Lz7jVdK6kabeSr1PZlWSUVqSitmHEe3Z00dtGTKieWnX9beafvavc32kjORa5Bai4QNHgFDwWJP+WtSQ==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.13.8.tgz", + "integrity": "sha512-aul6znYB4N4HGweImqKn59Su9RS8lbUIqxtXTOcAGtNIDczoEFv+l1EhmX8rUBp3G1jMjKJm8m0jXVp63ZpS4A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" } }, "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.13.0.tgz", - "integrity": "sha512-UkAvFA/9+lBBL015gjA68NvKiCReNxqFLm3SdNKaM3XXoDisA7tMAIX4PmIwatFoFqMxxT3WyG9sK3MO0Kting==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.13.8.tgz", + "integrity": "sha512-iePlDPBn//UhxExyS9KyeYU7RM9WScAG+D3Hhno0PLJebAEpDZMocbDe64eqynhNAnwz/vZoL/q/QB2T1OH39A==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.13.0", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" } }, "@babel/plugin-proposal-numeric-separator": { @@ -10189,35 +10240,37 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.13.0.tgz", - "integrity": "sha512-B4qphdSTp0nLsWcuei07JPKeZej4+Hd22MdnulJXQa1nCcGSBlk8FiqenGERaPZ+PuYhz4Li2Wjc8yfJvHgUMw==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.13.8.tgz", + "integrity": "sha512-DhB2EuB1Ih7S3/IRX5AFVgZ16k3EzfRbq97CxAVI1KSYcW+lexV8VZb7G7L8zuPVSdQMRn0kiBpf/Yzu9ZKH0g==", "dev": true, "requires": { + "@babel/compat-data": "^7.13.8", + "@babel/helper-compilation-targets": "^7.13.8", "@babel/helper-plugin-utils": "^7.13.0", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-transform-parameters": "^7.13.0" } }, "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.13.tgz", - "integrity": "sha512-9+MIm6msl9sHWg58NvqpNpLtuFbmpFYk37x8kgnGzAHvX35E1FyAwSUt5hIkSoWJFSAH+iwU8bJ4fcD1zKXOzg==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.13.8.tgz", + "integrity": "sha512-0wS/4DUF1CuTmGo+NiaHfHcVSeSLj5S3e6RivPTg/2k3wOv3jO35tZ6/ZWsQhQMvdgI7CwphjQa/ccarLymHVA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.12.13", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" } }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.13.0.tgz", - "integrity": "sha512-OVRQOZEBP2luZrvEbNSX5FfWDousthhdEoAOpej+Tpe58HFLvqRClT89RauIvBuCDFEip7GW1eT86/5lMy2RNA==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.13.8.tgz", + "integrity": "sha512-hpbBwbTgd7Cz1QryvwJZRo1U0k1q8uyBmeXOSQUjdg/A2TASkhR/rz7AyqZ/kS8kbpsNA80rOYbxySBJAqmhhQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.13.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1", - "@babel/plugin-syntax-optional-chaining": "^7.8.0" + "@babel/plugin-syntax-optional-chaining": "^7.8.3" } }, "@babel/plugin-proposal-private-methods": { @@ -10497,9 +10550,9 @@ } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.13.0.tgz", - "integrity": "sha512-j7397PkIB4lcn25U2dClK6VLC6pr2s3q+wbE8R3vJvY6U1UTBBj0n6F+5v6+Fd/UwfDPAorMOs2TV+T4M+owpQ==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.13.8.tgz", + "integrity": "sha512-9QiOx4MEGglfYZ4XOnU79OHr6vIWUakIj9b4mioN8eQIoEh+pf5p/zEB36JpDFWA12nNMiRf7bfoRvl9Rn79Bw==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.13.0", @@ -10509,14 +10562,14 @@ } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.13.tgz", - "integrity": "sha512-aHfVjhZ8QekaNF/5aNdStCGzwTbU7SI5hUybBKlMzqIMC7w7Ho8hx5a4R/DkTHfRfLwHGGxSpFt9BfxKCoXKoA==", + "version": "7.13.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.13.8.tgz", + "integrity": "sha512-hwqctPYjhM6cWvVIlOIe27jCIBgHCsdH2xCJVAYQm7V5yTMoilbVMi9f6wKg0rpQAOn6ZG4AOyvCqFF/hUh6+A==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.12.13", - "@babel/helper-module-transforms": "^7.12.13", - "@babel/helper-plugin-utils": "^7.12.13", + "@babel/helper-hoist-variables": "^7.13.0", + "@babel/helper-module-transforms": "^7.13.0", + "@babel/helper-plugin-utils": "^7.13.0", "@babel/helper-validator-identifier": "^7.12.11", "babel-plugin-dynamic-import-node": "^2.3.3" } @@ -10661,39 +10714,39 @@ } }, "@babel/preset-env": { - "version": "7.13.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.13.5.tgz", - "integrity": "sha512-xUeKBIIcbwxGevyWMSWZOW98W1lp7toITvVsMxSddCEQy932yYiF4fCB+CG3E/MXzFX3KbefgvCqEQ7TDoE6UQ==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.13.9.tgz", + "integrity": "sha512-mcsHUlh2rIhViqMG823JpscLMesRt3QbMsv1+jhopXEb3W2wXvQ9QoiOlZI9ZbR3XqPtaFpZwEZKYqGJnGMZTQ==", "dev": true, "requires": { - "@babel/compat-data": "^7.13.5", - "@babel/helper-compilation-targets": "^7.13.0", + "@babel/compat-data": "^7.13.8", + "@babel/helper-compilation-targets": "^7.13.8", "@babel/helper-plugin-utils": "^7.13.0", "@babel/helper-validator-option": "^7.12.17", - "@babel/plugin-proposal-async-generator-functions": "^7.13.5", + "@babel/plugin-proposal-async-generator-functions": "^7.13.8", "@babel/plugin-proposal-class-properties": "^7.13.0", - "@babel/plugin-proposal-dynamic-import": "^7.12.17", + "@babel/plugin-proposal-dynamic-import": "^7.13.8", "@babel/plugin-proposal-export-namespace-from": "^7.12.13", - "@babel/plugin-proposal-json-strings": "^7.12.13", - "@babel/plugin-proposal-logical-assignment-operators": "^7.12.13", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.0", + "@babel/plugin-proposal-json-strings": "^7.13.8", + "@babel/plugin-proposal-logical-assignment-operators": "^7.13.8", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", "@babel/plugin-proposal-numeric-separator": "^7.12.13", - "@babel/plugin-proposal-object-rest-spread": "^7.13.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.12.13", - "@babel/plugin-proposal-optional-chaining": "^7.13.0", + "@babel/plugin-proposal-object-rest-spread": "^7.13.8", + "@babel/plugin-proposal-optional-catch-binding": "^7.13.8", + "@babel/plugin-proposal-optional-chaining": "^7.13.8", "@babel/plugin-proposal-private-methods": "^7.13.0", "@babel/plugin-proposal-unicode-property-regex": "^7.12.13", - "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-top-level-await": "^7.12.13", "@babel/plugin-transform-arrow-functions": "^7.13.0", "@babel/plugin-transform-async-to-generator": "^7.13.0", @@ -10710,8 +10763,8 @@ "@babel/plugin-transform-literals": "^7.12.13", "@babel/plugin-transform-member-expression-literals": "^7.12.13", "@babel/plugin-transform-modules-amd": "^7.13.0", - "@babel/plugin-transform-modules-commonjs": "^7.13.0", - "@babel/plugin-transform-modules-systemjs": "^7.12.13", + "@babel/plugin-transform-modules-commonjs": "^7.13.8", + "@babel/plugin-transform-modules-systemjs": "^7.13.8", "@babel/plugin-transform-modules-umd": "^7.13.0", "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.13", "@babel/plugin-transform-new-target": "^7.12.13", @@ -10727,13 +10780,21 @@ "@babel/plugin-transform-typeof-symbol": "^7.12.13", "@babel/plugin-transform-unicode-escapes": "^7.12.13", "@babel/plugin-transform-unicode-regex": "^7.12.13", - "@babel/preset-modules": "^0.1.3", + "@babel/preset-modules": "^0.1.4", "@babel/types": "^7.13.0", "babel-plugin-polyfill-corejs2": "^0.1.4", "babel-plugin-polyfill-corejs3": "^0.1.3", "babel-plugin-polyfill-regenerator": "^0.1.2", "core-js-compat": "^3.9.0", - "semver": "7.0.0" + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "@babel/preset-modules": { @@ -10850,9 +10911,9 @@ } }, "@popperjs/core": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.8.4.tgz", - "integrity": "sha512-h0lY7g36rhjNV8KVHKS3/BEOgfsxu0AiRI8+ry5IFBGEsQFkpjxtcpVc9ndN8zrKUeMZXAWMc7eQMepfgykpxQ==" + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.0.tgz", + "integrity": "sha512-wjtKehFAIARq2OxK8j3JrggNlEslJfNuSm2ArteIbKyRMts2g0a7KzTxfRVNUM+O0gnBJ2hNV8nWPOYBgI1sew==" }, "@types/eslint": { "version": "7.2.6", @@ -11126,6 +11187,11 @@ "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", "dev": true }, + "alpinejs": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-2.8.1.tgz", + "integrity": "sha512-ETJ/k0fbiBeP+OSd5Fhj70c+zb+YRzcVbyh5DVeLT3FBWMUeUvjOSWLi53IVLPSehaT2SKmB7w08WGF2jYTqNA==" + }, "ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -11850,9 +11916,9 @@ } }, "css-loader": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.1.0.tgz", - "integrity": "sha512-mFs3Xe2UrzRzL0+ML6e7Q2e/Ozp/WpDcam0l1X+rXgkuFjjsNSrjiyimG6malUOZGVuEjzKp1NqEqN3exG7ZqQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.1.1.tgz", + "integrity": "sha512-5FfhpjwtuRgxqmusDidowqmLlcb+1HgnEDMsi2JhiUrZUcoc+cqw+mUtMIF/+OfeMYaaFCLYp1TaIt9H6I/fKA==", "dev": true, "requires": { "camelcase": "^6.2.0", @@ -13572,9 +13638,9 @@ "dev": true }, "mini-css-extract-plugin": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.3.8.tgz", - "integrity": "sha512-u+2kVov/Gcs74iz+x3phEBWMAGw2djjnKfYez+Pl/b5dyXL7aM4Lp5QQtIq16CDwRHT/woUJki49gBNMhfm1eA==", + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.3.9.tgz", + "integrity": "sha512-Ac4s+xhVbqlyhXS5J/Vh/QXUz3ycXlCqoCPpg0vdfhsIBH9eg/It/9L1r1XhSCH737M1lqcWnMuWL13zcygn5A==", "dev": true, "requires": { "loader-utils": "^2.0.0", diff --git a/assets/package.json b/assets/package.json index bf341fb..c527731 100644 --- a/assets/package.json +++ b/assets/package.json @@ -10,6 +10,7 @@ "@fontsource/lato": "^4.2.1", "@mdi/svg": "^5.9.55", "@popperjs/core": "^2.8.4", + "alpinejs": "^2.8.1", "bootstrap": "^5.0.0-beta2", "bootstrap-icons": "^1.4.0", "hamburgers": "^1.1.3", diff --git a/lib/bones73k_web/live/modal_component.ex b/lib/bones73k_web/live/modal_component.ex index 403245f..8d5ec26 100644 --- a/lib/bones73k_web/live/modal_component.ex +++ b/lib/bones73k_web/live/modal_component.ex @@ -4,16 +4,26 @@ defmodule Bones73kWeb.ModalComponent do @impl true def render(assigns) do ~L""" -
-
- <%= live_patch raw("×"), to: @return_to, class: "phx-modal-close" %> - <%= live_component @socket, @component, @opts %> +
""" @@ -23,4 +33,9 @@ defmodule Bones73kWeb.ModalComponent do def handle_event("close", _, socket) do {:noreply, push_patch(socket, to: socket.assigns.return_to)} end + + @impl true + def handle_event("hide", _, socket) do + {:noreply, push_event(socket, "modal-please-hide", %{})} + end end diff --git a/lib/bones73k_web/live/property_live/form_component.ex b/lib/bones73k_web/live/property_live/form_component.ex index 00357b3..ef5f902 100644 --- a/lib/bones73k_web/live/property_live/form_component.ex +++ b/lib/bones73k_web/live/property_live/form_component.ex @@ -5,12 +5,10 @@ defmodule Bones73kWeb.PropertyLive.FormComponent do @impl true def update(%{property: property} = assigns, socket) do - changeset = Properties.change_property(property) - - {:ok, - socket - |> assign(assigns) - |> assign(:changeset, changeset)} + socket + |> assign(assigns) + |> assign(:changeset, Properties.change_property(property)) + |> live_okreply() end @impl true @@ -30,10 +28,10 @@ defmodule Bones73kWeb.PropertyLive.FormComponent do defp save_property(socket, :edit, property_params) do case Properties.update_property(socket.assigns.property, property_params) do {:ok, _property} -> - {:noreply, - socket - |> put_flash(:info, "Property updated successfully") - |> push_redirect(to: socket.assigns.return_to)} + socket + |> put_flash(:info, "Property updated successfully") + |> push_event("modal-please-hide", %{}) + |> live_noreply() {:error, %Ecto.Changeset{} = changeset} -> {:noreply, assign(socket, :changeset, changeset)} @@ -46,10 +44,10 @@ defmodule Bones73kWeb.PropertyLive.FormComponent do case Properties.create_property(property_params) do {:ok, _property} -> - {:noreply, - socket - |> put_flash(:info, "Property created successfully") - |> push_redirect(to: socket.assigns.return_to)} + socket + |> put_flash(:info, "Property created successfully") + |> push_event("modal-please-hide", %{}) + |> live_noreply() {:error, %Ecto.Changeset{} = changeset} -> {:noreply, assign(socket, changeset: changeset)} diff --git a/lib/bones73k_web/live/property_live/form_component.html.leex b/lib/bones73k_web/live/property_live/form_component.html.leex index 31841ec..a25b1f8 100644 --- a/lib/bones73k_web/live/property_live/form_component.html.leex +++ b/lib/bones73k_web/live/property_live/form_component.html.leex @@ -1,22 +1,44 @@ -

<%= @title %>

+<%= form_for @changeset, "#", [ + phx_target: @myself, + phx_change: "validate", + phx_submit: "save" + ], fn f -> %> -<%= f = form_for @changeset, "#", - id: "property-form", - phx_target: @myself, - phx_change: "validate", - phx_submit: "save" %> - <%= label f, :name %> - <%= text_input f, :name %> - <%= error_tag f, :name %> +
+ <%= label f, :name, class: "form-label" %> +
+ <%= text_input f, :name, + class: input_class(f, :name, "form-control"), + aria_describedby: error_id(f, :name) + %> + <%= error_tag f, :name %> +
+
- <%= label f, :price %> - <%= number_input f, :price, step: "any" %> - <%= error_tag f, :price %> +
+ <%= label f, :price, class: "form-label" %> +
+ <%= number_input f, :price, + class: input_class(f, :price, "form-control"), + step: "any", + aria_describedby: error_id(f, :price) + %> + <%= error_tag f, :price %> +
+
- <%= label f, :description %> - <%= textarea f, :description %> - <%= error_tag f, :description %> +
+ <%= label f, :description, class: "form-label" %> +
+ <%= textarea f, :description, + class: input_class(f, :description, "form-control"), + aria_describedby: error_id(f, :description) + %> + <%= error_tag f, :description %> +
+
- <%= submit "Save", phx_disable_with: "Saving..." %> - + <%= submit "Save", phx_disable_with: "Saving...", class: "btn btn-primary" %> + +<% end %> diff --git a/lib/bones73k_web/live/user/registration.ex b/lib/bones73k_web/live/user/registration.ex index 0ad56c7..977c47a 100644 --- a/lib/bones73k_web/live/user/registration.ex +++ b/lib/bones73k_web/live/user/registration.ex @@ -30,7 +30,7 @@ defmodule Bones73kWeb.UserLive.Registration do @impl true def handle_event("validate", %{"user" => user_params}, socket) do cs = Accounts.change_user_registration(%User{}, user_params) - {:noreply, assign(socket, changeset: %{cs | action: :update})} + {:noreply, assign(socket, changeset: %{cs | action: :validate})} end @impl true diff --git a/lib/bones73k_web/live/user/reset_password.ex b/lib/bones73k_web/live/user/reset_password.ex index b7d751b..0594546 100644 --- a/lib/bones73k_web/live/user/reset_password.ex +++ b/lib/bones73k_web/live/user/reset_password.ex @@ -19,7 +19,7 @@ defmodule Bones73kWeb.UserLive.ResetPassword do @impl true def handle_event("validate", %{"user" => user_params}, socket) do cs = Accounts.change_user_password(socket.assigns.user, user_params) - {:noreply, socket |> assign(changeset: %{cs | action: :update})} + {:noreply, socket |> assign(changeset: %{cs | action: :validate})} end def handle_event("save", %{"user" => user_params}, socket) do @@ -34,7 +34,7 @@ defmodule Bones73kWeb.UserLive.ResetPassword do {:noreply, socket |> put_flash(:error, "Please check the errors below.") - |> assign(changeset: %{changeset | action: :update})} + |> assign(changeset: changeset)} end end end diff --git a/lib/bones73k_web/live/user/settings/email.ex b/lib/bones73k_web/live/user/settings/email.ex index 341ed0f..49915d6 100644 --- a/lib/bones73k_web/live/user/settings/email.ex +++ b/lib/bones73k_web/live/user/settings/email.ex @@ -20,7 +20,7 @@ defmodule Bones73kWeb.UserLive.Settings.Email do @impl true def handle_event("validate", %{"user" => user_params}, socket) do cs = get_changeset(socket.assigns.current_user, user_params) - {:noreply, assign(socket, changeset: %{cs | action: :update})} + {:noreply, assign(socket, changeset: %{cs | action: :validate})} end # user_settings_path GET /users/settings/confirm_email/:token Bones73kWeb.UserSettingsController :confirm_email diff --git a/lib/bones73k_web/live/user/settings/email.html.leex b/lib/bones73k_web/live/user/settings/email.html.leex index ee5a505..353b07d 100644 --- a/lib/bones73k_web/live/user/settings/email.html.leex +++ b/lib/bones73k_web/live/user/settings/email.html.leex @@ -30,6 +30,7 @@ <%= icon_div @socket, "bi-lock", [class: "icon fs-5"] %> <%= password_input f, :current_password, + value: input_value(f, :current_password), class: "form-control", required: true, aria_describedby: error_id(f, :current_password) diff --git a/lib/bones73k_web/live/user/settings/password.ex b/lib/bones73k_web/live/user/settings/password.ex index 2225ff9..4a670af 100644 --- a/lib/bones73k_web/live/user/settings/password.ex +++ b/lib/bones73k_web/live/user/settings/password.ex @@ -30,7 +30,7 @@ defmodule Bones73kWeb.UserLive.Settings.Password do @impl true def handle_event("validate", %{"user" => user_params}, socket) do cs = get_changeset(socket.assigns.current_user, user_params) - {:noreply, assign(socket, changeset: %{cs | action: :update})} + {:noreply, assign(socket, changeset: %{cs | action: :validate})} end @impl true diff --git a/lib/bones73k_web/live/user/settings/password.html.leex b/lib/bones73k_web/live/user/settings/password.html.leex index 736b261..7c7debc 100644 --- a/lib/bones73k_web/live/user/settings/password.html.leex +++ b/lib/bones73k_web/live/user/settings/password.html.leex @@ -44,6 +44,7 @@ <%= icon_div @socket, "bi-lock", [class: "icon fs-5"] %> <%= password_input f, :current_password, + value: input_value(f, :current_password), class: "form-control", required: true, aria_describedby: error_id(f, :current_password) diff --git a/lib/bones73k_web/templates/other/index.html.eex b/lib/bones73k_web/templates/other/index.html.eex index b42a562..531dfaf 100644 --- a/lib/bones73k_web/templates/other/index.html.eex +++ b/lib/bones73k_web/templates/other/index.html.eex @@ -11,27 +11,31 @@
%>

- Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatibus dolore sunt quia aperiam sint id - reprehenderit? Dolore incidunt alias inventore accusantium nulla optio, ducimus eius aliquam hic, pariatur - voluptate distinctio. + Praesent velit justo, auctor ut nibh id, fermentum eleifend nunc. Cras sed purus dignissim, ornare elit et, ultrices elit. Sed quis neque consequat, laoreet ante a, hendrerit elit. Maecenas dapibus sed nulla vitae consectetur. Duis sollicitudin augue nisl, et rhoncus enim tempor at. Fusce scelerisque sollicitudin purus sit amet iaculis. Phasellus lacinia mi ut laoreet accumsan. Sed sagittis erat nec sem placerat, ut volutpat neque porttitor. Suspendisse tempor mauris vel mollis sagittis. In ut laoreet arcu. Duis sed felis in dui imperdiet luctus nec faucibus sem. Donec commodo urna ut enim fringilla, quis lacinia ligula malesuada. Quisque feugiat fermentum pretium. Integer sed porttitor lacus, sed bibendum diam. Aliquam dapibus neque et pharetra interdum.

-<%#
-
+ + -
- Other Page + + %> +
diff --git a/lib/bones73k_web/views/error_helpers.ex b/lib/bones73k_web/views/error_helpers.ex index 5ed367d..fb44ac6 100644 --- a/lib/bones73k_web/views/error_helpers.ex +++ b/lib/bones73k_web/views/error_helpers.ex @@ -30,37 +30,13 @@ defmodule Bones73kWeb.ErrorHelpers do def error_id(input_id) when is_binary(input_id), do: "#{input_id}_feedback" def input_class(form, field, classes \\ "") do - case field_status(form, field) do - :ok -> "#{classes} is-valid" - :error -> "#{classes} is-invalid" - _ -> classes - end - end - - defp field_status(form, field) do - case field_has_data?(form, field) do - true -> - form.errors - |> Keyword.get_values(field) - |> Enum.empty?() - |> case do - true -> :ok - false -> :error + case form.source.action do + nil -> classes + _ -> + case Keyword.has_key?(form.errors, field) do + true -> "#{classes} is-invalid" + _ -> "#{classes} is-valid" end - - false -> - :default - end - end - - defp field_has_data?(form, field) when is_atom(field), - do: field_has_data?(form, Atom.to_string(field)) - - defp field_has_data?(form, field) when is_binary(field) do - case Map.get(form.params, field) do - nil -> false - "" -> false - _ -> true end end