diff --git a/app/Enums/FormBlockInteractionType.php b/app/Enums/FormBlockInteractionType.php index 2aacebb2..7a829b7c 100644 --- a/app/Enums/FormBlockInteractionType.php +++ b/app/Enums/FormBlockInteractionType.php @@ -8,6 +8,7 @@ enum FormBlockInteractionType: string case textarea = 'textarea'; case button = 'button'; case consent = 'consent'; + case file = 'file'; case range = 'range'; diff --git a/app/Enums/FormBlockType.php b/app/Enums/FormBlockType.php index 1139e8a2..85f5ea32 100644 --- a/app/Enums/FormBlockType.php +++ b/app/Enums/FormBlockType.php @@ -12,6 +12,8 @@ enum FormBlockType: string case checkbox = 'checkbox'; case radio = 'radio'; + case file = 'input-file'; + case long = 'input-long'; case short = 'input-short'; case email = 'input-email'; diff --git a/app/Http/Controllers/Api/FormSubmitController.php b/app/Http/Controllers/Api/FormSubmitController.php index e710ab6c..a8ffb1b4 100644 --- a/app/Http/Controllers/Api/FormSubmitController.php +++ b/app/Http/Controllers/Api/FormSubmitController.php @@ -37,16 +37,22 @@ public function __invoke(Request $request, Form $form) { $request->validate([ 'token' => 'required|string', - 'payload' => 'array', + 'is_uploading' => 'boolean', + 'payload' => 'array|nullable', ]); $session = $form->formSessions() ->where('token', $request->input('token')) - ->firstOrFail() - ->submit($request->input('payload')); + ->firstOrFail(); - event(new FormSessionCompletedEvent($session)); + if (!is_null($request->payload)) { + $session->submit($request->input('payload')); + } - return response()->json($session, 200); + if (!$request->input('is_uploading', false)) { + event(new FormSessionCompletedEvent($session)); + } + + return response()->json($session->setHidden(['form']), 200); } } diff --git a/app/Http/Controllers/Api/FormUploadController.php b/app/Http/Controllers/Api/FormUploadController.php new file mode 100644 index 00000000..66ba6f09 --- /dev/null +++ b/app/Http/Controllers/Api/FormUploadController.php @@ -0,0 +1,38 @@ +validate([ + 'token' => 'required|string', + 'actionId' => 'required|string', + 'file' => 'file', + ]); + + $interaction = FormBlockInteraction::withUuid($request->input('actionId')) + ->firstOrFail(); + + // Validate that action belongs to the form + if ($interaction->formBlock->form->id !== $form->id) { + abort(404, 'Action not found'); + } + + $session = $form->formSessions() + ->where('token', $request->input('token')) + ->firstOrFail(); + + $sessionResponse = $session->formSessionResponses->where('form_block_interaction_id', $interaction->id)->first(); + + $upload = $sessionResponse->saveUpload($request->file('file')); + + return response()->json($upload, 201); + } +} diff --git a/app/Http/Controllers/Api/PurgeFormSubmissionsController.php b/app/Http/Controllers/Api/PurgeFormSubmissionsController.php index a12870b6..516166fe 100644 --- a/app/Http/Controllers/Api/PurgeFormSubmissionsController.php +++ b/app/Http/Controllers/Api/PurgeFormSubmissionsController.php @@ -18,7 +18,7 @@ public function __invoke(Form $form) { $this->authorize('update', $form); - $form->formSessions()->delete(); + $form->formSessions->each(fn ($session) => $session->delete()); return response()->json(null, 204); } diff --git a/app/Http/Controllers/FormUploadsDownloadController.php b/app/Http/Controllers/FormUploadsDownloadController.php new file mode 100644 index 00000000..1fc6f65a --- /dev/null +++ b/app/Http/Controllers/FormUploadsDownloadController.php @@ -0,0 +1,21 @@ +firstOrFail(); + + if (!Storage::fileExists($upload->path)) { + abort(404); + } + + return Storage::download($upload->path, $upload->name); + } +} diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 4bdb5c2c..3b04ebd5 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -71,6 +71,7 @@ class Kernel extends HttpKernel 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'check-user-setup' => CheckUserSetup::class, + 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, ]; /** diff --git a/app/Http/Resources/FormSessionResponseResource.php b/app/Http/Resources/FormSessionResponseResource.php index 3b1a78eb..0a464eae 100644 --- a/app/Http/Resources/FormSessionResponseResource.php +++ b/app/Http/Resources/FormSessionResponseResource.php @@ -21,7 +21,8 @@ public function toArray($request) 'message' => strip_tags($this->formBlock->message), 'name' => $this->formBlock->title ?? $this->formBlock->uuid, 'value' => $this->formatValue($this->value), - 'original' => $this->value, + 'original' => $this->formBlock->type === FormBlockType::file ? $this->appendFiles() : $this->value, + 'type' => $this->formBlock->type, ]; } catch (\Exception $e) { return [ @@ -29,6 +30,7 @@ public function toArray($request) 'value' => '', 'original' => '', 'message' => '', + 'type' => '', ]; } } @@ -50,13 +52,28 @@ protected function formatValue($value) if ($this->formBlock->type === FormBlockType::consent) { $accepted = $value['accepted'] ? 'yes' : 'no'; - return $value['consent'].': '.$accepted; + return $value['consent'] . ': ' . $accepted; } if ($this->formBlock->type === FormBlockType::rating || $this->formBlock->type === FormBlockType::scale) { return $value; } + if ($this->formBlock->type === FormBlockType::file) { + return $this->formSessionUploads->map(fn ($upload) => $upload->downloadUrl)->join(', '); + } + return 'Unsupported value type'; } + + protected function appendFiles() + { + return $this->formSessionUploads->map(function ($upload) { + return [ + 'uuid' => $upload->uuid, + 'name' => $upload->name, + 'url' => $upload->downloadUrl, + ]; + }); + } } diff --git a/app/Models/FormBlock.php b/app/Models/FormBlock.php index f448e008..48bd9ccd 100644 --- a/app/Models/FormBlock.php +++ b/app/Models/FormBlock.php @@ -124,6 +124,9 @@ public function getInteractionType(): ?FormBlockInteractionType case FormBlockType::long: return FormBlockInteractionType::textarea; + case FormBlockType::file: + return FormBlockInteractionType::file; + case FormBlockType::checkbox: case FormBlockType::radio: return FormBlockInteractionType::button; diff --git a/app/Models/FormSession.php b/app/Models/FormSession.php index a2dd5cdb..54f23a98 100644 --- a/app/Models/FormSession.php +++ b/app/Models/FormSession.php @@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Carbon; +use Illuminate\Support\Facades\Storage; class FormSession extends Model { @@ -26,6 +27,17 @@ class FormSession extends Model 'is_completed', ]; + protected static function booted(): void + { + static::deleting(function (FormSession $session) { + $session->responses->each(function (FormSessionResponse $response) { + $response->formSessionUploads->each(function (FormSessionUpload $upload) { + Storage::delete($upload->path); + }); + }); + }); + } + public function form() { return $this->belongsTo(Form::class, 'form_id', 'id'); @@ -36,6 +48,11 @@ public function webhooks() return $this->hasMany(FormSessionWebhook::class); } + public function responses() + { + return $this->hasMany(FormSessionResponse::class); + } + public static function getByTokenAndForm(string $token, Form $form) { return self::where('token', $token)->where('form_id', $form->id)->first(); diff --git a/app/Models/FormSessionResponse.php b/app/Models/FormSessionResponse.php index 97e05500..b5b0ae06 100644 --- a/app/Models/FormSessionResponse.php +++ b/app/Models/FormSessionResponse.php @@ -4,6 +4,8 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Http\UploadedFile; +use Illuminate\Support\Str; class FormSessionResponse extends Model { @@ -38,17 +40,33 @@ public function formSession() return $this->belongsTo(FormSession::class, 'form_session_id'); } + public function formSessionUploads() + { + return $this->hasMany(FormSessionUpload::class); + } + public function setValueAttribute($new) { - $this->attributes['value'] = encrypt($new); + $this->attributes['value'] = config('app.debug') ? json_encode($new) : encrypt($new); } public function getValueAttribute() { try { - return decrypt($this->attributes['value']); + return config('app.debug') ? json_decode($this->attributes['value'], true) : decrypt($this->attributes['value']); } catch (\Throwable $th) { return $this->attributes['value']; } } + + public function saveUpload(UploadedFile $file) + { + return $this->formSessionUploads()->create([ + 'uuid' => Str::uuid(), + 'name' => $file->getClientOriginalName(), + 'path' => $file->store(implode('/', ['uploads', $this->id])), + 'type' => $file->getClientMimeType(), + 'size' => $file->getSize(), + ]); + } } diff --git a/app/Models/FormSessionUpload.php b/app/Models/FormSessionUpload.php new file mode 100644 index 00000000..e5a2ba84 --- /dev/null +++ b/app/Models/FormSessionUpload.php @@ -0,0 +1,29 @@ +belongsTo(FormSessionResponse::class); + } + + public function downloadUrl(): Attribute + { + return Attribute::make( + get: fn (mixed $value, array $attributes) => URL::temporarySignedRoute('forms.submission-uploads.download', now()->addDays(7), $attributes['uuid']) + ); + } +} diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 1d7ccce7..7c5c0f9b 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -22,7 +22,11 @@ public function register() $this->app->bind( HttpClientInterface::class, function ($app) { - return new NoPrivateNetworkHttpClient(HttpClient::create()); + return new NoPrivateNetworkHttpClient(HttpClient::create([ + 'headers' => [ + 'user-agent' => 'Input-App/1.0', + ], + ])); } ); diff --git a/database/migrations/2024_02_22_142342_create_form_session_uploads_table.php b/database/migrations/2024_02_22_142342_create_form_session_uploads_table.php new file mode 100644 index 00000000..b74e0710 --- /dev/null +++ b/database/migrations/2024_02_22_142342_create_form_session_uploads_table.php @@ -0,0 +1,33 @@ +id(); + $table->uuid('uuid'); + $table->string('name'); + $table->string('path'); + $table->string('type'); + $table->string('size'); + $table->unsignedBigInteger('form_session_response_id'); + $table->timestamps(); + }); + + Schema::table('form_session_uploads', function (Blueprint $table) { + if (DB::getDriverName() !== 'sqlite') { + $table->foreign('form_session_response_id') + ->references('id')->on('form_session_responses') + ->onDelete('CASCADE'); + } + }); + } +}; diff --git a/docker-compose.yml b/docker-compose.yml index 72b6bae9..48915125 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -79,10 +79,10 @@ services: MINIO_ROOT_USER: "sail" MINIO_ROOT_PASSWORD: "password" volumes: - - "./storage/minio:/data/export" + - "sail-minio:/data/minio" networks: - sail - command: minio server /data/export --console-address ":8900" + command: minio server /data/minio --console-address ":8900" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] retries: 3 diff --git a/package-lock.json b/package-lock.json index 325ac156..8ba0a418 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,58 +9,57 @@ "version": "1.5.0", "license": "GNU Affero General Public License v3.0", "dependencies": { - "@deck9/ui": "^0.14.6", - "@headlessui/vue": "^1.7.17", + "@deck9/ui": "^0.14.10", + "@headlessui/vue": "^1.7.22", "@highlightjs/vue-plugin": "^2.1.0", "@inertiajs/inertia": "^0.11.1", "@inertiajs/inertia-vue3": "^0.6.0", "@inertiajs/progress": "^0.2.7", "@pinia/plugin-debounce": "^0.1.0", "@tailwindcss/forms": "^0.5.7", - "@tailwindcss/typography": "^0.5.10", + "@tailwindcss/typography": "^0.5.13", "@tiptap/extension-link": "^2.0.0-beta.36", "@tiptap/starter-kit": "^2.0.0-beta.181", "@tiptap/vue-3": "^2.0.0-beta.90", - "@types/lodash": "^4.14.202", - "@types/node": "^20.11.10", - "@types/ziggy-js": "^1.8.0", + "@types/lodash": "^4.17.6", + "@types/node": "^20.14.10", "@typescript-eslint/eslint-plugin": "^6.19.1", "@typescript-eslint/parser": "^6.19.1", "@vitejs/plugin-vue": "^4.5.0", "@vitest/coverage-v8": "^0.34.6", - "@vueuse/core": "^10.7.2", - "autoprefixer": "^10.4.17", - "axios": "^1.6.7", + "@vueuse/core": "^10.11.0", + "autoprefixer": "^10.4.19", + "axios": "^1.7.2", "copy-text-to-clipboard": "^3.2.0", "eslint": "^8.56.0", - "eslint-plugin-vue": "^9.20.1", + "eslint-plugin-vue": "^9.27.0", "floating-vue": "^2.0.0-beta.20", - "highlight.js": "^11.9.0", + "highlight.js": "^11.10.0", "laravel-vite-plugin": "^0.8.1", "lodash": "^4.17.19", "pinia": "^2.1.7", - "postcss": "^8.4.33", + "postcss": "^8.4.39", "postcss-import": "^15.1.0", "striptags": "^3.2.0", - "tailwindcss": "^3.4.1", - "typescript": "^5.3.3", - "vite-plugin-css-injected-by-js": "^3.3.1", - "vue": "^3.4.15", - "vue-i18n": "^9.9.0", - "vue-tsc": "^1.8.27", + "tailwindcss": "^3.4.4", + "typescript": "^5.5.3", + "vite-plugin-css-injected-by-js": "^3.5.1", + "vue": "^3.4.38", + "vue-i18n": "^9.13.1", + "vue-tsc": "^2.0.26", "vue3-smooth-dnd": "^0.0.6", - "yup": "^1.3.3", + "yup": "^1.4.0", "ziggy-js": "^1.8.1" }, "devDependencies": { "@pinia/testing": "^0.1.3", "@vitest/coverage-c8": "^0.33.0", - "@vue/test-utils": "^2.4.4", + "@vue/test-utils": "^2.4.6", "browser-sync": "^2.29.3", "jsdom": "^23.0.0", - "prettier": "^3.2.4", + "prettier": "^3.3.2", "prettier-eslint": "^16.3.0", - "prettier-plugin-tailwindcss": "^0.5.11", + "prettier-plugin-tailwindcss": "^0.6.5", "puppeteer": "^21.9.0", "tailwind-config-viewer": "^1.7.3", "vite": "^4.5.0", @@ -176,11 +175,20 @@ "node": ">=4" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -262,9 +270,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", + "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.2" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -272,6 +284,20 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/types": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", + "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", @@ -286,9 +312,9 @@ } }, "node_modules/@deck9/ui": { - "version": "0.14.6", - "resolved": "https://registry.npmjs.org/@deck9/ui/-/ui-0.14.6.tgz", - "integrity": "sha512-h5unBL0SFOwvYBkq50STYnQXyDO45XAlRaadP9ngwY+myG6r38jtDP8BZF/MSR5V/mBhYvm4NTmsIT+sxMgSZw==", + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/@deck9/ui/-/ui-0.14.10.tgz", + "integrity": "sha512-DxIAP0jObGhlcYasZphjdft2gRxhHg0+kIDPgOeKv62SzT0DU0v2pmRKv+KTML2RO6IZt1ekhUBnq769AyUoKQ==", "dependencies": { "@deck9/tailwindcss-recursive-font-helper": "^1.0.1", "@floating-ui/vue": "^1.0.4", @@ -730,18 +756,18 @@ } }, "node_modules/@floating-ui/vue/node_modules/@floating-ui/dom": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.1.tgz", - "integrity": "sha512-iA8qE43/H5iGozC3W0YSnVSW42Vh522yyM1gj+BqRwVsTNOyr231PsXDaV04yT39PsO0QL2QpbI/M0ZaLUQgRQ==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz", + "integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==", "dependencies": { - "@floating-ui/core": "^1.6.0", - "@floating-ui/utils": "^0.2.1" + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" } }, "node_modules/@floating-ui/vue/node_modules/vue-demi": { - "version": "0.14.6", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", - "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", "hasInstallScript": true, "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", @@ -764,75 +790,75 @@ } }, "node_modules/@fortawesome/fontawesome-common-types": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.2.tgz", - "integrity": "sha512-1DgP7f+XQIJbLFCTX1V2QnxVmpLdKdzzo2k8EmvDOePfchaIGQ9eCHj2up3/jNEbZuBqel5OxiaOJf37TWauRA==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.1.tgz", + "integrity": "sha512-GkWzv+L6d2bI5f/Vk6ikJ9xtl7dfXtoRu3YGE6nq0p/FFqA1ebMOAWg3XgRyb0I6LYyYkiAo+3/KrwuBp8xG7A==", "hasInstallScript": true, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.2.tgz", - "integrity": "sha512-gjYDSKv3TrM2sLTOKBc5rH9ckje8Wrwgx1CxAPbN5N3Fm4prfi7NsJVWd1jklp7i5uSCVwhZS5qlhMXqLrpAIg==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.1.tgz", + "integrity": "sha512-MfRCYlQPXoLlpem+egxjfkEuP9UQswTrlCOsknus/NcMoblTH2g0jPrapbcIb04KGA7E2GZxbAccGZfWoYgsrQ==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "6.4.2" + "@fortawesome/fontawesome-common-types": "6.5.1" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-brands-svg-icons": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.4.2.tgz", - "integrity": "sha512-LKOwJX0I7+mR/cvvf6qIiqcERbdnY+24zgpUSouySml+5w8B4BJOx8EhDR/FTKAu06W12fmUIcv6lzPSwYKGGg==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.5.1.tgz", + "integrity": "sha512-093l7DAkx0aEtBq66Sf19MgoZewv1zeY9/4C7vSKPO4qMwEsW/2VYTUTpBtLwfb9T2R73tXaRDPmE4UqLCYHfg==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "6.4.2" + "@fortawesome/fontawesome-common-types": "6.5.1" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-regular-svg-icons": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.4.2.tgz", - "integrity": "sha512-0+sIUWnkgTVVXVAPQmW4vxb9ZTHv0WstOa3rBx9iPxrrrDH6bNLsDYuwXF9b6fGm+iR7DKQvQshUH/FJm3ed9Q==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.5.1.tgz", + "integrity": "sha512-m6ShXn+wvqEU69wSP84coxLbNl7sGVZb+Ca+XZq6k30SzuP3X4TfPqtycgUh9ASwlNh5OfQCd8pDIWxl+O+LlQ==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "6.4.2" + "@fortawesome/fontawesome-common-types": "6.5.1" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-solid-svg-icons": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.2.tgz", - "integrity": "sha512-sYwXurXUEQS32fZz9hVCUUv/xu49PEJEyUOsA51l6PU/qVgfbTb2glsTEaJngVVT8VqBATRIdh7XVgV1JF1LkA==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.1.tgz", + "integrity": "sha512-S1PPfU3mIJa59biTtXJz1oI0+KAXW6bkAb31XKhxdxtuXDiUIFsih4JR1v5BbxY7hVHsD1RKq+jRkVRaf773NQ==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "6.4.2" + "@fortawesome/fontawesome-common-types": "6.5.1" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/vue-fontawesome": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.0.5.tgz", - "integrity": "sha512-isZZ4+utQH9qg9cWxWYHQ9GwI3r5FeO7GnmzKYV+gbjxcptQhh+F99iZXi1Y9AvFUEgy8kRpAdvDlbb3drWFrw==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.0.6.tgz", + "integrity": "sha512-akrL7lTroyNpPkoHtvK2UpsMzJr6jXdHaQ0YdcwqDsB8jdwlpNHZYijpOUd9KJsARr+VB3WXY4EyObepqJ4ytQ==", "peerDependencies": { "@fortawesome/fontawesome-svg-core": "~1 || ~6", "vue": ">= 3.0.0 < 4" } }, "node_modules/@headlessui/vue": { - "version": "1.7.17", - "resolved": "https://registry.npmjs.org/@headlessui/vue/-/vue-1.7.17.tgz", - "integrity": "sha512-hmJChv8HzKorxd9F70RGnECAwZfkvmmwOqreuKLWY/19d5qbWnSdw+DNbuA/Uo6X5rb4U5B3NrT+qBKPmjhRqw==", + "version": "1.7.22", + "resolved": "https://registry.npmjs.org/@headlessui/vue/-/vue-1.7.22.tgz", + "integrity": "sha512-Hoffjoolq1rY+LOfJ+B/OvkhuBXXBFgd8oBlN+l1TApma2dB0En0ucFZrwQtb33SmcCqd32EQd0y07oziXWNYg==", "dependencies": { "@tanstack/vue-virtual": "^3.0.0-beta.60" }, @@ -925,12 +951,12 @@ } }, "node_modules/@intlify/core-base": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.9.0.tgz", - "integrity": "sha512-C7UXPymDIOlMGSNjAhNLtKgzITc/8BjINK5gNKXg8GiWCTwL6n3MWr55czksxn8RM5wTMz0qcLOFT+adtaVQaA==", + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.13.1.tgz", + "integrity": "sha512-+bcQRkJO9pcX8d0gel9ZNfrzU22sZFSA0WVhfXrf5jdJOS24a+Bp8pozuS9sBI9Hk/tGz83pgKfmqcn/Ci7/8w==", "dependencies": { - "@intlify/message-compiler": "9.9.0", - "@intlify/shared": "9.9.0" + "@intlify/message-compiler": "9.13.1", + "@intlify/shared": "9.13.1" }, "engines": { "node": ">= 16" @@ -940,11 +966,11 @@ } }, "node_modules/@intlify/message-compiler": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.9.0.tgz", - "integrity": "sha512-yDU/jdUm9KuhEzYfS+wuyja209yXgdl1XFhMlKtXEgSFTxz4COZQCRXXbbH8JrAjMsaJ7bdoPSLsKlY6mXG2iA==", + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.13.1.tgz", + "integrity": "sha512-SKsVa4ajYGBVm7sHMXd5qX70O2XXjm55zdZB3VeMFCvQyvLew/dLvq3MqnaIsTMF1VkkOb9Ttr6tHcMlyPDL9w==", "dependencies": { - "@intlify/shared": "9.9.0", + "@intlify/shared": "9.13.1", "source-map-js": "^1.0.2" }, "engines": { @@ -955,9 +981,9 @@ } }, "node_modules/@intlify/shared": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.9.0.tgz", - "integrity": "sha512-1ECUyAHRrzOJbOizyGufYP2yukqGrWXtkmTu4PcswVnWbkcjzk3YQGmJ0bLkM7JZ0ZYAaohLGdYvBYnTOGYJ9g==", + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.13.1.tgz", + "integrity": "sha512-u3b6BKGhE6j/JeRU6C/RL2FgyJfy6LakbtfeVF8fJXURpZZTzfh3e05J0bu0XPw447Q6/WUp3C4ajv4TMS4YsQ==", "engines": { "node": ">= 16" }, @@ -1125,12 +1151,12 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "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==", + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@koa/router": { @@ -1342,9 +1368,9 @@ } }, "node_modules/@storybook/node-logger": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.5.3.tgz", - "integrity": "sha512-7ZZDw/q3hakBj1FngsBjaHNIBguYAWojp7R1fFTvwkeunCi21EUzZjRBcqp10kB6BP3/NLX32bIQknsCWD76rQ==", + "version": "7.6.16", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.6.16.tgz", + "integrity": "sha512-s18wgtLynLWnunz47lkVIpjk8J6LxT/OmfzkggieU8cG2XYRbf//t7/EOUpOqK77+Xqm3epSwgDAxOXGfjOjAA==", "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" @@ -1362,9 +1388,10 @@ } }, "node_modules/@tailwindcss/typography": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.10.tgz", - "integrity": "sha512-Pe8BuPJQJd3FfRnm6H0ulKIGoMEQS+Vq01R6M5aCrFB/ccR/shT+0kXLjouGC1gFLm9hopTFN+DMP0pfwRWzPw==", + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.13.tgz", + "integrity": "sha512-ADGcJ8dX21dVVHIwTRgzrcunY6YY9uSlAHHGVKvkA+vLc5qLwEszvKts40lx7z0qc4clpjclwLeK5rVCV2P/uw==", + "license": "MIT", "dependencies": { "lodash.castarray": "^4.4.0", "lodash.isplainobject": "^4.0.6", @@ -1796,9 +1823,9 @@ "dev": true }, "node_modules/@types/eslint": { - "version": "8.44.7", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.7.tgz", - "integrity": "sha512-f5ORu2hcBbKei97U73mf+l9t4zTGl74IqZ0GQk4oVea/VS8tQZYkUveSYojk+frraAVYId0V2WC9O4PTNru2FQ==", + "version": "8.56.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.2.tgz", + "integrity": "sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw==", "peer": true, "dependencies": { "@types/estree": "*", @@ -1832,14 +1859,15 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" }, "node_modules/@types/lodash": { - "version": "4.14.202", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz", - "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==" + "version": "4.17.6", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.6.tgz", + "integrity": "sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA==" }, "node_modules/@types/node": { - "version": "20.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz", - "integrity": "sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg==", + "version": "20.14.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", + "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "license": "MIT", "dependencies": { "undici-types": "~5.26.4" } @@ -1967,15 +1995,6 @@ "@types/node": "*" } }, - "node_modules/@types/ziggy-js": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@types/ziggy-js/-/ziggy-js-1.8.0.tgz", - "integrity": "sha512-5MIf/vogCutjZLjSqyizK/KLWKRe+ulnMdUZqrdEkG3K6/6k/UQhCGfM6WC4aGM8BQpEc+55fwSGAtEMqesDAQ==", - "deprecated": "This is a stub types definition. ziggy-js provides its own type definitions, so you do not need this installed.", - "dependencies": { - "ziggy-js": "*" - } - }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "6.19.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.1.tgz", @@ -2305,74 +2324,79 @@ } }, "node_modules/@volar/language-core": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.11.1.tgz", - "integrity": "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==", + "version": "2.4.0-alpha.15", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.0-alpha.15.tgz", + "integrity": "sha512-mt8z4Fm2WxfQYoQHPcKVjLQV6PgPqyKLbkCVY2cr5RSaamqCHjhKEpsFX66aL4D/7oYguuaUw9Bx03Vt0TpIIA==", + "license": "MIT", "dependencies": { - "@volar/source-map": "1.11.1" + "@volar/source-map": "2.4.0-alpha.15" } }, "node_modules/@volar/source-map": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.11.1.tgz", - "integrity": "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==", - "dependencies": { - "muggle-string": "^0.3.1" - } + "version": "2.4.0-alpha.15", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.0-alpha.15.tgz", + "integrity": "sha512-8Htngw5TmBY4L3ClDqBGyfLhsB8EmoEXUH1xydyEtEoK0O6NX5ur4Jw8jgvscTlwzizyl/wsN1vn0cQXVbbXYg==", + "license": "MIT" }, "node_modules/@volar/typescript": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.11.1.tgz", - "integrity": "sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==", + "version": "2.4.0-alpha.15", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.0-alpha.15.tgz", + "integrity": "sha512-U3StRBbDuxV6Woa4hvGS4kz3XcOzrWUKgFdEFN+ba1x3eaYg7+ytau8ul05xgA+UNGLXXsKur7fTUhDFyISk0w==", + "license": "MIT", "dependencies": { - "@volar/language-core": "1.11.1", - "path-browserify": "^1.0.1" + "@volar/language-core": "2.4.0-alpha.15", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" } }, "node_modules/@vue/compiler-core": { - "version": "3.4.15", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.15.tgz", - "integrity": "sha512-XcJQVOaxTKCnth1vCxEChteGuwG6wqnUHxAm1DO3gCz0+uXKaJNx8/digSz4dLALCy8n2lKq24jSUs8segoqIw==", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.38.tgz", + "integrity": "sha512-8IQOTCWnLFqfHzOGm9+P8OPSEDukgg3Huc92qSG49if/xI2SAwLHQO2qaPQbjCWPBcQoO1WYfXfTACUrWV3c5A==", + "license": "MIT", "dependencies": { - "@babel/parser": "^7.23.6", - "@vue/shared": "3.4.15", + "@babel/parser": "^7.24.7", + "@vue/shared": "3.4.38", "entities": "^4.5.0", "estree-walker": "^2.0.2", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.0" } }, "node_modules/@vue/compiler-dom": { - "version": "3.4.15", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.15.tgz", - "integrity": "sha512-wox0aasVV74zoXyblarOM3AZQz/Z+OunYcIHe1OsGclCHt8RsRm04DObjefaI82u6XDzv+qGWZ24tIsRAIi5MQ==", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.38.tgz", + "integrity": "sha512-Osc/c7ABsHXTsETLgykcOwIxFktHfGSUDkb05V61rocEfsFDcjDLH/IHJSNJP+/Sv9KeN2Lx1V6McZzlSb9EhQ==", + "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.4.15", - "@vue/shared": "3.4.15" + "@vue/compiler-core": "3.4.38", + "@vue/shared": "3.4.38" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.4.15", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.15.tgz", - "integrity": "sha512-LCn5M6QpkpFsh3GQvs2mJUOAlBQcCco8D60Bcqmf3O3w5a+KWS5GvYbrrJBkgvL1BDnTp+e8q0lXCLgHhKguBA==", - "dependencies": { - "@babel/parser": "^7.23.6", - "@vue/compiler-core": "3.4.15", - "@vue/compiler-dom": "3.4.15", - "@vue/compiler-ssr": "3.4.15", - "@vue/shared": "3.4.15", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.38.tgz", + "integrity": "sha512-s5QfZ+9PzPh3T5H4hsQDJtI8x7zdJaew/dCGgqZ2630XdzaZ3AD8xGZfBqpT8oaD/p2eedd+pL8tD5vvt5ZYJQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.24.7", + "@vue/compiler-core": "3.4.38", + "@vue/compiler-dom": "3.4.38", + "@vue/compiler-ssr": "3.4.38", + "@vue/shared": "3.4.38", "estree-walker": "^2.0.2", - "magic-string": "^0.30.5", - "postcss": "^8.4.33", - "source-map-js": "^1.0.2" + "magic-string": "^0.30.10", + "postcss": "^8.4.40", + "source-map-js": "^1.2.0" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.4.15", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.15.tgz", - "integrity": "sha512-1jdeQyiGznr8gjFDadVmOJqZiLNSsMa5ZgqavkPZ8O2wjHv0tVuAEsw5hTdUoUW4232vpBbL/wJhzVW/JwY1Uw==", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.38.tgz", + "integrity": "sha512-YXznKFQ8dxYpAz9zLuVvfcXhc31FSPFDcqr0kyujbOwNhlmaNvL2QfIy+RZeJgSn5Fk54CWoEUeW+NVBAogGaw==", + "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.4.15", - "@vue/shared": "3.4.15" + "@vue/compiler-dom": "3.4.38", + "@vue/shared": "3.4.38" } }, "node_modules/@vue/devtools-api": { @@ -2381,17 +2405,17 @@ "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==" }, "node_modules/@vue/language-core": { - "version": "1.8.27", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.27.tgz", - "integrity": "sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==", - "dependencies": { - "@volar/language-core": "~1.11.1", - "@volar/source-map": "~1.11.1", - "@vue/compiler-dom": "^3.3.0", - "@vue/shared": "^3.3.0", + "version": "2.0.26", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.0.26.tgz", + "integrity": "sha512-/lt6SfQ3O1yDAhPsnLv9iSUgXd1dMHqUm/t3RctfqjuwQf1LnftZ414X3UBn6aXT4MiwXWtbNJ4Z0NZWwDWgJQ==", + "license": "MIT", + "dependencies": { + "@volar/language-core": "~2.4.0-alpha.15", + "@vue/compiler-dom": "^3.4.0", + "@vue/shared": "^3.4.0", "computeds": "^0.0.1", "minimatch": "^9.0.3", - "muggle-string": "^0.3.1", + "muggle-string": "^0.4.1", "path-browserify": "^1.0.1", "vue-template-compiler": "^2.7.14" }, @@ -2408,14 +2432,16 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/@vue/language-core/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -2427,86 +2453,83 @@ } }, "node_modules/@vue/reactivity": { - "version": "3.4.15", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.15.tgz", - "integrity": "sha512-55yJh2bsff20K5O84MxSvXKPHHt17I2EomHznvFiJCAZpJTNW8IuLj1xZWMLELRhBK3kkFV/1ErZGHJfah7i7w==", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.38.tgz", + "integrity": "sha512-4vl4wMMVniLsSYYeldAKzbk72+D3hUnkw9z8lDeJacTxAkXeDAP1uE9xr2+aKIN0ipOL8EG2GPouVTH6yF7Gnw==", + "license": "MIT", "dependencies": { - "@vue/shared": "3.4.15" + "@vue/shared": "3.4.38" } }, "node_modules/@vue/runtime-core": { - "version": "3.4.15", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.15.tgz", - "integrity": "sha512-6E3by5m6v1AkW0McCeAyhHTw+3y17YCOKG0U0HDKDscV4Hs0kgNT5G+GCHak16jKgcCDHpI9xe5NKb8sdLCLdw==", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.38.tgz", + "integrity": "sha512-21z3wA99EABtuf+O3IhdxP0iHgkBs1vuoCAsCKLVJPEjpVqvblwBnTj42vzHRlWDCyxu9ptDm7sI2ZMcWrQqlA==", + "license": "MIT", "dependencies": { - "@vue/reactivity": "3.4.15", - "@vue/shared": "3.4.15" + "@vue/reactivity": "3.4.38", + "@vue/shared": "3.4.38" } }, "node_modules/@vue/runtime-dom": { - "version": "3.4.15", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.15.tgz", - "integrity": "sha512-EVW8D6vfFVq3V/yDKNPBFkZKGMFSvZrUQmx196o/v2tHKdwWdiZjYUBS+0Ez3+ohRyF8Njwy/6FH5gYJ75liUw==", - "dependencies": { - "@vue/runtime-core": "3.4.15", - "@vue/shared": "3.4.15", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.38.tgz", + "integrity": "sha512-afZzmUreU7vKwKsV17H1NDThEEmdYI+GCAK/KY1U957Ig2NATPVjCROv61R19fjZNzMmiU03n79OMnXyJVN0UA==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.4.38", + "@vue/runtime-core": "3.4.38", + "@vue/shared": "3.4.38", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.4.15", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.15.tgz", - "integrity": "sha512-3HYzaidu9cHjrT+qGUuDhFYvF/j643bHC6uUN9BgM11DVy+pM6ATsG6uPBLnkwOgs7BpJABReLmpL3ZPAsUaqw==", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.38.tgz", + "integrity": "sha512-NggOTr82FbPEkkUvBm4fTGcwUY8UuTsnWC/L2YZBmvaQ4C4Jl/Ao4HHTB+l7WnFCt5M/dN3l0XLuyjzswGYVCA==", + "license": "MIT", "dependencies": { - "@vue/compiler-ssr": "3.4.15", - "@vue/shared": "3.4.15" + "@vue/compiler-ssr": "3.4.38", + "@vue/shared": "3.4.38" }, "peerDependencies": { - "vue": "3.4.15" + "vue": "3.4.38" } }, "node_modules/@vue/shared": { - "version": "3.4.15", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.15.tgz", - "integrity": "sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g==" + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.38.tgz", + "integrity": "sha512-q0xCiLkuWWQLzVrecPb0RMsNWyxICOjPrcrwxTUEHb1fsnvni4dcuyG7RT/Ie7VPTvnjzIaWzRMUBsrqNj/hhw==", + "license": "MIT" }, "node_modules/@vue/test-utils": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.4.tgz", - "integrity": "sha512-8jkRxz8pNhClAf4Co4ZrpAoFISdvT3nuSkUlY6Ys6rmTpw3DMWG/X3mw3gQ7QJzgCZO9f+zuE2kW57fi09MW7Q==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.6.tgz", + "integrity": "sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==", "dev": true, "dependencies": { "js-beautify": "^1.14.9", - "vue-component-type-helpers": "^1.8.21" - }, - "peerDependencies": { - "@vue/server-renderer": "^3.0.1", - "vue": "^3.0.1" - }, - "peerDependenciesMeta": { - "@vue/server-renderer": { - "optional": true - } + "vue-component-type-helpers": "^2.0.0" } }, "node_modules/@vueuse/core": { - "version": "10.7.2", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.7.2.tgz", - "integrity": "sha512-AOyAL2rK0By62Hm+iqQn6Rbu8bfmbgaIMXcE3TSr7BdQ42wnSFlwIdPjInO62onYsEMK/yDMU8C6oGfDAtZ2qQ==", + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.11.0.tgz", + "integrity": "sha512-x3sD4Mkm7PJ+pcq3HX8PLPBadXCAlSDR/waK87dz0gQE+qJnaaFhc/dZVfJz+IUYzTMVGum2QlR7ImiJQN4s6g==", "dependencies": { "@types/web-bluetooth": "^0.0.20", - "@vueuse/metadata": "10.7.2", - "@vueuse/shared": "10.7.2", - "vue-demi": ">=0.14.6" + "@vueuse/metadata": "10.11.0", + "@vueuse/shared": "10.11.0", + "vue-demi": ">=0.14.8" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@vueuse/core/node_modules/vue-demi": { - "version": "0.14.6", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", - "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", + "version": "0.14.8", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.8.tgz", + "integrity": "sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==", "hasInstallScript": true, "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", @@ -2529,28 +2552,28 @@ } }, "node_modules/@vueuse/metadata": { - "version": "10.7.2", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.7.2.tgz", - "integrity": "sha512-kCWPb4J2KGrwLtn1eJwaJD742u1k5h6v/St5wFe8Quih90+k2a0JP8BS4Zp34XUuJqS2AxFYMb1wjUL8HfhWsQ==", + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.11.0.tgz", + "integrity": "sha512-kQX7l6l8dVWNqlqyN3ePW3KmjCQO3ZMgXuBMddIu83CmucrsBfXlH+JoviYyRBws/yLTQO8g3Pbw+bdIoVm4oQ==", "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@vueuse/shared": { - "version": "10.7.2", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.7.2.tgz", - "integrity": "sha512-qFbXoxS44pi2FkgFjPvF4h7c9oMDutpyBdcJdMYIMg9XyXli2meFMuaKn+UMgsClo//Th6+beeCgqweT/79BVA==", + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.11.0.tgz", + "integrity": "sha512-fyNoIXEq3PfX1L3NkNhtVQUSRtqYwJtJg+Bp9rIzculIZWHTkKSysujrOk2J+NrRulLTQH9+3gGSfYLWSEWU1A==", "dependencies": { - "vue-demi": ">=0.14.6" + "vue-demi": ">=0.14.8" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@vueuse/shared/node_modules/vue-demi": { - "version": "0.14.6", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz", - "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==", + "version": "0.14.8", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.8.tgz", + "integrity": "sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==", "hasInstallScript": true, "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", @@ -2934,9 +2957,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.17", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz", - "integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==", + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", + "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", "funding": [ { "type": "opencollective", @@ -2952,8 +2975,8 @@ } ], "dependencies": { - "browserslist": "^4.22.2", - "caniuse-lite": "^1.0.30001578", + "browserslist": "^4.23.0", + "caniuse-lite": "^1.0.30001599", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.0.0", @@ -2970,11 +2993,11 @@ } }, "node_modules/axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", "dependencies": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -3268,9 +3291,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", - "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", + "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", "funding": [ { "type": "opencollective", @@ -3286,10 +3309,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001580", - "electron-to-chromium": "^1.4.648", + "caniuse-lite": "^1.0.30001629", + "electron-to-chromium": "^1.4.796", "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "update-browserslist-db": "^1.0.16" }, "bin": { "browserslist": "cli.js" @@ -3446,9 +3469,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001581", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001581.tgz", - "integrity": "sha512-whlTkwhqV2tUmP3oYhtNfaWGYHDdS3JYFQBKXxcUR9qqPWsRhFHhoISO2Xnl/g0xyKzht9mI1LZpiNWfMzHixQ==", + "version": "1.0.30001636", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz", + "integrity": "sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==", "funding": [ { "type": "opencollective", @@ -3635,7 +3658,8 @@ "node_modules/computeds": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", - "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==" + "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", + "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", @@ -3873,7 +3897,8 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" }, "node_modules/data-uri-to-buffer": { "version": "6.0.1", @@ -3900,7 +3925,8 @@ "node_modules/de-indent": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", - "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==" + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "license": "MIT" }, "node_modules/debug": { "version": "4.3.4", @@ -4143,9 +4169,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.648", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.648.tgz", - "integrity": "sha512-EmFMarXeqJp9cUKu/QEciEApn0S/xRcpZWuAm32U7NgoZCimjsilKXHRO9saeEW55eHZagIDg6XTUOv32w9pjg==" + "version": "1.4.806", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.806.tgz", + "integrity": "sha512-nkoEX2QIB8kwCOtvtgwhXWy2IHVcOLQZu9Qo36uaGB835mdX/h8uLRlosL6QIhLVUnAiicXRW00PwaPZC74Nrg==" }, "node_modules/emoji-regex": { "version": "8.0.0", @@ -4344,9 +4370,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "engines": { "node": ">=6" } @@ -4442,29 +4468,30 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "9.20.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.20.1.tgz", - "integrity": "sha512-GyCs8K3lkEvoyC1VV97GJhP1SvqsKCiWGHnbn0gVUYiUhaH2+nB+Dv1uekv1THFMPbBfYxukrzQdltw950k+LQ==", + "version": "9.27.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.27.0.tgz", + "integrity": "sha512-5Dw3yxEyuBSXTzT5/Ge1X5kIkRTQ3nvBn/VwPwInNiZBSJOO/timWMUaflONnFBzU6NhB68lxnCda7ULV5N7LA==", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", + "globals": "^13.24.0", "natural-compare": "^1.4.0", "nth-check": "^2.1.1", - "postcss-selector-parser": "^6.0.13", - "semver": "^7.5.4", - "vue-eslint-parser": "^9.4.0", + "postcss-selector-parser": "^6.0.15", + "semver": "^7.6.0", + "vue-eslint-parser": "^9.4.3", "xml-name-validator": "^4.0.0" }, "engines": { "node": "^14.17.0 || >=16.0.0" }, "peerDependencies": { - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0" + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" } }, "node_modules/eslint-plugin-vue/node_modules/postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz", + "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -4583,7 +4610,8 @@ "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" }, "node_modules/esutils": { "version": "2.0.3", @@ -4757,9 +4785,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -5086,14 +5114,16 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "license": "MIT", "bin": { "he": "bin/he" } }, "node_modules/highlight.js": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz", - "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==", + "version": "11.10.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.10.0.tgz", + "integrity": "sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==", + "license": "BSD-3-Clause", "engines": { "node": ">=12.0.0" } @@ -6125,14 +6155,11 @@ } }, "node_modules/magic-string": { - "version": "0.30.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", - "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" - }, - "engines": { - "node": ">=12" } }, "node_modules/magic-string/node_modules/@jridgewell/sourcemap-codec": { @@ -6292,9 +6319,10 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/muggle-string": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz", - "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "license": "MIT" }, "node_modules/mz": { "version": "2.7.0", @@ -6689,7 +6717,8 @@ "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "license": "MIT" }, "node_modules/path-exists": { "version": "4.0.0", @@ -6770,9 +6799,9 @@ "dev": true }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -6899,9 +6928,9 @@ } }, "node_modules/postcss": { - "version": "8.4.33", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", - "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", + "version": "8.4.41", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", + "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", "funding": [ { "type": "opencollective", @@ -6916,10 +6945,11 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" @@ -7043,9 +7073,9 @@ } }, "node_modules/prettier": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", - "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -7093,10 +7123,11 @@ } }, "node_modules/prettier-plugin-tailwindcss": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.11.tgz", - "integrity": "sha512-AvI/DNyMctyyxGOjyePgi/gqj5hJYClZ1avtQvLlqMT3uDZkRbi4HhGUpok3DRzv9z7Lti85Kdj3s3/1CeNI0w==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.5.tgz", + "integrity": "sha512-axfeOArc/RiGHjOIy9HytehlC0ZLeMaqY09mm8YCkMzznKiDkwFzOpBvtuhuv3xG5qB73+Mj7OCe2j/L1ryfuQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.21.3" }, @@ -7105,6 +7136,7 @@ "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", + "@zackad/prettier-plugin-twig-melody": "*", "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", @@ -7113,6 +7145,7 @@ "prettier-plugin-marko": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", + "prettier-plugin-sort-imports": "*", "prettier-plugin-style-order": "*", "prettier-plugin-svelte": "*" }, @@ -7129,6 +7162,9 @@ "@trivago/prettier-plugin-sort-imports": { "optional": true }, + "@zackad/prettier-plugin-twig-melody": { + "optional": true + }, "prettier-plugin-astro": { "optional": true }, @@ -7150,13 +7186,13 @@ "prettier-plugin-organize-imports": { "optional": true }, - "prettier-plugin-style-order": { + "prettier-plugin-sort-imports": { "optional": true }, - "prettier-plugin-svelte": { + "prettier-plugin-style-order": { "optional": true }, - "prettier-plugin-twig-melody": { + "prettier-plugin-svelte": { "optional": true } } @@ -7779,12 +7815,9 @@ } }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "bin": { "semver": "bin/semver.js" }, @@ -7792,26 +7825,10 @@ "node": ">=10" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "peer": true, "dependencies": { "randombytes": "^2.1.0" @@ -8063,9 +8080,9 @@ } }, "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==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "engines": { "node": ">=0.10.0" } @@ -8346,9 +8363,9 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", - "integrity": "sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==", + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz", + "integrity": "sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -8358,7 +8375,7 @@ "fast-glob": "^3.3.0", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.19.1", + "jiti": "^1.21.0", "lilconfig": "^2.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", @@ -8448,9 +8465,9 @@ } }, "node_modules/terser": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", - "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==", + "version": "5.27.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.1.tgz", + "integrity": "sha512-29wAr6UU/oQpnTw5HoadwjUZnFQXGdOfj0LjZ4sVxzqwHh/QVkvr7m8y9WoR4iN3FRitVduTc6KdjcW38Npsug==", "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -8466,16 +8483,16 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.9", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", - "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", "peer": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", + "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.1", - "terser": "^5.16.8" + "terser": "^5.26.0" }, "engines": { "node": ">= 10.13.0" @@ -8582,6 +8599,15 @@ "@popperjs/core": "^2.9.0" } }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -8718,9 +8744,9 @@ } }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", + "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -8787,9 +8813,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", "funding": [ { "type": "opencollective", @@ -8805,8 +8831,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -8964,9 +8990,9 @@ } }, "node_modules/vite-plugin-css-injected-by-js": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/vite-plugin-css-injected-by-js/-/vite-plugin-css-injected-by-js-3.3.1.tgz", - "integrity": "sha512-PjM/X45DR3/V1K1fTRs8HtZHEQ55kIfdrn+dzaqNBFrOYO073SeSNCxp4j7gSYhV9NffVHaEnOL4myoko0ePAg==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/vite-plugin-css-injected-by-js/-/vite-plugin-css-injected-by-js-3.5.1.tgz", + "integrity": "sha512-9ioqwDuEBxW55gNoWFEDhfLTrVKXEEZgl5adhWmmqa88EQGKfTmexy4v1Rh0pAS6RhKQs2bUYQArprB32JpUZQ==", "peerDependencies": { "vite": ">2.0.0-0" } @@ -9056,16 +9082,23 @@ } } }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "license": "MIT" + }, "node_modules/vue": { - "version": "3.4.15", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.15.tgz", - "integrity": "sha512-jC0GH4KkWLWJOEQjOpkqU1bQsBwf4R1rsFtw5GQJbjHVKWDzO6P0nWWBTmjp1xSemAioDFj1jdaK1qa3DnMQoQ==", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.38.tgz", + "integrity": "sha512-f0ZgN+mZ5KFgVv9wz0f4OgVKukoXtS3nwET4c2vLBGQR50aI8G0cqbFtLlX9Yiyg3LFGBitruPHt2PxwTduJEw==", + "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.4.15", - "@vue/compiler-sfc": "3.4.15", - "@vue/runtime-dom": "3.4.15", - "@vue/server-renderer": "3.4.15", - "@vue/shared": "3.4.15" + "@vue/compiler-dom": "3.4.38", + "@vue/compiler-sfc": "3.4.38", + "@vue/runtime-dom": "3.4.38", + "@vue/server-renderer": "3.4.38", + "@vue/shared": "3.4.38" }, "peerDependencies": { "typescript": "*" @@ -9077,15 +9110,15 @@ } }, "node_modules/vue-component-type-helpers": { - "version": "1.8.22", - "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-1.8.22.tgz", - "integrity": "sha512-LK3wJHs3vJxHG292C8cnsRusgyC5SEZDCzDCD01mdE/AoREFMl2tzLRuzwyuEsOIz13tqgBcnvysN3Lxsa14Fw==", + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-2.0.21.tgz", + "integrity": "sha512-3NaicyZ7N4B6cft4bfb7dOnPbE9CjLcx+6wZWAg5zwszfO4qXRh+U52dN5r5ZZfc6iMaxKCEcoH9CmxxoFZHLg==", "dev": true }, "node_modules/vue-eslint-parser": { - "version": "9.4.2", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz", - "integrity": "sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==", + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", + "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==", "dependencies": { "debug": "^4.3.4", "eslint-scope": "^7.1.1", @@ -9106,12 +9139,12 @@ } }, "node_modules/vue-i18n": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.9.0.tgz", - "integrity": "sha512-xQ5SxszUAqK5n84N+uUyHH/PiQl9xZ24FOxyAaNonmOQgXeN+rD9z/6DStOpOxNFQn4Cgcquot05gZc+CdOujA==", + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.13.1.tgz", + "integrity": "sha512-mh0GIxx0wPtPlcB1q4k277y0iKgo25xmDPWioVVYanjPufDBpvu5ySTjP5wOrSvlYQ2m1xI+CFhGdauv/61uQg==", "dependencies": { - "@intlify/core-base": "9.9.0", - "@intlify/shared": "9.9.0", + "@intlify/core-base": "9.13.1", + "@intlify/shared": "9.13.1", "@vue/devtools-api": "^6.5.0" }, "engines": { @@ -9136,25 +9169,27 @@ "version": "2.7.16", "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", + "license": "MIT", "dependencies": { "de-indent": "^1.0.2", "he": "^1.2.0" } }, "node_modules/vue-tsc": { - "version": "1.8.27", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.27.tgz", - "integrity": "sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==", + "version": "2.0.26", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.0.26.tgz", + "integrity": "sha512-tOhuwy2bIXbMhz82ef37qeiaQHMXKQkD6mOF6CCPl3/uYtST3l6fdNyfMxipudrQTxTfXVPlgJdMENBFfC1CfQ==", + "license": "MIT", "dependencies": { - "@volar/typescript": "~1.11.1", - "@vue/language-core": "1.8.27", + "@volar/typescript": "~2.4.0-alpha.15", + "@vue/language-core": "2.0.26", "semver": "^7.5.4" }, "bin": { "vue-tsc": "bin/vue-tsc.js" }, "peerDependencies": { - "typescript": "*" + "typescript": ">=5.0.0" } }, "node_modules/vue3-smooth-dnd": { @@ -9217,19 +9252,19 @@ } }, "node_modules/webpack": { - "version": "5.89.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", - "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", + "version": "5.90.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.2.tgz", + "integrity": "sha512-ziXu8ABGr0InCMEYFnHrYweinHK2PWrMqnwdHk2oK3rRhv/1B+2FnfwYv5oD+RrknK/Pp/Hmyvu+eAsaMYhzCw==", "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", + "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.11.5", "@webassemblyjs/wasm-edit": "^1.11.5", "@webassemblyjs/wasm-parser": "^1.11.5", "acorn": "^8.7.1", "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", + "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.15.0", "es-module-lexer": "^1.2.1", @@ -9243,7 +9278,7 @@ "neo-async": "^2.6.2", "schema-utils": "^3.2.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", + "terser-webpack-plugin": "^5.3.10", "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, @@ -9551,9 +9586,9 @@ } }, "node_modules/yup": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/yup/-/yup-1.3.3.tgz", - "integrity": "sha512-v8QwZSsHH2K3/G9WSkp6mZKO+hugKT1EmnMqLNUcfu51HU9MDyhlETT/JgtzprnrnQHPWsjc6MUDMBp/l9fNnw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.4.0.tgz", + "integrity": "sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==", "dependencies": { "property-expr": "^2.0.5", "tiny-case": "^1.0.3", diff --git a/package.json b/package.json index abf866c6..d13b71db 100644 --- a/package.json +++ b/package.json @@ -20,59 +20,58 @@ "devDependencies": { "@pinia/testing": "^0.1.3", "@vitest/coverage-c8": "^0.33.0", - "@vue/test-utils": "^2.4.4", + "@vue/test-utils": "^2.4.6", "browser-sync": "^2.29.3", "jsdom": "^23.0.0", - "prettier": "^3.2.4", + "prettier": "^3.3.2", "prettier-eslint": "^16.3.0", - "prettier-plugin-tailwindcss": "^0.5.11", + "prettier-plugin-tailwindcss": "^0.6.5", "puppeteer": "^21.9.0", "tailwind-config-viewer": "^1.7.3", "vite": "^4.5.0", "vitest": "^0.34.6" }, "dependencies": { - "@deck9/ui": "^0.14.6", - "@headlessui/vue": "^1.7.17", + "@deck9/ui": "^0.14.10", + "@headlessui/vue": "^1.7.22", "@highlightjs/vue-plugin": "^2.1.0", "@inertiajs/inertia": "^0.11.1", "@inertiajs/inertia-vue3": "^0.6.0", "@inertiajs/progress": "^0.2.7", "@pinia/plugin-debounce": "^0.1.0", "@tailwindcss/forms": "^0.5.7", - "@tailwindcss/typography": "^0.5.10", + "@tailwindcss/typography": "^0.5.13", "@tiptap/extension-link": "^2.0.0-beta.36", "@tiptap/starter-kit": "^2.0.0-beta.181", "@tiptap/vue-3": "^2.0.0-beta.90", - "@types/lodash": "^4.14.202", - "@types/node": "^20.11.10", - "@types/ziggy-js": "^1.8.0", + "@types/lodash": "^4.17.6", + "@types/node": "^20.14.10", "@typescript-eslint/eslint-plugin": "^6.19.1", "@typescript-eslint/parser": "^6.19.1", "@vitejs/plugin-vue": "^4.5.0", "@vitest/coverage-v8": "^0.34.6", - "@vueuse/core": "^10.7.2", - "autoprefixer": "^10.4.17", - "axios": "^1.6.7", + "@vueuse/core": "^10.11.0", + "autoprefixer": "^10.4.19", + "axios": "^1.7.2", "copy-text-to-clipboard": "^3.2.0", "eslint": "^8.56.0", - "eslint-plugin-vue": "^9.20.1", + "eslint-plugin-vue": "^9.27.0", "floating-vue": "^2.0.0-beta.20", - "highlight.js": "^11.9.0", + "highlight.js": "^11.10.0", "laravel-vite-plugin": "^0.8.1", "lodash": "^4.17.19", "pinia": "^2.1.7", - "postcss": "^8.4.33", + "postcss": "^8.4.39", "postcss-import": "^15.1.0", "striptags": "^3.2.0", - "tailwindcss": "^3.4.1", - "typescript": "^5.3.3", - "vite-plugin-css-injected-by-js": "^3.3.1", - "vue": "^3.4.15", - "vue-i18n": "^9.9.0", - "vue-tsc": "^1.8.27", + "tailwindcss": "^3.4.4", + "typescript": "^5.5.3", + "vite-plugin-css-injected-by-js": "^3.5.1", + "vue": "^3.4.38", + "vue-i18n": "^9.13.1", + "vue-tsc": "^2.0.26", "vue3-smooth-dnd": "^0.0.6", - "yup": "^1.3.3", + "yup": "^1.4.0", "ziggy-js": "^1.8.1" } } diff --git a/resources/js/api/conversation.ts b/resources/js/api/conversation.ts index 8e1772e2..4fc79934 100644 --- a/resources/js/api/conversation.ts +++ b/resources/js/api/conversation.ts @@ -1,10 +1,10 @@ /* eslint-disable no-async-promise-executor */ -import { AxiosResponse } from "axios"; +import { AxiosProgressEvent, AxiosResponse } from "axios"; import handler from "./handler"; import { useRoutes } from "@/utils/useRoutes"; export function callGetForm( - uuid: string + uuid: string, ): Promise> { return new Promise(async (resolve, reject) => { try { @@ -27,7 +27,7 @@ export function callGetForm( } export function callGetFormStoryboard( - uuid: string + uuid: string, ): Promise> { return new Promise(async (resolve, reject) => { try { @@ -51,7 +51,7 @@ export function callGetFormStoryboard( export function callCreateFormSession( uuid: string, - params: Record + params: Record, ): Promise> { return new Promise(async (resolve, reject) => { try { @@ -78,7 +78,8 @@ export function callCreateFormSession( export function callSubmitForm( uuid: string, token: string, - payload: FormSubmitPayload + payload: FormSubmitPayload | null, + is_uploading: boolean = false, ): Promise> { return new Promise(async (resolve, reject) => { try { @@ -92,6 +93,7 @@ export function callSubmitForm( const response = await handler.post(resolvedRoute, { token, payload, + is_uploading, }); resolve(response as AxiosResponse); } else { @@ -102,3 +104,51 @@ export function callSubmitForm( } }); } + +export async function callUploadFiles( + uuid: string, + token: string, + payload: FormSubmitPayload, + progressCallback: (file, axiosProgressEvent: AxiosProgressEvent) => void, +): Promise { + const { route } = await useRoutes(); + + const resolvedRoute = route("api.public.forms.file-upload", { + uuid, + }); + + if (!resolvedRoute) { + return Promise.reject("route not found"); + } + + const requests: Promise[] = []; + + Object.values(payload).forEach((value) => { + if (Array.isArray(value)) { + return; + } + + value.payload.forEach((file: any, index: number) => { + const formData = new FormData(); + formData.append("file", file); + formData.append("token", token); + formData.append("actionId", value.actionId); + + requests.push( + handler.post(resolvedRoute, formData, { + headers: { + "Content-Type": "multipart/form-data", + }, + onUploadProgress: (progressEvent) => { + progressCallback( + `${value.actionId}[${index}]`, + progressEvent, + ); + }, + }), + ); + }); + }); + + return await Promise.all(requests); +} diff --git a/resources/js/components/AdvancedSettings.vue b/resources/js/components/AdvancedSettings.vue index 4393ab1f..db5d9cc2 100644 --- a/resources/js/components/AdvancedSettings.vue +++ b/resources/js/components/AdvancedSettings.vue @@ -1,6 +1,6 @@ @@ -19,6 +20,7 @@ import ConfigureDate from "./ConfigureDate.vue"; import ConfigureInput from "./ConfigureInput.vue"; import ConfigureRange from "./ConfigureRange.vue"; import ConfigureTextarea from "./ConfigureTextarea.vue"; +import ConfigureFile from "./ConfigureFile.vue"; const workbench = useWorkbench(); diff --git a/resources/js/components/Factory/Main/BlockType.vue b/resources/js/components/Factory/Main/BlockType.vue index 2af6f70e..48e3d2f8 100644 --- a/resources/js/components/Factory/Main/BlockType.vue +++ b/resources/js/components/Factory/Main/BlockType.vue @@ -10,7 +10,7 @@ icon="chevron-right" /> - +
+
+ +
+ +
+
+ +
+ + +
+ +
+ + +
+ + + diff --git a/resources/js/components/Factory/Main/ConfigureTextarea.vue b/resources/js/components/Factory/Main/ConfigureTextarea.vue index 14924497..f91c3d24 100644 --- a/resources/js/components/Factory/Main/ConfigureTextarea.vue +++ b/resources/js/components/Factory/Main/ConfigureTextarea.vue @@ -45,9 +45,9 @@ import { useInteractionsUtils } from "../utils/useInteractionsUtils"; const workbench = useWorkbench(); const { findOrCreate } = useInteractionsUtils(); -const label: Ref = ref(""); -const rows = >ref(5); -const maxChars = >ref(500); +const label = ref(""); +const rows = ref(5); +const maxChars = ref(500); const interaction = ref(null) as unknown as Ref; onMounted(async () => { diff --git a/resources/js/components/Factory/Main/Interactions/ClickInteraction.vue b/resources/js/components/Factory/Main/Interactions/ClickInteraction.vue index b154c529..fe166c1f 100644 --- a/resources/js/components/Factory/Main/Interactions/ClickInteraction.vue +++ b/resources/js/components/Factory/Main/Interactions/ClickInteraction.vue @@ -58,7 +58,7 @@ const props = withDefaults( }>(), { showReply: false, - } + }, ); const emit = defineEmits<{ @@ -68,11 +68,11 @@ const emit = defineEmits<{ (e: "onDelete", index: number): void; }>(); -const labelElement = ref(null) as unknown as Ref; +const labelElement = ref(null); const label: Ref = ref(props.item.label); const message: Ref = ref( - props.item.message + props.item.message, ); watch([label, message], (newValues) => { @@ -111,7 +111,13 @@ const keyboardCommands = async (event: KeyboardEvent) => { }; const focus = () => { - labelElement.value.focus(); + if (labelElement.value) { + try { + labelElement.value.$el.querySelector("input").focus(); + } catch (e) { + console.error("Could not focus ClickInteraction input", e); + } + } }; defineExpose({ diff --git a/resources/js/components/Factory/Settings/partials/ImageUpload.vue b/resources/js/components/Factory/Settings/partials/ImageUpload.vue index 1c78ecd5..3241e496 100644 --- a/resources/js/components/Factory/Settings/partials/ImageUpload.vue +++ b/resources/js/components/Factory/Settings/partials/ImageUpload.vue @@ -13,18 +13,14 @@ />
max 4MB
+ - + (); const store = useForm(); -const uploadInput = ref(null) as unknown as Ref; const isSelecting = ref(false); const isDeleting = ref(false); const uploadErrors = ref([]); +const { open, onChange } = useFileDialog({ + accept: "image/png,image/jpeg,image/jpg,image/gif", + multiple: false, +}); + // computed property to retrieve the image url base on the type const imageUrl = computed(() => { if (!store.form) return false; @@ -72,18 +73,8 @@ const imageUrl = computed(() => { : false; }); -const initUpload = () => { +onChange(async (files) => { isSelecting.value = true; - uploadInput.value?.click(); - - setTimeout(() => { - isSelecting.value = false; - }, 2000); -}; - -const selectFiles = async (payload: Event) => { - const files = (payload?.target as HTMLInputElement).files; - if (files && files.length > 0) { const file = files[0]; try { @@ -94,7 +85,8 @@ const selectFiles = async (payload: Event) => { } } } -}; + isSelecting.value = false; +}); const deleteImage = async () => { isDeleting.value = true; diff --git a/resources/js/components/Factory/Submissions/SubmissionTableItem.vue b/resources/js/components/Factory/Submissions/SubmissionTableItem.vue index f7ed98e6..d63ee562 100644 --- a/resources/js/components/Factory/Submissions/SubmissionTableItem.vue +++ b/resources/js/components/Factory/Submissions/SubmissionTableItem.vue @@ -42,14 +42,26 @@ v-for="header in headers" :key="submission.id + header.id" > - - + - @@ -60,7 +72,7 @@ import FormattedDate from "@/forms/common/LocaleDate.vue"; import SubmissionParams from "@/components/Factory/Submissions/SubmissionParams.vue"; import SubmissionWebhookStatus from "@/components/Factory/Submissions/SubmissionWebhookStatus.vue"; -import { D9Button } from "@deck9/ui"; +import { D9Button, D9Icon } from "@deck9/ui"; import { callDeleteFormSubmission } from "@/api/forms"; import { useForm } from "@/stores"; import { useClipboard } from "@vueuse/core"; @@ -96,7 +108,7 @@ const deleteSubmission = async () => { try { await callDeleteFormSubmission( store.form, - props.submission as FormSessionModel + props.submission as FormSessionModel, ); emits("deleted", props.submission.id); diff --git a/resources/js/components/Factory/utils/useBlockTypes.ts b/resources/js/components/Factory/utils/useBlockTypes.ts index 75b6d264..92372995 100644 --- a/resources/js/components/Factory/utils/useBlockTypes.ts +++ b/resources/js/components/Factory/utils/useBlockTypes.ts @@ -17,6 +17,7 @@ export const useBlockTypes = (): { { label: "Rating", value: "rating", icon: "star" }, { label: "Scale", value: "scale", icon: "signal" }, { label: "Date", value: "date", icon: "calendar" }, + { label: "File", value: "input-file", icon: "cloud-arrow-up" }, { label: "Consent", value: "consent", icon: "user-shield" }, ]; diff --git a/resources/js/forms/classic/ClassicForm.vue b/resources/js/forms/classic/ClassicForm.vue index 0a33211e..42df8e37 100644 --- a/resources/js/forms/classic/ClassicForm.vue +++ b/resources/js/forms/classic/ClassicForm.vue @@ -42,6 +42,7 @@ v-bind="{ hideNavigation: flags.hideNavigation, block: store.currentBlock, + key: store.currentBlock?.id, }" :class="{ 'pointer-events-none opacity-0': store.isSubmitted, diff --git a/resources/js/forms/classic/components/UploadFileItem.vue b/resources/js/forms/classic/components/UploadFileItem.vue new file mode 100644 index 00000000..624f0531 --- /dev/null +++ b/resources/js/forms/classic/components/UploadFileItem.vue @@ -0,0 +1,79 @@ + + + diff --git a/resources/js/forms/classic/interactions/ButtonAction.vue b/resources/js/forms/classic/interactions/ButtonAction.vue index 3c45178a..738f9589 100644 --- a/resources/js/forms/classic/interactions/ButtonAction.vue +++ b/resources/js/forms/classic/interactions/ButtonAction.vue @@ -29,15 +29,13 @@ @keydown.enter="stopEditing($event, true)" type="text" :placeholder=" - isChecked && !otherValue - ? t('Type your answer') - : action.label ?? t('Other') + isChecked && !otherValue ? t('type') : action.label ?? t('other') " v-model="otherValue" class="block w-full border-0 focus:ring-0" :class="{ 'pointer-events-none': !isChecked }" /> - {{ + {{ action.label }}
e - Enter + {{ + t("enter") + }}
@@ -94,6 +94,7 @@ const props = defineProps<{ const disableFocus: ComputedRef | undefined = inject("disableFocus"); const buttonElement = ref(null); const otherInput = ref(null); +const otherValue = ref(""); const inputType = props.block.type === "checkbox" ? "checkbox" : "radio"; const shortcutKey = (props.index + 1).toString(); @@ -115,8 +116,6 @@ const isOtherOption = computed(() => { return props.action.name === "alt_response"; }); -const otherValue = ref(""); - const isVisible = computed(() => { return ( !isOtherOption.value || diff --git a/resources/js/forms/classic/interactions/FileAction.vue b/resources/js/forms/classic/interactions/FileAction.vue new file mode 100644 index 00000000..4e66d4d8 --- /dev/null +++ b/resources/js/forms/classic/interactions/FileAction.vue @@ -0,0 +1,189 @@ + + + diff --git a/resources/js/forms/classic/interactions/__snapshots__/ButtonAction.test.ts.snap b/resources/js/forms/classic/interactions/__snapshots__/ButtonAction.test.ts.snap index 85c31362..213baf4f 100644 --- a/resources/js/forms/classic/interactions/__snapshots__/ButtonAction.test.ts.snap +++ b/resources/js/forms/classic/interactions/__snapshots__/ButtonAction.test.ts.snap @@ -2,7 +2,7 @@ exports[`ButtonAction > should mount correctly 1`] = ` "" diff --git a/resources/js/forms/classic/interactions/useButtonAction.ts b/resources/js/forms/classic/interactions/useButtonAction.ts index d2e4018d..ef6e5263 100644 --- a/resources/js/forms/classic/interactions/useButtonAction.ts +++ b/resources/js/forms/classic/interactions/useButtonAction.ts @@ -1,10 +1,12 @@ import ButtonAction from "@/forms/classic/interactions/ButtonAction.vue"; +import { useI18n } from "vue-i18n"; export function useButtonAction(block: PublicFormBlockModel) { + const { t } = useI18n(); const useThis = ["radio", "checkbox"].includes(block.type); const validator = (input: any) => { - const validationMessage = "Please select an option."; + const validationMessage = t("validation.option_required"); if (block.is_required) { if (!input) { diff --git a/resources/js/forms/classic/interactions/useDateAction.ts b/resources/js/forms/classic/interactions/useDateAction.ts index fe318993..9f2e1ff1 100644 --- a/resources/js/forms/classic/interactions/useDateAction.ts +++ b/resources/js/forms/classic/interactions/useDateAction.ts @@ -1,12 +1,14 @@ import DateAction from "@/forms/classic/interactions/DateAction.vue"; +import { useI18n } from "vue-i18n"; export function useDateAction(block: PublicFormBlockModel) { + const { t } = useI18n(); const useThis = ["date"].includes(block.type); const validator = (input: any) => { return { valid: block.is_required ? input?.payload.length > 0 : true, - message: "This field is required", + message: t("validation.field_required"), }; }; diff --git a/resources/js/forms/classic/interactions/useFileAction.ts b/resources/js/forms/classic/interactions/useFileAction.ts new file mode 100644 index 00000000..80e3a00b --- /dev/null +++ b/resources/js/forms/classic/interactions/useFileAction.ts @@ -0,0 +1,66 @@ +import FileAction from "@/forms/classic/interactions/FileAction.vue"; +import { useI18n } from "vue-i18n"; + +export function useFileAction(block: PublicFormBlockModel) { + const { t } = useI18n(); + const useThis = [ + "input-file", + ].includes(block.type); + + const validator = (input: any) => { + + // check if the block is required + if (block.is_required && (!input?.payload || input?.payload.length === 0)) { + return { + valid: false, + message: t("validation.field_required"), + } + } + + // get constraints from block file interaction + const interaction = block.interactions.find((interaction) => { + return interaction.type === "file"; + }) + + if (!interaction) { + return { + valid: false, + message: t("validation.no_file_interaction"), + } + } + + const maxFiles = interaction.options?.allowedFiles; + const maxFileSize = interaction.options?.allowedFileSize ? interaction.options?.allowedFileSize * Math.pow(10,6) : 0; + + // check for max files constrains + if (maxFiles && input?.payload.length > maxFiles) { + return { + valid: false, + message: t(`validation.too_many_files`, { maxFiles }), + } + } + + // check for file size constraints + if (input?.payload && input.payload.length > 0) { + for (const file of input.payload) { + // check for max file size + if (maxFileSize && file.size > maxFileSize) { + return { + valid: false, + message: t(`validation.file_size`, { + fileName: file.name, + maxFileSize: interaction.options?.allowedFileSize + }), + } + } + } + } + + return { + valid: true, + message: "", + } + }; + + return { useThis, component: FileAction, validator, props: {} }; +} diff --git a/resources/js/forms/classic/interactions/useInputAction.ts b/resources/js/forms/classic/interactions/useInputAction.ts index 30251e11..44c961b0 100644 --- a/resources/js/forms/classic/interactions/useInputAction.ts +++ b/resources/js/forms/classic/interactions/useInputAction.ts @@ -1,7 +1,9 @@ import InputAction from "@/forms/classic/interactions/InputAction.vue"; import { string, number } from "yup"; +import { useI18n } from "vue-i18n"; export function useInputAction(block: PublicFormBlockModel) { + const { t } = useI18n(); const useThis = [ "input-short", "input-email", @@ -28,35 +30,35 @@ export function useInputAction(block: PublicFormBlockModel) { valid: (!block.is_required && !input?.payload) || emailValidator.isValidSync(input?.payload), - message: "Please enter a valid email.", + message: t("validation.valid_email"), }; case "input-number": return { valid: (!block.is_required && !input?.payload) || numberValidator.isValidSync(input?.payload), - message: "Please enter a valid number.", + message: t("validation.valid_number"), }; case "input-link": return { valid: (!block.is_required && !input?.payload) || linkValidator.isValidSync(input?.payload), - message: "Please enter a valid link.", + message: t("validation.valid_link"), }; case "input-phone": return { valid: (!block.is_required && !input?.payload) || phoneValidator.isValidSync(input?.payload), - message: "Please enter a valid phone number.", + message: t("validation.valid_phone") }; default: return { valid: (!block.is_required && !input?.payload) || defaultValidator.isValidSync(input?.payload), - message: "Please enter a valid short text.", + message: t("validation.field_required"), }; } }; diff --git a/resources/js/forms/classic/interactions/useRangeAction.ts b/resources/js/forms/classic/interactions/useRangeAction.ts index b47e1c98..09dd22b4 100644 --- a/resources/js/forms/classic/interactions/useRangeAction.ts +++ b/resources/js/forms/classic/interactions/useRangeAction.ts @@ -1,10 +1,11 @@ import RangeAction from "@/forms/classic/interactions/RangeAction.vue"; - +import { useI18n } from "vue-i18n"; export function useRangeAction(block: PublicFormBlockModel) { + const { t } = useI18n(); const useThis = ["rating", "scale"].includes(block.type); const validator = (input: any) => { - const validationMessage = "Please choose a rating."; + const validationMessage = t("validation.rating_required"); if (block.is_required) { if (!input) { diff --git a/resources/js/forms/classic/interactions/useTextareaAction.ts b/resources/js/forms/classic/interactions/useTextareaAction.ts index b816bbe4..cede6432 100644 --- a/resources/js/forms/classic/interactions/useTextareaAction.ts +++ b/resources/js/forms/classic/interactions/useTextareaAction.ts @@ -1,6 +1,8 @@ import TextareaAction from "@/forms/classic/interactions/TextareaAction.vue"; +import { useI18n } from "vue-i18n"; export function useTextareaAction(block: PublicFormBlockModel) { + const { t } = useI18n(); const useThis = ["input-long"].includes(block.type); const validator = (input: any) => { @@ -8,7 +10,7 @@ export function useTextareaAction(block: PublicFormBlockModel) { block.is_required && (!input || input?.payload?.trim().length === 0) ) { - return { valid: false, message: "This field is required" }; + return { valid: false, message: t("validation.field_required") }; } const action = block.interactions[0]; @@ -22,7 +24,7 @@ export function useTextareaAction(block: PublicFormBlockModel) { return { valid: false, message: - "You have exceeded the maximum number of characters allowed.", + t("validation.max_characters"), }; } } diff --git a/resources/js/forms/classic/layout/Block.vue b/resources/js/forms/classic/layout/Block.vue index 3665e3f8..939dc531 100644 --- a/resources/js/forms/classic/layout/Block.vue +++ b/resources/js/forms/classic/layout/Block.vue @@ -10,6 +10,7 @@ > { if (store.currentBlock?.type === "consent") { if (!store.hasRequiredFields && store.countCurrentSelections === 0) { - return store.isLastBlock ? t("Submit") : t("Continue"); + return store.isLastBlock ? t("submit") : t("continue"); } else { - return store.isLastBlock ? t("Accept & Submit") : t("Accept"); + return store.isLastBlock ? t("accept_submit") : t("accept"); } } else { - return store.isLastBlock ? t("Submit") : t("Next"); + return store.isLastBlock ? t("submit") : t("next"); } }); diff --git a/resources/js/forms/classic/layout/FooterNavigation.vue b/resources/js/forms/classic/layout/FooterNavigation.vue index fa8b1f60..f451cbef 100644 --- a/resources/js/forms/classic/layout/FooterNavigation.vue +++ b/resources/js/forms/classic/layout/FooterNavigation.vue @@ -5,14 +5,14 @@ v-if="form?.privacy_link" :href="form?.privacy_link" target="_blank" - >{{ t("Privacy Policy") }}{{ t("privacy_policy") }} {{ t("Legal Notice") }}{{ t("legal_notice") }} diff --git a/resources/js/forms/classic/layout/FormButton.vue b/resources/js/forms/classic/layout/FormButton.vue index 08186435..b24140a5 100644 --- a/resources/js/forms/classic/layout/FormButton.vue +++ b/resources/js/forms/classic/layout/FormButton.vue @@ -16,6 +16,9 @@ class="absolute inset-0 flex items-center justify-center" > + {{ uploadProgress }}%
@@ -24,7 +27,7 @@ :class="{ 'pointer-events-none opacity-0': isDisabled }" class="ml-4 inline-flex items-center justify-center text-xs font-bold leading-none text-content/80 transition duration-150" > - {{ t("Enter") }} + {{ t("enter") }}
@@ -39,6 +42,7 @@ import { useI18n } from "vue-i18n"; defineProps<{ isDisabled?: boolean; isProcessing?: boolean; + uploadProgress?: number | false; label: string; enableInputMode?: boolean; }>(); diff --git a/resources/js/forms/classic/layout/FormSubmittedPage.vue b/resources/js/forms/classic/layout/FormSubmittedPage.vue index 1e05f894..c07d553c 100644 --- a/resources/js/forms/classic/layout/FormSubmittedPage.vue +++ b/resources/js/forms/classic/layout/FormSubmittedPage.vue @@ -1,7 +1,7 @@