diff --git a/.gitignore b/.gitignore index 317a9850..f12825e6 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ composer.lock .DS_Store .idea/php.xml .idea/workspace.xml -.phpunit.cache \ No newline at end of file +.phpunit.cache +workbench \ No newline at end of file diff --git a/.idea/blade.xml b/.idea/blade.xml index 1429e5a2..37317adf 100644 --- a/.idea/blade.xml +++ b/.idea/blade.xml @@ -5,6 +5,7 @@ + @@ -32,6 +33,7 @@ + @@ -51,6 +53,7 @@ + @@ -58,13 +61,16 @@ + + + @@ -84,11 +90,16 @@ + + + + + @@ -100,6 +111,7 @@ + @@ -110,6 +122,8 @@ + + diff --git a/.idea/laravel-idea.xml b/.idea/laravel-idea.xml index 793d126e..d8e17ddc 100644 --- a/.idea/laravel-idea.xml +++ b/.idea/laravel-idea.xml @@ -1,7 +1,12 @@ + + + + \ No newline at end of file diff --git a/.idea/php.xml b/.idea/php.xml index 62ddcaef..5c1487bd 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -17,144 +17,140 @@ - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + diff --git a/.idea/phpspec.xml b/.idea/phpspec.xml index ec7e1d44..1360994f 100644 --- a/.idea/phpspec.xml +++ b/.idea/phpspec.xml @@ -8,6 +8,39 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/watcherTasks.xml b/.idea/watcherTasks.xml new file mode 100644 index 00000000..c70980f4 --- /dev/null +++ b/.idea/watcherTasks.xml @@ -0,0 +1,25 @@ + + + + + + + + \ No newline at end of file diff --git a/.phpunit.cache/test-results b/.phpunit.cache/test-results deleted file mode 100644 index d72f85c3..00000000 --- a/.phpunit.cache/test-results +++ /dev/null @@ -1 +0,0 @@ -{"version":"pest_2.36.0","defects":{"P\\Tests\\Unit\\Helpers\\TypeTest::__pest_evaluable_it_should_return_alert_type_from_prefixed_type":8},"times":{"P\\Tests\\Unit\\Helpers\\AttributeTest::__pest_evaluable_it_can_generate_html_element_attribute_from_an_array":0.035,"P\\Tests\\Unit\\Helpers\\SessionKeyTest::__pest_evaluable_it_can_generate_a_session_key_from_tag_name_and_alert_type":0.001,"P\\Tests\\Feature\\Component\\ButtonTest::__pest_evaluable_it_can_create_button_component":0.001,"P\\Tests\\Feature\\Components\\FieldBagTest::__pest_evaluable_it_can_render_validation_errors_for_the_field_view_component":0.03,"P\\Tests\\Feature\\Components\\FieldTest::__pest_evaluable_it_can_render_a_default_field_view_component":0.002,"P\\Tests\\Feature\\Components\\FieldTest::__pest_evaluable_it_can_render_a_tagged_field_view_component":0.002,"P\\Tests\\Feature\\Components\\MessageTest::__pest_evaluable_it_can_render_a_default_message_alert":0.002,"P\\Tests\\Feature\\Components\\ModalTest::__pest_evaluable_it_can_render_a_default_modal_view_component":0.003,"P\\Tests\\Feature\\Components\\ModalTest::__pest_evaluable_it_can_render_a_default_modal_with_buttons_and_title":0.002,"P\\Tests\\Feature\\Components\\ModalTest::__pest_evaluable_it_can_render_a_default_modal_a_the_right_position":0.001,"P\\Tests\\Feature\\Components\\ModalTest::__pest_evaluable_it_can_render_a_default_modal_a_the_right_size":0.004,"P\\Tests\\Feature\\Components\\NotifyTest::__pest_evaluable_it_can_render_a_default_notify_alert":0.002,"P\\Tests\\Feature\\Components\\NotifyTest::__pest_evaluable_it_can_render_a_tagged_notify_alert":0.001,"P\\Tests\\Feature\\Components\\StickyTest::__pest_evaluable_it_can_render_a_default_sticky_alert":0.002,"P\\Tests\\Feature\\Components\\StickyTest::__pest_evaluable_it_can_render_a_tagged_sticky_alert":0.001,"P\\Tests\\Feature\\Components\\StickyTest::__pest_evaluable_it_can_render_a_tagged_sticky_alert_button":0.001,"P\\Tests\\Feature\\Traits\\LevelableTest::__pest_evaluable_it_can_sets_the_correct_levels":0.001,"P\\Tests\\Feature\\Types\\FieldTest::__pest_evaluable_it_can_create_an_alert":0,"P\\Tests\\Feature\\Types\\MessageTest::__pest_evaluable_it_can_create_a_default_alert":0,"P\\Tests\\Feature\\Types\\ModalTest::__pest_evaluable_it_can_create_a_modal_alert":0,"P\\Tests\\Feature\\Types\\NotifyTest::__pest_evaluable_it_can_create_a_notify_alert":0,"P\\Tests\\Feature\\Types\\NotifyTest::__pest_evaluable_it_can_create_a_notify_alert_position":0.001,"P\\Tests\\Feature\\Types\\StickyTest::__pest_evaluable_it_can_create_a_sticky_alert":0,"P\\Tests\\Feature\\Types\\StickyTest::__pest_evaluable_it_can_create_a_sticky_alert_title":0,"P\\Tests\\Feature\\Types\\StickyTest::__pest_evaluable_it_can_create_a_sticky_alert_button":0,"P\\Tests\\Feature\\Components\\FieldTest::__pest_evaluable_it_can_render_a_named_field_view_component":0.002,"P\\Tests\\Feature\\Helpers\\FieldTest::__pest_evaluable_it_can_create_an_alert_with_helper":0.001,"P\\Tests\\Feature\\Helpers\\MessageTest::__pest_evaluable_it_can_create_a_default_alert_with_helper":0,"P\\Tests\\Feature\\Helpers\\ModalTest::__pest_evaluable_it_can_create_a_modal_alert_with_helper":0,"P\\Tests\\Feature\\Helpers\\NotifyTest::__pest_evaluable_it_can_create_a_notify_alert__with_helper":0,"P\\Tests\\Feature\\Helpers\\StickyTest::__pest_evaluable_it_can_create_a_sticky_alert__with_helper":0,"P\\Tests\\Unit\\Helpers\\ThemeTest::__pest_evaluable_it_can_get_the_correct_theme_name":0,"P\\Tests\\Unit\\Helpers\\ThemeTest::__pest_evaluable_it_can_get_all_themes":0.004,"P\\Tests\\Unit\\Helpers\\ThemeTest::__pest_evaluable_it_can_get_the_correct_theme_based_on_config":0,"P\\Tests\\Unit\\Helpers\\TypeTest::__pest_evaluable_it_should_return_alert_types":0.001,"P\\Tests\\Unit\\Helpers\\TypeTest::__pest_evaluable_it_should_return_prefixed_alert_type":0,"P\\Tests\\Unit\\Helpers\\TypeTest::__pest_evaluable_it_should_check_if_alert_type_exists":0.001,"P\\Tests\\Unit\\Helpers\\TypeTest::__pest_evaluable_it_should_return_alert_type":0.001,"P\\Tests\\Unit\\Helpers\\TypeTest::__pest_evaluable_it_should_return_alert_class_name":0,"P\\Tests\\Unit\\Helpers\\TypeTest::__pest_evaluable_it_should_throw_exception_if_alert_type_does_not_exist":0.001,"P\\Tests\\Unit\\Helpers\\TypeTest::__pest_evaluable_it_should_return_alert_type_from_prefixed_type":0.014}} \ No newline at end of file diff --git a/composer.json b/composer.json index 220f8a14..67fb00a4 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "digitlimit/alert", - "description": "An easy way of flashing messages in Laravel Application", + "description": "An easy way of flashing messages in Laravel Application, with support for Livewire, Inertia, TailwindCSS, and Bootstrap.", "license": "MIT", "authors": [ { @@ -21,18 +21,9 @@ ], "require": { "ext-json": "*", - "php": "^8.0", - "illuminate/contracts": "^7.20|^8.19|^9.0|^10.0|^11.0", - "illuminate/support": "^7.20|^8.19|^9.0|^10.0|^11.0" - }, - "require-dev": { - "guzzlehttp/guzzle": "^7.3", - "laravel/framework": "^7.20|^8.19|^9.0|^10.0|^11.0", - "phpunit/phpunit": "^10.0", - "orchestra/testbench": "^8.5", - "nunomaduro/collision": "^7.5", - "pestphp/pest": "^2.5", - "laravel/pint": "^1.10" + "php": "^8.2", + "laravel/framework": "^10.0 || ^11.0 || ^12.0", + "livewire/livewire": "^2.12 || ^3.6" }, "autoload": { "psr-4": { @@ -44,7 +35,10 @@ }, "autoload-dev": { "psr-4": { - "Digitlimit\\Alert\\Tests\\": "tests" + "Digitlimit\\Alert\\Tests\\": "tests", + "App\\": "workbench/app/", + "Database\\Factories\\": "workbench/database/factories/", + "Database\\Seeders\\": "workbench/database/seeders/" } }, "extra": { @@ -57,16 +51,38 @@ } } }, - "scripts": { - "post-autoload-dump": [ - "@php vendor/bin/testbench package:discover --ansi" - ] - }, "config": { "allow-plugins": { - "pestphp/pest-plugin": true + "pestphp/pest-plugin": true, + "composer/installers": true } }, - "minimum-stability": "dev", - "prefer-stable": true -} + "minimum-stability": "stable", + "prefer-stable": true, + "require-dev": { + "laravel/pint": "^1.21", + "pestphp/pest": "^3.7", + "orchestra/testbench": "^10.0" + }, + "scripts": { + "post-autoload-dump": [ + "@clear", + "@prepare" + ], + "clear": "@php vendor/bin/testbench package:purge-skeleton --ansi", + "prepare": "@php vendor/bin/testbench package:discover --ansi", + "build": "@php vendor/bin/testbench workbench:build --ansi", + "serve": [ + "Composer\\Config::disableProcessTimeout", + "@build", + "@php vendor/bin/testbench serve --ansi" + ], + "lint": [ + "@php vendor/bin/pint --ansi" + ], + "test": [ + "@clear", + "@php vendor/bin/pest" + ] + } +} \ No newline at end of file diff --git a/config/alert.php b/config/alert.php index 506b88cf..f722eb26 100644 --- a/config/alert.php +++ b/config/alert.php @@ -1,7 +1,7 @@ 'bootstrap5', + 'theme' => 'tailwind', /* |-------------------------------------------------------------------------- @@ -25,83 +25,141 @@ | */ 'themes' => [ - 'classic' => [ - 'components' => 'Digitlimit\Alert\View\Components\Themes\Classic', - 'types' => [ - 'message' => [ - 'view' => 'alert-message', - 'alert' => Types\Message::class, - 'component' => Themes\Classic\Message::class, - ], + 'tailwind' => Themes\Tailwind\Tailwind::class, + ], - 'field' => [ - 'view' => 'alert-field', - 'alert' => Types\Field::class, - 'component' => Themes\Classic\Field::class, - ], + /* + |-------------------------------------------------------------------------- + | Themes Settings + |-------------------------------------------------------------------------- + | + | Themes settings + | + */ + 'tailwind' => [ + 'types' => [ + 'message' => [ + 'view' => 'alert-message', + 'alert' => Types\Message::class, + 'component' => Themes\Tailwind\Components\Message::class, + ], - 'bag' => [ - 'view' => 'alert-field', - 'alert' => Types\FieldBag::class, - 'component' => Themes\Classic\Field::class, - ], + 'field' => [ + 'view' => 'alert-field', + 'alert' => Types\Field::class, + 'component' => Themes\Tailwind\Components\Field::class, + ], - 'modal' => [ - 'view' => 'alert-modal', - 'alert' => Types\Modal::class, - 'component' => Themes\Classic\Modal::class, - ], + 'modal' => [ + 'view' => 'alert-modal', + 'alert' => Types\Modal::class, + 'component' => Themes\Tailwind\Components\Modal::class, + ], - 'notify' => [ - 'view' => 'alert-notify', - 'alert' => Types\Notify::class, - 'component' => Themes\Classic\Notify::class, + 'notify' => [ + 'view' => 'alert-notify', + 'alert' => Types\Notify::class, + 'component' => Themes\Tailwind\Components\Notify::class, + ], + ], + 'attributes' => [ + 'buttons' => [ + 'action' => [ + 'type' => 'button', + '@click' => 'show = false;', ], - - 'sticky' => [ - 'view' => 'alert-sticky', - 'alert' => Types\Sticky::class, - 'component' => Themes\Classic\Sticky::class, + 'cancel' => [ + 'type' => 'button', + '@click' => 'show = false;', ], ], - ], - 'bootstrap5' => [ - 'components' => 'Digitlimit\Alert\View\Components\Themes\Bootstrap5', - 'types' => [ - 'message' => [ - 'view' => 'alert-message', - 'alert' => Types\Message::class, - 'component' => Themes\Bootstrap5\Message::class, + 'links' => [ + 'action' => [ + 'type' => 'button', + '@click' => 'show = false;', ], - - 'field' => [ - 'view' => 'alert-field', - 'alert' => Types\Field::class, - 'component' => Themes\Bootstrap5\Field::class, + 'cancel' => [ + 'type' => 'button', + '@click' => 'show = false;', ], + ], + ], + 'classes' => [ + 'buttons' => [ + 'primary' => 'inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-900 focus:ring-offset-2 bg-neutral-950 hover:bg-neutral-900', + 'secondary' => 'inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium transition-colors border rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-100 focus:ring-offset-2', + + 'success' => 'inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-green-700 focus:ring-offset-2 bg-green-600 hover:bg-green-700', + 'error' => 'inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-red-700 focus:ring-offset-2 bg-red-600 hover:bg-red-700', + 'warning' => 'inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-black transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-yellow-600 focus:ring-offset-2 bg-yellow-400 hover:bg-yellow-500', + 'info' => 'inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-blue-700 focus:ring-offset-2 bg-blue-600 hover:bg-blue-700', + 'light' => 'inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-black transition-colors border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-300 focus:ring-offset-2 bg-white hover:bg-gray-100', + 'dark' => 'inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-gray-900 focus:ring-offset-2 bg-gray-800 hover:bg-gray-900', + 'link' => 'inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-blue-600 transition-colors rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 hover:underline', + ], - 'bag' => [ - 'view' => 'alert-field', - 'alert' => Types\FieldBag::class, - 'component' => Themes\Bootstrap5\Field::class, + 'field' => [ + 'levels' => [ + 'success' => [ + 'container' => 'p-3 text-green-800', + ], + 'error' => [ + 'container' => 'p-3 text-red-800', + ], + 'warning' => [ + 'container' => 'p-3 text-yellow-800', + ], + 'info' => [ + 'container' => 'p-3 text-blue-800', + ], ], + ], - 'modal' => [ - 'view' => 'alert-modal', - 'alert' => Types\Modal::class, - 'component' => Themes\Bootstrap5\Modal::class, + 'notify' => [ + 'levels' => [ + 'success' => [ + 'container' => 'bg-gray-900 bg-gradient-to-r text-white rounded-t mb-3 shadow-lg flex items-center from-green-400 to-green-500', + ], + 'error' => [ + 'container' => 'bg-gray-900 bg-gradient-to-r text-white rounded-t mb-3 shadow-lg flex items-center from-red-400 to-pink-500', + ], + 'warning' => [ + 'container' => 'bg-gray-900 bg-gradient-to-r text-white rounded-t mb-3 shadow-lg flex items-center from-yellow-400 to-yellow-500', + ], + 'info' => [ + 'container' => 'bg-gray-900 bg-gradient-to-r text-white rounded-t mb-3 shadow-lg flex items-center from-blue-400 to-blue-500', + ], ], - 'notify' => [ - 'view' => 'alert-notify', - 'alert' => Types\Notify::class, - 'component' => Themes\Bootstrap5\Notify::class, + 'position' => [ + 'top-right' => 'top-0 right-0', + 'top-left' => 'top-0 left-0', + 'bottom-right' => 'bottom-0 right-0', + 'bottom-left' => 'bottom-0 left-0', + 'top-center' => 'top-0 left-1/2 transform -translate-x-1/2', + 'bottom-center' => 'bottom-0 left-1/2 transform -translate-x-1/2', + 'center' => 'top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2', ], + ], - 'sticky' => [ - 'view' => 'alert-sticky', - 'alert' => Types\Sticky::class, - 'component' => Themes\Bootstrap5\Sticky::class, + 'message' => [ + 'levels' => [ + 'success' => [ + 'container' => 'flex items-center p-4 mb-4 text-green-800 rounded-lg bg-green-50 dark:bg-gray-800 dark:text-green-400', + 'close' => 'ms-auto -mx-1.5 -my-1.5 bg-blue-50 text-blue-500 rounded-lg focus:ring-2 focus:ring-blue-400 p-1.5 hover:bg-blue-200 inline-flex items-center justify-center h-8 w-8 dark:bg-gray-800 dark:text-blue-400 dark:hover:bg-gray-700', + ], + 'error' => [ + 'container' => 'flex items-center p-4 mb-4 text-red-800 rounded-lg bg-red-50 dark:bg-gray-800 dark:text-red-400', + 'close' => 'ms-auto -mx-1.5 -my-1.5 bg-red-50 text-red-500 rounded-lg focus:ring-2 focus:ring-red-400 p-1.5 hover:bg-red-200 inline-flex items-center justify-center h-8 w-8 dark:bg-gray-800 dark:text-red-400 dark:hover:bg-gray-700', + ], + 'warning' => [ + 'container' => 'flex items-center p-4 mb-4 text-yellow-800 rounded-lg bg-yellow-50 dark:bg-gray-800 dark:text-yellow-300', + 'close' => 'ms-auto -mx-1.5 -my-1.5 bg-yellow-50 text-yellow-500 rounded-lg focus:ring-2 focus:ring-yellow-400 p-1.5 hover:bg-yellow-200 inline-flex items-center justify-center h-8 w-8 dark:bg-gray-800 dark:text-yellow-400 dark:hover:bg-gray-700', + ], + 'info' => [ + 'container' => 'flex items-center p-4 mb-4 text-blue-800 rounded-lg bg-blue-50 dark:bg-gray-800 dark:text-blue-400', + 'close' => 'ms-auto -mx-1.5 -my-1.5 bg-blue-50 text-blue-500 rounded-lg focus:ring-2 focus:ring-blue-400 p-1.5 hover:bg-blue-200 inline-flex items-center justify-center h-8 w-8 dark:bg-gray-800 dark:text-blue-400 dark:hover:bg-gray-700', + ], ], ], ], diff --git a/index.html b/index.html deleted file mode 100644 index c49b4164..00000000 --- a/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - Alert - - -

Digitlimit Alert

-

A Laravel package for alert messaging.

- - diff --git a/package-lock.json b/package-lock.json index 772c55da..02306f19 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,342 +1,17 @@ { "name": "alert", - "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "alert", - "version": "1.0.0", - "license": "ISC", "devDependencies": { - "@rollup/plugin-babel": "^6.0.4", - "@rollup/plugin-commonjs": "^28.0.2", - "@rollup/plugin-node-resolve": "^16.0.0", - "@rollup/plugin-terser": "^0.4.4", - "cssnano": "^7.0.6", - "postcss": "^8.4.49", - "rollup": "^4.30.1", - "rollup-plugin-scss": "^4.0.1", - "sass": "^1.83.1" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.3.tgz", - "integrity": "sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", - "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", - "dev": true, - "peer": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.0", - "@babel/generator": "^7.26.0", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.0", - "@babel/parser": "^7.26.0", - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.26.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", - "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.26.3", - "@babel/types": "^7.26.3", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", - "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/compat-data": "^7.25.9", - "@babel/helper-validator-option": "^7.25.9", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", - "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", - "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.26.3" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/template": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", - "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.26.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz", - "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.3", - "@babel/parser": "^7.26.3", - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.3", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", - "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "sass": "^1.85.1" } }, "node_modules/@parcel/watcher": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz", - "integrity": "sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -355,25 +30,25 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.5.0", - "@parcel/watcher-darwin-arm64": "2.5.0", - "@parcel/watcher-darwin-x64": "2.5.0", - "@parcel/watcher-freebsd-x64": "2.5.0", - "@parcel/watcher-linux-arm-glibc": "2.5.0", - "@parcel/watcher-linux-arm-musl": "2.5.0", - "@parcel/watcher-linux-arm64-glibc": "2.5.0", - "@parcel/watcher-linux-arm64-musl": "2.5.0", - "@parcel/watcher-linux-x64-glibc": "2.5.0", - "@parcel/watcher-linux-x64-musl": "2.5.0", - "@parcel/watcher-win32-arm64": "2.5.0", - "@parcel/watcher-win32-ia32": "2.5.0", - "@parcel/watcher-win32-x64": "2.5.0" + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@parcel/watcher-win32-x64": "2.5.1" } }, "node_modules/@parcel/watcher-android-arm64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz", - "integrity": "sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", "cpu": [ "arm64" ], @@ -392,9 +67,9 @@ } }, "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz", - "integrity": "sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", "cpu": [ "arm64" ], @@ -413,9 +88,9 @@ } }, "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz", - "integrity": "sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", "cpu": [ "x64" ], @@ -434,9 +109,9 @@ } }, "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz", - "integrity": "sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", "cpu": [ "x64" ], @@ -455,9 +130,9 @@ } }, "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz", - "integrity": "sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", "cpu": [ "arm" ], @@ -476,9 +151,9 @@ } }, "node_modules/@parcel/watcher-linux-arm-musl": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz", - "integrity": "sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", "cpu": [ "arm" ], @@ -497,9 +172,9 @@ } }, "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz", - "integrity": "sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", "cpu": [ "arm64" ], @@ -518,9 +193,9 @@ } }, "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz", - "integrity": "sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", "cpu": [ "arm64" ], @@ -539,9 +214,9 @@ } }, "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz", - "integrity": "sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", "cpu": [ "x64" ], @@ -560,9 +235,9 @@ } }, "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz", - "integrity": "sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", "cpu": [ "x64" ], @@ -581,9 +256,9 @@ } }, "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz", - "integrity": "sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", "cpu": [ "arm64" ], @@ -602,9 +277,9 @@ } }, "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz", - "integrity": "sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", "cpu": [ "ia32" ], @@ -623,9 +298,9 @@ } }, "node_modules/@parcel/watcher-win32-x64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz", - "integrity": "sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", "cpu": [ "x64" ], @@ -643,1882 +318,162 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/@rollup/plugin-babel": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-6.0.4.tgz", - "integrity": "sha512-YF7Y52kFdFT/xVSuVdjkV5ZdX/3YtmX0QulG+x0taQOtJdHYzVU61aSSkAgVJ7NOv6qPkIYiJSgSWWN/DM5sGw==", + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@rollup/pluginutils": "^5.0.1" + "fill-range": "^7.1.1" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0", - "@types/babel__core": "^7.1.9", - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "@types/babel__core": { - "optional": true - }, - "rollup": { - "optional": true - } + "node": ">=8" } }, - "node_modules/@rollup/plugin-commonjs": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.2.tgz", - "integrity": "sha512-BEFI2EDqzl+vA1rl97IDRZ61AIwGH093d9nz8+dThxJNH8oSoB7MjWvPCX3dkaK1/RCJ/1v/R1XB15FuSs0fQw==", + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, + "license": "MIT", "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "commondir": "^1.0.1", - "estree-walker": "^2.0.2", - "fdir": "^6.2.0", - "is-reference": "1.2.1", - "magic-string": "^0.30.3", - "picomatch": "^4.0.2" + "readdirp": "^4.0.1" }, "engines": { - "node": ">=16.0.0 || 14 >= 14.17" + "node": ">= 14.16.0" }, - "peerDependencies": { - "rollup": "^2.68.0||^3.0.0||^4.0.0" + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "engines": { + "node": ">=0.10" } }, - "node_modules/@rollup/plugin-commonjs/node_modules/fdir": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", - "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, - "peerDependencies": { - "picomatch": "^3 || ^4" + "license": "MIT", + "optional": true, + "dependencies": { + "to-regex-range": "^5.0.1" }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "engines": { + "node": ">=8" } }, - "node_modules/@rollup/plugin-commonjs/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "node_modules/immutable": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz", + "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", + "optional": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=0.10.0" } }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.0.tgz", - "integrity": "sha512-0FPvAeVUT/zdWoO0jnb/V5BlBsUSNfkIOtFHzMO4H9MOklrmQFY6FduVHKucNb/aTFxvnGhj4MNj/T1oNdDfNg==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "@types/resolve": "1.20.2", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.22.1" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.78.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "node": ">=0.10.0" } }, - "node_modules/@rollup/plugin-terser": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", - "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "dependencies": { - "serialize-javascript": "^6.0.1", - "smob": "^1.0.0", - "terser": "^5.17.4" - }, + "license": "MIT", + "optional": true, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "node": ">=0.12.0" } }, - "node_modules/@rollup/pluginutils": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", - "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^4.0.2" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "node": ">=8.6" } }, - "node_modules/@rollup/pluginutils/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", + "optional": true, "engines": { - "node": ">=12" + "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.30.1.tgz", - "integrity": "sha512-pSWY+EVt3rJ9fQ3IqlrEUtXh3cGqGtPDH1FQlNZehO2yYxCHEX1SPsz1M//NXwYfbTlcKr9WObLnJX9FsS9K1Q==", - "cpu": [ - "arm" - ], + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, - "optional": true, - "os": [ - "android" - ] + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.30.1.tgz", - "integrity": "sha512-/NA2qXxE3D/BRjOJM8wQblmArQq1YoBVJjrjoTSBS09jgUisq7bqxNHJ8kjCHeV21W/9WDGwJEWSN0KQ2mtD/w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.30.1.tgz", - "integrity": "sha512-r7FQIXD7gB0WJ5mokTUgUWPl0eYIH0wnxqeSAhuIwvnnpjdVB8cRRClyKLQr7lgzjctkbp5KmswWszlwYln03Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.30.1.tgz", - "integrity": "sha512-x78BavIwSH6sqfP2xeI1hd1GpHL8J4W2BXcVM/5KYKoAD3nNsfitQhvWSw+TFtQTLZ9OmlF+FEInEHyubut2OA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.30.1.tgz", - "integrity": "sha512-HYTlUAjbO1z8ywxsDFWADfTRfTIIy/oUlfIDmlHYmjUP2QRDTzBuWXc9O4CXM+bo9qfiCclmHk1x4ogBjOUpUQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.30.1.tgz", - "integrity": "sha512-1MEdGqogQLccphhX5myCJqeGNYTNcmTyaic9S7CG3JhwuIByJ7J05vGbZxsizQthP1xpVx7kd3o31eOogfEirw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.30.1.tgz", - "integrity": "sha512-PaMRNBSqCx7K3Wc9QZkFx5+CX27WFpAMxJNiYGAXfmMIKC7jstlr32UhTgK6T07OtqR+wYlWm9IxzennjnvdJg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.30.1.tgz", - "integrity": "sha512-B8Rcyj9AV7ZlEFqvB5BubG5iO6ANDsRKlhIxySXcF1axXYUyqwBok+XZPgIYGBgs7LDXfWfifxhw0Ik57T0Yug==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.30.1.tgz", - "integrity": "sha512-hqVyueGxAj3cBKrAI4aFHLV+h0Lv5VgWZs9CUGqr1z0fZtlADVV1YPOij6AhcK5An33EXaxnDLmJdQikcn5NEw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.30.1.tgz", - "integrity": "sha512-i4Ab2vnvS1AE1PyOIGp2kXni69gU2DAUVt6FSXeIqUCPIR3ZlheMW3oP2JkukDfu3PsexYRbOiJrY+yVNSk9oA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.30.1.tgz", - "integrity": "sha512-fARcF5g296snX0oLGkVxPmysetwUk2zmHcca+e9ObOovBR++9ZPOhqFUM61UUZ2EYpXVPN1redgqVoBB34nTpQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.30.1.tgz", - "integrity": "sha512-GLrZraoO3wVT4uFXh67ElpwQY0DIygxdv0BNW9Hkm3X34wu+BkqrDrkcsIapAY+N2ATEbvak0XQ9gxZtCIA5Rw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.30.1.tgz", - "integrity": "sha512-0WKLaAUUHKBtll0wvOmh6yh3S0wSU9+yas923JIChfxOaaBarmb/lBKPF0w/+jTVozFnOXJeRGZ8NvOxvk/jcw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.30.1.tgz", - "integrity": "sha512-GWFs97Ruxo5Bt+cvVTQkOJ6TIx0xJDD/bMAOXWJg8TCSTEK8RnFeOeiFTxKniTc4vMIaWvCplMAFBt9miGxgkA==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.30.1.tgz", - "integrity": "sha512-UtgGb7QGgXDIO+tqqJ5oZRGHsDLO8SlpE4MhqpY9Llpzi5rJMvrK6ZGhsRCST2abZdBqIBeXW6WPD5fGK5SDwg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.30.1.tgz", - "integrity": "sha512-V9U8Ey2UqmQsBT+xTOeMzPzwDzyXmnAoO4edZhL7INkwQcaW1Ckv3WJX3qrrp/VHaDkEWIBWhRwP47r8cdrOow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.30.1.tgz", - "integrity": "sha512-WabtHWiPaFF47W3PkHnjbmWawnX/aE57K47ZDT1BXTS5GgrBUEpvOzq0FI0V/UYzQJgdb8XlhVNH8/fwV8xDjw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.30.1.tgz", - "integrity": "sha512-pxHAU+Zv39hLUTdQQHUVHf4P+0C47y/ZloorHpzs2SXMRqeAWmGghzAhfOlzFHHwjvgokdFAhC4V+6kC1lRRfw==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.30.1.tgz", - "integrity": "sha512-D6qjsXGcvhTjv0kI4fU8tUuBDF/Ueee4SVX79VfNDXZa64TfCW1Slkb6Z7O1p7vflqZjcmOVdZlqf8gvJxc6og==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true - }, - "node_modules/@types/resolve": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", - "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", - "dev": true - }, - "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dev": true, - "dependencies": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001690", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", - "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true - }, - "node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "peer": true - }, - "node_modules/css-declaration-sorter": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz", - "integrity": "sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==", - "dev": true, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss": "^8.0.9" - } - }, - "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-select/node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/css-select/node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/css-select/node_modules/domutils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", - "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", - "dev": true, - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/css-select/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, - "dependencies": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cssnano": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-7.0.6.tgz", - "integrity": "sha512-54woqx8SCbp8HwvNZYn68ZFAepuouZW4lTwiMVnBErM3VkO7/Sd4oTOt3Zz3bPx3kxQ36aISppyXj2Md4lg8bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssnano-preset-default": "^7.0.6", - "lilconfig": "^3.1.2" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/cssnano" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/cssnano-preset-default": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-7.0.6.tgz", - "integrity": "sha512-ZzrgYupYxEvdGGuqL+JKOY70s7+saoNlHSCK/OGn1vB2pQK8KSET8jvenzItcY+kA7NoWvfbb/YhlzuzNKjOhQ==", - "dev": true, - "dependencies": { - "browserslist": "^4.23.3", - "css-declaration-sorter": "^7.2.0", - "cssnano-utils": "^5.0.0", - "postcss-calc": "^10.0.2", - "postcss-colormin": "^7.0.2", - "postcss-convert-values": "^7.0.4", - "postcss-discard-comments": "^7.0.3", - "postcss-discard-duplicates": "^7.0.1", - "postcss-discard-empty": "^7.0.0", - "postcss-discard-overridden": "^7.0.0", - "postcss-merge-longhand": "^7.0.4", - "postcss-merge-rules": "^7.0.4", - "postcss-minify-font-values": "^7.0.0", - "postcss-minify-gradients": "^7.0.0", - "postcss-minify-params": "^7.0.2", - "postcss-minify-selectors": "^7.0.4", - "postcss-normalize-charset": "^7.0.0", - "postcss-normalize-display-values": "^7.0.0", - "postcss-normalize-positions": "^7.0.0", - "postcss-normalize-repeat-style": "^7.0.0", - "postcss-normalize-string": "^7.0.0", - "postcss-normalize-timing-functions": "^7.0.0", - "postcss-normalize-unicode": "^7.0.2", - "postcss-normalize-url": "^7.0.0", - "postcss-normalize-whitespace": "^7.0.0", - "postcss-ordered-values": "^7.0.1", - "postcss-reduce-initial": "^7.0.2", - "postcss-reduce-transforms": "^7.0.0", - "postcss-svgo": "^7.0.1", - "postcss-unique-selectors": "^7.0.3" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/cssnano-utils": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-5.0.0.tgz", - "integrity": "sha512-Uij0Xdxc24L6SirFr25MlwC2rCFX6scyUmuKpzI+JQ7cyqDEwD42fJ0xfB3yLfOnRDU5LKGgjQ9FA6LYh76GWQ==", - "dev": true, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/cssnano/node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "node_modules/csso": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", - "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dev": true, - "dependencies": { - "css-tree": "~2.2.0" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/csso/node_modules/css-tree": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", - "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dev": true, - "dependencies": { - "mdn-data": "2.0.28", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/csso/node_modules/mdn-data": { - "version": "2.0.28", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", - "dev": true - }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/electron-to-chromium": { - "version": "1.5.79", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.79.tgz", - "integrity": "sha512-nYOxJNxQ9Om4EC88BE4pPoNI8xwSFf8pU/BAeOl4Hh/b/i6V4biTAzwV7pXi3ARKeoYO5JZKMIXTryXSVer5RA==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "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==", - "dev": true - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/immutable": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz", - "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", - "dev": true - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", - "dev": true, - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "peer": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "peer": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/mdn-data": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-calc": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-10.1.0.tgz", - "integrity": "sha512-uQ/LDGsf3mgsSUEXmAt3VsCSHR3aKqtEIkmB+4PhzYwRYOW5MZs/GhCCFpsOtJJkP6EC6uGipbrnaTjqaJZcJw==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^7.0.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^18.12 || ^20.9 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.38" - } - }, - "node_modules/postcss-colormin": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-7.0.2.tgz", - "integrity": "sha512-YntRXNngcvEvDbEjTdRWGU606eZvB5prmHG4BF0yLmVpamXbpsRJzevyy6MZVyuecgzI2AWAlvFi8DAeCqwpvA==", - "dev": true, - "dependencies": { - "browserslist": "^4.23.3", - "caniuse-api": "^3.0.0", - "colord": "^2.9.3", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-convert-values": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-7.0.4.tgz", - "integrity": "sha512-e2LSXPqEHVW6aoGbjV9RsSSNDO3A0rZLCBxN24zvxF25WknMPpX8Dm9UxxThyEbaytzggRuZxaGXqaOhxQ514Q==", - "dev": true, - "dependencies": { - "browserslist": "^4.23.3", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-discard-comments": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-7.0.3.tgz", - "integrity": "sha512-q6fjd4WU4afNhWOA2WltHgCbkRhZPgQe7cXF74fuVB/ge4QbM9HEaOIzGSiMvM+g/cOsNAUGdf2JDzqA2F8iLA==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.1.2" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-discard-comments/node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-discard-duplicates": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-7.0.1.tgz", - "integrity": "sha512-oZA+v8Jkpu1ct/xbbrntHRsfLGuzoP+cpt0nJe5ED2FQF8n8bJtn7Bo28jSmBYwqgqnqkuSXJfSUEE7if4nClQ==", - "dev": true, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-discard-empty": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-7.0.0.tgz", - "integrity": "sha512-e+QzoReTZ8IAwhnSdp/++7gBZ/F+nBq9y6PomfwORfP7q9nBpK5AMP64kOt0bA+lShBFbBDcgpJ3X4etHg4lzA==", - "dev": true, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-discard-overridden": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-7.0.0.tgz", - "integrity": "sha512-GmNAzx88u3k2+sBTZrJSDauR0ccpE24omTQCVmaTTZFz1du6AasspjaUPMJ2ud4RslZpoFKyf+6MSPETLojc6w==", - "dev": true, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-merge-longhand": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-7.0.4.tgz", - "integrity": "sha512-zer1KoZA54Q8RVHKOY5vMke0cCdNxMP3KBfDerjH/BYHh4nCIh+1Yy0t1pAEQF18ac/4z3OFclO+ZVH8azjR4A==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^7.0.4" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-merge-rules": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-7.0.4.tgz", - "integrity": "sha512-ZsaamiMVu7uBYsIdGtKJ64PkcQt6Pcpep/uO90EpLS3dxJi6OXamIobTYcImyXGoW0Wpugh7DSD3XzxZS9JCPg==", - "dev": true, - "dependencies": { - "browserslist": "^4.23.3", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^5.0.0", - "postcss-selector-parser": "^6.1.2" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-merge-rules/node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-minify-font-values": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-7.0.0.tgz", - "integrity": "sha512-2ckkZtgT0zG8SMc5aoNwtm5234eUx1GGFJKf2b1bSp8UflqaeFzR50lid4PfqVI9NtGqJ2J4Y7fwvnP/u1cQog==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-minify-gradients": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-7.0.0.tgz", - "integrity": "sha512-pdUIIdj/C93ryCHew0UgBnL2DtUS3hfFa5XtERrs4x+hmpMYGhbzo6l/Ir5de41O0GaKVpK1ZbDNXSY6GkXvtg==", - "dev": true, - "dependencies": { - "colord": "^2.9.3", - "cssnano-utils": "^5.0.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-minify-params": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-7.0.2.tgz", - "integrity": "sha512-nyqVLu4MFl9df32zTsdcLqCFfE/z2+f8GE1KHPxWOAmegSo6lpV2GNy5XQvrzwbLmiU7d+fYay4cwto1oNdAaQ==", - "dev": true, - "dependencies": { - "browserslist": "^4.23.3", - "cssnano-utils": "^5.0.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-minify-selectors": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-7.0.4.tgz", - "integrity": "sha512-JG55VADcNb4xFCf75hXkzc1rNeURhlo7ugf6JjiiKRfMsKlDzN9CXHZDyiG6x/zGchpjQS+UAgb1d4nqXqOpmA==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "postcss-selector-parser": "^6.1.2" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-minify-selectors/node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-normalize-charset": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-7.0.0.tgz", - "integrity": "sha512-ABisNUXMeZeDNzCQxPxBCkXexvBrUHV+p7/BXOY+ulxkcjUZO0cp8ekGBwvIh2LbCwnWbyMPNJVtBSdyhM2zYQ==", - "dev": true, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-display-values": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-7.0.0.tgz", - "integrity": "sha512-lnFZzNPeDf5uGMPYgGOw7v0BfB45+irSRz9gHQStdkkhiM0gTfvWkWB5BMxpn0OqgOQuZG/mRlZyJxp0EImr2Q==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-positions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-7.0.0.tgz", - "integrity": "sha512-I0yt8wX529UKIGs2y/9Ybs2CelSvItfmvg/DBIjTnoUSrPxSV7Z0yZ8ShSVtKNaV/wAY+m7bgtyVQLhB00A1NQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-repeat-style": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-7.0.0.tgz", - "integrity": "sha512-o3uSGYH+2q30ieM3ppu9GTjSXIzOrRdCUn8UOMGNw7Af61bmurHTWI87hRybrP6xDHvOe5WlAj3XzN6vEO8jLw==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-string": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-7.0.0.tgz", - "integrity": "sha512-w/qzL212DFVOpMy3UGyxrND+Kb0fvCiBBujiaONIihq7VvtC7bswjWgKQU/w4VcRyDD8gpfqUiBQ4DUOwEJ6Qg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-timing-functions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-7.0.0.tgz", - "integrity": "sha512-tNgw3YV0LYoRwg43N3lTe3AEWZ66W7Dh7lVEpJbHoKOuHc1sLrzMLMFjP8SNULHaykzsonUEDbKedv8C+7ej6g==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-unicode": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-7.0.2.tgz", - "integrity": "sha512-ztisabK5C/+ZWBdYC+Y9JCkp3M9qBv/XFvDtSw0d/XwfT3UaKeW/YTm/MD/QrPNxuecia46vkfEhewjwcYFjkg==", - "dev": true, - "dependencies": { - "browserslist": "^4.23.3", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-url": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-7.0.0.tgz", - "integrity": "sha512-+d7+PpE+jyPX1hDQZYG+NaFD+Nd2ris6r8fPTBAjE8z/U41n/bib3vze8x7rKs5H1uEw5ppe9IojewouHk0klQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-normalize-whitespace": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-7.0.0.tgz", - "integrity": "sha512-37/toN4wwZErqohedXYqWgvcHUGlT8O/m2jVkAfAe9Bd4MzRqlBmXrJRePH0e9Wgnz2X7KymTgTOaaFizQe3AQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-ordered-values": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-7.0.1.tgz", - "integrity": "sha512-irWScWRL6nRzYmBOXReIKch75RRhNS86UPUAxXdmW/l0FcAsg0lvAXQCby/1lymxn/o0gVa6Rv/0f03eJOwHxw==", - "dev": true, - "dependencies": { - "cssnano-utils": "^5.0.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-reduce-initial": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-7.0.2.tgz", - "integrity": "sha512-pOnu9zqQww7dEKf62Nuju6JgsW2V0KRNBHxeKohU+JkHd/GAH5uvoObqFLqkeB2n20mr6yrlWDvo5UBU5GnkfA==", - "dev": true, - "dependencies": { - "browserslist": "^4.23.3", - "caniuse-api": "^3.0.0" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-reduce-transforms": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-7.0.0.tgz", - "integrity": "sha512-pnt1HKKZ07/idH8cpATX/ujMbtOGhUfE+m8gbqwJE05aTaNw8gbo34a2e3if0xc0dlu75sUOiqvwCGY3fzOHew==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-selector-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", - "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-svgo": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-7.0.1.tgz", - "integrity": "sha512-0WBUlSL4lhD9rA5k1e5D8EN5wCEyZD6HJk0jIvRxl+FDVOMlJ7DePHYWGGVc5QRqrJ3/06FTXM0bxjmJpmTPSA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0", - "svgo": "^3.3.2" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >= 18" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-unique-selectors": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-7.0.3.tgz", - "integrity": "sha512-J+58u5Ic5T1QjP/LDV9g3Cx4CNOgB5vz+kM6+OxHHhFACdcDeKhBXjQmB7fnIZM12YSTvsL0Opwco83DmacW2g==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.1.2" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/postcss-unique-selectors/node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/readdirp": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.1.tgz", - "integrity": "sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dev": true, - "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/rollup": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.30.1.tgz", - "integrity": "sha512-mlJ4glW020fPuLi7DkM/lN97mYEZGWeqBnrljzN0gs7GLctqX3lNWxKQ7Gl712UAX+6fog/L3jh4gb7R6aVi3w==", - "dev": true, - "dependencies": { - "@types/estree": "1.0.6" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.30.1", - "@rollup/rollup-android-arm64": "4.30.1", - "@rollup/rollup-darwin-arm64": "4.30.1", - "@rollup/rollup-darwin-x64": "4.30.1", - "@rollup/rollup-freebsd-arm64": "4.30.1", - "@rollup/rollup-freebsd-x64": "4.30.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.30.1", - "@rollup/rollup-linux-arm-musleabihf": "4.30.1", - "@rollup/rollup-linux-arm64-gnu": "4.30.1", - "@rollup/rollup-linux-arm64-musl": "4.30.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.30.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.30.1", - "@rollup/rollup-linux-riscv64-gnu": "4.30.1", - "@rollup/rollup-linux-s390x-gnu": "4.30.1", - "@rollup/rollup-linux-x64-gnu": "4.30.1", - "@rollup/rollup-linux-x64-musl": "4.30.1", - "@rollup/rollup-win32-arm64-msvc": "4.30.1", - "@rollup/rollup-win32-ia32-msvc": "4.30.1", - "@rollup/rollup-win32-x64-msvc": "4.30.1", - "fsevents": "~2.3.2" - } - }, - "node_modules/rollup-plugin-scss": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-scss/-/rollup-plugin-scss-4.0.1.tgz", - "integrity": "sha512-3W3+3OzR+shkDl3hJ1XTAuGkP4AfiLgIjie2GtcoZ9pHfRiNqeDbtCu1EUnkjZ98EPIM6nnMIXkKlc7Sx5bRvA==", - "dev": true, - "dependencies": { - "rollup-pluginutils": "^2.3.3" - } - }, - "node_modules/rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "dev": true, - "dependencies": { - "estree-walker": "^0.6.1" - } - }, - "node_modules/rollup-pluginutils/node_modules/estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/sass": { - "version": "1.83.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.83.1.tgz", - "integrity": "sha512-EVJbDaEs4Rr3F0glJzFSOvtg2/oy2V/YrGFPqPY24UqcLDWcI9ZY5sN+qyO3c/QCZwzgfirvhXvINiJCE/OLcA==", + "node_modules/sass": { + "version": "1.85.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.85.1.tgz", + "integrity": "sha512-Uk8WpxM5v+0cMR0XjX9KfRIacmSG86RH4DCCZjLU2rFh5tyutt9siAXJ7G+YfxQ99Q6wrRMbMlVl6KqUms71ag==", "dev": true, "license": "MIT", "dependencies": { @@ -2536,139 +491,16 @@ "@parcel/watcher": "^2.4.1" } }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/smob": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", - "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==", - "dev": true - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/stylehacks": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-7.0.4.tgz", - "integrity": "sha512-i4zfNrGMt9SB4xRK9L83rlsFCgdGANfeDAYacO1pkqcE7cRHPdWHwnKZVz7WY17Veq/FvyYsRAU++Ga+qDFIww==", - "dev": true, - "dependencies": { - "browserslist": "^4.23.3", - "postcss-selector-parser": "^6.1.2" - }, - "engines": { - "node": "^18.12.0 || ^20.9.0 || >=22.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" - } - }, - "node_modules/stylehacks/node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/svgo": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", - "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", - "dev": true, - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^5.1.0", - "css-tree": "^2.3.1", - "css-what": "^6.1.0", - "csso": "^5.0.5", - "picocolors": "^1.0.0" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/svgo" - } - }, - "node_modules/terser": { - "version": "5.37.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", - "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2682,49 +514,6 @@ "engines": { "node": ">=8.0" } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", - "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "peer": true } } } diff --git a/package.json b/package.json index 688a8a26..bd9deab5 100644 --- a/package.json +++ b/package.json @@ -1,22 +1,9 @@ { - "name": "alert", - "type": "module", - "version": "1.0.0", - "description": "Laravel alert package", - "main": "index.js", - "scripts": { - "build": "rollup -c" - }, - "license": "ISC", "devDependencies": { - "@rollup/plugin-babel": "^6.0.4", - "@rollup/plugin-commonjs": "^28.0.2", - "@rollup/plugin-node-resolve": "^16.0.0", - "@rollup/plugin-terser": "^0.4.4", - "cssnano": "^7.0.6", - "postcss": "^8.4.49", - "rollup": "^4.30.1", - "rollup-plugin-scss": "^4.0.1", - "sass": "^1.83.1" + "sass": "^1.85.1" + }, + "scripts": { + "sass": "sass --watch resources/scss/themes/tailwind:resources/css/themes/tailwind --no-source-map", + "sass:build": "sass resources/scss/themes/tailwind:resources/css/themes/tailwind --no-source-map --style=compressed" } } diff --git a/public/css/alert.css b/public/css/alert.css deleted file mode 100644 index fc85a191..00000000 --- a/public/css/alert.css +++ /dev/null @@ -1,850 +0,0 @@ -[data-bs-theme=light] { - --bs-blue: #0d6efd; - --bs-indigo: #6610f2; - --bs-purple: #6f42c1; - --bs-pink: #d63384; - --bs-red: #dc3545; - --bs-orange: #fd7e14; - --bs-yellow: #ffc107; - --bs-green: #198754; - --bs-teal: #20c997; - --bs-cyan: #0dcaf0; - --bs-black: #000; - --bs-white: #fff; - --bs-gray: #6c757d; - --bs-gray-dark: #343a40; - --bs-gray-100: #f8f9fa; - --bs-gray-200: #e9ecef; - --bs-gray-300: #dee2e6; - --bs-gray-400: #ced4da; - --bs-gray-500: #adb5bd; - --bs-gray-600: #6c757d; - --bs-gray-700: #495057; - --bs-gray-800: #343a40; - --bs-gray-900: #212529; - --bs-primary: #0d6efd; - --bs-secondary: #6c757d; - --bs-success: #198754; - --bs-info: #0dcaf0; - --bs-warning: #ffc107; - --bs-danger: #dc3545; - --bs-light: #f8f9fa; - --bs-dark: #212529; - --bs-primary-rgb: 13, 110, 253; - --bs-secondary-rgb: 108, 117, 125; - --bs-success-rgb: 25, 135, 84; - --bs-info-rgb: 13, 202, 240; - --bs-warning-rgb: 255, 193, 7; - --bs-danger-rgb: 220, 53, 69; - --bs-light-rgb: 248, 249, 250; - --bs-dark-rgb: 33, 37, 41; - --bs-primary-text-emphasis: #052c65; - --bs-secondary-text-emphasis: #2b2f32; - --bs-success-text-emphasis: #0a3622; - --bs-info-text-emphasis: #055160; - --bs-warning-text-emphasis: #664d03; - --bs-danger-text-emphasis: #58151c; - --bs-light-text-emphasis: #495057; - --bs-dark-text-emphasis: #495057; - --bs-primary-bg-subtle: #cfe2ff; - --bs-secondary-bg-subtle: #e2e3e5; - --bs-success-bg-subtle: #d1e7dd; - --bs-info-bg-subtle: #cff4fc; - --bs-warning-bg-subtle: #fff3cd; - --bs-danger-bg-subtle: #f8d7da; - --bs-light-bg-subtle: #fcfcfd; - --bs-dark-bg-subtle: #ced4da; - --bs-primary-border-subtle: #9ec5fe; - --bs-secondary-border-subtle: #c4c8cb; - --bs-success-border-subtle: #a3cfbb; - --bs-info-border-subtle: #9eeaf9; - --bs-warning-border-subtle: #ffe69c; - --bs-danger-border-subtle: #f1aeb5; - --bs-light-border-subtle: #e9ecef; - --bs-dark-border-subtle: #adb5bd; - --bs-white-rgb: 255, 255, 255; - --bs-black-rgb: 0, 0, 0; - --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); - --bs-body-font-family: var(--bs-font-sans-serif); - --bs-body-font-size: 1rem; - --bs-body-font-weight: 400; - --bs-body-line-height: 1.5; - --bs-body-color: #212529; - --bs-body-color-rgb: 33, 37, 41; - --bs-body-bg: #fff; - --bs-body-bg-rgb: 255, 255, 255; - --bs-emphasis-color: #000; - --bs-emphasis-color-rgb: 0, 0, 0; - --bs-secondary-color: rgba(33, 37, 41, 0.75); - --bs-secondary-color-rgb: 33, 37, 41; - --bs-secondary-bg: #e9ecef; - --bs-secondary-bg-rgb: 233, 236, 239; - --bs-tertiary-color: rgba(33, 37, 41, 0.5); - --bs-tertiary-color-rgb: 33, 37, 41; - --bs-tertiary-bg: #f8f9fa; - --bs-tertiary-bg-rgb: 248, 249, 250; - --bs-heading-color: inherit; - --bs-link-color: #0d6efd; - --bs-link-color-rgb: 13, 110, 253; - --bs-link-decoration: underline; - --bs-link-hover-color: #0a58ca; - --bs-link-hover-color-rgb: 10, 88, 202; - --bs-code-color: #d63384; - --bs-highlight-color: #212529; - --bs-highlight-bg: #fff3cd; - --bs-border-width: 1px; - --bs-border-style: solid; - --bs-border-color: #dee2e6; - --bs-border-color-translucent: rgba(0, 0, 0, 0.175); - --bs-border-radius: 0.375rem; - --bs-border-radius-sm: 0.25rem; - --bs-border-radius-lg: 0.5rem; - --bs-border-radius-xl: 1rem; - --bs-border-radius-xxl: 2rem; - --bs-border-radius-2xl: var(--bs-border-radius-xxl); - --bs-border-radius-pill: 50rem; - --bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); - --bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); - --bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175); - --bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075); - --bs-focus-ring-width: 0.25rem; - --bs-focus-ring-opacity: 0.25; - --bs-focus-ring-color: rgba(13, 110, 253, 0.25); - --bs-form-valid-color: #198754; - --bs-form-valid-border-color: #198754; - --bs-form-invalid-color: #dc3545; - --bs-form-invalid-border-color: #dc3545; -} - -[data-bs-theme=dark] { - color-scheme: dark; - --bs-body-color: #dee2e6; - --bs-body-color-rgb: 222, 226, 230; - --bs-body-bg: #212529; - --bs-body-bg-rgb: 33, 37, 41; - --bs-emphasis-color: #fff; - --bs-emphasis-color-rgb: 255, 255, 255; - --bs-secondary-color: rgba(222, 226, 230, 0.75); - --bs-secondary-color-rgb: 222, 226, 230; - --bs-secondary-bg: #343a40; - --bs-secondary-bg-rgb: 52, 58, 64; - --bs-tertiary-color: rgba(222, 226, 230, 0.5); - --bs-tertiary-color-rgb: 222, 226, 230; - --bs-tertiary-bg: #2b3035; - --bs-tertiary-bg-rgb: 43, 48, 53; - --bs-primary-text-emphasis: #6ea8fe; - --bs-secondary-text-emphasis: #a7acb1; - --bs-success-text-emphasis: #75b798; - --bs-info-text-emphasis: #6edff6; - --bs-warning-text-emphasis: #ffda6a; - --bs-danger-text-emphasis: #ea868f; - --bs-light-text-emphasis: #f8f9fa; - --bs-dark-text-emphasis: #dee2e6; - --bs-primary-bg-subtle: #031633; - --bs-secondary-bg-subtle: #161719; - --bs-success-bg-subtle: #051b11; - --bs-info-bg-subtle: #032830; - --bs-warning-bg-subtle: #332701; - --bs-danger-bg-subtle: #2c0b0e; - --bs-light-bg-subtle: #343a40; - --bs-dark-bg-subtle: #1a1d20; - --bs-primary-border-subtle: #084298; - --bs-secondary-border-subtle: #41464b; - --bs-success-border-subtle: #0f5132; - --bs-info-border-subtle: #087990; - --bs-warning-border-subtle: #997404; - --bs-danger-border-subtle: #842029; - --bs-light-border-subtle: #495057; - --bs-dark-border-subtle: #343a40; - --bs-heading-color: inherit; - --bs-link-color: #6ea8fe; - --bs-link-hover-color: #8bb9fe; - --bs-link-color-rgb: 110, 168, 254; - --bs-link-hover-color-rgb: 139, 185, 254; - --bs-code-color: #e685b5; - --bs-highlight-color: #dee2e6; - --bs-highlight-bg: #664d03; - --bs-border-color: #495057; - --bs-border-color-translucent: rgba(255, 255, 255, 0.15); - --bs-form-valid-color: #75b798; - --bs-form-valid-border-color: #75b798; - --bs-form-invalid-color: #ea868f; - --bs-form-invalid-border-color: #ea868f; -} - -.text-primary { - --bs-text-opacity: 1; - color: rgba(var(--bs-primary-rgb), var(--bs-text-opacity)) !important; -} - -.text-secondary { - --bs-text-opacity: 1; - color: rgba(var(--bs-secondary-rgb), var(--bs-text-opacity)) !important; -} - -.text-success { - --bs-text-opacity: 1; - color: rgba(var(--bs-success-rgb), var(--bs-text-opacity)) !important; -} - -.text-info { - --bs-text-opacity: 1; - color: rgba(var(--bs-info-rgb), var(--bs-text-opacity)) !important; -} - -.text-warning { - --bs-text-opacity: 1; - color: rgba(var(--bs-warning-rgb), var(--bs-text-opacity)) !important; -} - -.text-danger { - --bs-text-opacity: 1; - color: rgba(var(--bs-danger-rgb), var(--bs-text-opacity)) !important; -} - -.text-light { - --bs-text-opacity: 1; - color: rgba(var(--bs-light-rgb), var(--bs-text-opacity)) !important; -} - -.text-dark { - --bs-text-opacity: 1; - color: rgba(var(--bs-dark-rgb), var(--bs-text-opacity)) !important; -} - -.text-black { - --bs-text-opacity: 1; - color: rgba(var(--bs-black-rgb), var(--bs-text-opacity)) !important; -} - -.text-white { - --bs-text-opacity: 1; - color: rgba(var(--bs-white-rgb), var(--bs-text-opacity)) !important; -} - -.text-body { - --bs-text-opacity: 1; - color: rgba(var(--bs-body-color-rgb), var(--bs-text-opacity)) !important; -} - -.text-muted { - --bs-text-opacity: 1; - color: var(--bs-secondary-color) !important; -} - -.text-black-50 { - --bs-text-opacity: 1; - color: rgba(0, 0, 0, 0.5) !important; -} - -.text-white-50 { - --bs-text-opacity: 1; - color: rgba(255, 255, 255, 0.5) !important; -} - -.text-body-secondary { - --bs-text-opacity: 1; - color: var(--bs-secondary-color) !important; -} - -.text-body-tertiary { - --bs-text-opacity: 1; - color: var(--bs-tertiary-color) !important; -} - -.text-body-emphasis { - --bs-text-opacity: 1; - color: var(--bs-emphasis-color) !important; -} - -.text-reset { - --bs-text-opacity: 1; - color: inherit !important; -} - -.text-opacity-25 { - --bs-text-opacity: 0.25; -} - -.text-opacity-50 { - --bs-text-opacity: 0.5; -} - -.text-opacity-75 { - --bs-text-opacity: 0.75; -} - -.text-opacity-100 { - --bs-text-opacity: 1; -} - -.text-primary-emphasis { - color: var(--bs-primary-text-emphasis) !important; -} - -.text-secondary-emphasis { - color: var(--bs-secondary-text-emphasis) !important; -} - -.text-success-emphasis { - color: var(--bs-success-text-emphasis) !important; -} - -.text-info-emphasis { - color: var(--bs-info-text-emphasis) !important; -} - -.text-warning-emphasis { - color: var(--bs-warning-text-emphasis) !important; -} - -.text-danger-emphasis { - color: var(--bs-danger-text-emphasis) !important; -} - -.text-light-emphasis { - color: var(--bs-light-text-emphasis) !important; -} - -.text-dark-emphasis { - color: var(--bs-dark-text-emphasis) !important; -} - -.btn-close { - --bs-btn-close-color: #000; - --bs-btn-close-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e"); - --bs-btn-close-opacity: 0.5; - --bs-btn-close-hover-opacity: 0.75; - --bs-btn-close-focus-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); - --bs-btn-close-focus-opacity: 1; - --bs-btn-close-disabled-opacity: 0.25; - --bs-btn-close-white-filter: invert(1) grayscale(100%) brightness(200%); - box-sizing: content-box; - width: 1em; - height: 1em; - padding: 0.25em 0.25em; - color: var(--bs-btn-close-color); - background: transparent var(--bs-btn-close-bg) center/1em auto no-repeat; - border: 0; - border-radius: 0.375rem; - opacity: var(--bs-btn-close-opacity); -} - -.btn-close:hover { - color: var(--bs-btn-close-color); - text-decoration: none; - opacity: var(--bs-btn-close-hover-opacity); -} - -.btn-close:focus { - outline: 0; - box-shadow: var(--bs-btn-close-focus-shadow); - opacity: var(--bs-btn-close-focus-opacity); -} - -.btn-close:disabled, .btn-close.disabled { - pointer-events: none; - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; - opacity: var(--bs-btn-close-disabled-opacity); -} - -.btn-close:focus { - outline: none; - box-shadow: none; -} - -.btn-close-white { - filter: var(--bs-btn-close-white-filter); -} - -[data-bs-theme=dark] .btn-close { - filter: var(--bs-btn-close-white-filter); -} - -button, -[role=button] { - cursor: pointer; -} - -.toast { - --bs-toast-zindex: 1090; - --bs-toast-padding-x: 0.75rem; - --bs-toast-padding-y: 0.5rem; - --bs-toast-spacing: 1.5rem; - --bs-toast-max-width: 350px; - --bs-toast-font-size: 0.875rem; - --bs-toast-color: ; - --bs-toast-bg: rgba(var(--bs-body-bg-rgb), 0.85); - --bs-toast-border-width: var(--bs-border-width); - --bs-toast-border-color: var(--bs-border-color-translucent); - --bs-toast-border-radius: var(--bs-border-radius); - --bs-toast-box-shadow: var(--bs-box-shadow); - --bs-toast-header-color: var(--bs-secondary-color); - --bs-toast-header-bg: rgba(var(--bs-body-bg-rgb), 0.85); - --bs-toast-header-border-color: var(--bs-border-color-translucent); - width: var(--bs-toast-max-width); - max-width: 100%; - font-size: var(--bs-toast-font-size); - color: var(--bs-toast-color); - pointer-events: auto; - background-color: var(--bs-toast-bg); - background-clip: padding-box; - border: var(--bs-toast-border-width) solid var(--bs-toast-border-color); - box-shadow: var(--bs-toast-box-shadow); - border-radius: var(--bs-toast-border-radius); -} - -.toast.showing { - opacity: 0; -} - -.toast:not(.show) { - display: none; -} - -.toast-container { - --bs-toast-zindex: 1090; - position: absolute; - z-index: var(--bs-toast-zindex); - width: -webkit-max-content; - width: -moz-max-content; - width: max-content; - max-width: 100%; - pointer-events: none; -} - -.toast-container > :not(:last-child) { - margin-bottom: var(--bs-toast-spacing); -} - -.toast-header { - display: flex; - align-items: center; - padding: var(--bs-toast-padding-y) var(--bs-toast-padding-x); - color: var(--bs-toast-header-color); - background-color: var(--bs-toast-header-bg); - background-clip: padding-box; - border-bottom: var(--bs-toast-border-width) solid var(--bs-toast-header-border-color); - border-top-left-radius: calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width)); - border-top-right-radius: calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width)); -} - -.toast-header .btn-close { - margin-right: calc(-0.5 * var(--bs-toast-padding-x)); - margin-left: var(--bs-toast-padding-x); -} - -.toast-body { - padding: var(--bs-toast-padding-x); - word-wrap: break-word; -} - -.form-text { - margin-top: 0.25rem; - font-size: 0.875em; - color: var(--bs-secondary-color); -} - -.alert { - --bs-alert-bg: transparent; - --bs-alert-padding-x: 1rem; - --bs-alert-padding-y: 1rem; - --bs-alert-margin-bottom: 1rem; - --bs-alert-color: inherit; - --bs-alert-border-color: transparent; - --bs-alert-border: var(--bs-border-width) solid var(--bs-alert-border-color); - --bs-alert-border-radius: var(--bs-border-radius); - --bs-alert-link-color: inherit; - position: relative; - padding: var(--bs-alert-padding-y) var(--bs-alert-padding-x); - margin-bottom: var(--bs-alert-margin-bottom); - color: var(--bs-alert-color); - background-color: var(--bs-alert-bg); - border: var(--bs-alert-border); - border-radius: var(--bs-alert-border-radius); -} - -.alert-heading { - color: inherit; -} - -.alert-link { - font-weight: 700; - color: var(--bs-alert-link-color); -} - -.alert-dismissible { - padding-right: 3rem; -} - -.alert-dismissible .btn-close { - position: absolute; - top: 0; - right: 0; - z-index: 2; - padding: 1.25rem 1rem; -} - -.alert-primary { - --bs-alert-color: var(--bs-primary-text-emphasis); - --bs-alert-bg: var(--bs-primary-bg-subtle); - --bs-alert-border-color: var(--bs-primary-border-subtle); - --bs-alert-link-color: var(--bs-primary-text-emphasis); -} - -.alert-secondary { - --bs-alert-color: var(--bs-secondary-text-emphasis); - --bs-alert-bg: var(--bs-secondary-bg-subtle); - --bs-alert-border-color: var(--bs-secondary-border-subtle); - --bs-alert-link-color: var(--bs-secondary-text-emphasis); -} - -.alert-success { - --bs-alert-color: var(--bs-success-text-emphasis); - --bs-alert-bg: var(--bs-success-bg-subtle); - --bs-alert-border-color: var(--bs-success-border-subtle); - --bs-alert-link-color: var(--bs-success-text-emphasis); -} - -.alert-info { - --bs-alert-color: var(--bs-info-text-emphasis); - --bs-alert-bg: var(--bs-info-bg-subtle); - --bs-alert-border-color: var(--bs-info-border-subtle); - --bs-alert-link-color: var(--bs-info-text-emphasis); -} - -.alert-warning { - --bs-alert-color: var(--bs-warning-text-emphasis); - --bs-alert-bg: var(--bs-warning-bg-subtle); - --bs-alert-border-color: var(--bs-warning-border-subtle); - --bs-alert-link-color: var(--bs-warning-text-emphasis); -} - -.alert-danger { - --bs-alert-color: var(--bs-danger-text-emphasis); - --bs-alert-bg: var(--bs-danger-bg-subtle); - --bs-alert-border-color: var(--bs-danger-border-subtle); - --bs-alert-link-color: var(--bs-danger-text-emphasis); -} - -.alert-light { - --bs-alert-color: var(--bs-light-text-emphasis); - --bs-alert-bg: var(--bs-light-bg-subtle); - --bs-alert-border-color: var(--bs-light-border-subtle); - --bs-alert-link-color: var(--bs-light-text-emphasis); -} - -.alert-dark { - --bs-alert-color: var(--bs-dark-text-emphasis); - --bs-alert-bg: var(--bs-dark-bg-subtle); - --bs-alert-border-color: var(--bs-dark-border-subtle); - --bs-alert-link-color: var(--bs-dark-text-emphasis); -} - -.modal { - --bs-modal-zindex: 1055; - --bs-modal-width: 500px; - --bs-modal-padding: 1rem; - --bs-modal-margin: 0.5rem; - --bs-modal-color: ; - --bs-modal-bg: var(--bs-body-bg); - --bs-modal-border-color: var(--bs-border-color-translucent); - --bs-modal-border-width: var(--bs-border-width); - --bs-modal-border-radius: var(--bs-border-radius-lg); - --bs-modal-box-shadow: var(--bs-box-shadow-sm); - --bs-modal-inner-border-radius: calc(var(--bs-border-radius-lg) - (var(--bs-border-width))); - --bs-modal-header-padding-x: 1rem; - --bs-modal-header-padding-y: 1rem; - --bs-modal-header-padding: 1rem 1rem; - --bs-modal-header-border-color: var(--bs-border-color); - --bs-modal-header-border-width: var(--bs-border-width); - --bs-modal-title-line-height: 1.5; - --bs-modal-footer-gap: 0.5rem; - --bs-modal-footer-bg: ; - --bs-modal-footer-border-color: var(--bs-border-color); - --bs-modal-footer-border-width: var(--bs-border-width); - position: fixed; - top: 0; - left: 0; - z-index: var(--bs-modal-zindex); - display: none; - width: 100%; - height: 100%; - overflow-x: hidden; - overflow-y: auto; - outline: 0; -} - -.modal-dialog { - position: relative; - width: auto; - margin: var(--bs-modal-margin); - pointer-events: none; -} - -.modal.fade .modal-dialog { - transition: transform 0.3s ease-out; - transform: translate(0, -50px); -} - -@media (prefers-reduced-motion: reduce) { - .modal.fade .modal-dialog { - transition: none; - } -} -.modal.show .modal-dialog { - transform: none; -} - -.modal.modal-static .modal-dialog { - transform: scale(1.02); -} - -.modal-dialog-scrollable { - height: calc(100% - var(--bs-modal-margin) * 2); -} - -.modal-dialog-scrollable .modal-content { - max-height: 100%; - overflow: hidden; -} - -.modal-dialog-scrollable .modal-body { - overflow-y: auto; -} - -.modal-dialog-centered { - display: flex; - align-items: center; - min-height: calc(100% - var(--bs-modal-margin) * 2); -} - -.modal-content { - position: relative; - display: flex; - flex-direction: column; - width: 100%; - color: var(--bs-modal-color); - pointer-events: auto; - background-color: var(--bs-modal-bg); - background-clip: padding-box; - border: var(--bs-modal-border-width) solid var(--bs-modal-border-color); - border-radius: var(--bs-modal-border-radius); - outline: 0; -} - -.modal-backdrop { - --bs-backdrop-zindex: 1050; - --bs-backdrop-bg: #000; - --bs-backdrop-opacity: 0.5; - position: fixed; - top: 0; - left: 0; - z-index: var(--bs-backdrop-zindex); - width: 100vw; - height: 100vh; - background-color: var(--bs-backdrop-bg); -} - -.modal-backdrop.fade { - opacity: 0; -} - -.modal-backdrop.show { - opacity: var(--bs-backdrop-opacity); -} - -.modal-header { - display: flex; - flex-shrink: 0; - align-items: center; - padding: var(--bs-modal-header-padding); - border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color); - border-top-left-radius: var(--bs-modal-inner-border-radius); - border-top-right-radius: var(--bs-modal-inner-border-radius); -} - -.modal-header .btn-close { - padding: calc(var(--bs-modal-header-padding-y) * 0.5) calc(var(--bs-modal-header-padding-x) * 0.5); - margin: calc(-0.5 * var(--bs-modal-header-padding-y)) calc(-0.5 * var(--bs-modal-header-padding-x)) calc(-0.5 * var(--bs-modal-header-padding-y)) auto; -} - -.modal-title { - margin-bottom: 0; - line-height: var(--bs-modal-title-line-height); -} - -.modal-body { - position: relative; - flex: 1 1 auto; - padding: var(--bs-modal-padding); -} - -.modal-footer { - display: flex; - flex-shrink: 0; - flex-wrap: wrap; - align-items: center; - justify-content: flex-end; - padding: calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap) * 0.5); - background-color: var(--bs-modal-footer-bg); - border-top: var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color); - border-bottom-right-radius: var(--bs-modal-inner-border-radius); - border-bottom-left-radius: var(--bs-modal-inner-border-radius); -} - -.modal-footer > * { - margin: calc(var(--bs-modal-footer-gap) * 0.5); -} - -@media (min-width: 576px) { - .modal { - --bs-modal-margin: 1.75rem; - --bs-modal-box-shadow: var(--bs-box-shadow); - } - .modal-dialog { - max-width: var(--bs-modal-width); - margin-right: auto; - margin-left: auto; - } - .modal-sm { - --bs-modal-width: 300px; - } -} -@media (min-width: 992px) { - .modal-lg, - .modal-xl { - --bs-modal-width: 800px; - } -} -@media (min-width: 1200px) { - .modal-xl { - --bs-modal-width: 1140px; - } -} -.modal-fullscreen { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; -} - -.modal-fullscreen .modal-content { - height: 100%; - border: 0; - border-radius: 0; -} - -.modal-fullscreen .modal-header, -.modal-fullscreen .modal-footer { - border-radius: 0; -} - -.modal-fullscreen .modal-body { - overflow-y: auto; -} - -@media (max-width: 575.98px) { - .modal-fullscreen-sm-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; - } - .modal-fullscreen-sm-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; - } - .modal-fullscreen-sm-down .modal-header, - .modal-fullscreen-sm-down .modal-footer { - border-radius: 0; - } - .modal-fullscreen-sm-down .modal-body { - overflow-y: auto; - } -} -@media (max-width: 767.98px) { - .modal-fullscreen-md-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; - } - .modal-fullscreen-md-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; - } - .modal-fullscreen-md-down .modal-header, - .modal-fullscreen-md-down .modal-footer { - border-radius: 0; - } - .modal-fullscreen-md-down .modal-body { - overflow-y: auto; - } -} -@media (max-width: 991.98px) { - .modal-fullscreen-lg-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; - } - .modal-fullscreen-lg-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; - } - .modal-fullscreen-lg-down .modal-header, - .modal-fullscreen-lg-down .modal-footer { - border-radius: 0; - } - .modal-fullscreen-lg-down .modal-body { - overflow-y: auto; - } -} -@media (max-width: 1199.98px) { - .modal-fullscreen-xl-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; - } - .modal-fullscreen-xl-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; - } - .modal-fullscreen-xl-down .modal-header, - .modal-fullscreen-xl-down .modal-footer { - border-radius: 0; - } - .modal-fullscreen-xl-down .modal-body { - overflow-y: auto; - } -} -@media (max-width: 1399.98px) { - .modal-fullscreen-xxl-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; - } - .modal-fullscreen-xxl-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; - } - .modal-fullscreen-xxl-down .modal-header, - .modal-fullscreen-xxl-down .modal-footer { - border-radius: 0; - } - .modal-fullscreen-xxl-down .modal-body { - overflow-y: auto; - } -} \ No newline at end of file diff --git a/public/css/alert.min.css b/public/css/alert.min.css deleted file mode 100644 index 25c2ac72..00000000 --- a/public/css/alert.min.css +++ /dev/null @@ -1 +0,0 @@ -[data-bs-theme=light]{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-primary-text-emphasis:#052c65;--bs-secondary-text-emphasis:#2b2f32;--bs-success-text-emphasis:#0a3622;--bs-info-text-emphasis:#055160;--bs-warning-text-emphasis:#664d03;--bs-danger-text-emphasis:#58151c;--bs-light-text-emphasis:#495057;--bs-dark-text-emphasis:#495057;--bs-primary-bg-subtle:#cfe2ff;--bs-secondary-bg-subtle:#e2e3e5;--bs-success-bg-subtle:#d1e7dd;--bs-info-bg-subtle:#cff4fc;--bs-warning-bg-subtle:#fff3cd;--bs-danger-bg-subtle:#f8d7da;--bs-light-bg-subtle:#fcfcfd;--bs-dark-bg-subtle:#ced4da;--bs-primary-border-subtle:#9ec5fe;--bs-secondary-border-subtle:#c4c8cb;--bs-success-border-subtle:#a3cfbb;--bs-info-border-subtle:#9eeaf9;--bs-warning-border-subtle:#ffe69c;--bs-danger-border-subtle:#f1aeb5;--bs-light-border-subtle:#e9ecef;--bs-dark-border-subtle:#adb5bd;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg,hsla(0,0%,100%,.15),hsla(0,0%,100%,0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-color-rgb:33,37,41;--bs-body-bg:#fff;--bs-body-bg-rgb:255,255,255;--bs-emphasis-color:#000;--bs-emphasis-color-rgb:0,0,0;--bs-secondary-color:rgba(33,37,41,.75);--bs-secondary-color-rgb:33,37,41;--bs-secondary-bg:#e9ecef;--bs-secondary-bg-rgb:233,236,239;--bs-tertiary-color:rgba(33,37,41,.5);--bs-tertiary-color-rgb:33,37,41;--bs-tertiary-bg:#f8f9fa;--bs-tertiary-bg-rgb:248,249,250;--bs-heading-color:inherit;--bs-link-color:#0d6efd;--bs-link-color-rgb:13,110,253;--bs-link-decoration:underline;--bs-link-hover-color:#0a58ca;--bs-link-hover-color-rgb:10,88,202;--bs-code-color:#d63384;--bs-highlight-color:#212529;--bs-highlight-bg:#fff3cd;--bs-border-width:1px;--bs-border-style:solid;--bs-border-color:#dee2e6;--bs-border-color-translucent:rgba(0,0,0,.175);--bs-border-radius:0.375rem;--bs-border-radius-sm:0.25rem;--bs-border-radius-lg:0.5rem;--bs-border-radius-xl:1rem;--bs-border-radius-xxl:2rem;--bs-border-radius-2xl:var(--bs-border-radius-xxl);--bs-border-radius-pill:50rem;--bs-box-shadow:0 0.5rem 1rem rgba(0,0,0,.15);--bs-box-shadow-sm:0 0.125rem 0.25rem rgba(0,0,0,.075);--bs-box-shadow-lg:0 1rem 3rem rgba(0,0,0,.175);--bs-box-shadow-inset:inset 0 1px 2px rgba(0,0,0,.075);--bs-focus-ring-width:0.25rem;--bs-focus-ring-opacity:0.25;--bs-focus-ring-color:rgba(13,110,253,.25);--bs-form-valid-color:#198754;--bs-form-valid-border-color:#198754;--bs-form-invalid-color:#dc3545;--bs-form-invalid-border-color:#dc3545}[data-bs-theme=dark]{color-scheme:dark;--bs-body-color:#dee2e6;--bs-body-color-rgb:222,226,230;--bs-body-bg:#212529;--bs-body-bg-rgb:33,37,41;--bs-emphasis-color:#fff;--bs-emphasis-color-rgb:255,255,255;--bs-secondary-color:rgba(222,226,230,.75);--bs-secondary-color-rgb:222,226,230;--bs-secondary-bg:#343a40;--bs-secondary-bg-rgb:52,58,64;--bs-tertiary-color:rgba(222,226,230,.5);--bs-tertiary-color-rgb:222,226,230;--bs-tertiary-bg:#2b3035;--bs-tertiary-bg-rgb:43,48,53;--bs-primary-text-emphasis:#6ea8fe;--bs-secondary-text-emphasis:#a7acb1;--bs-success-text-emphasis:#75b798;--bs-info-text-emphasis:#6edff6;--bs-warning-text-emphasis:#ffda6a;--bs-danger-text-emphasis:#ea868f;--bs-light-text-emphasis:#f8f9fa;--bs-dark-text-emphasis:#dee2e6;--bs-primary-bg-subtle:#031633;--bs-secondary-bg-subtle:#161719;--bs-success-bg-subtle:#051b11;--bs-info-bg-subtle:#032830;--bs-warning-bg-subtle:#332701;--bs-danger-bg-subtle:#2c0b0e;--bs-light-bg-subtle:#343a40;--bs-dark-bg-subtle:#1a1d20;--bs-primary-border-subtle:#084298;--bs-secondary-border-subtle:#41464b;--bs-success-border-subtle:#0f5132;--bs-info-border-subtle:#087990;--bs-warning-border-subtle:#997404;--bs-danger-border-subtle:#842029;--bs-light-border-subtle:#495057;--bs-dark-border-subtle:#343a40;--bs-heading-color:inherit;--bs-link-color:#6ea8fe;--bs-link-hover-color:#8bb9fe;--bs-link-color-rgb:110,168,254;--bs-link-hover-color-rgb:139,185,254;--bs-code-color:#e685b5;--bs-highlight-color:#dee2e6;--bs-highlight-bg:#664d03;--bs-border-color:#495057;--bs-border-color-translucent:hsla(0,0%,100%,.15);--bs-form-valid-color:#75b798;--bs-form-valid-border-color:#75b798;--bs-form-invalid-color:#ea868f;--bs-form-invalid-border-color:#ea868f}.text-primary{--bs-text-opacity:1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))!important}.text-secondary{--bs-text-opacity:1;color:rgba(var(--bs-secondary-rgb),var(--bs-text-opacity))!important}.text-success{--bs-text-opacity:1;color:rgba(var(--bs-success-rgb),var(--bs-text-opacity))!important}.text-info{--bs-text-opacity:1;color:rgba(var(--bs-info-rgb),var(--bs-text-opacity))!important}.text-warning{--bs-text-opacity:1;color:rgba(var(--bs-warning-rgb),var(--bs-text-opacity))!important}.text-danger{--bs-text-opacity:1;color:rgba(var(--bs-danger-rgb),var(--bs-text-opacity))!important}.text-light{--bs-text-opacity:1;color:rgba(var(--bs-light-rgb),var(--bs-text-opacity))!important}.text-dark{--bs-text-opacity:1;color:rgba(var(--bs-dark-rgb),var(--bs-text-opacity))!important}.text-black{--bs-text-opacity:1;color:rgba(var(--bs-black-rgb),var(--bs-text-opacity))!important}.text-white{--bs-text-opacity:1;color:rgba(var(--bs-white-rgb),var(--bs-text-opacity))!important}.text-body{--bs-text-opacity:1;color:rgba(var(--bs-body-color-rgb),var(--bs-text-opacity))!important}.text-muted{--bs-text-opacity:1;color:var(--bs-secondary-color)!important}.text-black-50{--bs-text-opacity:1;color:rgba(0,0,0,.5)!important}.text-white-50{--bs-text-opacity:1;color:hsla(0,0%,100%,.5)!important}.text-body-secondary{--bs-text-opacity:1;color:var(--bs-secondary-color)!important}.text-body-tertiary{--bs-text-opacity:1;color:var(--bs-tertiary-color)!important}.text-body-emphasis{--bs-text-opacity:1;color:var(--bs-emphasis-color)!important}.text-reset{--bs-text-opacity:1;color:inherit!important}.text-opacity-25{--bs-text-opacity:0.25}.text-opacity-50{--bs-text-opacity:0.5}.text-opacity-75{--bs-text-opacity:0.75}.text-opacity-100{--bs-text-opacity:1}.text-primary-emphasis{color:var(--bs-primary-text-emphasis)!important}.text-secondary-emphasis{color:var(--bs-secondary-text-emphasis)!important}.text-success-emphasis{color:var(--bs-success-text-emphasis)!important}.text-info-emphasis{color:var(--bs-info-text-emphasis)!important}.text-warning-emphasis{color:var(--bs-warning-text-emphasis)!important}.text-danger-emphasis{color:var(--bs-danger-text-emphasis)!important}.text-light-emphasis{color:var(--bs-light-text-emphasis)!important}.text-dark-emphasis{color:var(--bs-dark-text-emphasis)!important}.btn-close{--bs-btn-close-color:#000;--bs-btn-close-bg:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414'/%3E%3C/svg%3E");--bs-btn-close-opacity:0.5;--bs-btn-close-hover-opacity:0.75;--bs-btn-close-focus-shadow:0 0 0 0.25rem rgba(13,110,253,.25);--bs-btn-close-focus-opacity:1;--bs-btn-close-disabled-opacity:0.25;--bs-btn-close-white-filter:invert(1) grayscale(100%) brightness(200%);background:transparent var(--bs-btn-close-bg) center/1em auto no-repeat;border:0;border-radius:.375rem;box-sizing:content-box;height:1em;opacity:var(--bs-btn-close-opacity);padding:.25em;width:1em}.btn-close,.btn-close:hover{color:var(--bs-btn-close-color)}.btn-close:hover{opacity:var(--bs-btn-close-hover-opacity);text-decoration:none}.btn-close:focus{box-shadow:var(--bs-btn-close-focus-shadow);opacity:var(--bs-btn-close-focus-opacity);outline:0}.btn-close.disabled,.btn-close:disabled{opacity:var(--bs-btn-close-disabled-opacity);pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.btn-close:focus{box-shadow:none;outline:none}.btn-close-white,[data-bs-theme=dark] .btn-close{filter:var(--bs-btn-close-white-filter)}[role=button],button{cursor:pointer}.toast{--bs-toast-zindex:1090;--bs-toast-padding-x:0.75rem;--bs-toast-padding-y:0.5rem;--bs-toast-spacing:1.5rem;--bs-toast-max-width:350px;--bs-toast-font-size:0.875rem;--bs-toast-color: ;--bs-toast-bg:rgba(var(--bs-body-bg-rgb),0.85);--bs-toast-border-width:var(--bs-border-width);--bs-toast-border-color:var(--bs-border-color-translucent);--bs-toast-border-radius:var(--bs-border-radius);--bs-toast-box-shadow:var(--bs-box-shadow);--bs-toast-header-color:var(--bs-secondary-color);--bs-toast-header-bg:rgba(var(--bs-body-bg-rgb),0.85);--bs-toast-header-border-color:var(--bs-border-color-translucent);background-clip:padding-box;background-color:var(--bs-toast-bg);border:var(--bs-toast-border-width) solid var(--bs-toast-border-color);border-radius:var(--bs-toast-border-radius);box-shadow:var(--bs-toast-box-shadow);color:var(--bs-toast-color);font-size:var(--bs-toast-font-size);max-width:100%;pointer-events:auto;width:var(--bs-toast-max-width)}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{--bs-toast-zindex:1090;max-width:100%;pointer-events:none;position:absolute;width:-webkit-max-content;width:-moz-max-content;width:max-content;z-index:var(--bs-toast-zindex)}.toast-container>:not(:last-child){margin-bottom:var(--bs-toast-spacing)}.toast-header{align-items:center;background-clip:padding-box;background-color:var(--bs-toast-header-bg);border-bottom:var(--bs-toast-border-width) solid var(--bs-toast-header-border-color);border-top-left-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width));border-top-right-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width));color:var(--bs-toast-header-color);display:flex;padding:var(--bs-toast-padding-y) var(--bs-toast-padding-x)}.toast-header .btn-close{margin-left:var(--bs-toast-padding-x);margin-right:calc(var(--bs-toast-padding-x)*-.5)}.toast-body{padding:var(--bs-toast-padding-x);word-wrap:break-word}.form-text{color:var(--bs-secondary-color);font-size:.875em;margin-top:.25rem}.alert{--bs-alert-bg:transparent;--bs-alert-padding-x:1rem;--bs-alert-padding-y:1rem;--bs-alert-margin-bottom:1rem;--bs-alert-color:inherit;--bs-alert-border-color:transparent;--bs-alert-border:var(--bs-border-width) solid var(--bs-alert-border-color);--bs-alert-border-radius:var(--bs-border-radius);--bs-alert-link-color:inherit;background-color:var(--bs-alert-bg);border:var(--bs-alert-border);border-radius:var(--bs-alert-border-radius);color:var(--bs-alert-color);margin-bottom:var(--bs-alert-margin-bottom);padding:var(--bs-alert-padding-y) var(--bs-alert-padding-x);position:relative}.alert-heading{color:inherit}.alert-link{color:var(--bs-alert-link-color);font-weight:700}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{padding:1.25rem 1rem;position:absolute;right:0;top:0;z-index:2}.alert-primary{--bs-alert-color:var(--bs-primary-text-emphasis);--bs-alert-bg:var(--bs-primary-bg-subtle);--bs-alert-border-color:var(--bs-primary-border-subtle);--bs-alert-link-color:var(--bs-primary-text-emphasis)}.alert-secondary{--bs-alert-color:var(--bs-secondary-text-emphasis);--bs-alert-bg:var(--bs-secondary-bg-subtle);--bs-alert-border-color:var(--bs-secondary-border-subtle);--bs-alert-link-color:var(--bs-secondary-text-emphasis)}.alert-success{--bs-alert-color:var(--bs-success-text-emphasis);--bs-alert-bg:var(--bs-success-bg-subtle);--bs-alert-border-color:var(--bs-success-border-subtle);--bs-alert-link-color:var(--bs-success-text-emphasis)}.alert-info{--bs-alert-color:var(--bs-info-text-emphasis);--bs-alert-bg:var(--bs-info-bg-subtle);--bs-alert-border-color:var(--bs-info-border-subtle);--bs-alert-link-color:var(--bs-info-text-emphasis)}.alert-warning{--bs-alert-color:var(--bs-warning-text-emphasis);--bs-alert-bg:var(--bs-warning-bg-subtle);--bs-alert-border-color:var(--bs-warning-border-subtle);--bs-alert-link-color:var(--bs-warning-text-emphasis)}.alert-danger{--bs-alert-color:var(--bs-danger-text-emphasis);--bs-alert-bg:var(--bs-danger-bg-subtle);--bs-alert-border-color:var(--bs-danger-border-subtle);--bs-alert-link-color:var(--bs-danger-text-emphasis)}.alert-light{--bs-alert-color:var(--bs-light-text-emphasis);--bs-alert-bg:var(--bs-light-bg-subtle);--bs-alert-border-color:var(--bs-light-border-subtle);--bs-alert-link-color:var(--bs-light-text-emphasis)}.alert-dark{--bs-alert-color:var(--bs-dark-text-emphasis);--bs-alert-bg:var(--bs-dark-bg-subtle);--bs-alert-border-color:var(--bs-dark-border-subtle);--bs-alert-link-color:var(--bs-dark-text-emphasis)}.modal{--bs-modal-zindex:1055;--bs-modal-width:500px;--bs-modal-padding:1rem;--bs-modal-margin:0.5rem;--bs-modal-color: ;--bs-modal-bg:var(--bs-body-bg);--bs-modal-border-color:var(--bs-border-color-translucent);--bs-modal-border-width:var(--bs-border-width);--bs-modal-border-radius:var(--bs-border-radius-lg);--bs-modal-box-shadow:var(--bs-box-shadow-sm);--bs-modal-inner-border-radius:calc(var(--bs-border-radius-lg) - var(--bs-border-width));--bs-modal-header-padding-x:1rem;--bs-modal-header-padding-y:1rem;--bs-modal-header-padding:1rem 1rem;--bs-modal-header-border-color:var(--bs-border-color);--bs-modal-header-border-width:var(--bs-border-width);--bs-modal-title-line-height:1.5;--bs-modal-footer-gap:0.5rem;--bs-modal-footer-bg: ;--bs-modal-footer-border-color:var(--bs-border-color);--bs-modal-footer-border-width:var(--bs-border-width);display:none;height:100%;left:0;outline:0;overflow-x:hidden;overflow-y:auto;position:fixed;top:0;width:100%;z-index:var(--bs-modal-zindex)}.modal-dialog{margin:var(--bs-modal-margin);pointer-events:none;position:relative;width:auto}.modal.fade .modal-dialog{transform:translateY(-50px);transition:transform .3s ease-out}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - var(--bs-modal-margin)*2)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{align-items:center;display:flex;min-height:calc(100% - var(--bs-modal-margin)*2)}.modal-content{background-clip:padding-box;background-color:var(--bs-modal-bg);border:var(--bs-modal-border-width) solid var(--bs-modal-border-color);border-radius:var(--bs-modal-border-radius);color:var(--bs-modal-color);display:flex;flex-direction:column;outline:0;pointer-events:auto;position:relative;width:100%}.modal-backdrop{--bs-backdrop-zindex:1050;--bs-backdrop-bg:#000;--bs-backdrop-opacity:0.5;background-color:var(--bs-backdrop-bg);height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:var(--bs-backdrop-zindex)}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:var(--bs-backdrop-opacity)}.modal-header{align-items:center;border-bottom:var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);border-top-left-radius:var(--bs-modal-inner-border-radius);border-top-right-radius:var(--bs-modal-inner-border-radius);display:flex;flex-shrink:0;padding:var(--bs-modal-header-padding)}.modal-header .btn-close{margin:calc(var(--bs-modal-header-padding-y)*-.5) calc(var(--bs-modal-header-padding-x)*-.5) calc(var(--bs-modal-header-padding-y)*-.5) auto;padding:calc(var(--bs-modal-header-padding-y)*.5) calc(var(--bs-modal-header-padding-x)*.5)}.modal-title{line-height:var(--bs-modal-title-line-height);margin-bottom:0}.modal-body{flex:1 1 auto;padding:var(--bs-modal-padding);position:relative}.modal-footer{align-items:center;background-color:var(--bs-modal-footer-bg);border-bottom-left-radius:var(--bs-modal-inner-border-radius);border-bottom-right-radius:var(--bs-modal-inner-border-radius);border-top:var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color);display:flex;flex-shrink:0;flex-wrap:wrap;justify-content:flex-end;padding:calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap)*.5)}.modal-footer>*{margin:calc(var(--bs-modal-footer-gap)*.5)}@media (min-width:576px){.modal{--bs-modal-margin:1.75rem;--bs-modal-box-shadow:var(--bs-box-shadow)}.modal-dialog{margin-left:auto;margin-right:auto;max-width:var(--bs-modal-width)}.modal-sm{--bs-modal-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{--bs-modal-width:800px}}@media (min-width:1200px){.modal-xl{--bs-modal-width:1140px}}.modal-fullscreen{height:100%;margin:0;max-width:none;width:100vw}.modal-fullscreen .modal-content{border:0;border-radius:0;height:100%}.modal-fullscreen .modal-footer,.modal-fullscreen .modal-header{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}@media (max-width:575.98px){.modal-fullscreen-sm-down{height:100%;margin:0;max-width:none;width:100vw}.modal-fullscreen-sm-down .modal-content{border:0;border-radius:0;height:100%}.modal-fullscreen-sm-down .modal-footer,.modal-fullscreen-sm-down .modal-header{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}}@media (max-width:767.98px){.modal-fullscreen-md-down{height:100%;margin:0;max-width:none;width:100vw}.modal-fullscreen-md-down .modal-content{border:0;border-radius:0;height:100%}.modal-fullscreen-md-down .modal-footer,.modal-fullscreen-md-down .modal-header{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}}@media (max-width:991.98px){.modal-fullscreen-lg-down{height:100%;margin:0;max-width:none;width:100vw}.modal-fullscreen-lg-down .modal-content{border:0;border-radius:0;height:100%}.modal-fullscreen-lg-down .modal-footer,.modal-fullscreen-lg-down .modal-header{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}}@media (max-width:1199.98px){.modal-fullscreen-xl-down{height:100%;margin:0;max-width:none;width:100vw}.modal-fullscreen-xl-down .modal-content{border:0;border-radius:0;height:100%}.modal-fullscreen-xl-down .modal-footer,.modal-fullscreen-xl-down .modal-header{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}}@media (max-width:1399.98px){.modal-fullscreen-xxl-down{height:100%;margin:0;max-width:none;width:100vw}.modal-fullscreen-xxl-down .modal-content{border:0;border-radius:0;height:100%}.modal-fullscreen-xxl-down .modal-footer,.modal-fullscreen-xxl-down .modal-header{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}} \ No newline at end of file diff --git a/public/js/alert.js b/public/js/alert.js deleted file mode 100644 index 00c364b3..00000000 --- a/public/js/alert.js +++ /dev/null @@ -1,1710 +0,0 @@ -var DigitlimitAlert = (function (exports) { - 'use strict'; - - /** - * -------------------------------------------------------------------------- - * Bootstrap dom/data.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ - - /** - * Constants - */ - - const elementMap = new Map(); - var Data = { - set(element, key, instance) { - if (!elementMap.has(element)) { - elementMap.set(element, new Map()); - } - const instanceMap = elementMap.get(element); - - // make it clear we only want one instance per element - // can be removed later when multiple key/instances are fine to be used - if (!instanceMap.has(key) && instanceMap.size !== 0) { - // eslint-disable-next-line no-console - console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`); - return; - } - instanceMap.set(key, instance); - }, - get(element, key) { - if (elementMap.has(element)) { - return elementMap.get(element).get(key) || null; - } - return null; - }, - remove(element, key) { - if (!elementMap.has(element)) { - return; - } - const instanceMap = elementMap.get(element); - instanceMap.delete(key); - - // free up element references if there are no instances left for an element - if (instanceMap.size === 0) { - elementMap.delete(element); - } - } - }; - - /** - * -------------------------------------------------------------------------- - * Bootstrap util/index.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ - - const MILLISECONDS_MULTIPLIER = 1000; - const TRANSITION_END = 'transitionend'; - - /** - * Properly escape IDs selectors to handle weird IDs - * @param {string} selector - * @returns {string} - */ - const parseSelector = selector => { - if (selector && window.CSS && window.CSS.escape) { - // document.querySelector needs escaping to handle IDs (html5+) containing for instance / - selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`); - } - return selector; - }; - - // Shout-out Angus Croll (https://goo.gl/pxwQGp) - const toType = object => { - if (object === null || object === undefined) { - return `${object}`; - } - return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase(); - }; - const getTransitionDurationFromElement = element => { - if (!element) { - return 0; - } - - // Get transition-duration of the element - let { - transitionDuration, - transitionDelay - } = window.getComputedStyle(element); - const floatTransitionDuration = Number.parseFloat(transitionDuration); - const floatTransitionDelay = Number.parseFloat(transitionDelay); - - // Return 0 if element or transition duration is not found - if (!floatTransitionDuration && !floatTransitionDelay) { - return 0; - } - - // If multiple durations are defined, take the first - transitionDuration = transitionDuration.split(',')[0]; - transitionDelay = transitionDelay.split(',')[0]; - return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER; - }; - const triggerTransitionEnd = element => { - element.dispatchEvent(new Event(TRANSITION_END)); - }; - const isElement = object => { - if (!object || typeof object !== 'object') { - return false; - } - if (typeof object.jquery !== 'undefined') { - object = object[0]; - } - return typeof object.nodeType !== 'undefined'; - }; - const getElement = object => { - // it's a jQuery object or a node element - if (isElement(object)) { - return object.jquery ? object[0] : object; - } - if (typeof object === 'string' && object.length > 0) { - return document.querySelector(parseSelector(object)); - } - return null; - }; - const isVisible = element => { - if (!isElement(element) || element.getClientRects().length === 0) { - return false; - } - const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible'; - // Handle `details` element as its content may falsie appear visible when it is closed - const closedDetails = element.closest('details:not([open])'); - if (!closedDetails) { - return elementIsVisible; - } - if (closedDetails !== element) { - const summary = element.closest('summary'); - if (summary && summary.parentNode !== closedDetails) { - return false; - } - if (summary === null) { - return false; - } - } - return elementIsVisible; - }; - const isDisabled = element => { - if (!element || element.nodeType !== Node.ELEMENT_NODE) { - return true; - } - if (element.classList.contains('disabled')) { - return true; - } - if (typeof element.disabled !== 'undefined') { - return element.disabled; - } - return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'; - }; - - /** - * Trick to restart an element's animation - * - * @param {HTMLElement} element - * @return void - * - * @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation - */ - const reflow = element => { - element.offsetHeight; // eslint-disable-line no-unused-expressions - }; - const getjQuery = () => { - if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) { - return window.jQuery; - } - return null; - }; - const DOMContentLoadedCallbacks = []; - const onDOMContentLoaded = callback => { - if (document.readyState === 'loading') { - // add listener on the first call when the document is in loading state - if (!DOMContentLoadedCallbacks.length) { - document.addEventListener('DOMContentLoaded', () => { - for (const callback of DOMContentLoadedCallbacks) { - callback(); - } - }); - } - DOMContentLoadedCallbacks.push(callback); - } else { - callback(); - } - }; - const isRTL = () => document.documentElement.dir === 'rtl'; - const defineJQueryPlugin = plugin => { - onDOMContentLoaded(() => { - const $ = getjQuery(); - /* istanbul ignore if */ - if ($) { - const name = plugin.NAME; - const JQUERY_NO_CONFLICT = $.fn[name]; - $.fn[name] = plugin.jQueryInterface; - $.fn[name].Constructor = plugin; - $.fn[name].noConflict = () => { - $.fn[name] = JQUERY_NO_CONFLICT; - return plugin.jQueryInterface; - }; - } - }); - }; - const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => { - return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue; - }; - const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => { - if (!waitForTransition) { - execute(callback); - return; - } - const durationPadding = 5; - const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding; - let called = false; - const handler = ({ - target - }) => { - if (target !== transitionElement) { - return; - } - called = true; - transitionElement.removeEventListener(TRANSITION_END, handler); - execute(callback); - }; - transitionElement.addEventListener(TRANSITION_END, handler); - setTimeout(() => { - if (!called) { - triggerTransitionEnd(transitionElement); - } - }, emulatedDuration); - }; - - /** - * -------------------------------------------------------------------------- - * Bootstrap dom/event-handler.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ - - - /** - * Constants - */ - - const namespaceRegex = /[^.]*(?=\..*)\.|.*/; - const stripNameRegex = /\..*/; - const stripUidRegex = /::\d+$/; - const eventRegistry = {}; // Events storage - let uidEvent = 1; - const customEvents = { - mouseenter: 'mouseover', - mouseleave: 'mouseout' - }; - const nativeEvents = new Set(['click', 'dblclick', 'mouseup', 'mousedown', 'contextmenu', 'mousewheel', 'DOMMouseScroll', 'mouseover', 'mouseout', 'mousemove', 'selectstart', 'selectend', 'keydown', 'keypress', 'keyup', 'orientationchange', 'touchstart', 'touchmove', 'touchend', 'touchcancel', 'pointerdown', 'pointermove', 'pointerup', 'pointerleave', 'pointercancel', 'gesturestart', 'gesturechange', 'gestureend', 'focus', 'blur', 'change', 'reset', 'select', 'submit', 'focusin', 'focusout', 'load', 'unload', 'beforeunload', 'resize', 'move', 'DOMContentLoaded', 'readystatechange', 'error', 'abort', 'scroll']); - - /** - * Private methods - */ - - function makeEventUid(element, uid) { - return uid && `${uid}::${uidEvent++}` || element.uidEvent || uidEvent++; - } - function getElementEvents(element) { - const uid = makeEventUid(element); - element.uidEvent = uid; - eventRegistry[uid] = eventRegistry[uid] || {}; - return eventRegistry[uid]; - } - function bootstrapHandler(element, fn) { - return function handler(event) { - hydrateObj(event, { - delegateTarget: element - }); - if (handler.oneOff) { - EventHandler.off(element, event.type, fn); - } - return fn.apply(element, [event]); - }; - } - function bootstrapDelegationHandler(element, selector, fn) { - return function handler(event) { - const domElements = element.querySelectorAll(selector); - for (let { - target - } = event; target && target !== this; target = target.parentNode) { - for (const domElement of domElements) { - if (domElement !== target) { - continue; - } - hydrateObj(event, { - delegateTarget: target - }); - if (handler.oneOff) { - EventHandler.off(element, event.type, selector, fn); - } - return fn.apply(target, [event]); - } - } - }; - } - function findHandler(events, callable, delegationSelector = null) { - return Object.values(events).find(event => event.callable === callable && event.delegationSelector === delegationSelector); - } - function normalizeParameters(originalTypeEvent, handler, delegationFunction) { - const isDelegated = typeof handler === 'string'; - // TODO: tooltip passes `false` instead of selector, so we need to check - const callable = isDelegated ? delegationFunction : handler || delegationFunction; - let typeEvent = getTypeEvent(originalTypeEvent); - if (!nativeEvents.has(typeEvent)) { - typeEvent = originalTypeEvent; - } - return [isDelegated, callable, typeEvent]; - } - function addHandler(element, originalTypeEvent, handler, delegationFunction, oneOff) { - if (typeof originalTypeEvent !== 'string' || !element) { - return; - } - let [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction); - - // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position - // this prevents the handler from being dispatched the same way as mouseover or mouseout does - if (originalTypeEvent in customEvents) { - const wrapFunction = fn => { - return function (event) { - if (!event.relatedTarget || event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget)) { - return fn.call(this, event); - } - }; - }; - callable = wrapFunction(callable); - } - const events = getElementEvents(element); - const handlers = events[typeEvent] || (events[typeEvent] = {}); - const previousFunction = findHandler(handlers, callable, isDelegated ? handler : null); - if (previousFunction) { - previousFunction.oneOff = previousFunction.oneOff && oneOff; - return; - } - const uid = makeEventUid(callable, originalTypeEvent.replace(namespaceRegex, '')); - const fn = isDelegated ? bootstrapDelegationHandler(element, handler, callable) : bootstrapHandler(element, callable); - fn.delegationSelector = isDelegated ? handler : null; - fn.callable = callable; - fn.oneOff = oneOff; - fn.uidEvent = uid; - handlers[uid] = fn; - element.addEventListener(typeEvent, fn, isDelegated); - } - function removeHandler(element, events, typeEvent, handler, delegationSelector) { - const fn = findHandler(events[typeEvent], handler, delegationSelector); - if (!fn) { - return; - } - element.removeEventListener(typeEvent, fn, Boolean(delegationSelector)); - delete events[typeEvent][fn.uidEvent]; - } - function removeNamespacedHandlers(element, events, typeEvent, namespace) { - const storeElementEvent = events[typeEvent] || {}; - for (const [handlerKey, event] of Object.entries(storeElementEvent)) { - if (handlerKey.includes(namespace)) { - removeHandler(element, events, typeEvent, event.callable, event.delegationSelector); - } - } - } - function getTypeEvent(event) { - // allow to get the native events from namespaced events ('click.bs.button' --> 'click') - event = event.replace(stripNameRegex, ''); - return customEvents[event] || event; - } - const EventHandler = { - on(element, event, handler, delegationFunction) { - addHandler(element, event, handler, delegationFunction, false); - }, - one(element, event, handler, delegationFunction) { - addHandler(element, event, handler, delegationFunction, true); - }, - off(element, originalTypeEvent, handler, delegationFunction) { - if (typeof originalTypeEvent !== 'string' || !element) { - return; - } - const [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction); - const inNamespace = typeEvent !== originalTypeEvent; - const events = getElementEvents(element); - const storeElementEvent = events[typeEvent] || {}; - const isNamespace = originalTypeEvent.startsWith('.'); - if (typeof callable !== 'undefined') { - // Simplest case: handler is passed, remove that listener ONLY. - if (!Object.keys(storeElementEvent).length) { - return; - } - removeHandler(element, events, typeEvent, callable, isDelegated ? handler : null); - return; - } - if (isNamespace) { - for (const elementEvent of Object.keys(events)) { - removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1)); - } - } - for (const [keyHandlers, event] of Object.entries(storeElementEvent)) { - const handlerKey = keyHandlers.replace(stripUidRegex, ''); - if (!inNamespace || originalTypeEvent.includes(handlerKey)) { - removeHandler(element, events, typeEvent, event.callable, event.delegationSelector); - } - } - }, - trigger(element, event, args) { - if (typeof event !== 'string' || !element) { - return null; - } - const $ = getjQuery(); - const typeEvent = getTypeEvent(event); - const inNamespace = event !== typeEvent; - let jQueryEvent = null; - let bubbles = true; - let nativeDispatch = true; - let defaultPrevented = false; - if (inNamespace && $) { - jQueryEvent = $.Event(event, args); - $(element).trigger(jQueryEvent); - bubbles = !jQueryEvent.isPropagationStopped(); - nativeDispatch = !jQueryEvent.isImmediatePropagationStopped(); - defaultPrevented = jQueryEvent.isDefaultPrevented(); - } - const evt = hydrateObj(new Event(event, { - bubbles, - cancelable: true - }), args); - if (defaultPrevented) { - evt.preventDefault(); - } - if (nativeDispatch) { - element.dispatchEvent(evt); - } - if (evt.defaultPrevented && jQueryEvent) { - jQueryEvent.preventDefault(); - } - return evt; - } - }; - function hydrateObj(obj, meta = {}) { - for (const [key, value] of Object.entries(meta)) { - try { - obj[key] = value; - } catch { - Object.defineProperty(obj, key, { - configurable: true, - get() { - return value; - } - }); - } - } - return obj; - } - - /** - * -------------------------------------------------------------------------- - * Bootstrap dom/manipulator.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ - - function normalizeData(value) { - if (value === 'true') { - return true; - } - if (value === 'false') { - return false; - } - if (value === Number(value).toString()) { - return Number(value); - } - if (value === '' || value === 'null') { - return null; - } - if (typeof value !== 'string') { - return value; - } - try { - return JSON.parse(decodeURIComponent(value)); - } catch { - return value; - } - } - function normalizeDataKey(key) { - return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`); - } - const Manipulator = { - setDataAttribute(element, key, value) { - element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value); - }, - removeDataAttribute(element, key) { - element.removeAttribute(`data-bs-${normalizeDataKey(key)}`); - }, - getDataAttributes(element) { - if (!element) { - return {}; - } - const attributes = {}; - const bsKeys = Object.keys(element.dataset).filter(key => key.startsWith('bs') && !key.startsWith('bsConfig')); - for (const key of bsKeys) { - let pureKey = key.replace(/^bs/, ''); - pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1); - attributes[pureKey] = normalizeData(element.dataset[key]); - } - return attributes; - }, - getDataAttribute(element, key) { - return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`)); - } - }; - - /** - * -------------------------------------------------------------------------- - * Bootstrap util/config.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ - - - /** - * Class definition - */ - - class Config { - // Getters - static get Default() { - return {}; - } - static get DefaultType() { - return {}; - } - static get NAME() { - throw new Error('You have to implement the static method "NAME", for each component!'); - } - _getConfig(config) { - config = this._mergeConfigObj(config); - config = this._configAfterMerge(config); - this._typeCheckConfig(config); - return config; - } - _configAfterMerge(config) { - return config; - } - _mergeConfigObj(config, element) { - const jsonConfig = isElement(element) ? Manipulator.getDataAttribute(element, 'config') : {}; // try to parse - - return { - ...this.constructor.Default, - ...(typeof jsonConfig === 'object' ? jsonConfig : {}), - ...(isElement(element) ? Manipulator.getDataAttributes(element) : {}), - ...(typeof config === 'object' ? config : {}) - }; - } - _typeCheckConfig(config, configTypes = this.constructor.DefaultType) { - for (const [property, expectedTypes] of Object.entries(configTypes)) { - const value = config[property]; - const valueType = isElement(value) ? 'element' : toType(value); - if (!new RegExp(expectedTypes).test(valueType)) { - throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`); - } - } - } - } - - /** - * -------------------------------------------------------------------------- - * Bootstrap base-component.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ - - - /** - * Constants - */ - - const VERSION = '5.3.3'; - - /** - * Class definition - */ - - class BaseComponent extends Config { - constructor(element, config) { - super(); - element = getElement(element); - if (!element) { - return; - } - this._element = element; - this._config = this._getConfig(config); - Data.set(this._element, this.constructor.DATA_KEY, this); - } - - // Public - dispose() { - Data.remove(this._element, this.constructor.DATA_KEY); - EventHandler.off(this._element, this.constructor.EVENT_KEY); - for (const propertyName of Object.getOwnPropertyNames(this)) { - this[propertyName] = null; - } - } - _queueCallback(callback, element, isAnimated = true) { - executeAfterTransition(callback, element, isAnimated); - } - _getConfig(config) { - config = this._mergeConfigObj(config, this._element); - config = this._configAfterMerge(config); - this._typeCheckConfig(config); - return config; - } - - // Static - static getInstance(element) { - return Data.get(getElement(element), this.DATA_KEY); - } - static getOrCreateInstance(element, config = {}) { - return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null); - } - static get VERSION() { - return VERSION; - } - static get DATA_KEY() { - return `bs.${this.NAME}`; - } - static get EVENT_KEY() { - return `.${this.DATA_KEY}`; - } - static eventName(name) { - return `${name}${this.EVENT_KEY}`; - } - } - - /** - * -------------------------------------------------------------------------- - * Bootstrap dom/selector-engine.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ - - const getSelector = element => { - let selector = element.getAttribute('data-bs-target'); - if (!selector || selector === '#') { - let hrefAttribute = element.getAttribute('href'); - - // The only valid content that could double as a selector are IDs or classes, - // so everything starting with `#` or `.`. If a "real" URL is used as the selector, - // `document.querySelector` will rightfully complain it is invalid. - // See https://github.com/twbs/bootstrap/issues/32273 - if (!hrefAttribute || !hrefAttribute.includes('#') && !hrefAttribute.startsWith('.')) { - return null; - } - - // Just in case some CMS puts out a full URL with the anchor appended - if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) { - hrefAttribute = `#${hrefAttribute.split('#')[1]}`; - } - selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null; - } - return selector ? selector.split(',').map(sel => parseSelector(sel)).join(',') : null; - }; - const SelectorEngine = { - find(selector, element = document.documentElement) { - return [].concat(...Element.prototype.querySelectorAll.call(element, selector)); - }, - findOne(selector, element = document.documentElement) { - return Element.prototype.querySelector.call(element, selector); - }, - children(element, selector) { - return [].concat(...element.children).filter(child => child.matches(selector)); - }, - parents(element, selector) { - const parents = []; - let ancestor = element.parentNode.closest(selector); - while (ancestor) { - parents.push(ancestor); - ancestor = ancestor.parentNode.closest(selector); - } - return parents; - }, - prev(element, selector) { - let previous = element.previousElementSibling; - while (previous) { - if (previous.matches(selector)) { - return [previous]; - } - previous = previous.previousElementSibling; - } - return []; - }, - // TODO: this is now unused; remove later along with prev() - next(element, selector) { - let next = element.nextElementSibling; - while (next) { - if (next.matches(selector)) { - return [next]; - } - next = next.nextElementSibling; - } - return []; - }, - focusableChildren(element) { - const focusables = ['a', 'button', 'input', 'textarea', 'select', 'details', '[tabindex]', '[contenteditable="true"]'].map(selector => `${selector}:not([tabindex^="-"])`).join(','); - return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el)); - }, - getSelectorFromElement(element) { - const selector = getSelector(element); - if (selector) { - return SelectorEngine.findOne(selector) ? selector : null; - } - return null; - }, - getElementFromSelector(element) { - const selector = getSelector(element); - return selector ? SelectorEngine.findOne(selector) : null; - }, - getMultipleElementsFromSelector(element) { - const selector = getSelector(element); - return selector ? SelectorEngine.find(selector) : []; - } - }; - - /** - * -------------------------------------------------------------------------- - * Bootstrap util/component-functions.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ - - const enableDismissTrigger = (component, method = 'hide') => { - const clickEvent = `click.dismiss${component.EVENT_KEY}`; - const name = component.NAME; - EventHandler.on(document, clickEvent, `[data-bs-dismiss="${name}"]`, function (event) { - if (['A', 'AREA'].includes(this.tagName)) { - event.preventDefault(); - } - if (isDisabled(this)) { - return; - } - const target = SelectorEngine.getElementFromSelector(this) || this.closest(`.${name}`); - const instance = component.getOrCreateInstance(target); - - // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method - instance[method](); - }); - }; - - /** - * -------------------------------------------------------------------------- - * Bootstrap alert.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ - - - /** - * Constants - */ - - const NAME$5 = 'alert'; - const DATA_KEY$4 = 'bs.alert'; - const EVENT_KEY$4 = `.${DATA_KEY$4}`; - const EVENT_CLOSE = `close${EVENT_KEY$4}`; - const EVENT_CLOSED = `closed${EVENT_KEY$4}`; - const CLASS_NAME_FADE$3 = 'fade'; - const CLASS_NAME_SHOW$3 = 'show'; - - /** - * Class definition - */ - - class Alert extends BaseComponent { - // Getters - static get NAME() { - return NAME$5; - } - - // Public - close() { - const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE); - if (closeEvent.defaultPrevented) { - return; - } - this._element.classList.remove(CLASS_NAME_SHOW$3); - const isAnimated = this._element.classList.contains(CLASS_NAME_FADE$3); - this._queueCallback(() => this._destroyElement(), this._element, isAnimated); - } - - // Private - _destroyElement() { - this._element.remove(); - EventHandler.trigger(this._element, EVENT_CLOSED); - this.dispose(); - } - - // Static - static jQueryInterface(config) { - return this.each(function () { - const data = Alert.getOrCreateInstance(this); - if (typeof config !== 'string') { - return; - } - if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { - throw new TypeError(`No method named "${config}"`); - } - data[config](this); - }); - } - } - - /** - * Data API implementation - */ - - enableDismissTrigger(Alert, 'close'); - - /** - * jQuery - */ - - defineJQueryPlugin(Alert); - - /** - * -------------------------------------------------------------------------- - * Bootstrap button.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ - - - /** - * Constants - */ - - const NAME$4 = 'button'; - const DATA_KEY$3 = 'bs.button'; - const EVENT_KEY$3 = `.${DATA_KEY$3}`; - const DATA_API_KEY$1 = '.data-api'; - const CLASS_NAME_ACTIVE = 'active'; - const SELECTOR_DATA_TOGGLE$1 = '[data-bs-toggle="button"]'; - const EVENT_CLICK_DATA_API$1 = `click${EVENT_KEY$3}${DATA_API_KEY$1}`; - - /** - * Class definition - */ - - class Button extends BaseComponent { - // Getters - static get NAME() { - return NAME$4; - } - - // Public - toggle() { - // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method - this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE)); - } - - // Static - static jQueryInterface(config) { - return this.each(function () { - const data = Button.getOrCreateInstance(this); - if (config === 'toggle') { - data[config](); - } - }); - } - } - - /** - * Data API implementation - */ - - EventHandler.on(document, EVENT_CLICK_DATA_API$1, SELECTOR_DATA_TOGGLE$1, event => { - event.preventDefault(); - const button = event.target.closest(SELECTOR_DATA_TOGGLE$1); - const data = Button.getOrCreateInstance(button); - data.toggle(); - }); - - /** - * jQuery - */ - - defineJQueryPlugin(Button); - - /** - * -------------------------------------------------------------------------- - * Bootstrap util/backdrop.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ - - - /** - * Constants - */ - - const NAME$3 = 'backdrop'; - const CLASS_NAME_FADE$2 = 'fade'; - const CLASS_NAME_SHOW$2 = 'show'; - const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$3}`; - const Default$3 = { - className: 'modal-backdrop', - clickCallback: null, - isAnimated: false, - isVisible: true, - // if false, we use the backdrop helper without adding any element to the dom - rootElement: 'body' // give the choice to place backdrop under different elements - }; - const DefaultType$3 = { - className: 'string', - clickCallback: '(function|null)', - isAnimated: 'boolean', - isVisible: 'boolean', - rootElement: '(element|string)' - }; - - /** - * Class definition - */ - - class Backdrop extends Config { - constructor(config) { - super(); - this._config = this._getConfig(config); - this._isAppended = false; - this._element = null; - } - - // Getters - static get Default() { - return Default$3; - } - static get DefaultType() { - return DefaultType$3; - } - static get NAME() { - return NAME$3; - } - - // Public - show(callback) { - if (!this._config.isVisible) { - execute(callback); - return; - } - this._append(); - const element = this._getElement(); - if (this._config.isAnimated) { - reflow(element); - } - element.classList.add(CLASS_NAME_SHOW$2); - this._emulateAnimation(() => { - execute(callback); - }); - } - hide(callback) { - if (!this._config.isVisible) { - execute(callback); - return; - } - this._getElement().classList.remove(CLASS_NAME_SHOW$2); - this._emulateAnimation(() => { - this.dispose(); - execute(callback); - }); - } - dispose() { - if (!this._isAppended) { - return; - } - EventHandler.off(this._element, EVENT_MOUSEDOWN); - this._element.remove(); - this._isAppended = false; - } - - // Private - _getElement() { - if (!this._element) { - const backdrop = document.createElement('div'); - backdrop.className = this._config.className; - if (this._config.isAnimated) { - backdrop.classList.add(CLASS_NAME_FADE$2); - } - this._element = backdrop; - } - return this._element; - } - _configAfterMerge(config) { - // use getElement() with the default "body" to get a fresh Element on each instantiation - config.rootElement = getElement(config.rootElement); - return config; - } - _append() { - if (this._isAppended) { - return; - } - const element = this._getElement(); - this._config.rootElement.append(element); - EventHandler.on(element, EVENT_MOUSEDOWN, () => { - execute(this._config.clickCallback); - }); - this._isAppended = true; - } - _emulateAnimation(callback) { - executeAfterTransition(callback, this._getElement(), this._config.isAnimated); - } - } - - /** - * -------------------------------------------------------------------------- - * Bootstrap util/focustrap.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ - - - /** - * Constants - */ - - const NAME$2 = 'focustrap'; - const DATA_KEY$2 = 'bs.focustrap'; - const EVENT_KEY$2 = `.${DATA_KEY$2}`; - const EVENT_FOCUSIN$1 = `focusin${EVENT_KEY$2}`; - const EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY$2}`; - const TAB_KEY = 'Tab'; - const TAB_NAV_FORWARD = 'forward'; - const TAB_NAV_BACKWARD = 'backward'; - const Default$2 = { - autofocus: true, - trapElement: null // The element to trap focus inside of - }; - const DefaultType$2 = { - autofocus: 'boolean', - trapElement: 'element' - }; - - /** - * Class definition - */ - - class FocusTrap extends Config { - constructor(config) { - super(); - this._config = this._getConfig(config); - this._isActive = false; - this._lastTabNavDirection = null; - } - - // Getters - static get Default() { - return Default$2; - } - static get DefaultType() { - return DefaultType$2; - } - static get NAME() { - return NAME$2; - } - - // Public - activate() { - if (this._isActive) { - return; - } - if (this._config.autofocus) { - this._config.trapElement.focus(); - } - EventHandler.off(document, EVENT_KEY$2); // guard against infinite focus loop - EventHandler.on(document, EVENT_FOCUSIN$1, event => this._handleFocusin(event)); - EventHandler.on(document, EVENT_KEYDOWN_TAB, event => this._handleKeydown(event)); - this._isActive = true; - } - deactivate() { - if (!this._isActive) { - return; - } - this._isActive = false; - EventHandler.off(document, EVENT_KEY$2); - } - - // Private - _handleFocusin(event) { - const { - trapElement - } = this._config; - if (event.target === document || event.target === trapElement || trapElement.contains(event.target)) { - return; - } - const elements = SelectorEngine.focusableChildren(trapElement); - if (elements.length === 0) { - trapElement.focus(); - } else if (this._lastTabNavDirection === TAB_NAV_BACKWARD) { - elements[elements.length - 1].focus(); - } else { - elements[0].focus(); - } - } - _handleKeydown(event) { - if (event.key !== TAB_KEY) { - return; - } - this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD; - } - } - - /** - * -------------------------------------------------------------------------- - * Bootstrap util/scrollBar.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ - - - /** - * Constants - */ - - const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'; - const SELECTOR_STICKY_CONTENT = '.sticky-top'; - const PROPERTY_PADDING = 'padding-right'; - const PROPERTY_MARGIN = 'margin-right'; - - /** - * Class definition - */ - - class ScrollBarHelper { - constructor() { - this._element = document.body; - } - - // Public - getWidth() { - // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes - const documentWidth = document.documentElement.clientWidth; - return Math.abs(window.innerWidth - documentWidth); - } - hide() { - const width = this.getWidth(); - this._disableOverFlow(); - // give padding to element to balance the hidden scrollbar width - this._setElementAttributes(this._element, PROPERTY_PADDING, calculatedValue => calculatedValue + width); - // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth - this._setElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING, calculatedValue => calculatedValue + width); - this._setElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN, calculatedValue => calculatedValue - width); - } - reset() { - this._resetElementAttributes(this._element, 'overflow'); - this._resetElementAttributes(this._element, PROPERTY_PADDING); - this._resetElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING); - this._resetElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN); - } - isOverflowing() { - return this.getWidth() > 0; - } - - // Private - _disableOverFlow() { - this._saveInitialAttribute(this._element, 'overflow'); - this._element.style.overflow = 'hidden'; - } - _setElementAttributes(selector, styleProperty, callback) { - const scrollbarWidth = this.getWidth(); - const manipulationCallBack = element => { - if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) { - return; - } - this._saveInitialAttribute(element, styleProperty); - const calculatedValue = window.getComputedStyle(element).getPropertyValue(styleProperty); - element.style.setProperty(styleProperty, `${callback(Number.parseFloat(calculatedValue))}px`); - }; - this._applyManipulationCallback(selector, manipulationCallBack); - } - _saveInitialAttribute(element, styleProperty) { - const actualValue = element.style.getPropertyValue(styleProperty); - if (actualValue) { - Manipulator.setDataAttribute(element, styleProperty, actualValue); - } - } - _resetElementAttributes(selector, styleProperty) { - const manipulationCallBack = element => { - const value = Manipulator.getDataAttribute(element, styleProperty); - // We only want to remove the property if the value is `null`; the value can also be zero - if (value === null) { - element.style.removeProperty(styleProperty); - return; - } - Manipulator.removeDataAttribute(element, styleProperty); - element.style.setProperty(styleProperty, value); - }; - this._applyManipulationCallback(selector, manipulationCallBack); - } - _applyManipulationCallback(selector, callBack) { - if (isElement(selector)) { - callBack(selector); - return; - } - for (const sel of SelectorEngine.find(selector, this._element)) { - callBack(sel); - } - } - } - - /** - * -------------------------------------------------------------------------- - * Bootstrap modal.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ - - - /** - * Constants - */ - - const NAME$1 = 'modal'; - const DATA_KEY$1 = 'bs.modal'; - const EVENT_KEY$1 = `.${DATA_KEY$1}`; - const DATA_API_KEY = '.data-api'; - const ESCAPE_KEY = 'Escape'; - const EVENT_HIDE$1 = `hide${EVENT_KEY$1}`; - const EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY$1}`; - const EVENT_HIDDEN$1 = `hidden${EVENT_KEY$1}`; - const EVENT_SHOW$1 = `show${EVENT_KEY$1}`; - const EVENT_SHOWN$1 = `shown${EVENT_KEY$1}`; - const EVENT_RESIZE = `resize${EVENT_KEY$1}`; - const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY$1}`; - const EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY$1}`; - const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY$1}`; - const EVENT_CLICK_DATA_API = `click${EVENT_KEY$1}${DATA_API_KEY}`; - const CLASS_NAME_OPEN = 'modal-open'; - const CLASS_NAME_FADE$1 = 'fade'; - const CLASS_NAME_SHOW$1 = 'show'; - const CLASS_NAME_STATIC = 'modal-static'; - const OPEN_SELECTOR = '.modal.show'; - const SELECTOR_DIALOG = '.modal-dialog'; - const SELECTOR_MODAL_BODY = '.modal-body'; - const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="modal"]'; - const Default$1 = { - backdrop: true, - focus: true, - keyboard: true - }; - const DefaultType$1 = { - backdrop: '(boolean|string)', - focus: 'boolean', - keyboard: 'boolean' - }; - - /** - * Class definition - */ - - class Modal extends BaseComponent { - constructor(element, config) { - super(element, config); - this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element); - this._backdrop = this._initializeBackDrop(); - this._focustrap = this._initializeFocusTrap(); - this._isShown = false; - this._isTransitioning = false; - this._scrollBar = new ScrollBarHelper(); - this._addEventListeners(); - } - - // Getters - static get Default() { - return Default$1; - } - static get DefaultType() { - return DefaultType$1; - } - static get NAME() { - return NAME$1; - } - - // Public - toggle(relatedTarget) { - return this._isShown ? this.hide() : this.show(relatedTarget); - } - show(relatedTarget) { - if (this._isShown || this._isTransitioning) { - return; - } - const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$1, { - relatedTarget - }); - if (showEvent.defaultPrevented) { - return; - } - this._isShown = true; - this._isTransitioning = true; - this._scrollBar.hide(); - document.body.classList.add(CLASS_NAME_OPEN); - this._adjustDialog(); - this._backdrop.show(() => this._showElement(relatedTarget)); - } - hide() { - if (!this._isShown || this._isTransitioning) { - return; - } - const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$1); - if (hideEvent.defaultPrevented) { - return; - } - this._isShown = false; - this._isTransitioning = true; - this._focustrap.deactivate(); - this._element.classList.remove(CLASS_NAME_SHOW$1); - this._queueCallback(() => this._hideModal(), this._element, this._isAnimated()); - } - dispose() { - EventHandler.off(window, EVENT_KEY$1); - EventHandler.off(this._dialog, EVENT_KEY$1); - this._backdrop.dispose(); - this._focustrap.deactivate(); - super.dispose(); - } - handleUpdate() { - this._adjustDialog(); - } - - // Private - _initializeBackDrop() { - return new Backdrop({ - isVisible: Boolean(this._config.backdrop), - // 'static' option will be translated to true, and booleans will keep their value, - isAnimated: this._isAnimated() - }); - } - _initializeFocusTrap() { - return new FocusTrap({ - trapElement: this._element - }); - } - _showElement(relatedTarget) { - // try to append dynamic modal - if (!document.body.contains(this._element)) { - document.body.append(this._element); - } - this._element.style.display = 'block'; - this._element.removeAttribute('aria-hidden'); - this._element.setAttribute('aria-modal', true); - this._element.setAttribute('role', 'dialog'); - this._element.scrollTop = 0; - const modalBody = SelectorEngine.findOne(SELECTOR_MODAL_BODY, this._dialog); - if (modalBody) { - modalBody.scrollTop = 0; - } - reflow(this._element); - this._element.classList.add(CLASS_NAME_SHOW$1); - const transitionComplete = () => { - if (this._config.focus) { - this._focustrap.activate(); - } - this._isTransitioning = false; - EventHandler.trigger(this._element, EVENT_SHOWN$1, { - relatedTarget - }); - }; - this._queueCallback(transitionComplete, this._dialog, this._isAnimated()); - } - _addEventListeners() { - EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => { - if (event.key !== ESCAPE_KEY) { - return; - } - if (this._config.keyboard) { - this.hide(); - return; - } - this._triggerBackdropTransition(); - }); - EventHandler.on(window, EVENT_RESIZE, () => { - if (this._isShown && !this._isTransitioning) { - this._adjustDialog(); - } - }); - EventHandler.on(this._element, EVENT_MOUSEDOWN_DISMISS, event => { - // a bad trick to segregate clicks that may start inside dialog but end outside, and avoid listen to scrollbar clicks - EventHandler.one(this._element, EVENT_CLICK_DISMISS, event2 => { - if (this._element !== event.target || this._element !== event2.target) { - return; - } - if (this._config.backdrop === 'static') { - this._triggerBackdropTransition(); - return; - } - if (this._config.backdrop) { - this.hide(); - } - }); - }); - } - _hideModal() { - this._element.style.display = 'none'; - this._element.setAttribute('aria-hidden', true); - this._element.removeAttribute('aria-modal'); - this._element.removeAttribute('role'); - this._isTransitioning = false; - this._backdrop.hide(() => { - document.body.classList.remove(CLASS_NAME_OPEN); - this._resetAdjustments(); - this._scrollBar.reset(); - EventHandler.trigger(this._element, EVENT_HIDDEN$1); - }); - } - _isAnimated() { - return this._element.classList.contains(CLASS_NAME_FADE$1); - } - _triggerBackdropTransition() { - const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED); - if (hideEvent.defaultPrevented) { - return; - } - const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; - const initialOverflowY = this._element.style.overflowY; - // return if the following background transition hasn't yet completed - if (initialOverflowY === 'hidden' || this._element.classList.contains(CLASS_NAME_STATIC)) { - return; - } - if (!isModalOverflowing) { - this._element.style.overflowY = 'hidden'; - } - this._element.classList.add(CLASS_NAME_STATIC); - this._queueCallback(() => { - this._element.classList.remove(CLASS_NAME_STATIC); - this._queueCallback(() => { - this._element.style.overflowY = initialOverflowY; - }, this._dialog); - }, this._dialog); - this._element.focus(); - } - - /** - * The following methods are used to handle overflowing modals - */ - - _adjustDialog() { - const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; - const scrollbarWidth = this._scrollBar.getWidth(); - const isBodyOverflowing = scrollbarWidth > 0; - if (isBodyOverflowing && !isModalOverflowing) { - const property = isRTL() ? 'paddingLeft' : 'paddingRight'; - this._element.style[property] = `${scrollbarWidth}px`; - } - if (!isBodyOverflowing && isModalOverflowing) { - const property = isRTL() ? 'paddingRight' : 'paddingLeft'; - this._element.style[property] = `${scrollbarWidth}px`; - } - } - _resetAdjustments() { - this._element.style.paddingLeft = ''; - this._element.style.paddingRight = ''; - } - - // Static - static jQueryInterface(config, relatedTarget) { - return this.each(function () { - const data = Modal.getOrCreateInstance(this, config); - if (typeof config !== 'string') { - return; - } - if (typeof data[config] === 'undefined') { - throw new TypeError(`No method named "${config}"`); - } - data[config](relatedTarget); - }); - } - } - - /** - * Data API implementation - */ - - EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) { - const target = SelectorEngine.getElementFromSelector(this); - if (['A', 'AREA'].includes(this.tagName)) { - event.preventDefault(); - } - EventHandler.one(target, EVENT_SHOW$1, showEvent => { - if (showEvent.defaultPrevented) { - // only register focus restorer if modal will actually get shown - return; - } - EventHandler.one(target, EVENT_HIDDEN$1, () => { - if (isVisible(this)) { - this.focus(); - } - }); - }); - - // avoid conflict when clicking modal toggler while another one is open - const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR); - if (alreadyOpen) { - Modal.getInstance(alreadyOpen).hide(); - } - const data = Modal.getOrCreateInstance(target); - data.toggle(this); - }); - enableDismissTrigger(Modal); - - /** - * jQuery - */ - - defineJQueryPlugin(Modal); - - /** - * -------------------------------------------------------------------------- - * Bootstrap toast.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - * -------------------------------------------------------------------------- - */ - - - /** - * Constants - */ - - const NAME = 'toast'; - const DATA_KEY = 'bs.toast'; - const EVENT_KEY = `.${DATA_KEY}`; - const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}`; - const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}`; - const EVENT_FOCUSIN = `focusin${EVENT_KEY}`; - const EVENT_FOCUSOUT = `focusout${EVENT_KEY}`; - const EVENT_HIDE = `hide${EVENT_KEY}`; - const EVENT_HIDDEN = `hidden${EVENT_KEY}`; - const EVENT_SHOW = `show${EVENT_KEY}`; - const EVENT_SHOWN = `shown${EVENT_KEY}`; - const CLASS_NAME_FADE = 'fade'; - const CLASS_NAME_HIDE = 'hide'; // @deprecated - kept here only for backwards compatibility - const CLASS_NAME_SHOW = 'show'; - const CLASS_NAME_SHOWING = 'showing'; - const DefaultType = { - animation: 'boolean', - autohide: 'boolean', - delay: 'number' - }; - const Default = { - animation: true, - autohide: true, - delay: 5000 - }; - - /** - * Class definition - */ - - class Toast extends BaseComponent { - constructor(element, config) { - super(element, config); - this._timeout = null; - this._hasMouseInteraction = false; - this._hasKeyboardInteraction = false; - this._setListeners(); - } - - // Getters - static get Default() { - return Default; - } - static get DefaultType() { - return DefaultType; - } - static get NAME() { - return NAME; - } - - // Public - show() { - const showEvent = EventHandler.trigger(this._element, EVENT_SHOW); - if (showEvent.defaultPrevented) { - return; - } - this._clearTimeout(); - if (this._config.animation) { - this._element.classList.add(CLASS_NAME_FADE); - } - const complete = () => { - this._element.classList.remove(CLASS_NAME_SHOWING); - EventHandler.trigger(this._element, EVENT_SHOWN); - this._maybeScheduleHide(); - }; - this._element.classList.remove(CLASS_NAME_HIDE); // @deprecated - reflow(this._element); - this._element.classList.add(CLASS_NAME_SHOW, CLASS_NAME_SHOWING); - this._queueCallback(complete, this._element, this._config.animation); - } - hide() { - if (!this.isShown()) { - return; - } - const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE); - if (hideEvent.defaultPrevented) { - return; - } - const complete = () => { - this._element.classList.add(CLASS_NAME_HIDE); // @deprecated - this._element.classList.remove(CLASS_NAME_SHOWING, CLASS_NAME_SHOW); - EventHandler.trigger(this._element, EVENT_HIDDEN); - }; - this._element.classList.add(CLASS_NAME_SHOWING); - this._queueCallback(complete, this._element, this._config.animation); - } - dispose() { - this._clearTimeout(); - if (this.isShown()) { - this._element.classList.remove(CLASS_NAME_SHOW); - } - super.dispose(); - } - isShown() { - return this._element.classList.contains(CLASS_NAME_SHOW); - } - - // Private - - _maybeScheduleHide() { - if (!this._config.autohide) { - return; - } - if (this._hasMouseInteraction || this._hasKeyboardInteraction) { - return; - } - this._timeout = setTimeout(() => { - this.hide(); - }, this._config.delay); - } - _onInteraction(event, isInteracting) { - switch (event.type) { - case 'mouseover': - case 'mouseout': - { - this._hasMouseInteraction = isInteracting; - break; - } - case 'focusin': - case 'focusout': - { - this._hasKeyboardInteraction = isInteracting; - break; - } - } - if (isInteracting) { - this._clearTimeout(); - return; - } - const nextElement = event.relatedTarget; - if (this._element === nextElement || this._element.contains(nextElement)) { - return; - } - this._maybeScheduleHide(); - } - _setListeners() { - EventHandler.on(this._element, EVENT_MOUSEOVER, event => this._onInteraction(event, true)); - EventHandler.on(this._element, EVENT_MOUSEOUT, event => this._onInteraction(event, false)); - EventHandler.on(this._element, EVENT_FOCUSIN, event => this._onInteraction(event, true)); - EventHandler.on(this._element, EVENT_FOCUSOUT, event => this._onInteraction(event, false)); - } - _clearTimeout() { - clearTimeout(this._timeout); - this._timeout = null; - } - - // Static - static jQueryInterface(config) { - return this.each(function () { - const data = Toast.getOrCreateInstance(this, config); - if (typeof config === 'string') { - if (typeof data[config] === 'undefined') { - throw new TypeError(`No method named "${config}"`); - } - data[config](this); - } - }); - } - } - - /** - * Data API implementation - */ - - enableDismissTrigger(Toast); - - /** - * jQuery - */ - - defineJQueryPlugin(Toast); - - exports.Alert = Alert; - exports.Button = Button; - exports.Modal = Modal; - exports.Toast = Toast; - - return exports; - -})({}); diff --git a/public/js/alert.min.js b/public/js/alert.min.js deleted file mode 100644 index b4cf5796..00000000 --- a/public/js/alert.min.js +++ /dev/null @@ -1 +0,0 @@ -var DigitlimitAlert=function(t){"use strict";const e=new Map;var i={set(t,i,s){e.has(t)||e.set(t,new Map);const n=e.get(t);n.has(i)||0===n.size?n.set(i,s):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(n.keys())[0]}.`)},get:(t,i)=>e.has(t)&&e.get(t).get(i)||null,remove(t,i){if(!e.has(t))return;const s=e.get(t);s.delete(i),0===s.size&&e.delete(t)}};const s="transitionend",n=t=>(t&&window.CSS&&window.CSS.escape&&(t=t.replace(/#([^\s"#']+)/g,((t,e)=>`#${CSS.escape(e)}`))),t),o=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),r=t=>o(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(n(t)):null,a=t=>{if(!o(t)||0===t.getClientRects().length)return!1;const e="visible"===getComputedStyle(t).getPropertyValue("visibility"),i=t.closest("details:not([open])");if(!i)return e;if(i!==t){const e=t.closest("summary");if(e&&e.parentNode!==i)return!1;if(null===e)return!1}return e},l=t=>!t||t.nodeType!==Node.ELEMENT_NODE||(!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled"))),c=t=>{t.offsetHeight},u=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,h=[],d=()=>"rtl"===document.documentElement.dir,m=t=>{var e;e=()=>{const e=u();if(e){const i=t.NAME,s=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=s,t.jQueryInterface)}},"loading"===document.readyState?(h.length||document.addEventListener("DOMContentLoaded",(()=>{for(const t of h)t()})),h.push(e)):e()},f=(t,e=[],i=t)=>"function"==typeof t?t.call(...e):i,g=(t,e,i=!0)=>{if(!i)return void f(t);const n=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const s=Number.parseFloat(e),n=Number.parseFloat(i);return s||n?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0})(e)+5;let o=!1;const r=({target:i})=>{i===e&&(o=!0,e.removeEventListener(s,r),f(t))};e.addEventListener(s,r),setTimeout((()=>{o||e.dispatchEvent(new Event(s))}),n)},_=/[^.]*(?=\..*)\.|.*/,p=/\..*/,b=/::\d+$/,y={};let v=1;const E={mouseenter:"mouseover",mouseleave:"mouseout"},A=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function w(t,e){return e&&`${e}::${v++}`||t.uidEvent||v++}function k(t){const e=w(t);return t.uidEvent=e,y[e]=y[e]||{},y[e]}function T(t,e,i=null){return Object.values(t).find((t=>t.callable===e&&t.delegationSelector===i))}function C(t,e,i){const s="string"==typeof e,n=s?i:e||i;let o=N(t);return A.has(o)||(o=t),[s,n,o]}function $(t,e,i,s,n){if("string"!=typeof e||!t)return;let[o,r,a]=C(e,i,s);if(e in E){const t=t=>function(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};r=t(r)}const l=k(t),c=l[a]||(l[a]={}),u=T(c,r,o?i:null);if(u)return void(u.oneOff=u.oneOff&&n);const h=w(r,e.replace(_,"")),d=o?function(t,e,i){return function s(n){const o=t.querySelectorAll(e);for(let{target:r}=n;r&&r!==this;r=r.parentNode)for(const a of o)if(a===r)return L(n,{delegateTarget:r}),s.oneOff&&O.off(t,n.type,e,i),i.apply(r,[n])}}(t,i,r):function(t,e){return function i(s){return L(s,{delegateTarget:t}),i.oneOff&&O.off(t,s.type,e),e.apply(t,[s])}}(t,r);d.delegationSelector=o?i:null,d.callable=r,d.oneOff=n,d.uidEvent=h,c[h]=d,t.addEventListener(a,d,o)}function D(t,e,i,s,n){const o=T(e[i],s,n);o&&(t.removeEventListener(i,o,Boolean(n)),delete e[i][o.uidEvent])}function S(t,e,i,s){const n=e[i]||{};for(const[o,r]of Object.entries(n))o.includes(s)&&D(t,e,i,r.callable,r.delegationSelector)}function N(t){return t=t.replace(p,""),E[t]||t}const O={on(t,e,i,s){$(t,e,i,s,!1)},one(t,e,i,s){$(t,e,i,s,!0)},off(t,e,i,s){if("string"!=typeof e||!t)return;const[n,o,r]=C(e,i,s),a=r!==e,l=k(t),c=l[r]||{},u=e.startsWith(".");if(void 0===o){if(u)for(const i of Object.keys(l))S(t,l,i,e.slice(1));for(const[i,s]of Object.entries(c)){const n=i.replace(b,"");a&&!e.includes(n)||D(t,l,r,s.callable,s.delegationSelector)}}else{if(!Object.keys(c).length)return;D(t,l,r,o,n?i:null)}},trigger(t,e,i){if("string"!=typeof e||!t)return null;const s=u();let n=null,o=!0,r=!0,a=!1;e!==N(e)&&s&&(n=s.Event(e,i),s(t).trigger(n),o=!n.isPropagationStopped(),r=!n.isImmediatePropagationStopped(),a=n.isDefaultPrevented());const l=L(new Event(e,{bubbles:o,cancelable:!0}),i);return a&&l.preventDefault(),r&&t.dispatchEvent(l),l.defaultPrevented&&n&&n.preventDefault(),l}};function L(t,e={}){for(const[i,s]of Object.entries(e))try{t[i]=s}catch{Object.defineProperty(t,i,{configurable:!0,get:()=>s})}return t}function j(t){if("true"===t)return!0;if("false"===t)return!1;if(t===Number(t).toString())return Number(t);if(""===t||"null"===t)return null;if("string"!=typeof t)return t;try{return JSON.parse(decodeURIComponent(t))}catch{return t}}function I(t){return t.replace(/[A-Z]/g,(t=>`-${t.toLowerCase()}`))}const M={setDataAttribute(t,e,i){t.setAttribute(`data-bs-${I(e)}`,i)},removeDataAttribute(t,e){t.removeAttribute(`data-bs-${I(e)}`)},getDataAttributes(t){if(!t)return{};const e={},i=Object.keys(t.dataset).filter((t=>t.startsWith("bs")&&!t.startsWith("bsConfig")));for(const s of i){let i=s.replace(/^bs/,"");i=i.charAt(0).toLowerCase()+i.slice(1),e[i]=j(t.dataset[s])}return e},getDataAttribute:(t,e)=>j(t.getAttribute(`data-bs-${I(e)}`))};class x{static get Default(){return{}}static get DefaultType(){return{}}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}_getConfig(t){return t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t}_mergeConfigObj(t,e){const i=o(e)?M.getDataAttribute(e,"config"):{};return{...this.constructor.Default,..."object"==typeof i?i:{},...o(e)?M.getDataAttributes(e):{},..."object"==typeof t?t:{}}}_typeCheckConfig(t,e=this.constructor.DefaultType){for(const[s,n]of Object.entries(e)){const e=t[s],r=o(e)?"element":null==(i=e)?`${i}`:Object.prototype.toString.call(i).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(n).test(r))throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${s}" provided type "${r}" but expected type "${n}".`)}var i}}class P extends x{constructor(t,e){super(),(t=r(t))&&(this._element=t,this._config=this._getConfig(e),i.set(this._element,this.constructor.DATA_KEY,this))}dispose(){i.remove(this._element,this.constructor.DATA_KEY),O.off(this._element,this.constructor.EVENT_KEY);for(const t of Object.getOwnPropertyNames(this))this[t]=null}_queueCallback(t,e,i=!0){g(t,e,i)}_getConfig(t){return t=this._mergeConfigObj(t,this._element),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}static getInstance(t){return i.get(r(t),this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return"5.3.3"}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}static eventName(t){return`${t}${this.EVENT_KEY}`}}const F=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?i.trim():null}return e?e.split(",").map((t=>n(t))).join(","):null},q={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter((t=>t.matches(e))),parents(t,e){const i=[];let s=t.parentNode.closest(e);for(;s;)i.push(s),s=s.parentNode.closest(e);return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]},focusableChildren(t){const e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map((t=>`${t}:not([tabindex^="-"])`)).join(",");return this.find(e,t).filter((t=>!l(t)&&a(t)))},getSelectorFromElement(t){const e=F(t);return e&&q.findOne(e)?e:null},getElementFromSelector(t){const e=F(t);return e?q.findOne(e):null},getMultipleElementsFromSelector(t){const e=F(t);return e?q.find(e):[]}},K=(t,e="hide")=>{const i=`click.dismiss${t.EVENT_KEY}`,s=t.NAME;O.on(document,i,`[data-bs-dismiss="${s}"]`,(function(i){if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),l(this))return;const n=q.getElementFromSelector(this)||this.closest(`.${s}`);t.getOrCreateInstance(n)[e]()}))},W=".bs.alert",B=`close${W}`,V=`closed${W}`;class Y extends P{static get NAME(){return"alert"}close(){if(O.trigger(this._element,B).defaultPrevented)return;this._element.classList.remove("show");const t=this._element.classList.contains("fade");this._queueCallback((()=>this._destroyElement()),this._element,t)}_destroyElement(){this._element.remove(),O.trigger(this._element,V),this.dispose()}static jQueryInterface(t){return this.each((function(){const e=Y.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}K(Y,"close"),m(Y);const z='[data-bs-toggle="button"]';class R extends P{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each((function(){const e=R.getOrCreateInstance(this);"toggle"===t&&e[t]()}))}}O.on(document,"click.bs.button.data-api",z,(t=>{t.preventDefault();const e=t.target.closest(z);R.getOrCreateInstance(e).toggle()})),m(R);const H="backdrop",Q="show",U=`mousedown.bs.${H}`,J={className:"modal-backdrop",clickCallback:null,isAnimated:!1,isVisible:!0,rootElement:"body"},Z={className:"string",clickCallback:"(function|null)",isAnimated:"boolean",isVisible:"boolean",rootElement:"(element|string)"};class G extends x{constructor(t){super(),this._config=this._getConfig(t),this._isAppended=!1,this._element=null}static get Default(){return J}static get DefaultType(){return Z}static get NAME(){return H}show(t){if(!this._config.isVisible)return void f(t);this._append();const e=this._getElement();this._config.isAnimated&&c(e),e.classList.add(Q),this._emulateAnimation((()=>{f(t)}))}hide(t){this._config.isVisible?(this._getElement().classList.remove(Q),this._emulateAnimation((()=>{this.dispose(),f(t)}))):f(t)}dispose(){this._isAppended&&(O.off(this._element,U),this._element.remove(),this._isAppended=!1)}_getElement(){if(!this._element){const t=document.createElement("div");t.className=this._config.className,this._config.isAnimated&&t.classList.add("fade"),this._element=t}return this._element}_configAfterMerge(t){return t.rootElement=r(t.rootElement),t}_append(){if(this._isAppended)return;const t=this._getElement();this._config.rootElement.append(t),O.on(t,U,(()=>{f(this._config.clickCallback)})),this._isAppended=!0}_emulateAnimation(t){g(t,this._getElement(),this._config.isAnimated)}}const X=".bs.focustrap",tt=`focusin${X}`,et=`keydown.tab${X}`,it="backward",st={autofocus:!0,trapElement:null},nt={autofocus:"boolean",trapElement:"element"};class ot extends x{constructor(t){super(),this._config=this._getConfig(t),this._isActive=!1,this._lastTabNavDirection=null}static get Default(){return st}static get DefaultType(){return nt}static get NAME(){return"focustrap"}activate(){this._isActive||(this._config.autofocus&&this._config.trapElement.focus(),O.off(document,X),O.on(document,tt,(t=>this._handleFocusin(t))),O.on(document,et,(t=>this._handleKeydown(t))),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,O.off(document,X))}_handleFocusin(t){const{trapElement:e}=this._config;if(t.target===document||t.target===e||e.contains(t.target))return;const i=q.focusableChildren(e);0===i.length?e.focus():this._lastTabNavDirection===it?i[i.length-1].focus():i[0].focus()}_handleKeydown(t){"Tab"===t.key&&(this._lastTabNavDirection=t.shiftKey?it:"forward")}}const rt=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",at=".sticky-top",lt="padding-right",ct="margin-right";class ut{constructor(){this._element=document.body}getWidth(){const t=document.documentElement.clientWidth;return Math.abs(window.innerWidth-t)}hide(){const t=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,lt,(e=>e+t)),this._setElementAttributes(rt,lt,(e=>e+t)),this._setElementAttributes(at,ct,(e=>e-t))}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,lt),this._resetElementAttributes(rt,lt),this._resetElementAttributes(at,ct)}isOverflowing(){return this.getWidth()>0}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,i){const s=this.getWidth();this._applyManipulationCallback(t,(t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+s)return;this._saveInitialAttribute(t,e);const n=window.getComputedStyle(t).getPropertyValue(e);t.style.setProperty(e,`${i(Number.parseFloat(n))}px`)}))}_saveInitialAttribute(t,e){const i=t.style.getPropertyValue(e);i&&M.setDataAttribute(t,e,i)}_resetElementAttributes(t,e){this._applyManipulationCallback(t,(t=>{const i=M.getDataAttribute(t,e);null!==i?(M.removeDataAttribute(t,e),t.style.setProperty(e,i)):t.style.removeProperty(e)}))}_applyManipulationCallback(t,e){if(o(t))e(t);else for(const i of q.find(t,this._element))e(i)}}const ht=".bs.modal",dt=`hide${ht}`,mt=`hidePrevented${ht}`,ft=`hidden${ht}`,gt=`show${ht}`,_t=`shown${ht}`,pt=`resize${ht}`,bt=`click.dismiss${ht}`,yt=`mousedown.dismiss${ht}`,vt=`keydown.dismiss${ht}`,Et=`click${ht}.data-api`,At="modal-open",wt="show",kt="modal-static",Tt={backdrop:!0,focus:!0,keyboard:!0},Ct={backdrop:"(boolean|string)",focus:"boolean",keyboard:"boolean"};class $t extends P{constructor(t,e){super(t,e),this._dialog=q.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._isTransitioning=!1,this._scrollBar=new ut,this._addEventListeners()}static get Default(){return Tt}static get DefaultType(){return Ct}static get NAME(){return"modal"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){if(this._isShown||this._isTransitioning)return;O.trigger(this._element,gt,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isTransitioning=!0,this._scrollBar.hide(),document.body.classList.add(At),this._adjustDialog(),this._backdrop.show((()=>this._showElement(t))))}hide(){if(!this._isShown||this._isTransitioning)return;O.trigger(this._element,dt).defaultPrevented||(this._isShown=!1,this._isTransitioning=!0,this._focustrap.deactivate(),this._element.classList.remove(wt),this._queueCallback((()=>this._hideModal()),this._element,this._isAnimated()))}dispose(){O.off(window,ht),O.off(this._dialog,ht),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new G({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new ot({trapElement:this._element})}_showElement(t){document.body.contains(this._element)||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0;const e=q.findOne(".modal-body",this._dialog);e&&(e.scrollTop=0),c(this._element),this._element.classList.add(wt);this._queueCallback((()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,O.trigger(this._element,_t,{relatedTarget:t})}),this._dialog,this._isAnimated())}_addEventListeners(){O.on(this._element,vt,(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():this._triggerBackdropTransition())})),O.on(window,pt,(()=>{this._isShown&&!this._isTransitioning&&this._adjustDialog()})),O.on(this._element,yt,(t=>{O.one(this._element,bt,(e=>{this._element===t.target&&this._element===e.target&&("static"!==this._config.backdrop?this._config.backdrop&&this.hide():this._triggerBackdropTransition())}))}))}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide((()=>{document.body.classList.remove(At),this._resetAdjustments(),this._scrollBar.reset(),O.trigger(this._element,ft)}))}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(O.trigger(this._element,mt).defaultPrevented)return;const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._element.style.overflowY;"hidden"===e||this._element.classList.contains(kt)||(t||(this._element.style.overflowY="hidden"),this._element.classList.add(kt),this._queueCallback((()=>{this._element.classList.remove(kt),this._queueCallback((()=>{this._element.style.overflowY=e}),this._dialog)}),this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),i=e>0;if(i&&!t){const t=d()?"paddingLeft":"paddingRight";this._element.style[t]=`${e}px`}if(!i&&t){const t=d()?"paddingRight":"paddingLeft";this._element.style[t]=`${e}px`}}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each((function(){const i=$t.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}}))}}O.on(document,Et,'[data-bs-toggle="modal"]',(function(t){const e=q.getElementFromSelector(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),O.one(e,gt,(t=>{t.defaultPrevented||O.one(e,ft,(()=>{a(this)&&this.focus()}))}));const i=q.findOne(".modal.show");i&&$t.getInstance(i).hide();$t.getOrCreateInstance(e).toggle(this)})),K($t),m($t);const Dt=".bs.toast",St=`mouseover${Dt}`,Nt=`mouseout${Dt}`,Ot=`focusin${Dt}`,Lt=`focusout${Dt}`,jt=`hide${Dt}`,It=`hidden${Dt}`,Mt=`show${Dt}`,xt=`shown${Dt}`,Pt="hide",Ft="show",qt="showing",Kt={animation:"boolean",autohide:"boolean",delay:"number"},Wt={animation:!0,autohide:!0,delay:5e3};class Bt extends P{constructor(t,e){super(t,e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get Default(){return Wt}static get DefaultType(){return Kt}static get NAME(){return"toast"}show(){if(O.trigger(this._element,Mt).defaultPrevented)return;this._clearTimeout(),this._config.animation&&this._element.classList.add("fade");this._element.classList.remove(Pt),c(this._element),this._element.classList.add(Ft,qt),this._queueCallback((()=>{this._element.classList.remove(qt),O.trigger(this._element,xt),this._maybeScheduleHide()}),this._element,this._config.animation)}hide(){if(!this.isShown())return;if(O.trigger(this._element,jt).defaultPrevented)return;this._element.classList.add(qt),this._queueCallback((()=>{this._element.classList.add(Pt),this._element.classList.remove(qt,Ft),O.trigger(this._element,It)}),this._element,this._config.animation)}dispose(){this._clearTimeout(),this.isShown()&&this._element.classList.remove(Ft),super.dispose()}isShown(){return this._element.classList.contains(Ft)}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout((()=>{this.hide()}),this._config.delay)))}_onInteraction(t,e){switch(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const i=t.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){O.on(this._element,St,(t=>this._onInteraction(t,!0))),O.on(this._element,Nt,(t=>this._onInteraction(t,!1))),O.on(this._element,Ot,(t=>this._onInteraction(t,!0))),O.on(this._element,Lt,(t=>this._onInteraction(t,!1)))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each((function(){const e=Bt.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}return K(Bt),m(Bt),t.Alert=Y,t.Button=R,t.Modal=$t,t.Toast=Bt,t}({}); diff --git a/public/modal.css b/public/modal.css deleted file mode 100644 index f9c954cd..00000000 --- a/public/modal.css +++ /dev/null @@ -1,125 +0,0 @@ -.btn { - padding: 10px 20px; - border: none; - border-radius: 4px; - cursor: pointer; - font-size: 16px; - transition: background-color 0.3s ease; -} -.btn-primary { - background-color: #007bff; - color: white; -} -.btn-primary:hover { - background-color: rgb(0, 98.4, 204); -} -.btn-secondary { - background-color: #6c757d; - color: white; -} -.btn-secondary:hover { - background-color: rgb(84.3605150215, 91.3905579399, 97.6394849785); -} -.btn-close { - background: none; - border: none; - font-size: 24px; - cursor: pointer; -} -.btn-close:hover { - color: #ff0000; -} - -.modal-overlay { - display: none; - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.5); - z-index: 1000; -} - -.modal { - display: none; - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 1001; -} -.modal .modal-dialog { - position: relative; - width: 90%; - max-width: 500px; - margin: auto; - background-color: white; - border-radius: 8px; - box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); - overflow: hidden; -} -.modal .modal-dialog.modal-size-small { - max-width: 300px; -} -.modal .modal-dialog.modal-size-large { - max-width: 800px; -} -.modal .modal-dialog.modal-size-extra-large { - max-width: 1140px; -} -.modal .modal-dialog.modal-fullscreen { - width: 100vw; - height: 100vh; - max-width: none; - border-radius: 0; - margin: 0; -} -.modal .modal-dialog.modal-centered { - top: 50%; - left: 50%; - transform: translate(-50%, -50%); -} -.modal .modal-dialog.modal-scrollable { - max-height: 90vh; - overflow-y: auto; -} -.modal .modal-dialog .modal-content { - width: 100%; - height: 100%; -} -.modal .modal-dialog .modal-content .modal-header { - padding: 16px; - border-bottom: 1px solid #ddd; - display: flex; - justify-content: space-between; - align-items: center; -} -.modal .modal-dialog .modal-content .modal-header .modal-title { - margin: 0; - font-size: 20px; -} -.modal .modal-dialog .modal-content .modal-body { - padding: 16px; -} -.modal .modal-dialog .modal-content .modal-footer { - padding: 16px; - border-top: 1px solid #ddd; - display: flex; - justify-content: flex-end; - gap: 8px; -} - -@media (max-width: 768px) { - .modal .modal-dialog { - width: 95%; - max-width: none; - } - .modal .modal-dialog.modal-fullscreen { - width: 100vw; - height: 100vh; - } -} - -/*# sourceMappingURL=modal.css.map */ diff --git a/public/modal.css.map b/public/modal.css.map deleted file mode 100644 index bd9b886a..00000000 --- a/public/modal.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sourceRoot":"","sources":["modal.scss"],"names":[],"mappings":"AAGA;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AACA;EACE;;AAIJ;EACE;EACA;;AACA;EACE;;AAIJ;EACE;EACA;EACA;EACA;;AACA;EACE;;;AAMN;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGA;EACE;;AAGF;EACE;;AAGF;EACE;;AAIF;EACE;EACA;EACA;EACA;EACA;;AAIF;EACE;EACA;EACA;;AAIF;EACE;EACA;;AAIF;EACE;EACA;;AAGA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAKJ;EACE;;AAIF;EACE;EACA;EACA;EACA;EACA;;;AAOR;EACE;IACE;IACA;;EAEA;IACE;IACA","file":"modal.css"} \ No newline at end of file diff --git a/public/modal.js b/public/modal.js deleted file mode 100644 index eb1e50ce..00000000 --- a/public/modal.js +++ /dev/null @@ -1,44 +0,0 @@ -class Modal { - constructor(modalId) { - this.modal = document.getElementById(modalId); - this.overlay = document.createElement('div'); - this.overlay.classList.add('modal-overlay'); - document.body.appendChild(this.overlay); - - this.init(); - } - - // Initialize event listeners - init() { - // Close modal when clicking the overlay - this.overlay.addEventListener('click', () => this.close()); - - // Close modal when clicking the close button - const closeButtons = this.modal.querySelectorAll('[data-dismiss="modal"]'); - closeButtons.forEach(button => { - button.addEventListener('click', () => this.close()); - }); - } - - // Open the modal - open() { - this.modal.style.display = 'block'; - this.overlay.style.display = 'block'; - document.body.style.overflow = 'hidden'; // Prevent scrolling - } - - // Close the modal - close() { - this.modal.style.display = 'none'; - this.overlay.style.display = 'none'; - document.body.style.overflow = 'auto'; // Restore scrolling - } -} - -// Initialize the modal -const modal = new Modal('exampleModal'); - -// Open modal when the button is clicked -document.getElementById('open-modal-btn').addEventListener('click', () => { - modal.open(); -}); \ No newline at end of file diff --git a/public/modal.scss b/public/modal.scss deleted file mode 100644 index 1e5f7825..00000000 --- a/public/modal.scss +++ /dev/null @@ -1,154 +0,0 @@ -@use "sass:color"; - -// Base styles for buttons -.btn { - padding: 10px 20px; - border: none; - border-radius: 4px; - cursor: pointer; - font-size: 16px; - transition: background-color 0.3s ease; - - &-primary { - background-color: #007bff; - color: white; - &:hover { - background-color: color.adjust(#007bff, $lightness: -10%); - } - } - - &-secondary { - background-color: #6c757d; - color: white; - &:hover { - background-color: color.adjust(#6c757d, $lightness: -10%); - } - } - - &-close { - background: none; - border: none; - font-size: 24px; - cursor: pointer; - &:hover { - color: #ff0000; - } - } -} - -// Modal overlay -.modal-overlay { - display: none; - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.5); - z-index: 1000; -} - -// Modal container -.modal { - display: none; - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 1001; - - // Modal dialog - .modal-dialog { - position: relative; - width: 90%; // Default width for responsiveness - max-width: 500px; // Default max width - margin: auto; - background-color: white; - border-radius: 8px; - box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); - overflow: hidden; - - // Modal sizes - &.modal-size-small { - max-width: 300px; - } - - &.modal-size-large { - max-width: 800px; - } - - &.modal-size-extra-large { - max-width: 1140px; - } - - // Fullscreen modal - &.modal-fullscreen { - width: 100vw; - height: 100vh; - max-width: none; - border-radius: 0; - margin: 0; - } - - // Centered modal - &.modal-centered { - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - } - - // Scrollable modal - &.modal-scrollable { - max-height: 90vh; - overflow-y: auto; - } - - // Modal content - .modal-content { - width: 100%; - height: 100%; - - // Modal header - .modal-header { - padding: 16px; - border-bottom: 1px solid #ddd; - display: flex; - justify-content: space-between; - align-items: center; - - .modal-title { - margin: 0; - font-size: 20px; - } - } - - // Modal body - .modal-body { - padding: 16px; - } - - // Modal footer - .modal-footer { - padding: 16px; - border-top: 1px solid #ddd; - display: flex; - justify-content: flex-end; - gap: 8px; - } - } - } -} - -// Responsive adjustments -@media (max-width: 768px) { - .modal .modal-dialog { - width: 95%; // Wider on smaller screens - max-width: none; - - &.modal-fullscreen { - width: 100vw; - height: 100vh; - } - } -} \ No newline at end of file diff --git a/resources/css/themes/tailwind/alert.css b/resources/css/themes/tailwind/alert.css new file mode 100644 index 00000000..259159f8 --- /dev/null +++ b/resources/css/themes/tailwind/alert.css @@ -0,0 +1,281 @@ +.alert-button.primary { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-900 focus:ring-offset-2 bg-neutral-950 hover:bg-neutral-900; +} + +.alert-button.secondary { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium transition-colors border rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-100 focus:ring-offset-2; +} + +.alert-button.success { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-green-700 focus:ring-offset-2 bg-green-600 hover:bg-green-700; +} + +.alert-button.error { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-red-700 focus:ring-offset-2 bg-red-600 hover:bg-red-700; +} + +.alert-button.warning { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-black transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-yellow-600 focus:ring-offset-2 bg-yellow-400 hover:bg-yellow-500; +} + +.alert-button.info { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-blue-700 focus:ring-offset-2 bg-blue-600 hover:bg-blue-700; +} + +.alert-button.light { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-black transition-colors border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-300 focus:ring-offset-2 bg-white hover:bg-gray-100; +} + +.alert-button.dark { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-gray-900 focus:ring-offset-2 bg-gray-800 hover:bg-gray-900; +} + +.alert-button.link { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-blue-600 transition-colors rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 hover:underline; +} + +.alert-notify-position { + @apply fixed px-2 mt-3 overflow-x-hidden z-50; +} + +.alert-notify-position.top-right { + @apply top-0 right-0; +} + +.alert-notify-position.top-left { + @apply top-0 left-0; +} + +.alert-notify-position.bottom-right { + @apply bottom-0 right-0; +} + +.alert-notify-position.bottom-left { + @apply bottom-0 left-0; +} + +.alert-notify-position.top-center { + @apply top-0 left-1/2 transform -translate-x-1/2; +} + +.alert-notify-position.bottom-center { + @apply bottom-0 left-1/2 transform -translate-x-1/2; +} + +.alert-notify-position.center { + @apply top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2; +} + +.alert-field.success { + @apply p-3 text-green-800; +} + +.alert-field.error { + @apply p-3 text-red-800; +} + +.alert-field.warning { + @apply p-3 text-yellow-800; +} + +.alert-field.info { + @apply p-3 text-blue-800; +} + +.alert-message { + @apply flex items-center p-4 mb-4 rounded-lg; +} + +.alert-message .sr-only-fix { + @apply sr-only; +} + +.alert-message.success { + @apply text-green-800 bg-green-50 dark:bg-gray-800 dark:text-green-400; +} + +.alert-message.error { + @apply text-red-800 bg-red-50 dark:bg-gray-800 dark:text-red-400; +} + +.alert-message.warning { + @apply text-yellow-800 bg-yellow-50 dark:bg-gray-800 dark:text-yellow-300; +} + +.alert-message.info { + @apply text-blue-800 bg-blue-50 dark:bg-gray-800 dark:text-blue-400; +} + +.alert-message .icon { + @apply shrink-0 w-4 h-4; +} + +.alert-message .message { + @apply ms-3 text-sm font-medium flex items-center gap-2; +} + +.alert-message .message .title { + @apply text-lg font-semibold; +} + +.alert-message .close { + @apply ms-auto -mx-1.5 -my-1.5 p-1.5 inline-flex items-center justify-center h-8 w-8 rounded-lg focus:ring-2; +} + +.alert-message .close.success { + @apply bg-blue-50 text-blue-500 focus:ring-blue-400 hover:bg-blue-200 dark:bg-gray-800 dark:text-blue-400 dark:hover:bg-gray-700; +} + +.alert-message .close.error { + @apply bg-red-50 text-red-500 focus:ring-red-400 hover:bg-red-200 dark:bg-gray-800 dark:text-red-400 dark:hover:bg-gray-700; +} + +.alert-message .close.warning { + @apply bg-yellow-50 text-yellow-500 focus:ring-yellow-400 hover:bg-yellow-200 dark:bg-gray-800 dark:text-yellow-400 dark:hover:bg-gray-700; +} + +.alert-message .close.info { + @apply bg-blue-50 text-blue-500 focus:ring-blue-400 hover:bg-blue-200 dark:bg-gray-800 dark:text-blue-400 dark:hover:bg-gray-700; +} + +.alert-message .close .close-icon { + @apply w-3 h-3; +} + +.alert-message .close .sr-only-fix { + @apply sr-only; +} + +.alert-notify { + @apply bg-gray-900 bg-gradient-to-r text-white rounded-t mb-3 shadow-lg flex items-center; +} + +.alert-notify.success { + @apply from-green-400 to-green-500; +} + +.alert-notify.error { + @apply from-red-400 to-pink-500; +} + +.alert-notify.warning { + @apply from-yellow-400 to-yellow-500; +} + +.alert-notify.info { + @apply from-blue-400 to-blue-500; +} + +.alert-notify.top-right { + @apply top-0 right-0; +} + +.alert-notify.top-left { + @apply top-0 left-0; +} + +.alert-notify.bottom-right { + @apply bottom-0 right-0; +} + +.alert-notify.bottom-left { + @apply bottom-0 left-0; +} + +.alert-notify.top-center { + @apply top-0 left-1/2 transform -translate-x-1/2; +} + +.alert-notify.bottom-center { + @apply bottom-0 left-1/2 transform -translate-x-1/2; +} + +.alert-notify.center { + @apply top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2; +} + +.alert-modal { + @apply fixed top-0 left-0 z-[99] flex items-center justify-center w-screen h-screen; +} + +.alert-modal .modal-overlay { + @apply absolute inset-0 w-full h-full bg-white backdrop-blur-sm bg-opacity-70; +} + +.alert-modal .modal-content { + @apply bg-white p-6 rounded-lg shadow-lg relative max-w-full; +} + +.alert-modal .modal-content.small { + @apply w-1/4; +} + +.alert-modal .modal-content.medium { + @apply w-1/2; +} + +.alert-modal .modal-content.large { + @apply w-3/4; +} + +.alert-modal .modal-content.extra-large { + @apply w-4/5; +} + +.alert-modal .modal-content.fullscreen { + @apply w-full h-full; +} + +.alert-modal .modal-content.scrollable { + @apply max-h-[80vh] overflow-y-auto; +} + +.alert-modal .modal-header { + @apply flex items-center justify-between pb-3; +} + +.alert-modal .modal-header.text-success { + @apply text-green-500; +} + +.alert-modal .modal-header.text-error { + @apply text-red-500; +} + +.alert-modal .modal-header.text-warning { + @apply text-yellow-500; +} + +.alert-modal .modal-header.text-info { + @apply text-blue-500; +} + +.alert-modal .modal-header .modal-title { + @apply text-lg font-semibold; +} + +.alert-modal .modal-header .modal-close { + @apply absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5 text-gray-600 rounded-full hover:text-gray-800 hover:bg-gray-50; +} + +.alert-modal .modal-header .modal-close-icon { + @apply w-5 h-5; +} + +.alert-modal .modal-body { + @apply relative w-auto pb-8; +} + +.alert-modal .modal-footer { + @apply flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2; +} + +.alert-modal .modal-footer .modal-action-button { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-900 focus:ring-offset-2 bg-neutral-950 hover:bg-neutral-900; +} + +.alert-modal .modal-footer .modal-cancel-button { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium transition-colors border rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-100 focus:ring-offset-2; +} + + diff --git a/resources/css/themes/tailwind/components/button.css b/resources/css/themes/tailwind/components/button.css new file mode 100644 index 00000000..32ea50b7 --- /dev/null +++ b/resources/css/themes/tailwind/components/button.css @@ -0,0 +1,27 @@ +.alert-button.primary { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-900 focus:ring-offset-2 bg-neutral-950 hover:bg-neutral-900; +} +.alert-button.secondary { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium transition-colors border rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-100 focus:ring-offset-2; +} +.alert-button.success { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-green-700 focus:ring-offset-2 bg-green-600 hover:bg-green-700; +} +.alert-button.error { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-red-700 focus:ring-offset-2 bg-red-600 hover:bg-red-700; +} +.alert-button.warning { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-black transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-yellow-600 focus:ring-offset-2 bg-yellow-400 hover:bg-yellow-500; +} +.alert-button.info { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-blue-700 focus:ring-offset-2 bg-blue-600 hover:bg-blue-700; +} +.alert-button.light { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-black transition-colors border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-300 focus:ring-offset-2 bg-white hover:bg-gray-100; +} +.alert-button.dark { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-gray-900 focus:ring-offset-2 bg-gray-800 hover:bg-gray-900; +} +.alert-button.link { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-blue-600 transition-colors rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 hover:underline; +} diff --git a/resources/css/themes/tailwind/components/field.css b/resources/css/themes/tailwind/components/field.css new file mode 100644 index 00000000..cb5c5ee9 --- /dev/null +++ b/resources/css/themes/tailwind/components/field.css @@ -0,0 +1,12 @@ +.alert-field.success { + @apply p-3 text-green-800; +} +.alert-field.error { + @apply p-3 text-red-800; +} +.alert-field.warning { + @apply p-3 text-yellow-800; +} +.alert-field.info { + @apply p-3 text-blue-800; +} diff --git a/resources/css/themes/tailwind/components/message.css b/resources/css/themes/tailwind/components/message.css new file mode 100644 index 00000000..2f1f0777 --- /dev/null +++ b/resources/css/themes/tailwind/components/message.css @@ -0,0 +1,48 @@ +.alert-message { + @apply flex items-center p-4 mb-4 rounded-lg; +} +.alert-message .sr-only-fix { + @apply sr-only; +} +.alert-message.success { + @apply text-green-800 bg-green-50 dark:bg-gray-800 dark:text-green-400; +} +.alert-message.error { + @apply text-red-800 bg-red-50 dark:bg-gray-800 dark:text-red-400; +} +.alert-message.warning { + @apply text-yellow-800 bg-yellow-50 dark:bg-gray-800 dark:text-yellow-300; +} +.alert-message.info { + @apply text-blue-800 bg-blue-50 dark:bg-gray-800 dark:text-blue-400; +} +.alert-message .icon { + @apply shrink-0 w-4 h-4; +} +.alert-message .message { + @apply ms-3 text-sm font-medium flex items-center gap-2; +} +.alert-message .message .title { + @apply text-lg font-semibold; +} +.alert-message .close { + @apply ms-auto -mx-1.5 -my-1.5 p-1.5 inline-flex items-center justify-center h-8 w-8 rounded-lg focus:ring-2; +} +.alert-message .close.success { + @apply bg-blue-50 text-blue-500 focus:ring-blue-400 hover:bg-blue-200 dark:bg-gray-800 dark:text-blue-400 dark:hover:bg-gray-700; +} +.alert-message .close.error { + @apply bg-red-50 text-red-500 focus:ring-red-400 hover:bg-red-200 dark:bg-gray-800 dark:text-red-400 dark:hover:bg-gray-700; +} +.alert-message .close.warning { + @apply bg-yellow-50 text-yellow-500 focus:ring-yellow-400 hover:bg-yellow-200 dark:bg-gray-800 dark:text-yellow-400 dark:hover:bg-gray-700; +} +.alert-message .close.info { + @apply bg-blue-50 text-blue-500 focus:ring-blue-400 hover:bg-blue-200 dark:bg-gray-800 dark:text-blue-400 dark:hover:bg-gray-700; +} +.alert-message .close .close-icon { + @apply w-3 h-3; +} +.alert-message .close .sr-only-fix { + @apply sr-only; +} diff --git a/resources/css/themes/tailwind/components/modal.css b/resources/css/themes/tailwind/components/modal.css new file mode 100644 index 00000000..25b9a0f3 --- /dev/null +++ b/resources/css/themes/tailwind/components/modal.css @@ -0,0 +1,63 @@ +.alert-modal { + @apply fixed top-0 left-0 z-[99] flex items-center justify-center w-screen h-screen; +} +.alert-modal .modal-overlay { + @apply absolute inset-0 w-full h-full bg-white backdrop-blur-sm bg-opacity-70; +} +.alert-modal .modal-content { + @apply bg-white p-6 rounded-lg shadow-lg relative max-w-full; +} +.alert-modal .modal-content.small { + @apply w-1/4; +} +.alert-modal .modal-content.medium { + @apply w-1/2; +} +.alert-modal .modal-content.large { + @apply w-3/4; +} +.alert-modal .modal-content.extra-large { + @apply w-4/5; +} +.alert-modal .modal-content.fullscreen { + @apply w-full h-full; +} +.alert-modal .modal-content.scrollable { + @apply max-h-[80vh] overflow-y-auto; +} +.alert-modal .modal-header { + @apply flex items-center justify-between pb-3; +} +.alert-modal .modal-header.text-success { + @apply text-green-500; +} +.alert-modal .modal-header.text-error { + @apply text-red-500; +} +.alert-modal .modal-header.text-warning { + @apply text-yellow-500; +} +.alert-modal .modal-header.text-info { + @apply text-blue-500; +} +.alert-modal .modal-header .modal-title { + @apply text-lg font-semibold; +} +.alert-modal .modal-header .modal-close { + @apply absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5 text-gray-600 rounded-full hover:text-gray-800 hover:bg-gray-50; +} +.alert-modal .modal-header .modal-close-icon { + @apply w-5 h-5; +} +.alert-modal .modal-body { + @apply relative w-auto pb-8; +} +.alert-modal .modal-footer { + @apply flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2; +} +.alert-modal .modal-footer .modal-action-button { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-900 focus:ring-offset-2 bg-neutral-950 hover:bg-neutral-900; +} +.alert-modal .modal-footer .modal-cancel-button { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium transition-colors border rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-100 focus:ring-offset-2; +} diff --git a/resources/css/themes/tailwind/components/notify.css b/resources/css/themes/tailwind/components/notify.css new file mode 100644 index 00000000..00092304 --- /dev/null +++ b/resources/css/themes/tailwind/components/notify.css @@ -0,0 +1,36 @@ +.alert-notify { + @apply bg-gray-900 bg-gradient-to-r text-white rounded-t mb-3 shadow-lg flex items-center; +} +.alert-notify.success { + @apply from-green-400 to-green-500; +} +.alert-notify.error { + @apply from-red-400 to-pink-500; +} +.alert-notify.warning { + @apply from-yellow-400 to-yellow-500; +} +.alert-notify.info { + @apply from-blue-400 to-blue-500; +} +.alert-notify.top-right { + @apply top-0 right-0; +} +.alert-notify.top-left { + @apply top-0 left-0; +} +.alert-notify.bottom-right { + @apply bottom-0 right-0; +} +.alert-notify.bottom-left { + @apply bottom-0 left-0; +} +.alert-notify.top-center { + @apply top-0 left-1/2 transform -translate-x-1/2; +} +.alert-notify.bottom-center { + @apply bottom-0 left-1/2 transform -translate-x-1/2; +} +.alert-notify.center { + @apply top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2; +} diff --git a/resources/css/themes/tailwind/components/position.css b/resources/css/themes/tailwind/components/position.css new file mode 100644 index 00000000..05acb563 --- /dev/null +++ b/resources/css/themes/tailwind/components/position.css @@ -0,0 +1,24 @@ +.alert-notify-position { + @apply fixed px-2 mt-3 overflow-x-hidden z-50; +} +.alert-notify-position.top-right { + @apply top-0 right-0; +} +.alert-notify-position.top-left { + @apply top-0 left-0; +} +.alert-notify-position.bottom-right { + @apply bottom-0 right-0; +} +.alert-notify-position.bottom-left { + @apply bottom-0 left-0; +} +.alert-notify-position.top-center { + @apply top-0 left-1/2 transform -translate-x-1/2; +} +.alert-notify-position.bottom-center { + @apply bottom-0 left-1/2 transform -translate-x-1/2; +} +.alert-notify-position.center { + @apply top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2; +} diff --git a/resources/js/alert.js b/resources/js/alert.js deleted file mode 100644 index b540dc8b..00000000 --- a/resources/js/alert.js +++ /dev/null @@ -1,6 +0,0 @@ -import '../scss/alert.scss' - -export { default as Alert } from './src/alert.js' -export { default as Button } from './src/button.js' -export { default as Modal } from './src/modal.js' -export { default as Toast } from './src/toast.js' \ No newline at end of file diff --git a/resources/js/src/alert.js b/resources/js/src/alert.js deleted file mode 100644 index 7cc105bc..00000000 --- a/resources/js/src/alert.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * -------------------------------------------------------------------------- - * alert.js - * -------------------------------------------------------------------------- - */ - -import BaseComponent from './base-component.js' -import EventHandler from './dom/event-handler.js' -import { enableDismissTrigger } from './util/component-functions.js' -import { defineJQueryPlugin } from './util/index.js' - -/** - * Constants - */ - -const NAME = 'alert' -const DATA_KEY = 'dl.alert' -const EVENT_KEY = `.${DATA_KEY}` - -const EVENT_CLOSE = `close${EVENT_KEY}` -const EVENT_CLOSED = `closed${EVENT_KEY}` -const CLASS_NAME_FADE = 'fade' -const CLASS_NAME_SHOW = 'show' - -/** - * Class definition - */ - -class Alert extends BaseComponent { - // Getters - static get NAME() { - return NAME - } - - // Public - close() { - const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE) - - if (closeEvent.defaultPrevented) { - return - } - - this._element.classList.remove(CLASS_NAME_SHOW) - - const isAnimated = this._element.classList.contains(CLASS_NAME_FADE) - this._queueCallback(() => this._destroyElement(), this._element, isAnimated) - } - - // Private - _destroyElement() { - this._element.remove() - EventHandler.trigger(this._element, EVENT_CLOSED) - this.dispose() - } - - // Static - static jQueryInterface(config) { - return this.each(function () { - const data = Alert.getOrCreateInstance(this) - - if (typeof config !== 'string') { - return - } - - if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { - throw new TypeError(`No method named "${config}"`) - } - - data[config](this) - }) - } -} - -/** - * Data API implementation - */ - -enableDismissTrigger(Alert, 'close') - -/** - * jQuery - */ - -defineJQueryPlugin(Alert) - -export default Alert diff --git a/resources/js/src/base-component.js b/resources/js/src/base-component.js deleted file mode 100644 index 70f51f85..00000000 --- a/resources/js/src/base-component.js +++ /dev/null @@ -1,78 +0,0 @@ -import Data from './dom/data.js' -import EventHandler from './dom/event-handler.js' -import Config from './util/config.js' -import { executeAfterTransition, getElement } from './util/index.js' - -/** - * Constants - */ - -const VERSION = '5.3.3' - -/** - * Class definition - */ - -class BaseComponent extends Config { - constructor(element, config) { - super() - - element = getElement(element) - if (!element) { - return - } - - this._element = element - this._config = this._getConfig(config) - - Data.set(this._element, this.constructor.DATA_KEY, this) - } - - // Public - dispose() { - Data.remove(this._element, this.constructor.DATA_KEY) - EventHandler.off(this._element, this.constructor.EVENT_KEY) - - for (const propertyName of Object.getOwnPropertyNames(this)) { - this[propertyName] = null - } - } - - _queueCallback(callback, element, isAnimated = true) { - executeAfterTransition(callback, element, isAnimated) - } - - _getConfig(config) { - config = this._mergeConfigObj(config, this._element) - config = this._configAfterMerge(config) - this._typeCheckConfig(config) - return config - } - - // Static - static getInstance(element) { - return Data.get(getElement(element), this.DATA_KEY) - } - - static getOrCreateInstance(element, config = {}) { - return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null) - } - - static get VERSION() { - return VERSION - } - - static get DATA_KEY() { - return `dl.${this.NAME}` - } - - static get EVENT_KEY() { - return `.${this.DATA_KEY}` - } - - static eventName(name) { - return `${name}${this.EVENT_KEY}` - } -} - -export default BaseComponent diff --git a/resources/js/src/button.js b/resources/js/src/button.js deleted file mode 100644 index 23d4b2b1..00000000 --- a/resources/js/src/button.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * -------------------------------------------------------------------------- - * button.js - * -------------------------------------------------------------------------- - */ - -import BaseComponent from './base-component.js' -import EventHandler from './dom/event-handler.js' -import { defineJQueryPlugin } from './util/index.js' - -/** - * Constants - */ - -const NAME = 'button' -const DATA_KEY = 'dl.button' -const EVENT_KEY = `.${DATA_KEY}` -const DATA_API_KEY = '.data-api' - -const CLASS_NAME_ACTIVE = 'active' -const SELECTOR_DATA_TOGGLE = '[data-dl-toggle="button"]' -const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}` - -/** - * Class definition - */ - -class Button extends BaseComponent { - // Getters - static get NAME() { - return NAME - } - - // Public - toggle() { - // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method - this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE)) - } - - // Static - static jQueryInterface(config) { - return this.each(function () { - const data = Button.getOrCreateInstance(this) - - if (config === 'toggle') { - data[config]() - } - }) - } -} - -/** - * Data API implementation - */ - -EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, event => { - event.preventDefault() - - const button = event.target.closest(SELECTOR_DATA_TOGGLE) - const data = Button.getOrCreateInstance(button) - - data.toggle() -}) - -/** - * jQuery - */ - -defineJQueryPlugin(Button) - -export default Button diff --git a/resources/js/src/dom/data.js b/resources/js/src/dom/data.js deleted file mode 100644 index 4d51412a..00000000 --- a/resources/js/src/dom/data.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * -------------------------------------------------------------------------- - * dom/data.js - * -------------------------------------------------------------------------- - */ - -/** - * Constants - */ - -const elementMap = new Map() - -export default { - set(element, key, instance) { - if (!elementMap.has(element)) { - elementMap.set(element, new Map()) - } - - const instanceMap = elementMap.get(element) - - // make it clear we only want one instance per element - // can be removed later when multiple key/instances are fine to be used - if (!instanceMap.has(key) && instanceMap.size !== 0) { - // eslint-disable-next-line no-console - console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`) - return - } - - instanceMap.set(key, instance) - }, - - get(element, key) { - if (elementMap.has(element)) { - return elementMap.get(element).get(key) || null - } - - return null - }, - - remove(element, key) { - if (!elementMap.has(element)) { - return - } - - const instanceMap = elementMap.get(element) - - instanceMap.delete(key) - - // free up element references if there are no instances left for an element - if (instanceMap.size === 0) { - elementMap.delete(element) - } - } -} diff --git a/resources/js/src/dom/event-handler.js b/resources/js/src/dom/event-handler.js deleted file mode 100644 index a0e4f2d2..00000000 --- a/resources/js/src/dom/event-handler.js +++ /dev/null @@ -1,316 +0,0 @@ -/** - * -------------------------------------------------------------------------- - * dom/event-handler.js - * -------------------------------------------------------------------------- - */ - -import { getjQuery } from '../util/index.js' - -/** - * Constants - */ - -const namespaceRegex = /[^.]*(?=\..*)\.|.*/ -const stripNameRegex = /\..*/ -const stripUidRegex = /::\d+$/ -const eventRegistry = {} // Events storage -let uidEvent = 1 -const customEvents = { - mouseenter: 'mouseover', - mouseleave: 'mouseout' -} - -const nativeEvents = new Set([ - 'click', - 'dblclick', - 'mouseup', - 'mousedown', - 'contextmenu', - 'mousewheel', - 'DOMMouseScroll', - 'mouseover', - 'mouseout', - 'mousemove', - 'selectstart', - 'selectend', - 'keydown', - 'keypress', - 'keyup', - 'orientationchange', - 'touchstart', - 'touchmove', - 'touchend', - 'touchcancel', - 'pointerdown', - 'pointermove', - 'pointerup', - 'pointerleave', - 'pointercancel', - 'gesturestart', - 'gesturechange', - 'gestureend', - 'focus', - 'blur', - 'change', - 'reset', - 'select', - 'submit', - 'focusin', - 'focusout', - 'load', - 'unload', - 'beforeunload', - 'resize', - 'move', - 'DOMContentLoaded', - 'readystatechange', - 'error', - 'abort', - 'scroll' -]) - -/** - * Private methods - */ - -function makeEventUid(element, uid) { - return (uid && `${uid}::${uidEvent++}`) || element.uidEvent || uidEvent++ -} - -function getElementEvents(element) { - const uid = makeEventUid(element) - - element.uidEvent = uid - eventRegistry[uid] = eventRegistry[uid] || {} - - return eventRegistry[uid] -} - -function bootstrapHandler(element, fn) { - return function handler(event) { - hydrateObj(event, { delegateTarget: element }) - - if (handler.oneOff) { - EventHandler.off(element, event.type, fn) - } - - return fn.apply(element, [event]) - } -} - -function bootstrapDelegationHandler(element, selector, fn) { - return function handler(event) { - const domElements = element.querySelectorAll(selector) - - for (let { target } = event; target && target !== this; target = target.parentNode) { - for (const domElement of domElements) { - if (domElement !== target) { - continue - } - - hydrateObj(event, { delegateTarget: target }) - - if (handler.oneOff) { - EventHandler.off(element, event.type, selector, fn) - } - - return fn.apply(target, [event]) - } - } - } -} - -function findHandler(events, callable, delegationSelector = null) { - return Object.values(events) - .find(event => event.callable === callable && event.delegationSelector === delegationSelector) -} - -function normalizeParameters(originalTypeEvent, handler, delegationFunction) { - const isDelegated = typeof handler === 'string' - // TODO: tooltip passes `false` instead of selector, so we need to check - const callable = isDelegated ? delegationFunction : (handler || delegationFunction) - let typeEvent = getTypeEvent(originalTypeEvent) - - if (!nativeEvents.has(typeEvent)) { - typeEvent = originalTypeEvent - } - - return [isDelegated, callable, typeEvent] -} - -function addHandler(element, originalTypeEvent, handler, delegationFunction, oneOff) { - if (typeof originalTypeEvent !== 'string' || !element) { - return - } - - let [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction) - - // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position - // this prevents the handler from being dispatched the same way as mouseover or mouseout does - if (originalTypeEvent in customEvents) { - const wrapFunction = fn => { - return function (event) { - if (!event.relatedTarget || (event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget))) { - return fn.call(this, event) - } - } - } - - callable = wrapFunction(callable) - } - - const events = getElementEvents(element) - const handlers = events[typeEvent] || (events[typeEvent] = {}) - const previousFunction = findHandler(handlers, callable, isDelegated ? handler : null) - - if (previousFunction) { - previousFunction.oneOff = previousFunction.oneOff && oneOff - - return - } - - const uid = makeEventUid(callable, originalTypeEvent.replace(namespaceRegex, '')) - const fn = isDelegated ? - bootstrapDelegationHandler(element, handler, callable) : - bootstrapHandler(element, callable) - - fn.delegationSelector = isDelegated ? handler : null - fn.callable = callable - fn.oneOff = oneOff - fn.uidEvent = uid - handlers[uid] = fn - - element.addEventListener(typeEvent, fn, isDelegated) -} - -function removeHandler(element, events, typeEvent, handler, delegationSelector) { - const fn = findHandler(events[typeEvent], handler, delegationSelector) - - if (!fn) { - return - } - - element.removeEventListener(typeEvent, fn, Boolean(delegationSelector)) - delete events[typeEvent][fn.uidEvent] -} - -function removeNamespacedHandlers(element, events, typeEvent, namespace) { - const storeElementEvent = events[typeEvent] || {} - - for (const [handlerKey, event] of Object.entries(storeElementEvent)) { - if (handlerKey.includes(namespace)) { - removeHandler(element, events, typeEvent, event.callable, event.delegationSelector) - } - } -} - -function getTypeEvent(event) { - // allow to get the native events from namespaced events ('click.dl.button' --> 'click') - event = event.replace(stripNameRegex, '') - return customEvents[event] || event -} - -const EventHandler = { - on(element, event, handler, delegationFunction) { - addHandler(element, event, handler, delegationFunction, false) - }, - - one(element, event, handler, delegationFunction) { - addHandler(element, event, handler, delegationFunction, true) - }, - - off(element, originalTypeEvent, handler, delegationFunction) { - if (typeof originalTypeEvent !== 'string' || !element) { - return - } - - const [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction) - const inNamespace = typeEvent !== originalTypeEvent - const events = getElementEvents(element) - const storeElementEvent = events[typeEvent] || {} - const isNamespace = originalTypeEvent.startsWith('.') - - if (typeof callable !== 'undefined') { - // Simplest case: handler is passed, remove that listener ONLY. - if (!Object.keys(storeElementEvent).length) { - return - } - - removeHandler(element, events, typeEvent, callable, isDelegated ? handler : null) - return - } - - if (isNamespace) { - for (const elementEvent of Object.keys(events)) { - removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1)) - } - } - - for (const [keyHandlers, event] of Object.entries(storeElementEvent)) { - const handlerKey = keyHandlers.replace(stripUidRegex, '') - - if (!inNamespace || originalTypeEvent.includes(handlerKey)) { - removeHandler(element, events, typeEvent, event.callable, event.delegationSelector) - } - } - }, - - trigger(element, event, args) { - if (typeof event !== 'string' || !element) { - return null - } - - const $ = getjQuery() - const typeEvent = getTypeEvent(event) - const inNamespace = event !== typeEvent - - let jQueryEvent = null - let bubbles = true - let nativeDispatch = true - let defaultPrevented = false - - if (inNamespace && $) { - jQueryEvent = $.Event(event, args) - - $(element).trigger(jQueryEvent) - bubbles = !jQueryEvent.isPropagationStopped() - nativeDispatch = !jQueryEvent.isImmediatePropagationStopped() - defaultPrevented = jQueryEvent.isDefaultPrevented() - } - - const evt = hydrateObj(new Event(event, { bubbles, cancelable: true }), args) - - if (defaultPrevented) { - evt.preventDefault() - } - - if (nativeDispatch) { - element.dispatchEvent(evt) - } - - if (evt.defaultPrevented && jQueryEvent) { - jQueryEvent.preventDefault() - } - - return evt - } -} - -function hydrateObj(obj, meta = {}) { - for (const [key, value] of Object.entries(meta)) { - try { - obj[key] = value - } catch { - Object.defineProperty(obj, key, { - configurable: true, - get() { - return value - } - }) - } - } - - return obj -} - -export default EventHandler diff --git a/resources/js/src/dom/manipulator.js b/resources/js/src/dom/manipulator.js deleted file mode 100644 index bc18f412..00000000 --- a/resources/js/src/dom/manipulator.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - * -------------------------------------------------------------------------- - * dom/manipulator.js - * -------------------------------------------------------------------------- - */ - -function normalizeData(value) { - if (value === 'true') { - return true - } - - if (value === 'false') { - return false - } - - if (value === Number(value).toString()) { - return Number(value) - } - - if (value === '' || value === 'null') { - return null - } - - if (typeof value !== 'string') { - return value - } - - try { - return JSON.parse(decodeURIComponent(value)) - } catch { - return value - } -} - -function normalizeDataKey(key) { - return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`) -} - -const Manipulator = { - setDataAttribute(element, key, value) { - element.setAttribute(`data-dl-${normalizeDataKey(key)}`, value) - }, - - removeDataAttribute(element, key) { - element.removeAttribute(`data-dl-${normalizeDataKey(key)}`) - }, - - getDataAttributes(element) { - if (!element) { - return {} - } - - const attributes = {} - const dlKeys = Object.keys(element.dataset).filter(key => key.startsWith('dl') && !key.startsWith('dlConfig')) - - for (const key of dlKeys) { - let pureKey = key.replace(/^dl/, '') - pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1) - attributes[pureKey] = normalizeData(element.dataset[key]) - } - - return attributes - }, - - getDataAttribute(element, key) { - return normalizeData(element.getAttribute(`data-dl-${normalizeDataKey(key)}`)) - } -} - -export default Manipulator diff --git a/resources/js/src/dom/selector-engine.js b/resources/js/src/dom/selector-engine.js deleted file mode 100644 index b50d6805..00000000 --- a/resources/js/src/dom/selector-engine.js +++ /dev/null @@ -1,125 +0,0 @@ -/** - * -------------------------------------------------------------------------- - * dom/selector-engine.js - * -------------------------------------------------------------------------- - */ - -import { isDisabled, isVisible, parseSelector } from '../util/index.js' - -const getSelector = element => { - let selector = element.getAttribute('data-dl-target') - - if (!selector || selector === '#') { - let hrefAttribute = element.getAttribute('href') - - // The only valid content that could double as a selector are IDs or classes, - // so everything starting with `#` or `.`. If a "real" URL is used as the selector, - // `document.querySelector` will rightfully complain it is invalid. - // See https://github.com/twdl/bootstrap/issues/32273 - if (!hrefAttribute || (!hrefAttribute.includes('#') && !hrefAttribute.startsWith('.'))) { - return null - } - - // Just in case some CMS puts out a full URL with the anchor appended - if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) { - hrefAttribute = `#${hrefAttribute.split('#')[1]}` - } - - selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null - } - - return selector ? selector.split(',').map(sel => parseSelector(sel)).join(',') : null -} - -const SelectorEngine = { - find(selector, element = document.documentElement) { - return [].concat(...Element.prototype.querySelectorAll.call(element, selector)) - }, - - findOne(selector, element = document.documentElement) { - return Element.prototype.querySelector.call(element, selector) - }, - - children(element, selector) { - return [].concat(...element.children).filter(child => child.matches(selector)) - }, - - parents(element, selector) { - const parents = [] - let ancestor = element.parentNode.closest(selector) - - while (ancestor) { - parents.push(ancestor) - ancestor = ancestor.parentNode.closest(selector) - } - - return parents - }, - - prev(element, selector) { - let previous = element.previousElementSibling - - while (previous) { - if (previous.matches(selector)) { - return [previous] - } - - previous = previous.previousElementSibling - } - - return [] - }, - // TODO: this is now unused; remove later along with prev() - next(element, selector) { - let next = element.nextElementSibling - - while (next) { - if (next.matches(selector)) { - return [next] - } - - next = next.nextElementSibling - } - - return [] - }, - - focusableChildren(element) { - const focusables = [ - 'a', - 'button', - 'input', - 'textarea', - 'select', - 'details', - '[tabindex]', - '[contenteditable="true"]' - ].map(selector => `${selector}:not([tabindex^="-"])`).join(',') - - return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el)) - }, - - getSelectorFromElement(element) { - const selector = getSelector(element) - - if (selector) { - return SelectorEngine.findOne(selector) ? selector : null - } - - return null - }, - - getElementFromSelector(element) { - const selector = getSelector(element) - - return selector ? SelectorEngine.findOne(selector) : null - }, - - getMultipleElementsFromSelector(element) { - const selector = getSelector(element) - - return selector ? SelectorEngine.find(selector) : [] - } -} - -export default SelectorEngine diff --git a/resources/js/src/modal.js b/resources/js/src/modal.js deleted file mode 100644 index a37e0087..00000000 --- a/resources/js/src/modal.js +++ /dev/null @@ -1,68 +0,0 @@ -class Modal { - constructor(trigger, options = {}) { - this.options = { - size: options.size || "medium", - position: options.position || "center", - content: options.content || "This is a modal", - }; - this.trigger = trigger; - this.modal = document.querySelector(`[data-modal=${trigger}]`); - this.init(); - } - - init() { - if (!this.modal) { - console.error(`Modal with trigger [data-modal=${this.trigger}] not found.`); - return; - } - - console.log('modal', this.modal); - const contentWrapper = this.modal.querySelector('.content-wrapper'); - const close = this.modal.querySelector('.close'); - - if (close) { - close.addEventListener('click', () => this.close()); - } - - this.modal.addEventListener('click', () => this.close()); - - if (contentWrapper) { - contentWrapper.addEventListener('click', (e) => e.stopPropagation()); - } - } - - open() { - if (this.modal) { - this.modal.classList.add("open"); - } - } - - close() { - if (this.modal) { - this.modal.classList.remove("open"); - } - } - - toggle() { - if (this.modal) { - this.modal.classList.toggle("open"); - } - } - - resize(size) { - if (this.modal) { - this.modal.classList.remove("small", "medium", "large"); - this.modal.classList.add(size); - } - } - - reposition(position) { - if (this.modal) { - this.modal.classList.remove("top", "bottom", "left", "right", "center"); - this.modal.classList.add(position); - } - } -} - -// Exporting module -export default Modal; diff --git a/resources/js/src/toast.js b/resources/js/src/toast.js deleted file mode 100644 index ed897907..00000000 --- a/resources/js/src/toast.js +++ /dev/null @@ -1,605 +0,0 @@ -class Toast -{ - $container; - previousToast; - listener; - toastId = 0; - toastType = { - error: 'error', - info: 'info', - success: 'success', - warning: 'warning' - }; - - constructor() { - this.init(); - } - - init() { - const toasts = document.querySelectorAll('.toastr'); - - toasts.forEach(toastr => { - const id = toastr.getAttribute('id'); - const toast = this.firstEl('.toast'); - - if (!id || !toast) { - console.error('Toast not found.'); - return; - } - - const progress = this.firstEl('.toast-progress', toast); - const close = this.firstEl('.toast-close-button', toast); - const title = this.firstEl('.toast-title', toast)?.innerText ?? ''; - const message = this.firstEl('.toast-message', toast)?.innerText ?? ''; - const type = this.getToastType(toast) ?? 'info'; - const iconClass = this.getOptions().iconClasses[type]; - - this.$container = toast - - this.notify({ - iconClass, - type, - message, - title, - optionsOverride: { - containerId: id, - } - }); - }); - } - - getToastType(element) { - if (element.classList.contains('toast-success')) return 'success'; - if (element.classList.contains('toast-error')) return 'error'; - if (element.classList.contains('toast-info')) return 'info'; - if (element.classList.contains('toast-warning')) return 'warning'; - return 'info'; // Default type - } - - closeBtnEl() { - const button = document.createElement("button"); - - button.setAttribute("type", "button"); - - button.innerHTML = "×"; - - return button; - } - - fadeOut(el, duration, callback) { - el.style.opacity = 1; - (function fade() { - if ((el.style.opacity -= .1) < 0) { - el.style.display = "none"; - } else { - requestAnimationFrame(fade); - callback(); - } - })(); - }; - - fadeIn(el, duration) { - el.style.opacity = 0; - - const increment = 1 / (duration / 16); - - (function fade() { - let val = parseFloat(el.style.opacity); - - if (!((val += increment) > 1)) { - el.style.opacity = val; - requestAnimationFrame(fade); - } - })(); - }; - - el(selector, context = document) { - if(selector.startsWith('.')) { - return context.getElementsByClassName(selector.substring(1)); - } - - if(selector.startsWith('<') && selector.endsWith('>')) { - return context.createElement(selector.substring(1, selector.length - 2)); - } - - if(selector.startsWith('#')) { - return context.getElementById(selector.substring(1)); - } - - return context.querySelector(selector); - } - - firstEl(selector, context = document) { - return this.el(selector, context)[0] ?? null; - } - - toastr() { - return { - clear: this.clear, - remove: this.remove, - error: this.error, - getContainer: this.getContainer, - info: this.info, - options: {}, - subscribe: this.subscribe, - success: this.success, - version: '1.0.0', - warning: this.warning - } - } - - error(message, title, optionsOverride) { - return this.notify({ - type: this.toastType.error, - iconClass: this.getOptions().iconClasses.error, - message: message, - optionsOverride: optionsOverride, - title: title - }); - } - - getContainer(options, create) { - if (!options) { options = this.getOptions(); } - this.$container = this.$container ?? document.getElementById(options.containerId); - - if (this.$container) { - return this.$container; - } - - if (create) { - this.$container = this.createContainer(options); - } - return this.$container; - } - - info(message, title, optionsOverride) { - return this.notify({ - type: this.toastType.info, - iconClass: this.getOptions().iconClasses.info, - message: message, - optionsOverride: optionsOverride, - title: title - }); - } - - subscribe(callback) { - this.listener = callback; - } - - success(message, title, optionsOverride) { - return this.notify({ - type: this.toastType.success, - iconClass: this.getOptions().iconClasses.success, - message: message, - optionsOverride: optionsOverride, - title: title - }); - } - - warning(message, title, optionsOverride) { - return this.notify({ - type: this.toastType.warning, - iconClass: this.getOptions().iconClasses.warning, - message: message, - optionsOverride: optionsOverride, - title: title - }); - } - - clear($toastElement, clearOptions) - { - const options = this.getOptions(); - - if (!this.$container) { - this.getContainer(options); - } - - if (!this.clearToast($toastElement, options, clearOptions)) { - this.clearContainer(options); - } - } - - remove($toastElement) { - let options = this.getOptions(); - if (!this.$container) { - this.getContainer(options); - } - - if ($toastElement && this.el(':focus', $toastElement).length === 0) { - this.removeToast($toastElement); - return; - } - - if (this.$container.children().length) { - this.$container.remove(); - } - } - - // internal functions - - clearContainer (options) { - const toastsToClear = this.$container.children(); - for (let i = toastsToClear.length - 1; i >= 0; i--) { - this.clearToast(this.el(toastsToClear[i]), options); - } - } - - clearToast ($toastElement, options, clearOptions) { - let force = clearOptions && clearOptions.force ? clearOptions.force : false; - if ($toastElement && (force || this.el(':focus', $toastElement).length === 0)) { - $toastElement[options.hideMethod]({ - duration: options.hideDuration, - easing: options.hideEasing, - complete: () =>{ - this.removeToast($toastElement); - } - }); - return true; - } - return false; - } - - createContainer(options) { - this.$container = this.el('
'); - this.$container.setAttribute('id', options.containerId); - this.$container.classList.add(options.positionClass); - - this.el(options.target).appendChild(this.$container); - return this.$container; - } - - getDefaults() { - return { - tapToDismiss: true, - toastClass: 'toast', - containerId: 'toast-container', - debug: false, - - showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery - showDuration: 300, - showEasing: 'swing', //swing and linear are built into jQuery - onShown: undefined, - hideMethod: 'fadeOut', - hideDuration: 1000, - hideEasing: 'swing', - onHidden: undefined, - closeMethod: false, - closeDuration: false, - closeEasing: false, - closeOnHover: true, - - extendedTimeOut: 1000, - iconClasses: { - error: 'toast-error', - info: 'toast-info', - success: 'toast-success', - warning: 'toast-warning' - }, - iconClass: 'toast-info', - positionClass: 'toast-top-right', - timeOut: 5000, // Set timeOut and extendedTimeOut to 0 to make it sticky - titleClass: 'toast-title', - messageClass: 'toast-message', - escapeHtml: false, - target: 'body', - closeHtml: '', - closeClass: 'toast-close-button', - newestOnTop: true, - preventDuplicates: false, - progressBar: false, - progressClass: 'toast-progress', - rtl: false - }; - } - - publish(args) { - if (!this.listener) { return; } - this.listener(args); - } - - notify(map) - { - let options = this.getOptions(); - let iconClass = map.iconClass || options.iconClass; - - if (typeof (map.optionsOverride) !== 'undefined') { - options = Object.assign(options, map.optionsOverride); - iconClass = map.optionsOverride.iconClass || iconClass; - } - - if (this.shouldExit(options, map)) { - return; - } - - this.toastId++; - this.$container = this.getContainer(options, true); - - let intervalId = null; - let $toastElement = this.el('
'); - let $titleElement = this.el('
'); - let $messageElement = this.el('
'); - let $progressElement = this.el('
'); - let $closeElement = this.closeBtnEl(); - let progressBar = { - intervalId: null, - hideEta: null, - maxHideTime: null - }; - let response = { - toastId: this.toastId, - state: 'visible', - startTime: new Date(), - options: options, - map: map - }; - - // personalize toast - this.setIcon(options, map, $toastElement); - this.setTitle(options, map, $titleElement, $toastElement); - this.setMessage(options, map, $messageElement, $toastElement); - this.setCloseButton(options, $toastElement, $closeElement); - this.setProgressBar(options, $toastElement, $progressElement); - this.setRTL(options, $toastElement); - this.setSequence(options, $toastElement); - this.setAria(map, $toastElement); - - this.displayToast(options, $toastElement, intervalId, progressBar, response); - - this.handleEvents(options, $toastElement, $closeElement, intervalId, progressBar, response); - - this.publish(response); - - // console.log(response); - - return $toastElement; - } - - - //-------------------------- - escapeHtml(source) { - if (source == null) { - source = ''; - } - - return source - .replace(/&/g, '&') - .replace(/"/g, '"') - .replace(/'/g, ''') - .replace(//g, '>'); - } - - - setAria(map, $toastElement) { - let ariaValue = ''; - switch (map.iconClass) { - case 'toast-success': - case 'toast-info': - ariaValue = 'polite'; - break; - default: - ariaValue = 'assertive'; - } - - $toastElement.setAttribute('aria-live', ariaValue); - - return $toastElement; - } - - handleEvents(options, $toastElement, $closeElement, intervalId, progressBar, response) - { - if (options.closeOnHover) { - $toastElement.addEventListener( - "mouseleave", - () => this.delayedHideToast(null, options, $toastElement, intervalId, progressBar, response) - ); - } - - if (!options.onclick && options.tapToDismiss) { - $toastElement.addEventListener( - 'click', - () => this.hideToast(null, options, $toastElement, intervalId, progressBar, response) - ); - } - - if (options.closeButton && $closeElement) { - $closeElement.click((event) => { - if (event.stopPropagation) { - event.stopPropagation(); - } else if (event.cancelBubble !== undefined && event.cancelBubble !== true) { - event.cancelBubble = true; - } - - if (options.onCloseClick) { - options.onCloseClick(event); - } - - // this.hideToast(true, options, $toastElement, intervalId, progressBar, response); // TODO: used arrow function to bind this - }); - } - - if (options.onclick) { - $toastElement.click((event) => { - options.onclick(event); - this.hideToast(null, options, $toastElement, intervalId, progressBar, response); // TODO: used arrow function to bind this - }); - } - } - - displayToast(options, $toastElement, intervalId, progressBar, response) { - $toastElement.style.display = "none"; - - // $toastElement[options.showMethod]( - // {duration: options.showDuration, easing: options.showEasing, complete: options.onShown} - // ); - - this.fadeIn($toastElement, options.showDuration); - - if (options.timeOut > 0) { - intervalId = setTimeout( - () => this.hideToast(null, options, $toastElement, intervalId, progressBar, response), - options.timeOut - ); - - progressBar.maxHideTime = parseFloat(options.timeOut); - progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime; - if (options.progressBar) { - progressBar.intervalId = setInterval(this.updateProgress, 10); - } - } - } - - setIcon(options, map, $toastElement) { - if (map.iconClass) { - $toastElement.classList.add(options.toastClass); - $toastElement.classList.add(map.iconClass); - } - } - - setSequence(options, $toastElement) { - if (options.newestOnTop) { - this.$container.insertBefore($toastElement, this.$container.firstChild); - } else { - this.$container.appendChild($toastElement); - } - } - - setTitle(options, map, $titleElement, $toastElement) { - if (map.title) { - let suffix = map.title; - if (options.escapeHtml) { - suffix = this.escapeHtml(map.title); - } - - $titleElement.append(suffix); - $titleElement.classList.add(options.titleClass); - $toastElement.append($titleElement); - } - } - - setMessage(options, map, $messageElement, $toastElement) { - if (map.message) { - let suffix = map.message; - if (options.escapeHtml) { - suffix = this.escapeHtml(map.message); - } - - $messageElement.append(suffix); - $messageElement.classList.add(options.messageClass); - $toastElement.append($messageElement); - } - } - - setCloseButton(options, $toastElement, $closeElement) { - if (options.closeButton) { - $closeElement.classList.add(options.closeClass); - $closeElement.setAttribute('role', 'button'); - $toastElement.prepend($closeElement); - } - } - - setProgressBar(options, $toastElement, $progressElement,) { - if (options.progressBar) { - $progressElement.classList.add(options.progressClass); - - $toastElement.prepend($progressElement); - } - } - - setRTL(options, $toastElement) { - if (options.rtl) { - $toastElement.classList.add('rtl'); - } - } - - shouldExit(options, map) { - if (options.preventDuplicates) { - if (map.message === this.previousToast) { - return true; - } else { - this.previousToast = map.message; - } - } - return false; - } - - hideToast(override, options, $toastElement, intervalId, progressBar, response) { - let method = override && options.closeMethod !== false ? options.closeMethod : options.hideMethod; - - let duration = override && options.closeDuration !== false ? - options.closeDuration : options.hideDuration; - - let easing = override && options.closeEasing !== false ? options.closeEasing : options.hideEasing; - if ($toastElement.querySelector(':focus') && !override) { - return; - } - - clearTimeout(progressBar.intervalId); - - return this.fadeOut($toastElement, duration, () => { - this.removeToast($toastElement); - - clearTimeout(intervalId); - - if (options.onHidden && response.state !== 'hidden') { - options.onHidden(); - } - - response.state = 'hidden'; - response.endTime = new Date(); - - this.publish(response); - }); - } - - delayedHideToast(override, options, $toastElement, intervalId, progressBar, response) { - if (options.timeOut > 0 || options.extendedTimeOut > 0) { - intervalId = setTimeout( - this.hideToast(override, options, $toastElement, intervalId, progressBar, response), - options.extendedTimeOut - ); - progressBar.maxHideTime = parseFloat(options.extendedTimeOut); - progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime; - } - } - - stickAround() { - clearTimeout(intervalId); - progressBar.hideEta = 0; - $toastElement.stop(true, true)[options.showMethod]( - {duration: options.showDuration, easing: options.showEasing} - ); - } - - updateProgress() { - var percentage = ((progressBar.hideEta - (new Date().getTime())) / progressBar.maxHideTime) * 100; - $progressElement.width(percentage + '%'); - } - //------------------------- - - - - - - - - getOptions() { - return Object.assign({}, this.getDefaults(), this.toastr.options); - } - - removeToast($toastElement) { - if (!this.$container) { - this.$container = this.getContainer(); - } - - $toastElement.remove(); - $toastElement = null; - - if (this.$container) { - this.$container.remove(); - this.previousToast = undefined; - } - } -} - -export default Toast; \ No newline at end of file diff --git a/resources/js/src/util/backdrop.js b/resources/js/src/util/backdrop.js deleted file mode 100644 index d744b030..00000000 --- a/resources/js/src/util/backdrop.js +++ /dev/null @@ -1,150 +0,0 @@ -/** - * -------------------------------------------------------------------------- - * util/backdrop.js - * -------------------------------------------------------------------------- - */ - -import EventHandler from '../dom/event-handler.js' -import Config from './config.js' -import { - execute, executeAfterTransition, getElement, reflow -} from './index.js' - -/** - * Constants - */ - -const NAME = 'backdrop' -const CLASS_NAME_FADE = 'fade' -const CLASS_NAME_SHOW = 'show' -const EVENT_MOUSEDOWN = `mousedown.dl.${NAME}` - -const Default = { - className: 'modal-backdrop', - clickCallback: null, - isAnimated: false, - isVisible: true, // if false, we use the backdrop helper without adding any element to the dom - rootElement: 'body' // give the choice to place backdrop under different elements -} - -const DefaultType = { - className: 'string', - clickCallback: '(function|null)', - isAnimated: 'boolean', - isVisible: 'boolean', - rootElement: '(element|string)' -} - -/** - * Class definition - */ - -class Backdrop extends Config { - constructor(config) { - super() - this._config = this._getConfig(config) - this._isAppended = false - this._element = null - } - - // Getters - static get Default() { - return Default - } - - static get DefaultType() { - return DefaultType - } - - static get NAME() { - return NAME - } - - // Public - show(callback) { - if (!this._config.isVisible) { - execute(callback) - return - } - - this._append() - - const element = this._getElement() - if (this._config.isAnimated) { - reflow(element) - } - - element.classList.add(CLASS_NAME_SHOW) - - this._emulateAnimation(() => { - execute(callback) - }) - } - - hide(callback) { - if (!this._config.isVisible) { - execute(callback) - return - } - - this._getElement().classList.remove(CLASS_NAME_SHOW) - - this._emulateAnimation(() => { - this.dispose() - execute(callback) - }) - } - - dispose() { - if (!this._isAppended) { - return - } - - EventHandler.off(this._element, EVENT_MOUSEDOWN) - - this._element.remove() - this._isAppended = false - } - - // Private - _getElement() { - if (!this._element) { - const backdrop = document.createElement('div') - backdrop.className = this._config.className - if (this._config.isAnimated) { - backdrop.classList.add(CLASS_NAME_FADE) - } - - this._element = backdrop - } - - return this._element - } - - _configAfterMerge(config) { - // use getElement() with the default "body" to get a fresh Element on each instantiation - config.rootElement = getElement(config.rootElement) - return config - } - - _append() { - if (this._isAppended) { - return - } - - const element = this._getElement() - this._config.rootElement.append(element) - - EventHandler.on(element, EVENT_MOUSEDOWN, () => { - execute(this._config.clickCallback) - }) - - this._isAppended = true - } - - _emulateAnimation(callback) { - executeAfterTransition(callback, this._getElement(), this._config.isAnimated) - } -} - -export default Backdrop diff --git a/resources/js/src/util/component-functions.js b/resources/js/src/util/component-functions.js deleted file mode 100644 index bcb6cfdd..00000000 --- a/resources/js/src/util/component-functions.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * -------------------------------------------------------------------------- - * util/component-functions.js - * -------------------------------------------------------------------------- - */ - -import EventHandler from '../dom/event-handler.js' -import SelectorEngine from '../dom/selector-engine.js' -import { isDisabled } from './index.js' - -const enableDismissTrigger = (component, method = 'hide') => { - const clickEvent = `click.dismiss${component.EVENT_KEY}` - const name = component.NAME - - EventHandler.on(document, clickEvent, `[data-dl-dismiss="${name}"]`, function (event) { - if (['A', 'AREA'].includes(this.tagName)) { - event.preventDefault() - } - - if (isDisabled(this)) { - return - } - - const target = SelectorEngine.getElementFromSelector(this) || this.closest(`.${name}`) - const instance = component.getOrCreateInstance(target) - - // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method - instance[method]() - }) -} - -export { - enableDismissTrigger -} diff --git a/resources/js/src/util/config.js b/resources/js/src/util/config.js deleted file mode 100644 index 36e71944..00000000 --- a/resources/js/src/util/config.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * -------------------------------------------------------------------------- - * util/config.js - * -------------------------------------------------------------------------- - */ - -import Manipulator from '../dom/manipulator.js' -import { isElement, toType } from './index.js' - -/** - * Class definition - */ - -class Config { - // Getters - static get Default() { - return {} - } - - static get DefaultType() { - return {} - } - - static get NAME() { - throw new Error('You have to implement the static method "NAME", for each component!') - } - - _getConfig(config) { - config = this._mergeConfigObj(config) - config = this._configAfterMerge(config) - this._typeCheckConfig(config) - return config - } - - _configAfterMerge(config) { - return config - } - - _mergeConfigObj(config, element) { - const jsonConfig = isElement(element) ? Manipulator.getDataAttribute(element, 'config') : {} // try to parse - - return { - ...this.constructor.Default, - ...(typeof jsonConfig === 'object' ? jsonConfig : {}), - ...(isElement(element) ? Manipulator.getDataAttributes(element) : {}), - ...(typeof config === 'object' ? config : {}) - } - } - - _typeCheckConfig(config, configTypes = this.constructor.DefaultType) { - for (const [property, expectedTypes] of Object.entries(configTypes)) { - const value = config[property] - const valueType = isElement(value) ? 'element' : toType(value) - - if (!new RegExp(expectedTypes).test(valueType)) { - throw new TypeError( - `${this.constructor.NAME.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".` - ) - } - } - } -} - -export default Config diff --git a/resources/js/src/util/focustrap.js b/resources/js/src/util/focustrap.js deleted file mode 100644 index 0e961794..00000000 --- a/resources/js/src/util/focustrap.js +++ /dev/null @@ -1,114 +0,0 @@ -/** - * -------------------------------------------------------------------------- - * util/focustrap.js - * -------------------------------------------------------------------------- - */ - -import EventHandler from '../dom/event-handler.js' -import SelectorEngine from '../dom/selector-engine.js' -import Config from './config.js' - -/** - * Constants - */ - -const NAME = 'focustrap' -const DATA_KEY = 'dl.focustrap' -const EVENT_KEY = `.${DATA_KEY}` -const EVENT_FOCUSIN = `focusin${EVENT_KEY}` -const EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY}` - -const TAB_KEY = 'Tab' -const TAB_NAV_FORWARD = 'forward' -const TAB_NAV_BACKWARD = 'backward' - -const Default = { - autofocus: true, - trapElement: null // The element to trap focus inside of -} - -const DefaultType = { - autofocus: 'boolean', - trapElement: 'element' -} - -/** - * Class definition - */ - -class FocusTrap extends Config { - constructor(config) { - super() - this._config = this._getConfig(config) - this._isActive = false - this._lastTabNavDirection = null - } - - // Getters - static get Default() { - return Default - } - - static get DefaultType() { - return DefaultType - } - - static get NAME() { - return NAME - } - - // Public - activate() { - if (this._isActive) { - return - } - - if (this._config.autofocus) { - this._config.trapElement.focus() - } - - EventHandler.off(document, EVENT_KEY) // guard against infinite focus loop - EventHandler.on(document, EVENT_FOCUSIN, event => this._handleFocusin(event)) - EventHandler.on(document, EVENT_KEYDOWN_TAB, event => this._handleKeydown(event)) - - this._isActive = true - } - - deactivate() { - if (!this._isActive) { - return - } - - this._isActive = false - EventHandler.off(document, EVENT_KEY) - } - - // Private - _handleFocusin(event) { - const { trapElement } = this._config - - if (event.target === document || event.target === trapElement || trapElement.contains(event.target)) { - return - } - - const elements = SelectorEngine.focusableChildren(trapElement) - - if (elements.length === 0) { - trapElement.focus() - } else if (this._lastTabNavDirection === TAB_NAV_BACKWARD) { - elements[elements.length - 1].focus() - } else { - elements[0].focus() - } - } - - _handleKeydown(event) { - if (event.key !== TAB_KEY) { - return - } - - this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD - } -} - -export default FocusTrap diff --git a/resources/js/src/util/index.js b/resources/js/src/util/index.js deleted file mode 100644 index 124687cb..00000000 --- a/resources/js/src/util/index.js +++ /dev/null @@ -1,305 +0,0 @@ -/** - * -------------------------------------------------------------------------- - * Bootstrap util/index.js - * -------------------------------------------------------------------------- - */ - -const MAX_UID = 1_000_000 -const MILLISECONDS_MULTIPLIER = 1000 -const TRANSITION_END = 'transitionend' - -/** - * Properly escape IDs selectors to handle weird IDs - * @param {string} selector - * @returns {string} - */ -const parseSelector = selector => { - if (selector && window.CSS && window.CSS.escape) { - // document.querySelector needs escaping to handle IDs (html5+) containing for instance / - selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`) - } - - return selector -} - -// Shout-out Angus Croll (https://goo.gl/pxwQGp) -const toType = object => { - if (object === null || object === undefined) { - return `${object}` - } - - return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase() -} - -/** - * Public Util API - */ - -const getUID = prefix => { - do { - prefix += Math.floor(Math.random() * MAX_UID) - } while (document.getElementById(prefix)) - - return prefix -} - -const getTransitionDurationFromElement = element => { - if (!element) { - return 0 - } - - // Get transition-duration of the element - let { transitionDuration, transitionDelay } = window.getComputedStyle(element) - - const floatTransitionDuration = Number.parseFloat(transitionDuration) - const floatTransitionDelay = Number.parseFloat(transitionDelay) - - // Return 0 if element or transition duration is not found - if (!floatTransitionDuration && !floatTransitionDelay) { - return 0 - } - - // If multiple durations are defined, take the first - transitionDuration = transitionDuration.split(',')[0] - transitionDelay = transitionDelay.split(',')[0] - - return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER -} - -const triggerTransitionEnd = element => { - element.dispatchEvent(new Event(TRANSITION_END)) -} - -const isElement = object => { - if (!object || typeof object !== 'object') { - return false - } - - if (typeof object.jquery !== 'undefined') { - object = object[0] - } - - return typeof object.nodeType !== 'undefined' -} - -const getElement = object => { - // it's a jQuery object or a node element - if (isElement(object)) { - return object.jquery ? object[0] : object - } - - if (typeof object === 'string' && object.length > 0) { - return document.querySelector(parseSelector(object)) - } - - return null -} - -const isVisible = element => { - if (!isElement(element) || element.getClientRects().length === 0) { - return false - } - - const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible' - // Handle `details` element as its content may falsie appear visible when it is closed - const closedDetails = element.closest('details:not([open])') - - if (!closedDetails) { - return elementIsVisible - } - - if (closedDetails !== element) { - const summary = element.closest('summary') - if (summary && summary.parentNode !== closedDetails) { - return false - } - - if (summary === null) { - return false - } - } - - return elementIsVisible -} - -const isDisabled = element => { - if (!element || element.nodeType !== Node.ELEMENT_NODE) { - return true - } - - if (element.classList.contains('disabled')) { - return true - } - - if (typeof element.disabled !== 'undefined') { - return element.disabled - } - - return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false' -} - -const findShadowRoot = element => { - if (!document.documentElement.attachShadow) { - return null - } - - // Can find the shadow root otherwise it'll return the document - if (typeof element.getRootNode === 'function') { - const root = element.getRootNode() - return root instanceof ShadowRoot ? root : null - } - - if (element instanceof ShadowRoot) { - return element - } - - // when we don't find a shadow root - if (!element.parentNode) { - return null - } - - return findShadowRoot(element.parentNode) -} - -const noop = () => {} - -/** - * Trick to restart an element's animation - * - * @param {HTMLElement} element - * @return void - * - * @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation - */ -const reflow = element => { - element.offsetHeight // eslint-disable-line no-unused-expressions -} - -const getjQuery = () => { - if (window.jQuery && !document.body.hasAttribute('data-dl-no-jquery')) { - return window.jQuery - } - - return null -} - -const DOMContentLoadedCallbacks = [] - -const onDOMContentLoaded = callback => { - if (document.readyState === 'loading') { - // add listener on the first call when the document is in loading state - if (!DOMContentLoadedCallbacks.length) { - document.addEventListener('DOMContentLoaded', () => { - for (const callback of DOMContentLoadedCallbacks) { - callback() - } - }) - } - - DOMContentLoadedCallbacks.push(callback) - } else { - callback() - } -} - -const isRTL = () => document.documentElement.dir === 'rtl' - -const defineJQueryPlugin = plugin => { - onDOMContentLoaded(() => { - const $ = getjQuery() - /* istanbul ignore if */ - if ($) { - const name = plugin.NAME - const JQUERY_NO_CONFLICT = $.fn[name] - $.fn[name] = plugin.jQueryInterface - $.fn[name].Constructor = plugin - $.fn[name].noConflict = () => { - $.fn[name] = JQUERY_NO_CONFLICT - return plugin.jQueryInterface - } - } - }) -} - -const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => { - return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue -} - -const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => { - if (!waitForTransition) { - execute(callback) - return - } - - const durationPadding = 5 - const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding - - let called = false - - const handler = ({ target }) => { - if (target !== transitionElement) { - return - } - - called = true - transitionElement.removeEventListener(TRANSITION_END, handler) - execute(callback) - } - - transitionElement.addEventListener(TRANSITION_END, handler) - setTimeout(() => { - if (!called) { - triggerTransitionEnd(transitionElement) - } - }, emulatedDuration) -} - -/** - * Return the previous/next element of a list. - * - * @param {array} list The list of elements - * @param activeElement The active element - * @param shouldGetNext Choose to get next or previous element - * @param isCycleAllowed - * @return {Element|elem} The proper element - */ -const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => { - const listLength = list.length - let index = list.indexOf(activeElement) - - // if the element does not exist in the list return an element - // depending on the direction and if cycle is allowed - if (index === -1) { - return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0] - } - - index += shouldGetNext ? 1 : -1 - - if (isCycleAllowed) { - index = (index + listLength) % listLength - } - - return list[Math.max(0, Math.min(index, listLength - 1))] -} - -export { - defineJQueryPlugin, - execute, - executeAfterTransition, - findShadowRoot, - getElement, - getjQuery, - getNextActiveElement, - getTransitionDurationFromElement, - getUID, - isDisabled, - isElement, - isRTL, - isVisible, - noop, - onDOMContentLoaded, - parseSelector, - reflow, - triggerTransitionEnd, - toType -} diff --git a/resources/js/src/util/sanitizer.js b/resources/js/src/util/sanitizer.js deleted file mode 100644 index e5b1da0f..00000000 --- a/resources/js/src/util/sanitizer.js +++ /dev/null @@ -1,116 +0,0 @@ -/** - * -------------------------------------------------------------------------- - * util/sanitizer.js - * -------------------------------------------------------------------------- - */ - -// js-docs-start allow-list -const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i - -export const DefaultAllowlist = { - // Global attributes allowed on any supplied element below. - '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], - a: ['target', 'href', 'title', 'rel'], - area: [], - b: [], - br: [], - col: [], - code: [], - dd: [], - div: [], - dl: [], - dt: [], - em: [], - hr: [], - h1: [], - h2: [], - h3: [], - h4: [], - h5: [], - h6: [], - i: [], - img: ['src', 'srcset', 'alt', 'title', 'width', 'height'], - li: [], - ol: [], - p: [], - pre: [], - s: [], - small: [], - span: [], - sub: [], - sup: [], - strong: [], - u: [], - ul: [] -} -// js-docs-end allow-list - -const uriAttributes = new Set([ - 'background', - 'cite', - 'href', - 'itemtype', - 'longdesc', - 'poster', - 'src', - 'xlink:href' -]) - -/** - * A pattern that recognizes URLs that are safe wrt. XSS in URL navigation - * contexts. - * - * Shout-out to Angular https://github.com/angular/angular/blob/15.2.8/packages/core/src/sanitization/url_sanitizer.ts#L38 - */ -// eslint-disable-next-line unicorn/better-regex -const SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i - -const allowedAttribute = (attribute, allowedAttributeList) => { - const attributeName = attribute.nodeName.toLowerCase() - - if (allowedAttributeList.includes(attributeName)) { - if (uriAttributes.has(attributeName)) { - return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue)) - } - - return true - } - - // Check if a regular expression validates the attribute. - return allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp) - .some(regex => regex.test(attributeName)) -} - -export function sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) { - if (!unsafeHtml.length) { - return unsafeHtml - } - - if (sanitizeFunction && typeof sanitizeFunction === 'function') { - return sanitizeFunction(unsafeHtml) - } - - const domParser = new window.DOMParser() - const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html') - const elements = [].concat(...createdDocument.body.querySelectorAll('*')) - - for (const element of elements) { - const elementName = element.nodeName.toLowerCase() - - if (!Object.keys(allowList).includes(elementName)) { - element.remove() - continue - } - - const attributeList = [].concat(...element.attributes) - const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || []) - - for (const attribute of attributeList) { - if (!allowedAttribute(attribute, allowedAttributes)) { - element.removeAttribute(attribute.nodeName) - } - } - } - - return createdDocument.body.innerHTML -} diff --git a/resources/js/src/util/scrollbar.js b/resources/js/src/util/scrollbar.js deleted file mode 100644 index bffde2fc..00000000 --- a/resources/js/src/util/scrollbar.js +++ /dev/null @@ -1,113 +0,0 @@ -/** - * -------------------------------------------------------------------------- - * util/scrollBar.js - * -------------------------------------------------------------------------- - */ - -import Manipulator from '../dom/manipulator.js' -import SelectorEngine from '../dom/selector-engine.js' -import { isElement } from './index.js' - -/** - * Constants - */ - -const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top' -const SELECTOR_STICKY_CONTENT = '.sticky-top' -const PROPERTY_PADDING = 'padding-right' -const PROPERTY_MARGIN = 'margin-right' - -/** - * Class definition - */ - -class ScrollBarHelper { - constructor() { - this._element = document.body - } - - // Public - getWidth() { - // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes - const documentWidth = document.documentElement.clientWidth - return Math.adl(window.innerWidth - documentWidth) - } - - hide() { - const width = this.getWidth() - this._disableOverFlow() - // give padding to element to balance the hidden scrollbar width - this._setElementAttributes(this._element, PROPERTY_PADDING, calculatedValue => calculatedValue + width) - // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth - this._setElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING, calculatedValue => calculatedValue + width) - this._setElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN, calculatedValue => calculatedValue - width) - } - - reset() { - this._resetElementAttributes(this._element, 'overflow') - this._resetElementAttributes(this._element, PROPERTY_PADDING) - this._resetElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING) - this._resetElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN) - } - - isOverflowing() { - return this.getWidth() > 0 - } - - // Private - _disableOverFlow() { - this._saveInitialAttribute(this._element, 'overflow') - this._element.style.overflow = 'hidden' - } - - _setElementAttributes(selector, styleProperty, callback) { - const scrollbarWidth = this.getWidth() - const manipulationCallBack = element => { - if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) { - return - } - - this._saveInitialAttribute(element, styleProperty) - const calculatedValue = window.getComputedStyle(element).getPropertyValue(styleProperty) - element.style.setProperty(styleProperty, `${callback(Number.parseFloat(calculatedValue))}px`) - } - - this._applyManipulationCallback(selector, manipulationCallBack) - } - - _saveInitialAttribute(element, styleProperty) { - const actualValue = element.style.getPropertyValue(styleProperty) - if (actualValue) { - Manipulator.setDataAttribute(element, styleProperty, actualValue) - } - } - - _resetElementAttributes(selector, styleProperty) { - const manipulationCallBack = element => { - const value = Manipulator.getDataAttribute(element, styleProperty) - // We only want to remove the property if the value is `null`; the value can also be zero - if (value === null) { - element.style.removeProperty(styleProperty) - return - } - - Manipulator.removeDataAttribute(element, styleProperty) - element.style.setProperty(styleProperty, value) - } - - this._applyManipulationCallback(selector, manipulationCallBack) - } - - _applyManipulationCallback(selector, callBack) { - if (isElement(selector)) { - callBack(selector) - return - } - - for (const sel of SelectorEngine.find(selector, this._element)) { - callBack(sel) - } - } -} - -export default ScrollBarHelper diff --git a/resources/js/src/util/swipe.js b/resources/js/src/util/swipe.js deleted file mode 100644 index deaf0909..00000000 --- a/resources/js/src/util/swipe.js +++ /dev/null @@ -1,145 +0,0 @@ -/** - * -------------------------------------------------------------------------- - * util/swipe.js - * -------------------------------------------------------------------------- - */ - -import EventHandler from '../dom/event-handler.js' -import Config from './config.js' -import { execute } from './index.js' - -/** - * Constants - */ - -const NAME = 'swipe' -const EVENT_KEY = '.dl.swipe' -const EVENT_TOUCHSTART = `touchstart${EVENT_KEY}` -const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY}` -const EVENT_TOUCHEND = `touchend${EVENT_KEY}` -const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY}` -const EVENT_POINTERUP = `pointerup${EVENT_KEY}` -const POINTER_TYPE_TOUCH = 'touch' -const POINTER_TYPE_PEN = 'pen' -const CLASS_NAME_POINTER_EVENT = 'pointer-event' -const SWIPE_THRESHOLD = 40 - -const Default = { - endCallback: null, - leftCallback: null, - rightCallback: null -} - -const DefaultType = { - endCallback: '(function|null)', - leftCallback: '(function|null)', - rightCallback: '(function|null)' -} - -/** - * Class definition - */ - -class Swipe extends Config { - constructor(element, config) { - super() - this._element = element - - if (!element || !Swipe.isSupported()) { - return - } - - this._config = this._getConfig(config) - this._deltaX = 0 - this._supportPointerEvents = Boolean(window.PointerEvent) - this._initEvents() - } - - // Getters - static get Default() { - return Default - } - - static get DefaultType() { - return DefaultType - } - - static get NAME() { - return NAME - } - - // Public - dispose() { - EventHandler.off(this._element, EVENT_KEY) - } - - // Private - _start(event) { - if (!this._supportPointerEvents) { - this._deltaX = event.touches[0].clientX - - return - } - - if (this._eventIsPointerPenTouch(event)) { - this._deltaX = event.clientX - } - } - - _end(event) { - if (this._eventIsPointerPenTouch(event)) { - this._deltaX = event.clientX - this._deltaX - } - - this._handleSwipe() - execute(this._config.endCallback) - } - - _move(event) { - this._deltaX = event.touches && event.touches.length > 1 ? - 0 : - event.touches[0].clientX - this._deltaX - } - - _handleSwipe() { - const absDeltaX = Math.abs(this._deltaX) - - if (absDeltaX <= SWIPE_THRESHOLD) { - return - } - - const direction = absDeltaX / this._deltaX - - this._deltaX = 0 - - if (!direction) { - return - } - - execute(direction > 0 ? this._config.rightCallback : this._config.leftCallback) - } - - _initEvents() { - if (this._supportPointerEvents) { - EventHandler.on(this._element, EVENT_POINTERDOWN, event => this._start(event)) - EventHandler.on(this._element, EVENT_POINTERUP, event => this._end(event)) - - this._element.classList.add(CLASS_NAME_POINTER_EVENT) - } else { - EventHandler.on(this._element, EVENT_TOUCHSTART, event => this._start(event)) - EventHandler.on(this._element, EVENT_TOUCHMOVE, event => this._move(event)) - EventHandler.on(this._element, EVENT_TOUCHEND, event => this._end(event)) - } - } - - _eventIsPointerPenTouch(event) { - return this._supportPointerEvents && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH) - } - - // Static - static isSupported() { - return 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0 - } -} - -export default Swipe diff --git a/resources/js/src/util/template-factory.js b/resources/js/src/util/template-factory.js deleted file mode 100644 index 9b56d7e3..00000000 --- a/resources/js/src/util/template-factory.js +++ /dev/null @@ -1,159 +0,0 @@ -/** - * -------------------------------------------------------------------------- - * util/template-factory.js - * -------------------------------------------------------------------------- - */ - -import SelectorEngine from '../dom/selector-engine.js' -import Config from './config.js' -import { DefaultAllowlist, sanitizeHtml } from './sanitizer.js' -import { execute, getElement, isElement } from './index.js' - -/** - * Constants - */ - -const NAME = 'TemplateFactory' - -const Default = { - allowList: DefaultAllowlist, - content: {}, // { selector : text , selector2 : text2 , } - extraClass: '', - html: false, - sanitize: true, - sanitizeFn: null, - template: '
' -} - -const DefaultType = { - allowList: 'object', - content: 'object', - extraClass: '(string|function)', - html: 'boolean', - sanitize: 'boolean', - sanitizeFn: '(null|function)', - template: 'string' -} - -const DefaultContentType = { - entry: '(string|element|function|null)', - selector: '(string|element)' -} - -/** - * Class definition - */ - -class TemplateFactory extends Config { - constructor(config) { - super() - this._config = this._getConfig(config) - } - - // Getters - static get Default() { - return Default - } - - static get DefaultType() { - return DefaultType - } - - static get NAME() { - return NAME - } - - // Public - getContent() { - return Object.values(this._config.content) - .map(config => this._resolvePossibleFunction(config)) - .filter(Boolean) - } - - hasContent() { - return this.getContent().length > 0 - } - - changeContent(content) { - this._checkContent(content) - this._config.content = { ...this._config.content, ...content } - return this - } - - toHtml() { - const templateWrapper = document.createElement('div') - templateWrapper.innerHTML = this._maybeSanitize(this._config.template) - - for (const [selector, text] of Object.entries(this._config.content)) { - this._setContent(templateWrapper, text, selector) - } - - const template = templateWrapper.children[0] - const extraClass = this._resolvePossibleFunction(this._config.extraClass) - - if (extraClass) { - template.classList.add(...extraClass.split(' ')) - } - - return template - } - - // Private - _typeCheckConfig(config) { - super._typeCheckConfig(config) - this._checkContent(config.content) - } - - _checkContent(arg) { - for (const [selector, content] of Object.entries(arg)) { - super._typeCheckConfig({ selector, entry: content }, DefaultContentType) - } - } - - _setContent(template, content, selector) { - const templateElement = SelectorEngine.findOne(selector, template) - - if (!templateElement) { - return - } - - content = this._resolvePossibleFunction(content) - - if (!content) { - templateElement.remove() - return - } - - if (isElement(content)) { - this._putElementInTemplate(getElement(content), templateElement) - return - } - - if (this._config.html) { - templateElement.innerHTML = this._maybeSanitize(content) - return - } - - templateElement.textContent = content - } - - _maybeSanitize(arg) { - return this._config.sanitize ? sanitizeHtml(arg, this._config.allowList, this._config.sanitizeFn) : arg - } - - _resolvePossibleFunction(arg) { - return execute(arg, [undefined, this]) - } - - _putElementInTemplate(element, templateElement) { - if (this._config.html) { - templateElement.innerHTML = '' - templateElement.append(element) - return - } - - templateElement.textContent = element.textContent - } -} - -export default TemplateFactory diff --git a/resources/scss/alert.scss b/resources/scss/alert.scss deleted file mode 100644 index a3c62fef..00000000 --- a/resources/scss/alert.scss +++ /dev/null @@ -1,9 +0,0 @@ -@use "shared/variables"; -@use "shared/variables-dark"; -@use "shared/text"; -@use "shared/button"; -@use "components/notify"; -@use "components/field"; -@use "components/message"; -@use "components/modal"; - diff --git a/resources/scss/components/_field.scss b/resources/scss/components/_field.scss deleted file mode 100644 index 29c97a32..00000000 --- a/resources/scss/components/_field.scss +++ /dev/null @@ -1,5 +0,0 @@ -.form-text { - margin-top: 0.25rem; - font-size: 0.875em; - color: var(--dl-secondary-color); -} \ No newline at end of file diff --git a/resources/scss/components/_message.scss b/resources/scss/components/_message.scss deleted file mode 100644 index cf01d408..00000000 --- a/resources/scss/components/_message.scss +++ /dev/null @@ -1,94 +0,0 @@ -.alert { - --dl-alert-bg: transparent; - --dl-alert-padding-x: 1rem; - --dl-alert-padding-y: 1rem; - --dl-alert-margin-bottom: 1rem; - --dl-alert-color: inherit; - --dl-alert-border-color: transparent; - --dl-alert-border: var(--dl-border-width) solid var(--dl-alert-border-color); - --dl-alert-border-radius: var(--dl-border-radius); - --dl-alert-link-color: inherit; - position: relative; - padding: var(--dl-alert-padding-y) var(--dl-alert-padding-x); - margin-bottom: var(--dl-alert-margin-bottom); - color: var(--dl-alert-color); - background-color: var(--dl-alert-bg); - border: var(--dl-alert-border); - border-radius: var(--dl-alert-border-radius); -} - -.alert-heading { - color: inherit; -} - -.alert-link { - font-weight: 700; - color: var(--dl-alert-link-color); -} - -.alert-dismissible { - padding-right: 3rem; -} -.alert-dismissible .btn-close { - position: absolute; - top: 0; - right: 0; - z-index: 2; - padding: 1.25rem 1rem; -} - -.alert-primary { - --dl-alert-color: var(--dl-primary-text-emphasis); - --dl-alert-bg: var(--dl-primary-bg-subtle); - --dl-alert-border-color: var(--dl-primary-border-subtle); - --dl-alert-link-color: var(--dl-primary-text-emphasis); -} - -.alert-secondary { - --dl-alert-color: var(--dl-secondary-text-emphasis); - --dl-alert-bg: var(--dl-secondary-bg-subtle); - --dl-alert-border-color: var(--dl-secondary-border-subtle); - --dl-alert-link-color: var(--dl-secondary-text-emphasis); -} - -.alert-success { - --dl-alert-color: var(--dl-success-text-emphasis); - --dl-alert-bg: var(--dl-success-bg-subtle); - --dl-alert-border-color: var(--dl-success-border-subtle); - --dl-alert-link-color: var(--dl-success-text-emphasis); -} - -.alert-info { - --dl-alert-color: var(--dl-info-text-emphasis); - --dl-alert-bg: var(--dl-info-bg-subtle); - --dl-alert-border-color: var(--dl-info-border-subtle); - --dl-alert-link-color: var(--dl-info-text-emphasis); -} - -.alert-warning { - --dl-alert-color: var(--dl-warning-text-emphasis); - --dl-alert-bg: var(--dl-warning-bg-subtle); - --dl-alert-border-color: var(--dl-warning-border-subtle); - --dl-alert-link-color: var(--dl-warning-text-emphasis); -} - -.alert-danger { - --dl-alert-color: var(--dl-danger-text-emphasis); - --dl-alert-bg: var(--dl-danger-bg-subtle); - --dl-alert-border-color: var(--dl-danger-border-subtle); - --dl-alert-link-color: var(--dl-danger-text-emphasis); -} - -.alert-light { - --dl-alert-color: var(--dl-light-text-emphasis); - --dl-alert-bg: var(--dl-light-bg-subtle); - --dl-alert-border-color: var(--dl-light-border-subtle); - --dl-alert-link-color: var(--dl-light-text-emphasis); -} - -.alert-dark { - --dl-alert-color: var(--dl-dark-text-emphasis); - --dl-alert-bg: var(--dl-dark-bg-subtle); - --dl-alert-border-color: var(--dl-dark-border-subtle); - --dl-alert-link-color: var(--dl-dark-text-emphasis); -} \ No newline at end of file diff --git a/resources/scss/components/_modal.scss b/resources/scss/components/_modal.scss deleted file mode 100644 index a38fdc45..00000000 --- a/resources/scss/components/_modal.scss +++ /dev/null @@ -1,230 +0,0 @@ -$base-duration: 0.25s; - -// Colors -$primary: slategray; -$accent: tomato; -$white: whitesmoke; -$green: #2ecc71; -$red: #e74c3c; - -.modal { - position: fixed; - top: 0; - left: 0; - display: flex; - align-items: center; - justify-content: center; - height: 0vh; - background-color: transparent; - overflow: hidden; - transition: background-color $base-duration ease; - z-index: 9999; - - button { - cursor: pointer; - } - - &.open { - position: fixed; - width: 100%; - height: 100vh; - background-color: rgba(0, 0, 0, 0.5); - transition: background-color $base-duration; - - > .content-wrapper { - transform: scale(1.0); - } - } - - .content-wrapper { - position: relative; - display: flex; - flex-direction: column; - align-items: center; - justify-content: flex-start; - margin: 0; - padding: 2.5rem; - background-color: white; - border-radius: 0.3125rem; - box-shadow: 0 0 2.5rem rgba(0, 0, 0, 0.5); - transform: scale(0.0); - transition: transform $base-duration; - transition-delay: 0.15s; - max-height: 80vh; - overflow-y: auto; - - &.small { - width: 30%; - padding: 1.5rem; - } - - &.medium { - width: 50%; - padding: 2rem; - } - - &.large { - width: 70%; - padding: 2.5rem; - } - - &.fullscreen { - width: 100%; - height: 100%; - border-radius: 0; - max-height: 100%; - padding: 2rem; - } - - @media (max-width: 768px) { - &.small { - width: 80%; - padding: 1rem; - } - - &.medium { - width: 90%; - padding: 1.5rem; - } - - &.large, - &.fullscreen { - width: 100%; - height: 100%; - border-radius: 0; - padding: 1.5rem; - } - } - - @media (max-width: 480px) { - &.small, - &.medium, - &.large, - &.fullscreen { - width: 100%; - height: 100%; - border-radius: 0; - padding: 1rem; - } - } - - .close { - position: absolute; - top: 0.5rem; - right: 0.5rem; - display: flex; - align-items: center; - justify-content: center; - width: 2.5rem; - height: 2.5rem; - border: none; - background-color: transparent; - font-size: 1.5rem; - transition: $base-duration linear; - - &:before, - &:after { - position: absolute; - content: ''; - width: 1.25rem; - height: 0.125rem; - background-color: black; - } - - &:before { - transform: rotate(-45deg); - } - - &:after { - transform: rotate(45deg); - } - - &:hover { - transform: rotate(360deg); - - &:before, - &:after { - background-color: $accent; - } - } - } - - .modal-header { - position: relative; - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - width: 100%; - margin: 0; - padding: 0 0 1.25rem; - - h2 { - font-size: 1.5rem; - font-weight: bold; - } - } - - .content { - position: relative; - display: flex; - flex-direction: column; - width: 100%; - - p { - font-size: 0.875rem; - line-height: 1.75; - } - } - - .modal-footer { - position: relative; - display: flex; - align-items: center; - justify-content: flex-end; - width: 100%; - margin: 0; - padding: 1.875rem 0 0; - - .action { - position: relative; - margin-left: 0.625rem; - padding: 0.625rem 1.25rem; - border: none; - background-color: $primary; - border-radius: 0.25rem; - color: white; - font-size: 0.87rem; - font-weight: 300; - overflow: hidden; - z-index: 1; - - &:before { - position: absolute; - content: ''; - top: 0; - left: 0; - width: 0%; - height: 100%; - background-color: rgba(255, 255, 255, 0.2); - transition: width $base-duration; - z-index: 0; - } - - &:first-child { - background-color: $green; - } - - &:last-child { - background-color: $red; - } - - &:hover { - &:before { - width: 100%; - } - } - } - } - } -} \ No newline at end of file diff --git a/resources/scss/components/_toast.scss b/resources/scss/components/_toast.scss deleted file mode 100644 index 5b0f606a..00000000 --- a/resources/scss/components/_toast.scss +++ /dev/null @@ -1,197 +0,0 @@ -.toast-title { - font-weight: bold; -} -.toast-message { - -ms-word-wrap: break-word; - word-wrap: break-word; -} -.toast-message a, -.toast-message label { - color: #ffffff; -} -.toast-message a:hover { - color: #cccccc; - text-decoration: none; -} -.toast-close-button { - position: relative; - right: -0.3em; - top: -0.3em; - float: right; - font-size: 20px; - font-weight: bold; - color: #ffffff; - -webkit-text-shadow: 0 1px 0 #ffffff; - text-shadow: 0 1px 0 #ffffff; - opacity: 0.8; - -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); - filter: alpha(opacity=80); -} -.toast-close-button:hover, -.toast-close-button:focus { - color: #000000; - text-decoration: none; - cursor: pointer; - opacity: 0.4; - -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); - filter: alpha(opacity=40); -} -/*Additional properties for button version - iOS requires the button element instead of an anchor tag. - If you want the anchor version, it requires `href="#"`.*/ -button.toast-close-button { - padding: 0; - cursor: pointer; - background: transparent; - border: 0; - -webkit-appearance: none; -} -.toast-top-center { - top: 0; - right: 0; - width: 100%; -} -.toast-bottom-center { - bottom: 0; - right: 0; - width: 100%; -} -.toast-top-full-width { - top: 0; - right: 0; - width: 100%; -} -.toast-bottom-full-width { - bottom: 0; - right: 0; - width: 100%; -} -.toast-top-left { - top: 12px; - left: 12px; -} -.toast-top-right { - top: 12px; - right: 12px; -} -.toast-bottom-right { - right: 12px; - bottom: 12px; -} -.toast-bottom-left { - bottom: 12px; - left: 12px; -} -.toastr { - position: fixed; - z-index: 999999; - /*overrides*/ -} -.toastr * { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; -} -.toastr > div { - position: relative; - overflow: hidden; - margin: 0 0 6px; - padding: 15px 15px 15px 50px; - width: 300px; - -moz-border-radius: 0.75rem; - -webkit-border-radius: 0.75rem; - border-radius: 0.75rem; - background-position: 15px center; - background-repeat: no-repeat; - color: #ffffff; - opacity: 0.8; - -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); - filter: alpha(opacity=80); -} -.toastr > div:hover { - opacity: 1; - -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); - filter: alpha(opacity=100); - cursor: pointer; -} -.toastr > .toast-info { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=") !important; -} -.toastr > .toast-error { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=") !important; -} -.toastr > .toast-success { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==") !important; -} -.toastr > .toast-warning { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=") !important; -} -.toastr.toast-top-center > div, -.toastr.toast-bottom-center > div { - width: 300px; - margin-left: auto; - margin-right: auto; -} -.toastr.toast-top-full-width > div, -.toastr.toast-bottom-full-width > div { - width: 96%; - margin-left: auto; - margin-right: auto; -} -.toast { - background-color: #030303; -} -.toast-success { - background-color: #17C653; -} - -.toast-error { - background-color: #F8285A; -} - -.toast-info { - background-color: #2f96b4; -} - -.toast-warning { - background-color: #F6C000; -} - -.toast-progress { - position: absolute; - left: 0; - bottom: 0; - height: 4px; - background-color: #000000; - opacity: 0.4; - -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); - filter: alpha(opacity=40); -} - -/*Responsive Design*/ -@media all and (max-width: 240px) { - .toastr > div { - padding: 8px 8px 8px 50px; - width: 11em; - } - .toastr .toast-close-button { - right: -0.2em; - top: -0.2em; - } -} -@media all and (min-width: 241px) and (max-width: 480px) { - .toastr > div { - padding: 8px 8px 8px 50px; - width: 18em; - } - .toastr .toast-close-button { - right: -0.2em; - top: -0.2em; - } -} -@media all and (min-width: 481px) and (max-width: 768px) { - .toastr > div { - padding: 15px 15px 15px 50px; - width: 25em; - } -} \ No newline at end of file diff --git a/resources/scss/shared/_button.scss b/resources/scss/shared/_button.scss deleted file mode 100644 index 335d36ec..00000000 --- a/resources/scss/shared/_button.scss +++ /dev/null @@ -1,54 +0,0 @@ -.btn-close { - --dl-btn-close-color: #000; - --dl-btn-close-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e"); - --dl-btn-close-opacity: 0.5; - --dl-btn-close-hover-opacity: 0.75; - --dl-btn-close-focus-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); - --dl-btn-close-focus-opacity: 1; - --dl-btn-close-disabled-opacity: 0.25; - --dl-btn-close-white-filter: invert(1) grayscale(100%) brightness(200%); - box-sizing: content-box; - width: 1em; - height: 1em; - padding: 0.25em 0.25em; - color: var(--dl-btn-close-color); - background: transparent var(--dl-btn-close-bg) center/1em auto no-repeat; - border: 0; - border-radius: 0.375rem; - opacity: var(--dl-btn-close-opacity); -} -.btn-close:hover { - color: var(--dl-btn-close-color); - text-decoration: none; - opacity: var(--dl-btn-close-hover-opacity); -} -.btn-close:focus { - outline: 0; - box-shadow: var(--dl-btn-close-focus-shadow); - opacity: var(--dl-btn-close-focus-opacity); -} -.btn-close:disabled, .btn-close.disabled { - pointer-events: none; - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; - opacity: var(--dl-btn-close-disabled-opacity); -} - -.btn-close:focus { - outline: none; - box-shadow: none; -} - -.btn-close-white { - filter: var(--dl-btn-close-white-filter); -} - -[data-dl-theme=dark] .btn-close { - filter: var(--dl-btn-close-white-filter); -} - -button, -[role=button] { - cursor: pointer; -} \ No newline at end of file diff --git a/resources/scss/shared/_text.scss b/resources/scss/shared/_text.scss deleted file mode 100644 index 136773d7..00000000 --- a/resources/scss/shared/_text.scss +++ /dev/null @@ -1,137 +0,0 @@ -.text-primary { - --dl-text-opacity: 1; - color: rgba(var(--dl-primary-rgb), var(--dl-text-opacity)) !important; -} - -.text-secondary { - --dl-text-opacity: 1; - color: rgba(var(--dl-secondary-rgb), var(--dl-text-opacity)) !important; -} - -.text-success { - --dl-text-opacity: 1; - color: rgba(var(--dl-success-rgb), var(--dl-text-opacity)) !important; -} - -.text-info { - --dl-text-opacity: 1; - color: rgba(var(--dl-info-rgb), var(--dl-text-opacity)) !important; -} - -.text-warning { - --dl-text-opacity: 1; - color: rgba(var(--dl-warning-rgb), var(--dl-text-opacity)) !important; -} - -.text-danger { - --dl-text-opacity: 1; - color: rgba(var(--dl-danger-rgb), var(--dl-text-opacity)) !important; -} - -.text-light { - --dl-text-opacity: 1; - color: rgba(var(--dl-light-rgb), var(--dl-text-opacity)) !important; -} - -.text-dark { - --dl-text-opacity: 1; - color: rgba(var(--dl-dark-rgb), var(--dl-text-opacity)) !important; -} - -.text-black { - --dl-text-opacity: 1; - color: rgba(var(--dl-black-rgb), var(--dl-text-opacity)) !important; -} - -.text-white { - --dl-text-opacity: 1; - color: rgba(var(--dl-white-rgb), var(--dl-text-opacity)) !important; -} - -.text-body { - --dl-text-opacity: 1; - color: rgba(var(--dl-body-color-rgb), var(--dl-text-opacity)) !important; -} - -.text-muted { - --dl-text-opacity: 1; - color: var(--dl-secondary-color) !important; -} - -.text-black-50 { - --dl-text-opacity: 1; - color: rgba(0, 0, 0, 0.5) !important; -} - -.text-white-50 { - --dl-text-opacity: 1; - color: rgba(255, 255, 255, 0.5) !important; -} - -.text-body-secondary { - --dl-text-opacity: 1; - color: var(--dl-secondary-color) !important; -} - -.text-body-tertiary { - --dl-text-opacity: 1; - color: var(--dl-tertiary-color) !important; -} - -.text-body-emphasis { - --dl-text-opacity: 1; - color: var(--dl-emphasis-color) !important; -} - -.text-reset { - --dl-text-opacity: 1; - color: inherit !important; -} - -.text-opacity-25 { - --dl-text-opacity: 0.25; -} - -.text-opacity-50 { - --dl-text-opacity: 0.5; -} - -.text-opacity-75 { - --dl-text-opacity: 0.75; -} - -.text-opacity-100 { - --dl-text-opacity: 1; -} - -.text-primary-emphasis { - color: var(--dl-primary-text-emphasis) !important; -} - -.text-secondary-emphasis { - color: var(--dl-secondary-text-emphasis) !important; -} - -.text-success-emphasis { - color: var(--dl-success-text-emphasis) !important; -} - -.text-info-emphasis { - color: var(--dl-info-text-emphasis) !important; -} - -.text-warning-emphasis { - color: var(--dl-warning-text-emphasis) !important; -} - -.text-danger-emphasis { - color: var(--dl-danger-text-emphasis) !important; -} - -.text-light-emphasis { - color: var(--dl-light-text-emphasis) !important; -} - -.text-dark-emphasis { - color: var(--dl-dark-text-emphasis) !important; -} diff --git a/resources/scss/shared/_variables-dark.scss b/resources/scss/shared/_variables-dark.scss deleted file mode 100644 index 40cedd1c..00000000 --- a/resources/scss/shared/_variables-dark.scss +++ /dev/null @@ -1,55 +0,0 @@ -[data-dl-theme=dark] { - color-scheme: dark; - --dl-body-color: #dee2e6; - --dl-body-color-rgb: 222, 226, 230; - --dl-body-bg: #212529; - --dl-body-bg-rgb: 33, 37, 41; - --dl-emphasis-color: #fff; - --dl-emphasis-color-rgb: 255, 255, 255; - --dl-secondary-color: rgba(222, 226, 230, 0.75); - --dl-secondary-color-rgb: 222, 226, 230; - --dl-secondary-bg: #343a40; - --dl-secondary-bg-rgb: 52, 58, 64; - --dl-tertiary-color: rgba(222, 226, 230, 0.5); - --dl-tertiary-color-rgb: 222, 226, 230; - --dl-tertiary-bg: #2b3035; - --dl-tertiary-bg-rgb: 43, 48, 53; - --dl-primary-text-emphasis: #6ea8fe; - --dl-secondary-text-emphasis: #a7acb1; - --dl-success-text-emphasis: #75b798; - --dl-info-text-emphasis: #6edff6; - --dl-warning-text-emphasis: #ffda6a; - --dl-danger-text-emphasis: #ea868f; - --dl-light-text-emphasis: #f8f9fa; - --dl-dark-text-emphasis: #dee2e6; - --dl-primary-bg-subtle: #031633; - --dl-secondary-bg-subtle: #161719; - --dl-success-bg-subtle: #051b11; - --dl-info-bg-subtle: #032830; - --dl-warning-bg-subtle: #332701; - --dl-danger-bg-subtle: #2c0b0e; - --dl-light-bg-subtle: #343a40; - --dl-dark-bg-subtle: #1a1d20; - --dl-primary-border-subtle: #084298; - --dl-secondary-border-subtle: #41464b; - --dl-success-border-subtle: #0f5132; - --dl-info-border-subtle: #087990; - --dl-warning-border-subtle: #997404; - --dl-danger-border-subtle: #842029; - --dl-light-border-subtle: #495057; - --dl-dark-border-subtle: #343a40; - --dl-heading-color: inherit; - --dl-link-color: #6ea8fe; - --dl-link-hover-color: #8bb9fe; - --dl-link-color-rgb: 110, 168, 254; - --dl-link-hover-color-rgb: 139, 185, 254; - --dl-code-color: #e685b5; - --dl-highlight-color: #dee2e6; - --dl-highlight-bg: #664d03; - --dl-border-color: #495057; - --dl-border-color-translucent: rgba(255, 255, 255, 0.15); - --dl-form-valid-color: #75b798; - --dl-form-valid-border-color: #75b798; - --dl-form-invalid-color: #ea868f; - --dl-form-invalid-border-color: #ea868f; -} \ No newline at end of file diff --git a/resources/scss/shared/_variables.scss b/resources/scss/shared/_variables.scss deleted file mode 100644 index 3d14d416..00000000 --- a/resources/scss/shared/_variables.scss +++ /dev/null @@ -1,119 +0,0 @@ -[data-dl-theme=light] { - --dl-blue: #0d6efd; - --dl-indigo: #6610f2; - --dl-purple: #6f42c1; - --dl-pink: #d63384; - --dl-red: #dc3545; - --dl-orange: #fd7e14; - --dl-yellow: #ffc107; - --dl-green: #198754; - --dl-teal: #20c997; - --dl-cyan: #0dcaf0; - --dl-black: #000; - --dl-white: #fff; - --dl-gray: #6c757d; - --dl-gray-dark: #343a40; - --dl-gray-100: #f8f9fa; - --dl-gray-200: #e9ecef; - --dl-gray-300: #dee2e6; - --dl-gray-400: #ced4da; - --dl-gray-500: #adb5bd; - --dl-gray-600: #6c757d; - --dl-gray-700: #495057; - --dl-gray-800: #343a40; - --dl-gray-900: #212529; - --dl-primary: #0d6efd; - --dl-secondary: #6c757d; - --dl-success: #198754; - --dl-info: #0dcaf0; - --dl-warning: #ffc107; - --dl-danger: #dc3545; - --dl-light: #f8f9fa; - --dl-dark: #212529; - --dl-primary-rgb: 13, 110, 253; - --dl-secondary-rgb: 108, 117, 125; - --dl-success-rgb: 25, 135, 84; - --dl-info-rgb: 13, 202, 240; - --dl-warning-rgb: 255, 193, 7; - --dl-danger-rgb: 220, 53, 69; - --dl-light-rgb: 248, 249, 250; - --dl-dark-rgb: 33, 37, 41; - --dl-primary-text-emphasis: #052c65; - --dl-secondary-text-emphasis: #2b2f32; - --dl-success-text-emphasis: #0a3622; - --dl-info-text-emphasis: #055160; - --dl-warning-text-emphasis: #664d03; - --dl-danger-text-emphasis: #58151c; - --dl-light-text-emphasis: #495057; - --dl-dark-text-emphasis: #495057; - --dl-primary-bg-subtle: #cfe2ff; - --dl-secondary-bg-subtle: #e2e3e5; - --dl-success-bg-subtle: #d1e7dd; - --dl-info-bg-subtle: #cff4fc; - --dl-warning-bg-subtle: #fff3cd; - --dl-danger-bg-subtle: #f8d7da; - --dl-light-bg-subtle: #fcfcfd; - --dl-dark-bg-subtle: #ced4da; - --dl-primary-border-subtle: #9ec5fe; - --dl-secondary-border-subtle: #c4c8cb; - --dl-success-border-subtle: #a3cfbb; - --dl-info-border-subtle: #9eeaf9; - --dl-warning-border-subtle: #ffe69c; - --dl-danger-border-subtle: #f1aeb5; - --dl-light-border-subtle: #e9ecef; - --dl-dark-border-subtle: #adb5bd; - --dl-white-rgb: 255, 255, 255; - --dl-black-rgb: 0, 0, 0; - --dl-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - --dl-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - --dl-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); - --dl-body-font-family: var(--dl-font-sans-serif); - --dl-body-font-size: 1rem; - --dl-body-font-weight: 400; - --dl-body-line-height: 1.5; - --dl-body-color: #212529; - --dl-body-color-rgb: 33, 37, 41; - --dl-body-bg: #fff; - --dl-body-bg-rgb: 255, 255, 255; - --dl-emphasis-color: #000; - --dl-emphasis-color-rgb: 0, 0, 0; - --dl-secondary-color: rgba(33, 37, 41, 0.75); - --dl-secondary-color-rgb: 33, 37, 41; - --dl-secondary-bg: #e9ecef; - --dl-secondary-bg-rgb: 233, 236, 239; - --dl-tertiary-color: rgba(33, 37, 41, 0.5); - --dl-tertiary-color-rgb: 33, 37, 41; - --dl-tertiary-bg: #f8f9fa; - --dl-tertiary-bg-rgb: 248, 249, 250; - --dl-heading-color: inherit; - --dl-link-color: #0d6efd; - --dl-link-color-rgb: 13, 110, 253; - --dl-link-decoration: underline; - --dl-link-hover-color: #0a58ca; - --dl-link-hover-color-rgb: 10, 88, 202; - --dl-code-color: #d63384; - --dl-highlight-color: #212529; - --dl-highlight-bg: #fff3cd; - --dl-border-width: 1px; - --dl-border-style: solid; - --dl-border-color: #dee2e6; - --dl-border-color-translucent: rgba(0, 0, 0, 0.175); - --dl-border-radius: 0.375rem; - --dl-border-radius-sm: 0.25rem; - --dl-border-radius-lg: 0.5rem; - --dl-border-radius-xl: 1rem; - --dl-border-radius-xxl: 2rem; - --dl-border-radius-2xl: var(--dl-border-radius-xxl); - --dl-border-radius-pill: 50rem; - --dl-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); - --dl-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); - --dl-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175); - --dl-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075); - --dl-focus-ring-width: 0.25rem; - --dl-focus-ring-opacity: 0.25; - --dl-focus-ring-color: rgba(13, 110, 253, 0.25); - --dl-form-valid-color: #198754; - --dl-form-valid-border-color: #198754; - --dl-form-invalid-color: #dc3545; - --dl-form-invalid-border-color: #dc3545; -} \ No newline at end of file diff --git a/resources/scss/themes/tailwind/alert.css b/resources/scss/themes/tailwind/alert.css new file mode 100644 index 00000000..1f3c93b0 --- /dev/null +++ b/resources/scss/themes/tailwind/alert.css @@ -0,0 +1,217 @@ +.alert-button.primary { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-900 focus:ring-offset-2 bg-neutral-950 hover:bg-neutral-900; +} +.alert-button.secondary { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium transition-colors border rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-100 focus:ring-offset-2; +} +.alert-button.success { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-green-700 focus:ring-offset-2 bg-green-600 hover:bg-green-700; +} +.alert-button.error { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-red-700 focus:ring-offset-2 bg-red-600 hover:bg-red-700; +} +.alert-button.warning { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-black transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-yellow-600 focus:ring-offset-2 bg-yellow-400 hover:bg-yellow-500; +} +.alert-button.info { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-blue-700 focus:ring-offset-2 bg-blue-600 hover:bg-blue-700; +} +.alert-button.light { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-black transition-colors border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-300 focus:ring-offset-2 bg-white hover:bg-gray-100; +} +.alert-button.dark { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-gray-900 focus:ring-offset-2 bg-gray-800 hover:bg-gray-900; +} +.alert-button.link { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-blue-600 transition-colors rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 hover:underline; +} + +.alert-notify-position { + @apply fixed px-2 mt-3 overflow-x-hidden z-50; +} +.alert-notify-position.top-right { + @apply top-0 right-0; +} +.alert-notify-position.top-left { + @apply top-0 left-0; +} +.alert-notify-position.bottom-right { + @apply bottom-0 right-0; +} +.alert-notify-position.bottom-left { + @apply bottom-0 left-0; +} +.alert-notify-position.top-center { + @apply top-0 left-1/2 transform -translate-x-1/2; +} +.alert-notify-position.bottom-center { + @apply bottom-0 left-1/2 transform -translate-x-1/2; +} +.alert-notify-position.center { + @apply top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2; +} + +.alert-field.success { + @apply p-3 text-green-800; +} +.alert-field.error { + @apply p-3 text-red-800; +} +.alert-field.warning { + @apply p-3 text-yellow-800; +} +.alert-field.info { + @apply p-3 text-blue-800; +} + +.alert-message { + @apply flex items-center p-4 mb-4 rounded-lg; +} +.alert-message .sr-only-fix { + @apply sr-only; +} +.alert-message.success { + @apply text-green-800 bg-green-50 dark:bg-gray-800 dark:text-green-400; +} +.alert-message.error { + @apply text-red-800 bg-red-50 dark:bg-gray-800 dark:text-red-400; +} +.alert-message.warning { + @apply text-yellow-800 bg-yellow-50 dark:bg-gray-800 dark:text-yellow-300; +} +.alert-message.info { + @apply text-blue-800 bg-blue-50 dark:bg-gray-800 dark:text-blue-400; +} +.alert-message .icon { + @apply shrink-0 w-4 h-4; +} +.alert-message .message { + @apply ms-3 text-sm font-medium flex items-center gap-2; +} +.alert-message .message .title { + @apply text-lg font-semibold; +} +.alert-message .close { + @apply ms-auto -mx-1.5 -my-1.5 p-1.5 inline-flex items-center justify-center h-8 w-8 rounded-lg focus:ring-2; +} +.alert-message .close.success { + @apply bg-blue-50 text-blue-500 focus:ring-blue-400 hover:bg-blue-200 dark:bg-gray-800 dark:text-blue-400 dark:hover:bg-gray-700; +} +.alert-message .close.error { + @apply bg-red-50 text-red-500 focus:ring-red-400 hover:bg-red-200 dark:bg-gray-800 dark:text-red-400 dark:hover:bg-gray-700; +} +.alert-message .close.warning { + @apply bg-yellow-50 text-yellow-500 focus:ring-yellow-400 hover:bg-yellow-200 dark:bg-gray-800 dark:text-yellow-400 dark:hover:bg-gray-700; +} +.alert-message .close.info { + @apply bg-blue-50 text-blue-500 focus:ring-blue-400 hover:bg-blue-200 dark:bg-gray-800 dark:text-blue-400 dark:hover:bg-gray-700; +} +.alert-message .close .close-icon { + @apply w-3 h-3; +} +.alert-message .close .sr-only-fix { + @apply sr-only; +} + +.alert-notify { + @apply bg-gray-900 bg-gradient-to-r text-white rounded-t mb-3 shadow-lg flex items-center; +} +.alert-notify.success { + @apply from-green-400 to-green-500; +} +.alert-notify.error { + @apply from-red-400 to-pink-500; +} +.alert-notify.warning { + @apply from-yellow-400 to-yellow-500; +} +.alert-notify.info { + @apply from-blue-400 to-blue-500; +} +.alert-notify.top-right { + @apply top-0 right-0; +} +.alert-notify.top-left { + @apply top-0 left-0; +} +.alert-notify.bottom-right { + @apply bottom-0 right-0; +} +.alert-notify.bottom-left { + @apply bottom-0 left-0; +} +.alert-notify.top-center { + @apply top-0 left-1/2 transform -translate-x-1/2; +} +.alert-notify.bottom-center { + @apply bottom-0 left-1/2 transform -translate-x-1/2; +} +.alert-notify.center { + @apply top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2; +} + +.alert-modal { + @apply fixed top-0 left-0 z-[99] flex items-center justify-center w-screen h-screen; +} +.alert-modal .modal-overlay { + @apply absolute inset-0 w-full h-full bg-white backdrop-blur-sm bg-opacity-70; +} +.alert-modal .modal-content { + @apply bg-white p-6 rounded-lg shadow-lg relative max-w-full; +} +.alert-modal .modal-content.small { + @apply w-1/4; +} +.alert-modal .modal-content.medium { + @apply w-1/2; +} +.alert-modal .modal-content.large { + @apply w-3/4; +} +.alert-modal .modal-content.extra-large { + @apply w-4/5; +} +.alert-modal .modal-content.fullscreen { + @apply w-full h-full; +} +.alert-modal .modal-content.scrollable { + @apply max-h-[80vh] overflow-y-auto; +} +.alert-modal .modal-header { + @apply flex items-center justify-between pb-3; +} +.alert-modal .modal-header.text-success { + @apply text-green-500; +} +.alert-modal .modal-header.text-error { + @apply text-red-500; +} +.alert-modal .modal-header.text-warning { + @apply text-yellow-500; +} +.alert-modal .modal-header.text-info { + @apply text-blue-500; +} +.alert-modal .modal-header .modal-title { + @apply text-lg font-semibold; +} +.alert-modal .modal-header .modal-close { + @apply absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5 text-gray-600 rounded-full hover:text-gray-800 hover:bg-gray-50; +} +.alert-modal .modal-header .modal-close-icon { + @apply w-5 h-5; +} +.alert-modal .modal-body { + @apply relative w-auto pb-8; +} +.alert-modal .modal-footer { + @apply flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2; +} +.alert-modal .modal-footer .modal-action-button { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-900 focus:ring-offset-2 bg-neutral-950 hover:bg-neutral-900; +} +.alert-modal .modal-footer .modal-cancel-button { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium transition-colors border rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-100 focus:ring-offset-2; +} + +/*# sourceMappingURL=alert.css.map */ diff --git a/resources/scss/themes/tailwind/alert.css.map b/resources/scss/themes/tailwind/alert.css.map new file mode 100644 index 00000000..d41e73e7 --- /dev/null +++ b/resources/scss/themes/tailwind/alert.css.map @@ -0,0 +1 @@ +{"version":3,"sourceRoot":"","sources":["components/button.scss","components/position.scss","components/field.scss","components/message.scss","components/notify.scss","components/modal.scss"],"names":[],"mappings":"AACI;EACI;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;;;AClCR;EACE;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;;AC3BF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;;ACdJ;EAEE;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAEA;EACI;;AAIN;EACE;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;;AC5DN;EACE;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;;AC5CJ;EACE;;AAEA;EACE;;AAGF;EACE;;AAEA;EAAU;;AACV;EAAW;;AACX;EAAU;;AACV;EAAgB;;AAChB;EAAe;;AACf;EAAe;;AAGjB;EACE;;AAEA;EAAiB;;AACjB;EAAe;;AACf;EAAiB;;AACjB;EAAc;;AAEd;EACE;;AAGF;EACE;;AAGF;EACE;;AAIJ;EACE;;AAGF;EACE;;AAEA;EACE;;AAGF;EACE","file":"alert.css"} \ No newline at end of file diff --git a/resources/scss/themes/tailwind/alert.scss b/resources/scss/themes/tailwind/alert.scss new file mode 100644 index 00000000..f5250412 --- /dev/null +++ b/resources/scss/themes/tailwind/alert.scss @@ -0,0 +1,6 @@ +@use "./components/button"; +@use "./components/position"; +@use "./components/field"; +@use "./components/message"; +@use "./components/notify"; +@use "./components/modal"; \ No newline at end of file diff --git a/resources/scss/themes/tailwind/components/button.scss b/resources/scss/themes/tailwind/components/button.scss new file mode 100644 index 00000000..22be242b --- /dev/null +++ b/resources/scss/themes/tailwind/components/button.scss @@ -0,0 +1,37 @@ +.alert-button { + &.primary { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-900 focus:ring-offset-2 bg-neutral-950 hover:bg-neutral-900; + } + + &.secondary { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium transition-colors border rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-100 focus:ring-offset-2; + } + + &.success { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-green-700 focus:ring-offset-2 bg-green-600 hover:bg-green-700; + } + + &.error { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-red-700 focus:ring-offset-2 bg-red-600 hover:bg-red-700; + } + + &.warning { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-black transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-yellow-600 focus:ring-offset-2 bg-yellow-400 hover:bg-yellow-500; + } + + &.info { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-blue-700 focus:ring-offset-2 bg-blue-600 hover:bg-blue-700; + } + + &.light { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-black transition-colors border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-300 focus:ring-offset-2 bg-white hover:bg-gray-100; + } + + &.dark { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-gray-900 focus:ring-offset-2 bg-gray-800 hover:bg-gray-900; + } + + &.link { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-blue-600 transition-colors rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 hover:underline; + } +} \ No newline at end of file diff --git a/resources/scss/themes/tailwind/components/field.scss b/resources/scss/themes/tailwind/components/field.scss new file mode 100644 index 00000000..12c1655e --- /dev/null +++ b/resources/scss/themes/tailwind/components/field.scss @@ -0,0 +1,17 @@ +.alert-field { + &.success { + @apply p-3 text-green-800; + } + + &.error { + @apply p-3 text-red-800; + } + + &.warning { + @apply p-3 text-yellow-800; + } + + &.info { + @apply p-3 text-blue-800; + } +} diff --git a/resources/scss/themes/tailwind/components/message.scss b/resources/scss/themes/tailwind/components/message.scss new file mode 100644 index 00000000..d3a0cd8a --- /dev/null +++ b/resources/scss/themes/tailwind/components/message.scss @@ -0,0 +1,65 @@ +.alert-message { + + @apply flex items-center p-4 mb-4 rounded-lg; + + .sr-only-fix { + @apply sr-only; + } + + &.success { + @apply text-green-800 bg-green-50 dark:bg-gray-800 dark:text-green-400; + } + + &.error { + @apply text-red-800 bg-red-50 dark:bg-gray-800 dark:text-red-400; + } + + &.warning { + @apply text-yellow-800 bg-yellow-50 dark:bg-gray-800 dark:text-yellow-300; + } + + &.info { + @apply text-blue-800 bg-blue-50 dark:bg-gray-800 dark:text-blue-400; + } + + .icon { + @apply shrink-0 w-4 h-4; + } + + .message { + @apply ms-3 text-sm font-medium flex items-center gap-2; + + .title { + @apply text-lg font-semibold; + } + } + + .close { + @apply ms-auto -mx-1.5 -my-1.5 p-1.5 inline-flex items-center justify-center h-8 w-8 rounded-lg focus:ring-2; + + &.success { + @apply bg-blue-50 text-blue-500 focus:ring-blue-400 hover:bg-blue-200 dark:bg-gray-800 dark:text-blue-400 dark:hover:bg-gray-700; + } + + &.error { + @apply bg-red-50 text-red-500 focus:ring-red-400 hover:bg-red-200 dark:bg-gray-800 dark:text-red-400 dark:hover:bg-gray-700; + } + + &.warning { + @apply bg-yellow-50 text-yellow-500 focus:ring-yellow-400 hover:bg-yellow-200 dark:bg-gray-800 dark:text-yellow-400 dark:hover:bg-gray-700; + } + + &.info { + @apply bg-blue-50 text-blue-500 focus:ring-blue-400 hover:bg-blue-200 dark:bg-gray-800 dark:text-blue-400 dark:hover:bg-gray-700; + } + + .close-icon { + @apply w-3 h-3; + } + + .sr-only-fix { + @apply sr-only; + } + + } +} diff --git a/resources/scss/themes/tailwind/components/modal.scss b/resources/scss/themes/tailwind/components/modal.scss new file mode 100644 index 00000000..86aae32c --- /dev/null +++ b/resources/scss/themes/tailwind/components/modal.scss @@ -0,0 +1,55 @@ +.alert-modal { + @apply fixed top-0 left-0 z-[99] flex items-center justify-center w-screen h-screen; + + .modal-overlay { + @apply absolute inset-0 w-full h-full bg-white backdrop-blur-sm bg-opacity-70; + } + + .modal-content { + @apply bg-white p-6 rounded-lg shadow-lg relative max-w-full; + + &.small { @apply w-1/4; } + &.medium { @apply w-1/2; } + &.large { @apply w-3/4; } + &.extra-large { @apply w-4/5; } + &.fullscreen { @apply w-full h-full; } + &.scrollable { @apply max-h-[80vh] overflow-y-auto; } + } + + .modal-header { + @apply flex items-center justify-between pb-3; + + &.text-success { @apply text-green-500; } + &.text-error { @apply text-red-500; } + &.text-warning { @apply text-yellow-500; } + &.text-info { @apply text-blue-500; } + + .modal-title { + @apply text-lg font-semibold; + } + + .modal-close { + @apply absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5 text-gray-600 rounded-full hover:text-gray-800 hover:bg-gray-50; + } + + .modal-close-icon { + @apply w-5 h-5; + } + } + + .modal-body { + @apply relative w-auto pb-8; + } + + .modal-footer { + @apply flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2; + + .modal-action-button { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium text-white transition-colors border border-transparent rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-900 focus:ring-offset-2 bg-neutral-950 hover:bg-neutral-900; + } + + .modal-cancel-button { + @apply inline-flex items-center justify-center h-10 px-4 py-2 text-sm font-medium transition-colors border rounded-md focus:outline-none focus:ring-2 focus:ring-neutral-100 focus:ring-offset-2; + } + } +} diff --git a/resources/scss/themes/tailwind/components/notify.scss b/resources/scss/themes/tailwind/components/notify.scss new file mode 100644 index 00000000..42366f91 --- /dev/null +++ b/resources/scss/themes/tailwind/components/notify.scss @@ -0,0 +1,47 @@ +.alert-notify { + @apply bg-gray-900 bg-gradient-to-r text-white rounded-t mb-3 shadow-lg flex items-center; + + &.success { + @apply from-green-400 to-green-500; + } + + &.error { + @apply from-red-400 to-pink-500; + } + + &.warning { + @apply from-yellow-400 to-yellow-500; + } + + &.info { + @apply from-blue-400 to-blue-500; + } + + &.top-right { + @apply top-0 right-0; + } + + &.top-left { + @apply top-0 left-0; + } + + &.bottom-right { + @apply bottom-0 right-0; + } + + &.bottom-left { + @apply bottom-0 left-0; + } + + &.top-center { + @apply top-0 left-1/2 transform -translate-x-1/2; + } + + &.bottom-center { + @apply bottom-0 left-1/2 transform -translate-x-1/2; + } + + &.center { + @apply top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2; + } +} diff --git a/resources/scss/themes/tailwind/components/position.scss b/resources/scss/themes/tailwind/components/position.scss new file mode 100644 index 00000000..9c27f487 --- /dev/null +++ b/resources/scss/themes/tailwind/components/position.scss @@ -0,0 +1,31 @@ +.alert-notify-position { + @apply fixed px-2 mt-3 overflow-x-hidden z-50; + + &.top-right { + @apply top-0 right-0; + } + + &.top-left { + @apply top-0 left-0; + } + + &.bottom-right { + @apply bottom-0 right-0; + } + + &.bottom-left { + @apply bottom-0 left-0; + } + + &.top-center { + @apply top-0 left-1/2 transform -translate-x-1/2; + } + + &.bottom-center { + @apply bottom-0 left-1/2 transform -translate-x-1/2; + } + + &.center { + @apply top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2; + } +} \ No newline at end of file diff --git a/resources/views/components/themes/bootstrap5/field.blade.php b/resources/views/components/themes/bootstrap5/field.blade.php deleted file mode 100644 index f1a7205e..00000000 --- a/resources/views/components/themes/bootstrap5/field.blade.php +++ /dev/null @@ -1,36 +0,0 @@ -@php - $name = $attributes->get('name'); - $tag = $attributes->get('tag', $defaultTag); - $field = $alert->named('field', $name, $tag) ?? $alert->tagged('field', $tag); - $bag = $alert->tagged('bag', $tag); -@endphp - -@if($slot->isNotEmpty()) - {{ $slot }} -@elseif($field && $field->name == $name) -
merge(['class' => 'form-text text-'.$field->getLevel()]) }}> - {{ $error ?? $field->getMessage() }} -
-@elseif($bag && $bag->messageFor($name)) -
merge(['class' => 'form-text text-'.$bag->getLevel()]) }}> - {{ $bag->messageFor($name) }} -
-@elseif(isset($errors)) - @php - $level = $field->getLevel() ?? 'danger'; - @endphp - - @error($name, $tag) -
merge(['class' => 'form-text text-'.$level ]) }}> - {{ $errors->$tag->first($name) }} -
- @enderror - - @if(empty($tag)) - @error($name) -
merge(['class' => 'form-text text-'.$level ]) }}> - {{ $errors->first($name) }} -
- @enderror - @endif -@endif \ No newline at end of file diff --git a/resources/views/components/themes/bootstrap5/message.blade.php b/resources/views/components/themes/bootstrap5/message.blade.php deleted file mode 100644 index 909cdb79..00000000 --- a/resources/views/components/themes/bootstrap5/message.blade.php +++ /dev/null @@ -1,18 +0,0 @@ -@php - $id = $attributes->get('id'); - $tag = $attributes->get('tag', $defaultTag); - $message = $alert->tagged('message', $tag); -@endphp -@if($message) - @php - $id = $id ?? $message->id; - @endphp -
merge(['class' => 'alert alert-dismissible alert-'.$message->getLevel()]) }} role="alert"> - @if ($slot->isNotEmpty()) - {{ $slot }} - @else - @if($message->getTitle()){{ $message->getTitle() }}@endif {{ $message->getMessage() }} - - @endif -
-@endif \ No newline at end of file diff --git a/resources/views/components/themes/bootstrap5/modal.blade.php b/resources/views/components/themes/bootstrap5/modal.blade.php deleted file mode 100644 index 5a77f22d..00000000 --- a/resources/views/components/themes/bootstrap5/modal.blade.php +++ /dev/null @@ -1,126 +0,0 @@ -@php - $tag = $attributes->get('tag', $defaultTag); - $id = $attributes->get('id'); - $modal = $alert->tagged('modal', $tag); - - $cancel = $modal->cancel ?? ''; - $action = $modal->action ?? ''; - $view = $modal->view ?? ''; -@endphp - -@props([ - 'header', - 'body', - 'footer' -]) - -@if($modal) - @php - $id = $id ?? $modal->id; - $hasBody = isset($body) && $body->isNotEmpty(); - $hasHeader = isset($header) && $header->isNotEmpty(); - $hasFooter = isset($footer) && $footer->isNotEmpty(); - $hasTitle = $hasHeader || $modal->getTitle(); - @endphp -
merge(['id' => $id]) }} - {{ $attributes->merge(['class' => 'modal']) }} - {{ $attributes->merge(['tabindex' => '-1']) }} - > - -
- -@endif \ No newline at end of file diff --git a/resources/views/components/themes/bootstrap5/notify.blade.php b/resources/views/components/themes/bootstrap5/notify.blade.php deleted file mode 100644 index 76641ef2..00000000 --- a/resources/views/components/themes/bootstrap5/notify.blade.php +++ /dev/null @@ -1,71 +0,0 @@ -@php - $tag = $attributes->get('tag', $defaultTag); - $id = $attributes->get('id'); - $notify = $alert->tagged('notify', $tag); - $view = $notify->view ?? ''; - $position = $notify->position ?? 'bottom-0 end-0'; -@endphp -@if($notify) - @php - $id = $id ?? $notify->id; - $hasBody = isset($body) && $body->isNotEmpty(); - $hasHeader = isset($header) && $header->isNotEmpty(); - $hasTitle = $hasHeader || $notify->getTitle(); - @endphp -
merge(['class' => 'position-fixed p-3 ' . $position]) }} - {{ $attributes->merge(['z-index' => '100']) }} - > - -
- -@endif \ No newline at end of file diff --git a/resources/views/components/themes/bootstrap5/sticky.blade.php b/resources/views/components/themes/bootstrap5/sticky.blade.php deleted file mode 100644 index c052fd3b..00000000 --- a/resources/views/components/themes/bootstrap5/sticky.blade.php +++ /dev/null @@ -1,32 +0,0 @@ -@php - $id = $attributes->get('id'); - $tag = $attributes->get('tag', $defaultTag); - $sticky = $alert->tagged('sticky', $tag); - $action = $sticky->action ?? ''; -@endphp -@if($sticky) - @php - $id = $id ?? $sticky->id; - @endphp - -
merge(['class' => 'alert alert-dismissible alert-'.$sticky->getLevel()]) }} role="alert"> - @if ($slot->isNotEmpty()) - {{ $slot }} - @else - @if($sticky->getTitle()){{ $sticky->getTitle() }}@endif {{ $sticky->getMessage() }} - - @if($action->label) - @if($action->link) - attributes) !!}> - {{ $action->label }} - - @else - - @endif - @endif - - @endif -
-@endif \ No newline at end of file diff --git a/resources/views/components/themes/classic/field.blade.php b/resources/views/components/themes/classic/field.blade.php deleted file mode 100644 index 8c20a50f..00000000 --- a/resources/views/components/themes/classic/field.blade.php +++ /dev/null @@ -1,37 +0,0 @@ -@php - $name = $attributes->get('name'); - $tag = $attributes->get('tag', $defaultTag); - $field = $alert->named('field', $name, $tag) ?? $alert->tagged('field', $tag); - $bag = $alert->tagged('bag', $tag); - $theme = $attributes->get('theme', 'light'); -@endphp - -@if($slot->isNotEmpty()) - {{ $slot }} -@elseif($field && $field->name == $name) -
merge(['class' => 'form-text text-'.$field->getLevel()]) }}> - {{ $error ?? $field->getMessage() }} -
-@elseif($bag && $bag->messageFor($name)) -
merge(['class' => 'form-text text-'.$bag->getLevel()]) }}> - {{ $bag->messageFor($name) }} -
-@elseif(isset($errors)) - @php - $level = $field->getLevel() ?? 'danger'; - @endphp - - @error($name, $tag) -
merge(['class' => 'form-text text-'.$level ]) }}> - {{ $errors->$tag->first($name) }} -
- @enderror - - @if(empty($tag)) - @error($name) -
merge(['class' => 'form-text text-'.$level ]) }}> - {{ $errors->first($name) }} -
- @enderror - @endif -@endif \ No newline at end of file diff --git a/resources/views/components/themes/classic/message.blade.php b/resources/views/components/themes/classic/message.blade.php deleted file mode 100644 index 63677319..00000000 --- a/resources/views/components/themes/classic/message.blade.php +++ /dev/null @@ -1,19 +0,0 @@ -@php - $id = $attributes->get('id'); - $tag = $attributes->get('tag', $defaultTag); - $message = $alert->tagged('message', $tag); - $theme = $attributes->get('theme', 'light'); -@endphp -@if($message) - @php - $id = $id ?? $message->id; - @endphp -
merge(['class' => 'alert alert-dismissible alert-'.$message->getLevel()]) }} role="alert"> - @if ($slot->isNotEmpty()) - {{ $slot }} - @else - @if($message->getTitle()){{ $message->getTitle() }}@endif {{ $message->getMessage() }} - - @endif -
-@endif \ No newline at end of file diff --git a/resources/views/components/themes/classic/modal.blade.php b/resources/views/components/themes/classic/modal.blade.php deleted file mode 100644 index 27c5e3da..00000000 --- a/resources/views/components/themes/classic/modal.blade.php +++ /dev/null @@ -1,128 +0,0 @@ -@php - $tag = $attributes->get('tag', $defaultTag); - $id = $attributes->get('id'); - $modal = $alert->tagged('modal', $tag); - - $cancel = $modal->cancel ?? ''; - $action = $modal->action ?? ''; - $view = $modal->view ?? ''; - $theme = $attributes->get('theme', 'light'); -@endphp - -@props([ - 'header', - 'body', - 'footer' -]) - -@if($modal) - @php - $id = $id ?? $modal->id; - $hasBody = isset($body) && $body->isNotEmpty(); - $hasHeader = isset($header) && $header->isNotEmpty(); - $hasFooter = isset($footer) && $footer->isNotEmpty(); - $hasTitle = $hasHeader || $modal->getTitle(); - @endphp -
merge(['id' => $id]) }} - {{ $attributes->merge(['class' => 'modal']) }} - {{ $attributes->merge(['tabindex' => '-1']) }} - > - -
- -@endif \ No newline at end of file diff --git a/resources/views/components/themes/classic/notify.blade.php b/resources/views/components/themes/classic/notify.blade.php deleted file mode 100644 index b6b013c9..00000000 --- a/resources/views/components/themes/classic/notify.blade.php +++ /dev/null @@ -1,72 +0,0 @@ -@php - $tag = $attributes->get('tag', $defaultTag); - $id = $attributes->get('id'); - $notify = $alert->tagged('notify', $tag); - $view = $notify->view ?? ''; - $position = $notify->position ?? 'bottom-0 end-0'; - $theme = $attributes->get('theme', 'light'); -@endphp -@if($notify) - @php - $id = $id ?? $notify->id; - $hasBody = isset($body) && $body->isNotEmpty(); - $hasHeader = isset($header) && $header->isNotEmpty(); - $hasTitle = $hasHeader || $notify->getTitle(); - @endphp -
merge(['class' => 'position-fixed p-3 ' . $position]) }} - {{ $attributes->merge(['z-index' => '100']) }} - > - -
- -@endif \ No newline at end of file diff --git a/resources/views/components/themes/classic/sticky.blade.php b/resources/views/components/themes/classic/sticky.blade.php deleted file mode 100644 index dbad4457..00000000 --- a/resources/views/components/themes/classic/sticky.blade.php +++ /dev/null @@ -1,33 +0,0 @@ -@php - $id = $attributes->get('id'); - $tag = $attributes->get('tag', $defaultTag); - $sticky = $alert->tagged('sticky', $tag); - $action = $sticky->action ?? ''; - $theme = $attributes->get('theme', 'light'); -@endphp -@if($sticky) - @php - $id = $id ?? $sticky->id; - @endphp - -
merge(['class' => 'alert alert-dismissible alert-'.$sticky->getLevel()]) }} role="alert"> - @if ($slot->isNotEmpty()) - {{ $slot }} - @else - @if($sticky->getTitle()){{ $sticky->getTitle() }}@endif {{ $sticky->getMessage() }} - - @if($action->label) - @if($action->link) - attributes) !!}> - {{ $action->label }} - - @else - - @endif - @endif - - @endif -
-@endif \ No newline at end of file diff --git a/resources/views/index.blade.php b/resources/views/index.blade.php deleted file mode 100644 index 78e65daf..00000000 --- a/resources/views/index.blade.php +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - Custom Modal - - - - - - - - - - - - \ No newline at end of file diff --git a/resources/views/themes/tailwind/components/field.blade.php b/resources/views/themes/tailwind/components/field.blade.php new file mode 100644 index 00000000..2936879a --- /dev/null +++ b/resources/views/themes/tailwind/components/field.blade.php @@ -0,0 +1,54 @@ +
+ @inject('alert', 'Digitlimit\Alert\Alert') + @php + $field = $data ? $alert->fromArray($data) : null; + $bag = $data ? $alert->fieldBag($tag): null; + + if ($field && $field->getName() == $name) { + $level = $field->getLevel(); + $message = $field->getMessage(); + } elseif($bag && $bag->messageFor($name)) { + $level = $bag->getLevel(); + $message = $bag->messageFor($name); + } else { + $level = null; + $message = null; + } + @endphp + + @if($level && $message) + + @elseif($errors->has($name)) + + @endif +
diff --git a/resources/views/themes/tailwind/components/message.blade.php b/resources/views/themes/tailwind/components/message.blade.php new file mode 100644 index 00000000..1bccf8c3 --- /dev/null +++ b/resources/views/themes/tailwind/components/message.blade.php @@ -0,0 +1,57 @@ +
+ @inject('alert', 'Digitlimit\Alert\Alert') + @php + $message = $alert->fromArray($data); + $level = $message->getLevel(); + @endphp + +
diff --git a/resources/views/themes/tailwind/components/modal.blade.php b/resources/views/themes/tailwind/components/modal.blade.php new file mode 100644 index 00000000..f0b6ab87 --- /dev/null +++ b/resources/views/themes/tailwind/components/modal.blade.php @@ -0,0 +1,122 @@ +
+ @inject('alert', 'Digitlimit\Alert\Alert') + @php + $modal = $alert->fromArray($data); + $header = $header ?? null; + $body = $body ?? null; + $footer = $footer ?? null; + $hasBody = !is_null($body); + $hasHeader = !is_null($header); + $hasFooter = !is_null($footer); + + $hasTitle = $hasHeader || $modal->getTitle(); + @endphp +
+
+ + + + + + +
+
+
diff --git a/resources/views/themes/tailwind/components/modal1.blade.php b/resources/views/themes/tailwind/components/modal1.blade.php new file mode 100644 index 00000000..16f83d52 --- /dev/null +++ b/resources/views/themes/tailwind/components/modal1.blade.php @@ -0,0 +1,129 @@ +
+ @inject('alert', 'Digitlimit\Alert\Alert') + @php + $modal = $alert->fromArray($data); + $header = $header ?? null; + $body = $body ?? null; + $footer = $footer ?? null; + $hasBody = !is_null($body); + $hasHeader = !is_null($header); + $hasFooter = !is_null($footer); + + $hasTitle = $hasHeader || $modal->getTitle(); + @endphp +
+
+ + +
+
+ + +
+ + +
+ @if($modal->hasTitle()) +

{{ $modal->getTitle() }}

+ @endif + +
+ + @if($modal->hasView()) + {!! $modal->getView() !!} + @else +
+ @if($hasBody) + {{ $body }} + @elseif($modal->getMessage()) + {{ $modal->getMessage() }} + @endif +
+ @endif + +
+ @foreach($modal->getButtons() as $button) + @if($button->isAction()) + @if($button->isLink()) + actionLinkAttributes($button->getAttributes()) !!}> + {{ $button->getLabel() }} + + @else + + @endif + @elseif($button->isCancel()) + @if($button->isLink()) + cancelLinkAttributes($button->getAttributes()) !!}> + {{ $button->getLabel() }} + + @else + + @endif + @else + @if($button->isLink()) + getAttributes() !!}> + {{ $button->getLabel() }} + + @else + + @endif + @endif + @endforeach +
+
+
+
+
diff --git a/resources/views/themes/tailwind/components/notify.blade.php b/resources/views/themes/tailwind/components/notify.blade.php new file mode 100644 index 00000000..30995a93 --- /dev/null +++ b/resources/views/themes/tailwind/components/notify.blade.php @@ -0,0 +1,109 @@ +
+ @inject('alert', 'Digitlimit\Alert\Alert') + @php + $notify = $alert->fromArray($data); + @endphp +
+ +
+
\ No newline at end of file diff --git a/resources/views/themes/tailwind/components/notify1.blade.php b/resources/views/themes/tailwind/components/notify1.blade.php new file mode 100644 index 00000000..f530315a --- /dev/null +++ b/resources/views/themes/tailwind/components/notify1.blade.php @@ -0,0 +1,112 @@ +
+ @inject('alert', 'Digitlimit\Alert\Alert') + @php + $notify = $alert->fromArray($data); + $position = config('alert.tailwind.classes.notify.position.' . $notify->getPosition()); + $container = config('alert.tailwind.classes.notify.levels.' . $notify->getLevel() . '.container'); + @endphp +
diff --git a/rollup.config.js b/rollup.config.js deleted file mode 100644 index 12e16578..00000000 --- a/rollup.config.js +++ /dev/null @@ -1,48 +0,0 @@ -import resolve from '@rollup/plugin-node-resolve'; -import commonjs from '@rollup/plugin-commonjs'; -import babel from '@rollup/plugin-babel'; -import terser from '@rollup/plugin-terser'; -import scss from 'rollup-plugin-scss'; -import postcss from 'postcss'; -import cssnano from 'cssnano'; -import fs from 'fs'; - -export default { - input: 'resources/js/alert.js', - output: [ - { - file: 'public/js/alert.js', - format: 'iife', - name: 'DigitlimitAlert', - sourcemap: false, - }, - { - file: 'public/js/alert.min.js', - format: 'iife', - name: 'DigitlimitAlert', - plugins: [terser()], - sourcemap: false, - }, - ], - plugins: [ - resolve(), - commonjs(), - babel({ - babelHelpers: 'bundled', - exclude: 'node_modules/**', - }), - scss({ - output: (styles, styleNodes) => { - // Write the uncompressed CSS file - fs.writeFileSync('public/css/alert.css', styles); - - // Minify the CSS and write the minified file - postcss([cssnano()]) - .process(styles, { from: undefined }) - .then((result) => { - fs.writeFileSync('public/css/alert.min.css', result.css); - }); - }, - }), - ], -}; \ No newline at end of file diff --git a/src/Alert.php b/src/Alert.php index 89647eed..5906661a 100644 --- a/src/Alert.php +++ b/src/Alert.php @@ -2,14 +2,15 @@ namespace Digitlimit\Alert; +use Digitlimit\Alert\Contracts\HasName; +use Digitlimit\Alert\Contracts\Taggable; +use Digitlimit\Alert\Factory\AlertFactory; +use Digitlimit\Alert\Foundation\AlertInterface; use Digitlimit\Alert\Helpers\SessionKey; use Digitlimit\Alert\Helpers\Type; -use Digitlimit\Alert\Message\MessageFactory; -use Digitlimit\Alert\Message\MessageInterface; use Exception; -use Illuminate\Support\MessageBag; +use Illuminate\Support\Facades\Session; use Illuminate\Support\Traits\Macroable; -use Illuminate\Validation\Validator; class Alert { @@ -20,53 +21,46 @@ class Alert */ const DEFAULT_TAG = 'default'; - /** - * Create a new alert instance. - */ - public function __construct( - protected SessionInterface $session - ) { - } - /** * Fetch an alert based on the default tag. + * + * @throws Exception */ - public function default(string $type): ?MessageInterface + public function default(string $type): ?Taggable { return self::tagged($type, self::DEFAULT_TAG); } /** * Fetch an alert based on the type and named. + * + * @throws Exception */ - public function named( - string $type, - string $name, - ?string $tag = null - ): ?MessageInterface { - if (!Type::exists($type)) { + public static function named(string $type, string $name, string $tag): ?HasName + { + if (! Type::exists($type)) { throw new Exception("Invalid alert type '$type'. Check the alert config"); } - $tag = ($tag ?? self::DEFAULT_TAG).'.'.$name; + $tag = $tag.'.'.$name; - return $this->session->get( + return Session::get( SessionKey::key($type, $tag) ); } /** * Fetch an alert based on the tag name. + * + * @throws Exception */ - public function tagged( - string $type, - string $tag - ): ?MessageInterface { - if (!Type::exists($type)) { + public static function tagged(string $type, string $tag): ?Taggable + { + if (! Type::exists($type)) { throw new Exception("Invalid alert type '$type'. Check the alert config"); } - $tagged = $this->session->get( + $tagged = Session::get( SessionKey::key($type, $tag) ); @@ -78,74 +72,135 @@ public function tagged( } /** - * Fetch the field alert. + * @throws Exception */ - public function field(?string $name = null, ?string $message = null): MessageInterface + public static function taggedField(string $tag): ?Taggable { - return MessageFactory::make( - $this->session, - 'field', - $name, - $message - ); + return self::tagged('field', $tag); } /** - * Fetch the field bag alert. + * @throws Exception */ - public function fieldBag( - Validator|MessageBag|null $bag = null - ): MessageInterface { - return MessageFactory::make( - $this->session, - 'bag', - $bag - ); + public static function namedField(string $name, string $tag): ?AlertInterface + { + return self::named('field', $name, $tag); } /** - * Fetch the modal alert. + * @throws Exception */ - public function modal(?string $message = null): MessageInterface + public static function fieldBag(string $tag): ?Taggable { - return MessageFactory::make($this->session, 'modal', $message); + return self::tagged('bag', $tag); } /** - * Fetch the notify alert. + * @throws Exception */ - public function notify(?string $message = null): MessageInterface + public static function taggedMessage(string $tag): ?Taggable { - return MessageFactory::make($this->session, 'notify', $message); + return self::tagged('message', $tag); } /** - * Fetch the sticky alert. + * @throws Exception */ - public function sticky(?string $message = null): MessageInterface + public static function taggedModal(string $tag): ?Taggable { - return MessageFactory::make($this->session, 'sticky', $message); + return self::tagged('modal', $tag); } /** - * Fetch the default alert type, which is the message alert. + * @throws Exception */ - public function message(string $message): MessageInterface + public static function taggedNotify(string $tag): ?Taggable { - return MessageFactory::make($this->session, 'message', $message); + return self::tagged('notify', $tag); } /** * Fetch an alert from the given alert type. + * + * @throws Exception */ - public function from( - string $type, - ...$args - ): MessageInterface { - if (!Type::exists($type)) { + public static function from(string $type, ...$args): AlertInterface + { + if (! Type::exists($type)) { throw new Exception("Invalid alert type '$type'. Check the alert config"); } - return MessageFactory::make($this->session, $type, ...$args); + return AlertFactory::make($type, ...$args); + } + + /** + * @throws Exception + */ + public static function fromArray(array $alert): ?AlertInterface + { + if (empty($alert)) { + return null; + } + + $type = $alert['type'] ?? null; + + if (! $type || ! Type::exists($type)) { + throw new Exception("Invalid alert type '$type'. Check the alert config"); + } + + return AlertFactory::makeFromArray($alert); + } + + /** + * Fetch all alerts from the session. + */ + public static function has(string $type): bool + { + $types = Session::get(SessionKey::typeKey($type)) ?? []; + + return ! empty($types); + } + + /** + * Fetch all alerts from the session. + */ + public static function count(?string $type = null): int + { + $types = self::all($type); + + if ($type) { + return count($types); + } + + $count = 0; + foreach ($types as $type) { + $count += count($type); + } + + return $count; + } + + /** + * Fetch all alerts from the session. + */ + public static function all(?string $type = null): array + { + return $type + ? Session::get(SessionKey::typeKey($type), []) + : Session::get(SessionKey::mainKey(), []); + } + + /** + * Dynamically handle method calls for different alert types. + * + * @throws Exception + */ + public function __call($method, $parameters) + { + if (Type::exists($method)) { + return AlertFactory::make($method, ...$parameters); + } + + throw new Exception("Method '$method' not found in Alert class."); } } diff --git a/src/AlertServiceProvider.php b/src/AlertServiceProvider.php index 79ad3de4..50da161b 100644 --- a/src/AlertServiceProvider.php +++ b/src/AlertServiceProvider.php @@ -2,9 +2,7 @@ namespace Digitlimit\Alert; -use Digitlimit\Alert\Helpers\Theme; use Exception; -use Illuminate\Support\Facades\Blade; use Illuminate\Support\ServiceProvider; class AlertServiceProvider extends ServiceProvider @@ -18,13 +16,9 @@ public function boot(): void { $this->loadViewsFrom(__DIR__.'/../resources/views', 'alert'); - $this->registerComponents(); - $this->registerMacros(); $this->bootForConsole(); - - $this->registerBladeDirectives(); } /** @@ -32,14 +26,13 @@ public function boot(): void */ public function register(): void { - $this->app->bind(SessionInterface::class, Session::class); - $this->app->bind(ConfigInterface::class, Config::class); - $this->app->singleton('alert', function ($app) { return $app->make(Alert::class); }); $this->mergeConfigFrom(__DIR__.'/../config/alert.php', 'alert'); + + $this->app->register(Themes\Tailwind\TailwindServiceProvider::class); } /** @@ -68,26 +61,6 @@ protected function bootForConsole(): void ], 'alert.assets'); } - /** - * Register alert components. - * - * @throws Exception - */ - protected function registerComponents(): void - { - $theme = Theme::theme(); - - if (empty($theme)) { - throw new Exception('Invalid alert theme configuration'); - } - - Blade::componentNamespace($theme['components'], 'alert'); - - foreach ($theme['types'] as $type) { - Blade::component($type['view'], $type['component']); - } - } - /** * Register some helper macros. */ @@ -99,23 +72,4 @@ protected function registerMacros(): void ->forget($tag); }); } - - /** - * Register Blade directives. - */ - public function registerBladeDirectives(): void - { - $css = asset('vendor/alert/css/alert.css'); - $js = asset('vendor/alert/js/alert.js'); - - Blade::directive( - 'alertStyles', - fn () => '' - ); - - Blade::directive( - 'alertScripts', - fn () => '' - ); - } } diff --git a/src/Component/Button.php b/src/Component/Button.php index 7b3ea6c2..7c62d3fe 100644 --- a/src/Component/Button.php +++ b/src/Component/Button.php @@ -2,6 +2,9 @@ namespace Digitlimit\Alert\Component; +/** + * The button component. + */ class Button { /** @@ -10,33 +13,131 @@ class Button * @return void */ public function __construct( - public ?string $label = null, - public ?string $link = null, - public array $attributes = [] - ) { + protected string $name, + protected ?string $label = null, + protected ?string $link = null, + protected array $attributes = [] + ) {} + + /** + * Set the button name. + */ + public function name(string $name): self + { + $this->name = $name; + + return $this; } /** * Set the button label. */ - public function label(string $label): void + public function label(string $label): self { $this->label = $label; + + return $this; } /** * Set the button link. */ - public function link(string $link): void + public function link(string $link): self { $this->link = $link; + + return $this; } /** * Set the button attributes. */ - public function attributes(array $attributes): void + public function attributes(array $attributes): self { $this->attributes = $attributes; + + return $this; + } + + /** + * Get the button name. + */ + public function getName(): string + { + return $this->name; + } + + /** + * Get the button attributes. + */ + public function getAttributes(): array + { + return $this->attributes; + } + + /** + * Get the button link. + */ + public function getLink(): ?string + { + return $this->link; + } + + /** + * Get the button label. + */ + public function getLabel(): ?string + { + return $this->label; + } + + /** + * Check if button is link button. + */ + public function isLink(): bool + { + return ! empty($this->link); + } + + /** + * Check if button is action button. + */ + public function isAction(): bool + { + return $this->getName() === 'action'; + } + + /** + * Check if button is cancel button. + */ + public function isCancel(): bool + { + return $this->getName() === 'cancel'; + } + + /** + * Convert the button instance to an array. + */ + public function toArray(): array + { + return [ + 'name' => $this->getName(), + 'label' => $this->getLabel(), + 'link' => $this->getLink(), + 'attributes' => $this->getAttributes(), + ]; + } + + /** + * Fill the button from an array. + */ + public static function fill(array $button): self + { + return new static( + $button['name'], + $button['label'], + $button['link'], + $button['attributes'] + ); } } diff --git a/src/Config.php b/src/Config.php deleted file mode 100644 index 3a40a23e..00000000 --- a/src/Config.php +++ /dev/null @@ -1,26 +0,0 @@ -config = $config; - } - - /** - * Fetch value from the config based on the given key. - */ - public function get(string $key, mixed $default = null): mixed - { - return $this->config->get($key, $default); - } -} diff --git a/src/ConfigInterface.php b/src/ConfigInterface.php deleted file mode 100644 index 0ab506f1..00000000 --- a/src/ConfigInterface.php +++ /dev/null @@ -1,11 +0,0 @@ - + */ + public function broadcastOn(): array + { + return [ + new PrivateChannel('channel-name'), + ]; + } +} diff --git a/src/Events/Message/Flashed.php b/src/Events/Message/Flashed.php new file mode 100644 index 00000000..57c53064 --- /dev/null +++ b/src/Events/Message/Flashed.php @@ -0,0 +1,34 @@ + + */ + public function broadcastOn(): array + { + return [ + new PrivateChannel('channel-name'), + ]; + } +} diff --git a/src/Events/Modal/Flashed.php b/src/Events/Modal/Flashed.php new file mode 100644 index 00000000..5fc7fa87 --- /dev/null +++ b/src/Events/Modal/Flashed.php @@ -0,0 +1,34 @@ + + */ + public function broadcastOn(): array + { + return [ + new PrivateChannel('channel-name'), + ]; + } +} diff --git a/src/Events/Notify/Flashed.php b/src/Events/Notify/Flashed.php new file mode 100644 index 00000000..f934e2c1 --- /dev/null +++ b/src/Events/Notify/Flashed.php @@ -0,0 +1,34 @@ + + */ + public function broadcastOn(): array + { + return [ + new PrivateChannel('channel-name'), + ]; + } +} diff --git a/src/Facades/Alert.php b/src/Facades/Alert.php index 3dbe4813..ea9c5ab0 100644 --- a/src/Facades/Alert.php +++ b/src/Facades/Alert.php @@ -18,11 +18,6 @@ * @method static error(string $string) * @method static warning(string $string) * @method static info(string $string) - * @method static danger(string $string) - * @method static primary(string $string) - * @method static secondary(string $string) - * @method static dark(string $string) - * @method static light(string $string) */ class Alert extends Facade { diff --git a/src/Factory/AlertFactory.php b/src/Factory/AlertFactory.php new file mode 100644 index 00000000..d546fd8f --- /dev/null +++ b/src/Factory/AlertFactory.php @@ -0,0 +1,46 @@ +fill($alert); + } +} diff --git a/src/Foundation/AbstractAlert.php b/src/Foundation/AbstractAlert.php new file mode 100644 index 00000000..27feae82 --- /dev/null +++ b/src/Foundation/AbstractAlert.php @@ -0,0 +1,101 @@ +autoSetId(); + } + + /** + * Set alert ID. + */ + public function id(string|int $id): self + { + $this->id = $id; + + return $this; + } + + /** + * Set alert ID to auto generate. + */ + public function autoSetId(): self + { + $this->id($this->key().'-'.Helper::randomString()); + + return $this; + } + + /** + * Fetch the alert ID. + */ + public function getId(): string|int + { + return $this->id; + } + + /** + * Flash alert to store. + * Its temporal store that is deleted once pulled/fetched. + */ + public function flash(): void + { + $sessionKey = SessionKey::key($this->key(), $this->getTag()); + + if (empty($sessionKey)) { + return; + } + + Session::flash($sessionKey, $this); + } + + /** + * Remove alert from the store. + */ + public function forget(?string $tag = null): self + { + if (empty($tag)) { + $tag = ! empty($this->tag) + ? $this->tag + : Alert::DEFAULT_TAG; + } + + $sessionKey = SessionKey::key($this->key(), $tag); + + Session::forget($sessionKey); + + return $this; + } + + /** + * Convert alert to array. + */ + public function toArray(): array + { + return [ + 'id' => $this->getId(), + ]; + } +} diff --git a/src/Foundation/AbstractTheme.php b/src/Foundation/AbstractTheme.php new file mode 100644 index 00000000..846931eb --- /dev/null +++ b/src/Foundation/AbstractTheme.php @@ -0,0 +1,7 @@ +message($message) - ->info(); + ->message($message); + + $alert->level($level); if ($title) { $alert->title($title); } + $alert->flash(); + return $alert; } } -if (!function_exists('field')) { - function field(string $name, string $message, ?string $tag = null): mixed - { +if (! function_exists('field')) { + function field( + string $name, + string $message, + ?string $tag = null, + string $level = 'success' + ): Field { $alert = app('alert')->field($name, $message); if ($tag) { $alert->tag($tag); } + $alert->level($level); + + $alert->flash(); + return $alert; } } -if (!function_exists('fieldBag')) { - function fieldBag(Validator|MessageBag $bag): mixed +if (! function_exists('fieldBag')) { + function fieldBag(Validator|MessageBag $bag): FieldBag { - return app('alert') + $bag = app('alert') ->fieldBag($bag); + + $bag->flash(); + + return $bag; } } -if (!function_exists('modal')) { - function modal(string $message, ?string $title = null): mixed - { +if (! function_exists('modal')) { + function modal( + string $message, + ?string $title = null, + ?string $tag = null, + string $level = 'success' + ): Modal { $alert = app('alert')->modal($message); if ($title) { $alert->title($title); } + $alert->level($level); + + if ($tag) { + $alert->tag($tag); + } + + $alert->flash(); + return $alert; } } -if (!function_exists('notify')) { - function notify(string $message, ?string $title = null): mixed - { +if (! function_exists('notify')) { + function notify( + string $message, + ?string $title = null, + string $level = 'success', + string $position = 'top-right' + ): Notify { $alert = app('alert')->notify($message); if ($title) { $alert->title($title); } + $alert->level($level); + $alert->position($position); + + $alert->flash(); + return $alert; } } -if (!function_exists('sticky')) { - function sticky(string $message, ?string $title = null): mixed - { +if (! function_exists('sticky')) { + function sticky( + string $message, + ?string $title = null, + string $level = 'success' + ): Sticky { $alert = app('alert')->sticky($message); if ($title) { $alert->title($title); } + $alert->level($level); + + $alert->flash(); + return $alert; } } -if (!function_exists('forgetSticky')) { +if (! function_exists('forgetSticky')) { function forgetSticky(?string $name = null): void { app('alert')->stickForget($name); diff --git a/src/Helpers/Attribute.php b/src/Helpers/Attribute.php index d57fd3fb..8f1c3dd3 100644 --- a/src/Helpers/Attribute.php +++ b/src/Helpers/Attribute.php @@ -5,7 +5,7 @@ class Attribute { /** - * Convert attributes array to HTML string attributes. + * Convert an attribute array to HTML string attributes. */ public static function toString(array $attributes): string { diff --git a/src/Helpers/Helper.php b/src/Helpers/Helper.php index 67c7825a..5ac28a3e 100644 --- a/src/Helpers/Helper.php +++ b/src/Helpers/Helper.php @@ -2,8 +2,6 @@ namespace Digitlimit\Alert\Helpers; -use Digitlimit\Alert\ConfigInterface; - class Helper { /** @@ -13,9 +11,4 @@ public static function randomString(int $length = 10): string { return substr(md5(mt_rand()), 0, $length); } - - public static function config(): ConfigInterface - { - return app(ConfigInterface::class); - } } diff --git a/src/Helpers/SessionKey.php b/src/Helpers/SessionKey.php index ab66384d..21bb1e21 100644 --- a/src/Helpers/SessionKey.php +++ b/src/Helpers/SessionKey.php @@ -2,6 +2,9 @@ namespace Digitlimit\Alert\Helpers; +/** + * Session key helper class. + */ class SessionKey { /** @@ -9,13 +12,24 @@ class SessionKey */ const MAIN_KEY = 'digitlimit.alert'; + public static function mainKey(): string + { + return self::MAIN_KEY; + } + /** - * Get session key for a given type and tag. + * Get a session key for a given type and tag. */ public static function key(string $type, string $tag): string { - return self::MAIN_KEY - .'.'.$type - .'.'.$tag; + return self::mainKey() + .'.'.$type + .'.'.$tag; + } + + public static function typeKey(string $type): string + { + return self::mainKey() + .'.'.$type; } } diff --git a/src/Helpers/Theme.php b/src/Helpers/Theme.php index 9ebbf5a1..872d63a4 100644 --- a/src/Helpers/Theme.php +++ b/src/Helpers/Theme.php @@ -2,23 +2,39 @@ namespace Digitlimit\Alert\Helpers; +use Digitlimit\Alert\Contracts\ThemeInterface; +use Exception; +use Illuminate\Support\Facades\Config; + +/** + * Theme helper class. + */ class Theme { public static function name(): string { - return Helper::config()->get('alert.theme'); + return Config::get('alert.theme'); } public static function all(): array { - return Helper::config()->get('alert.themes'); + return Config::get('alert.themes'); } - public static function theme(): array + /** + * @throws Exception + */ + public static function theme(): ThemeInterface { $name = self::name(); $themes = self::all(); - return $themes[$name] ?? []; + $theme = $themes[$name] ?? null; + + if (! $theme) { + throw new Exception("Theme {$name} not found"); + } + + return app($theme); } } diff --git a/src/Helpers/Type.php b/src/Helpers/Type.php index 692c87d3..efeb57e8 100644 --- a/src/Helpers/Type.php +++ b/src/Helpers/Type.php @@ -4,6 +4,9 @@ use Exception; +/** + * Alert type helper. + */ class Type { /** @@ -13,12 +16,12 @@ class Type /** * Fetch alert types from the config file. + * + * @throws Exception */ public static function types(): array { - $theme = Theme::theme(); - - return $theme['types'] ?? []; + return Theme::theme()->types(); } /** @@ -54,10 +57,10 @@ public static function type(string $type): array */ public static function classname(string $type): string { - if (!self::exists($type)) { + if (! self::exists($type)) { throw new Exception("The alert type '$type' does not exist in config"); } return self::type($type)['alert']; } -} +} \ No newline at end of file diff --git a/src/Message/AbstractMessage.php b/src/Message/AbstractMessage.php deleted file mode 100644 index 0b6684e8..00000000 --- a/src/Message/AbstractMessage.php +++ /dev/null @@ -1,143 +0,0 @@ -id = $id; - $this->flash(); - - return $this; - } - - /** - * Set alert level. - */ - public function level(string $level): self - { - $this->level = $level; - $this->flash(); - - return $this; - } - - /** - * Set alert message. - */ - public function message(string $message): self - { - $this->message = $message; - $this->flash(); - - return $this; - } - - /** - * Set the alert title. - */ - public function title(string $title): self - { - $this->title = $title; - $this->flash(); - - return $this; - } - - /** - * Set the alert tag. - */ - public function tag(string $tag): self - { - $this->tag = $tag; - $this->flash(); - - return $this; - } - - /** - * Fetch the alert tag. - */ - public function getTag(): string - { - return $this->tag; - } - - /** - * Fetch the alert level. - */ - public function getLevel(): ?string - { - return $this->level ?? null; - } - - /** - * Fetch the alert title. - */ - public function getTitle(): ?string - { - return $this->title ?? null; - } - - /** - * Fetch the alert message. - */ - public function getMessage(): ?string - { - return $this->message ?? null; - } - - /** - * Flash alert to store. - * Its temporal store that is deleted once pulled/fetched. - */ - public function flash(): void - { - $sessionKey = SessionKey::key($this->key(), $this->getTag()); - - if (empty($sessionKey)) { - return; - } - - $this->session->flash($sessionKey, $this); - } -} diff --git a/src/Message/MessageFactory.php b/src/Message/MessageFactory.php deleted file mode 100644 index 60fd9179..00000000 --- a/src/Message/MessageFactory.php +++ /dev/null @@ -1,24 +0,0 @@ -data = $data; + } + + /** + * Create a new component instance. + * + * @throws Exception + */ + public function mount(): void + { + if (! empty($this->for)) { + $this->name = $this->for; + } + + if (! empty($this->name) && ! empty($this->tag)) { + $data = Alert::namedField($this->name, $this->tag)?->toArray(); + + if (! empty($data)) { + $this->setUp($data); + } + } + } + + #[On('refresh-alert-field')] + public function refresh(string $tag, array $data): void + { + if (empty($data) || empty($this->name)) { + return; + } + + if ($this->tag !== $tag || $this->name !== $data['name']) { + return; + } + + $this->setUp($data); + $this->dispatch('open-alert-field'); + } + + /** + * Get Laravel errors. + */ + public function getViewErrors(): MessageBag + { + $errors = session('errors'); + + return $errors instanceof MessageBag + ? $errors + : new MessageBag; + } + + /** + * Get tagged view errors. + */ + public function getTaggedViewErrors(string $tag): MessageBag + { + return $this->getViewErrors()->{$tag} ?? new MessageBag; + } + + public function getViewFieldError(string $name, string $tag): ?string + { + $taggedErrors = $this->getTaggedViewErrors($tag); + + if ($taggedErrors->has($name)) { + return $taggedErrors->first($name); + } + + $viewErrors = $this->getViewErrors(); + + if ($viewErrors->has($name)) { + return $viewErrors->first($name); + } + + return null; + } + + /** + * Get the view / contents that represent the component. + */ + public function render(): View + { + return view('alert::themes.tailwind.components.field', [ + 'error' => $this->getViewFieldError($this->name, $this->tag), + ]); + } +} diff --git a/src/Themes/Tailwind/Components/Message.php b/src/Themes/Tailwind/Components/Message.php new file mode 100644 index 00000000..e0bdb659 --- /dev/null +++ b/src/Themes/Tailwind/Components/Message.php @@ -0,0 +1,77 @@ +data = $data; + } + + /** + * Create a new component instance. + * + * @throws Exception + */ + public function mount(): void + { + $this->tag = $this->tag ?? $this->defaultTag; + $data = Alert::taggedModal($this->tag)?->toArray() ?? []; + + if (empty($data)) { + $this->skipRender(); + + return; + } + + $this->setUp($data); + } + + #[On('refresh-alert-message')] + public function refresh(string $tag, array $data): void + { + if ($this->tag !== $tag || empty($data)) { + return; + } + + $this->setUp($data); + $this->dispatch('open-alert-message'); + } + + /** + * Get the view / contents that represent the component. + */ + public function render(): View + { + return view('alert::themes.tailwind.components.message'); + } +} diff --git a/src/Themes/Tailwind/Components/Modal.php b/src/Themes/Tailwind/Components/Modal.php new file mode 100644 index 00000000..114eb7cf --- /dev/null +++ b/src/Themes/Tailwind/Components/Modal.php @@ -0,0 +1,133 @@ +tag = $this->tag ?? $this->defaultTag; + $this->data = Alert::taggedModal($this->tag)?->toArray() ?? []; + + if (empty($this->data)) { + $this->skipRender(); + } + } + + #[On('refresh-alert-modal')] + public function refresh(string $tag, array $data): void + { + if ($this->tag !== $tag) { + return; + } + + $this->data = $data; + $this->dispatch('open-alert-modal'); + } + + /** + * Merge and convert array attributes to HTML string attributes. + */ + public function actionAttributes(array $attributes = []): string + { +// $button = config('alert.tailwind.classes.buttons.primary'); + $buttonAttributes = config('alert.tailwind.attributes.buttons.action'); + $buttonAttributes['class'] = 'modal-action-button'; + + $newAttributes = array_merge( + $buttonAttributes, + $attributes + ); + + return Attribute::toString($newAttributes); + } + + /** + * Merge and convert array attributes to HTML string attributes. + */ + public function cancelAttributes(array $attributes = []): string + { +// $button = config('alert.tailwind.classes.buttons.secondary'); + $buttonAttributes = config('alert.tailwind.attributes.buttons.cancel'); + $buttonAttributes['class'] = 'modal-cancel-button'; + + $newAttributes = array_merge( + $buttonAttributes, + $attributes + ); + + return Attribute::toString($newAttributes); + } + + /** + * Merge and convert array attributes to HTML string attributes. + */ + public function actionLinkAttributes(array $attributes = []): string + { +// $button = config('alert.tailwind.classes.buttons.primary'); + $linkAttributes = config('alert.tailwind.attributes.links.action'); + $linkAttributes['class'] = 'modal-action-button'; + + $newAttributes = array_merge( + $linkAttributes, + $attributes + ); + + return Attribute::toString($newAttributes); + } + + /** + * Merge and convert array attributes to HTML string attributes. + */ + public function cancelLinkAttributes(array $attributes = []): string + { +// $button = config('alert.tailwind.classes.buttons.secondary'); + $linkAttributes = config('alert.tailwind.attributes.links.cancel'); + $linkAttributes['class'] = 'modal-cancel-button';; + + $newAttributes = array_merge( + $linkAttributes, + $attributes + ); + + return Attribute::toString($newAttributes); + } + + /** + * Get the view / contents that represent the component. + */ + public function render(): View + { + return view('alert::themes.tailwind.components.modal'); + } + +} diff --git a/src/Themes/Tailwind/Components/Notify.php b/src/Themes/Tailwind/Components/Notify.php new file mode 100644 index 00000000..aa2beee5 --- /dev/null +++ b/src/Themes/Tailwind/Components/Notify.php @@ -0,0 +1,71 @@ +data = $data; + } + + /** + * Create a new component instance. + * + * @throws Exception + */ + public function mount(): void + { + $data = Alert::taggedNotify($this->tag)?->toArray() ?? []; + + if (empty($data)) { + $this->skipRender(); + + return; + } + + $this->setUp($data); + } + + #[On('refresh-alert-notify')] + public function refresh(string $tag, array $data): void + { + if ($this->tag !== $tag || empty($data)) { + return; + } + + $this->setUp($data); + $this->dispatch('open-alert-notify'); + } + + /** + * Get the view / contents that represent the component. + */ + public function render(): View + { + return view('alert::themes.tailwind.components.notify'); + } +} diff --git a/src/Themes/Tailwind/Tailwind.php b/src/Themes/Tailwind/Tailwind.php new file mode 100644 index 00000000..70c6a408 --- /dev/null +++ b/src/Themes/Tailwind/Tailwind.php @@ -0,0 +1,102 @@ +has('redirect')) { + return false; + } + + if (count(session()->get(SessionKey::mainKey()) ?? []) <= 0) { + return false; + } + + if (is_a($component, LivewireInterface::class)) { + return false; + } + + foreach (Alert::all() as $alerts) { + + if (empty($alerts)) { + continue; + } + + foreach ($alerts as $tag => $alert) { + + // For single alert example message, modal + if (! is_array($alert)) { + self::dispatch($component, $alert); + + continue; + } + // For multiple alerts, usually from a field + foreach ($alert as $field) { + self::dispatch($component, $field); + } + } + } + + return $component; + }); + } + + /** + * Dispatch the alert to the component + */ + protected static function dispatch(Component $component, AlertInterface|Taggable $alert): Component + { + $event = 'refresh-alert-'.$alert->key(); + + $component->dispatch( + $event, + $alert->getTag(), + $alert->toArray() + ); + + return $component; + } +} diff --git a/src/Themes/Tailwind/TailwindServiceProvider.php b/src/Themes/Tailwind/TailwindServiceProvider.php new file mode 100644 index 00000000..6c3bca14 --- /dev/null +++ b/src/Themes/Tailwind/TailwindServiceProvider.php @@ -0,0 +1,74 @@ +bootForConsole(); + + $this->registerDirectives(); + } + + /** + * Register any package services. + */ + public function register(): void + { + $this->app->singleton('alert-theme', function ($app) { + return Theme::theme(); + }); + } + + /** + * Get the services provided by the provider. + */ + public function provides(): array + { + return ['alert-theme']; + } + + /** + * Console-specific booting. + */ + protected function bootForConsole(): void + { + // Define publishable SCSS assets + $this->publishes([ + __DIR__ . '/../../../resources/scss/themes/tailwind' => resource_path('scss/alert'), + ], 'alert-scss'); + + // Define publishable compiled CSS + $this->publishes([ + __DIR__ . '/../../../resources/css/themes/tailwind/alert.css' => public_path('vendor/alert/alert.css'), + ], 'alert-css'); + } + + /** + * Register directives + */ + public function registerDirectives(): void + { + Blade::directive('alertStyles', function () { + return ''; + }); + } +} diff --git a/src/Themes/Tailwind/Utils/Css.php b/src/Themes/Tailwind/Utils/Css.php new file mode 100644 index 00000000..fef9efb6 --- /dev/null +++ b/src/Themes/Tailwind/Utils/Css.php @@ -0,0 +1,91 @@ +classes = $classes; + } + + /** + * Set the classes + */ + public function setClasses(array $classes): self + { + $this->classes = $classes; + + return $this; + } + + /** + * Flush the cache + */ + public function forgetCache(): void + { + Session::forget($this->cacheKey); + } + + /** + * Retrieve unique Tailwind classes with caching + */ + public function uniqueClasses(): array + { + if (Session::has($this->cacheKey)) { + return Session::get($this->cacheKey); + } + + $uniqueClasses = $this->extractUniqueClasses($this->classes); + Session::put('alert_unique_tailwind_classes', $uniqueClasses); + + return $uniqueClasses; + } + + /** + * Recursively extract unique Tailwind classes from the provided array + */ + protected function extractUniqueClasses(array $array): array + { + $allClasses = []; + + array_walk_recursive($array, function ($value) use (&$allClasses) { + if (is_string($value)) { + $allClasses = array_merge($allClasses, explode(' ', $value)); + } + }); + + return array_values(array_unique($allClasses)); + } + + /** + * Convert the classes to a string + */ + public function toString(): string + { + return implode(' ', $this->uniqueClasses()); + } + + /** + * Convert the classes to a string + */ + public function __toString(): string + { + return $this->toString(); + } +} diff --git a/src/Traits/Closable.php b/src/Traits/Closable.php new file mode 100644 index 00000000..dbc24cf6 --- /dev/null +++ b/src/Traits/Closable.php @@ -0,0 +1,30 @@ +closable = $closable; + + return $this; + } + + public function notClosable(): self + { + $this->closable = false; + + return $this; + } + + public function isClosable(): bool + { + return $this->closable; + } +} diff --git a/src/Traits/Levelable.php b/src/Traits/Levelable.php index 005ef542..a6aaa2ba 100644 --- a/src/Traits/Levelable.php +++ b/src/Traits/Levelable.php @@ -2,27 +2,15 @@ namespace Digitlimit\Alert\Traits; +/** + * Levelable trait. + */ trait Levelable { /** - * Primary alert level. + * The level of the alert. */ - public function primary(): self - { - $this->level = 'primary'; - - return $this; - } - - /** - * Secondary alert level. - */ - public function secondary(): self - { - $this->level = 'secondary'; - - return $this; - } + protected string $level = ''; /** * Success alert level. @@ -49,7 +37,7 @@ public function info(): self */ public function error(): self { - $this->level = 'danger'; + $this->level = 'error'; return $this; } @@ -65,22 +53,20 @@ public function warning(): self } /** - * Light alert level. + * Set alert level. */ - public function light(): self + public function level(string $level): self { - $this->level = 'light'; + $this->level = $level; return $this; } /** - * Dark alert level. + * Fetch the alert level. */ - public function dark(): self + public function getLevel(): string { - $this->level = 'dark'; - - return $this; + return $this->level; } } diff --git a/src/Traits/Positionable.php b/src/Traits/Positionable.php new file mode 100644 index 00000000..4870df04 --- /dev/null +++ b/src/Traits/Positionable.php @@ -0,0 +1,112 @@ +position = 'centered'; + + return $this; + } + + /** + * Position on the top left of the screen. + */ + public function topLeft(): self + { + $this->position = 'top-left'; + + return $this; + } + + /** + * Position on the top right of the screen. + */ + public function topRight(): self + { + $this->position = 'top-right'; + + return $this; + } + + /** + * Position on the top center of the screen. + */ + public function topCenter(): self + { + $this->position = 'top-center'; + + return $this; + } + + /** + * Position on the bottom left of the screen. + */ + public function bottomLeft(): self + { + $this->position = 'bottom-left'; + + return $this; + } + + /** + * Position on the bottom right of the screen. + */ + public function bottomRight(): self + { + $this->position = 'bottom-right'; + + return $this; + } + + /** + * Position on the bottom center of the screen. + */ + public function bottomCenter(): self + { + $this->position = 'bottom-center'; + + return $this; + } + + /** + * Set the position of alert. + * + * @throws Exception + */ + public function position(string $position): self + { + $method = Str::camel($position); + + // check if function exists + if (! method_exists($this, $method)) { + throw new Exception("Position method {$method} does not exist."); + } + + return $this->{$method}(); + } + + /** + * Get the position of the alert. + */ + public function getPosition(): string + { + return $this->position; + } +} diff --git a/src/Traits/Scrollable.php b/src/Traits/Scrollable.php new file mode 100644 index 00000000..29d7b1bc --- /dev/null +++ b/src/Traits/Scrollable.php @@ -0,0 +1,30 @@ +scrollable = $scrollable; + + return $this; + } + + public function notScrollable(): self + { + $this->scrollable = false; + + return $this; + } + + public function isScrollable(): bool + { + return $this->scrollable; + } +} diff --git a/src/Traits/Sizable.php b/src/Traits/Sizable.php new file mode 100644 index 00000000..7801d611 --- /dev/null +++ b/src/Traits/Sizable.php @@ -0,0 +1,92 @@ +size = 'small'; + + return $this; + } + + /** + * Set modal size to medium. + */ + public function medium(): self + { + $this->size = 'medium'; + + return $this; + } + + /** + * Set modal size to large. + */ + public function large(): self + { + $this->size = 'large'; + + return $this; + } + + /** + * Set modal size to extra-large. + */ + public function extraLarge(): self + { + $this->size = 'extra-large'; + + return $this; + } + + /** + * Set modal size to fullscreen. + */ + public function fullscreen(): self + { + $this->size = 'fullscreen'; + + return $this; + } + + /** + * Set modal size + * + * @throws Exception + */ + public function size(string $size): self + { + $method = Str::camel($size); + + // check if function exists + if (! method_exists($this, $method)) { + throw new Exception("Size {$method} is not supported."); + } + + return $this->{$this->size}(); + } + + /** + * Get the size of the alert + */ + public function getSize(): string + { + return $this->size; + } +} diff --git a/src/Traits/Taggable.php b/src/Traits/Taggable.php new file mode 100644 index 00000000..51b43fb0 --- /dev/null +++ b/src/Traits/Taggable.php @@ -0,0 +1,39 @@ +tag = $tag; + + return $this; + } + + /** + * Get the alert tag. + */ + public function getTag(): string + { + return $this->tag; + } + + /** + * Check if the default tag is set. + */ + public function isDefaultTag(): bool + { + return $this->tag === Alert::DEFAULT_TAG; + } +} diff --git a/src/Traits/WithActionButton.php b/src/Traits/WithActionButton.php new file mode 100644 index 00000000..a140e0b8 --- /dev/null +++ b/src/Traits/WithActionButton.php @@ -0,0 +1,19 @@ +button('action', $label, $link, $attributes); + + return $this; + } +} diff --git a/src/Traits/WithButton.php b/src/Traits/WithButton.php new file mode 100644 index 00000000..2b6b7ac5 --- /dev/null +++ b/src/Traits/WithButton.php @@ -0,0 +1,73 @@ +buttons)) { + $this->buttons = new Collection; + } + + $this->buttons->push($button); + + return $this; + } + + /** + * Add multiple buttons to the alert. + */ + public function buttons(array $buttons): self + { + foreach ($buttons as $button) { + $this->button( + $button['name'], + $button['label'] ?? null, + $button['link'] ?? null, + $button['attributes'] ?? [] + ); + } + + return $this; + } + + /** + * Get the buttons for the alert. + */ + public function getButtons(): Collection + { + if (empty($this->buttons)) { + return new Collection; + } + + return $this->buttons; + } + + /** + * Convert the buttons to an array. + */ + public function buttonsToArray(): array + { + return $this->getButtons() + ->map(fn ($button) => $button->toArray()) + ->toArray(); + } +} diff --git a/src/Traits/WithCancelButton.php b/src/Traits/WithCancelButton.php new file mode 100644 index 00000000..55206159 --- /dev/null +++ b/src/Traits/WithCancelButton.php @@ -0,0 +1,19 @@ +button('cancel', $label, $link, $attributes); + + return $this; + } +} diff --git a/src/Traits/WithMessage.php b/src/Traits/WithMessage.php new file mode 100644 index 00000000..bd11db35 --- /dev/null +++ b/src/Traits/WithMessage.php @@ -0,0 +1,32 @@ +message = $message; + + return $this; + } + + /** + * Fetch the alert message. + */ + public function getMessage(): string + { + return $this->message; + } +} diff --git a/src/Traits/WithName.php b/src/Traits/WithName.php new file mode 100644 index 00000000..1850a59b --- /dev/null +++ b/src/Traits/WithName.php @@ -0,0 +1,37 @@ +name = $name; + + return $this; + } + + /** + * Get the field name. + */ + public function getName(): string + { + return $this->name; + } + + /* + * Check if the field has a name. + */ + public function hasName(): bool + { + return isset($this->name); + } +} diff --git a/src/Traits/WithSticky.php b/src/Traits/WithSticky.php new file mode 100644 index 00000000..07aff90b --- /dev/null +++ b/src/Traits/WithSticky.php @@ -0,0 +1,64 @@ +sticky = $sticky; + + return $this; + } + + /** + * Set the sticky property. + */ + public function stickyDuration(Carbon $carbon): self + { + $this->stickyDuration = $carbon; + + return $this; + } + + /** + * Check if the alert is sticky. + */ + public function isSticky(): bool + { + return $this->sticky; + } + + /** + * Flash the alert to the session. + */ + public function flashSticky(): self + { + $sessionKey = SessionKey::key($this->key(), $this->getTag()); + + if ($this->stickyDuration) { + Cache::put($sessionKey, $this, $this->stickyDuration); + Flashed::dispatch($this); + + return $this; + } + + Session::put($sessionKey, $this); + Flashed::dispatch($this); + + return $this; + } +} diff --git a/src/Traits/WithTimeout.php b/src/Traits/WithTimeout.php new file mode 100644 index 00000000..4eeb0eef --- /dev/null +++ b/src/Traits/WithTimeout.php @@ -0,0 +1,40 @@ +timeout = $timeout; + + return $this; + } + + /* + * Get the alert timeout. + */ + public function getTimeout(): int + { + return $this->timeout; + } + + /* + * Check if the field has a name. + */ + public function hasTimeout(): bool + { + return isset($this->timeout); + } +} diff --git a/src/Traits/WithTitle.php b/src/Traits/WithTitle.php new file mode 100644 index 00000000..028c16a9 --- /dev/null +++ b/src/Traits/WithTitle.php @@ -0,0 +1,34 @@ +title = $title; + + return $this; + } + + /** + * Fetch the alert title. + */ + public function getTitle(): ?string + { + return $this->title ?? null; + } + + public function hasTitle(): bool + { + return ! is_null($this->title); + } +} diff --git a/src/Traits/WithView.php b/src/Traits/WithView.php new file mode 100644 index 00000000..3e4e126c --- /dev/null +++ b/src/Traits/WithView.php @@ -0,0 +1,67 @@ +view = $view->render(); + + return $this; + } + + /** + * Set HTML string for the modal. + */ + public function html(string $html): self + { + $this->view = $html; + + return $this; + } + + /** + * @throws Throwable + */ + public function setView(string|View $view): self + { + if ($view instanceof View) { + return $this->view($view); + } + + return $this->html($view); + } + + /** + * Get the view for the modal. + */ + public function getView(): ?string + { + return $this->view; + } + + /** + * Determine if the modal has a view. + */ + public function hasView(): bool + { + return ! is_null($this->view); + } +} diff --git a/src/Types/Field.php b/src/Types/Field.php index 7beca47d..bbcf47ad 100644 --- a/src/Types/Field.php +++ b/src/Types/Field.php @@ -2,25 +2,54 @@ namespace Digitlimit\Alert\Types; -use Digitlimit\Alert\Helpers\Helper; +use Digitlimit\Alert\Contracts\HasMessage; +use Digitlimit\Alert\Contracts\HasName; +use Digitlimit\Alert\Contracts\HasTitle; +use Digitlimit\Alert\Contracts\Levelable; +use Digitlimit\Alert\Contracts\Taggable; +use Digitlimit\Alert\Events\Field\Flashed; +use Digitlimit\Alert\Foundation\AbstractAlert; +use Digitlimit\Alert\Foundation\AlertInterface; use Digitlimit\Alert\Helpers\SessionKey; -use Digitlimit\Alert\Message\AbstractMessage; -use Digitlimit\Alert\Message\MessageInterface; -use Digitlimit\Alert\SessionInterface; +use Digitlimit\Alert\Traits; +use Illuminate\Support\Facades\Session; -class Field extends AbstractMessage implements MessageInterface +/** + * Field alert class. + */ +class Field extends AbstractAlert implements AlertInterface, HasMessage, HasName, HasTitle, Levelable, Taggable { + use Traits\Levelable; + use Traits\Taggable; + use Traits\WithMessage; + use Traits\WithName; + use Traits\WithTitle; + + /** + * The default level of the alert. + */ + protected string $defaultLevel = 'error'; + /** * Create a new field alert instance. - * - * @return void */ public function __construct( - protected SessionInterface $session, - public string $name, - public string $message + protected string $name, + protected string $message ) { - $this->id($this->key().'-'.Helper::randomString()); + parent::__construct(); + } + + /** + * Fetch the alert level. + */ + public function getLevel(): string + { + if (empty($this->level)) { + return $this->defaultLevel; + } + + return $this->level; } /** @@ -36,12 +65,49 @@ public function key(): string */ public function getTag(): string { - if ($this->name) { - //e.g default.firstname - return $this->tag.'.'.$this->name; + return $this->tag; + } + + /** + * Get the named tag for the field alert. + */ + public function getNamedTag(): string + { + return $this->tag.'.'.$this->getName(); + } + + /** + * Get the field alert as an array. + */ + public function toArray(): array + { + return array_merge(parent::toArray(), [ + 'type' => $this->key(), + 'name' => $this->getName(), + 'tag' => $this->getTag(), + 'named_tag' => $this->getNamedTag(), + 'level' => $this->getLevel(), + 'title' => $this->getTitle(), + 'message' => $this->getMessage(), + ]); + } + + /** + * Fill the field alert from an array. + */ + public static function fill(array $alert): AlertInterface + { + $field = new static($alert['name'], $alert['message']); + + $field->id($alert['id']); + $field->tag($alert['tag']); + $field->level($alert['level']); + + if ($alert['title']) { + $field->title($alert['title']); } - return $this->tag; + return $field; } /** @@ -49,12 +115,16 @@ public function getTag(): string */ public function flash(): void { - $sessionKey = SessionKey::key($this->key(), $this->getTag()); - if (empty($this->name) || empty($this->message)) { return; } - $this->session->flash($sessionKey, $this); + $sessionKey = SessionKey::key( + $this->key(), + $this->getNamedTag() + ); + + Session::flash($sessionKey, $this); + Flashed::dispatch($this); } } diff --git a/src/Types/FieldBag.php b/src/Types/FieldBag.php deleted file mode 100644 index 23652817..00000000 --- a/src/Types/FieldBag.php +++ /dev/null @@ -1,76 +0,0 @@ -id($this->key().'-'.Helper::randomString()); - - if (is_a($bag, Validator::class)) { - $this->errors($bag); - } elseif (is_a($bag, MessageBag::class)) { - $this->messages($bag); - } else { - $this->messages = new MessageBag(); - } - } - - /** - * Message store key for the field alert. - */ - public function key(): string - { - return 'bag'; - } - - /** - * Set messages. - */ - public function messages(MessageBag $messages): self - { - $this->messages = $messages; - $this->flash(); - - return $this; - } - - /** - * Set errors. - */ - public function errors(Validator $validator): self - { - $this->messages = $validator->errors(); - $this->flash(); - - return $this; - } - - /** - * Fetch a message for a given field name. - */ - public function messageFor(string $name): string - { - return $this->messages->first($name); - } -} diff --git a/src/Types/Message.php b/src/Types/Message.php index 1e7e0639..7f644e29 100644 --- a/src/Types/Message.php +++ b/src/Types/Message.php @@ -2,23 +2,43 @@ namespace Digitlimit\Alert\Types; -use Digitlimit\Alert\Helpers\Helper; -use Digitlimit\Alert\Message\AbstractMessage; -use Digitlimit\Alert\Message\MessageInterface; -use Digitlimit\Alert\SessionInterface; +use Digitlimit\Alert\Contracts\Closable; +use Digitlimit\Alert\Contracts\HasMessage; +use Digitlimit\Alert\Contracts\HasSticky; +use Digitlimit\Alert\Contracts\HasTitle; +use Digitlimit\Alert\Contracts\Levelable; +use Digitlimit\Alert\Contracts\Taggable; +use Digitlimit\Alert\Events\Message\Flashed; +use Digitlimit\Alert\Foundation\AbstractAlert; +use Digitlimit\Alert\Foundation\AlertInterface; +use Digitlimit\Alert\Traits; -class Message extends AbstractMessage implements MessageInterface +/** + * Message alert class. + */ +class Message extends AbstractAlert implements AlertInterface, Closable, HasMessage, HasSticky, HasTitle, Levelable, Taggable { + use Traits\Closable; + use Traits\Levelable; + use Traits\Taggable; + use Traits\WithMessage; + use Traits\WithSticky; + use Traits\WithTitle; + + /** + * The default level of the alert. + */ + protected string $defaultLevel = 'info'; + /** * Create a new normal alert instance. * * @return void */ public function __construct( - protected SessionInterface $session, - public string $message + protected string $message ) { - $this->id($this->key().'-'.Helper::randomString()); + parent::__construct(); } /** @@ -28,4 +48,67 @@ public function key(): string { return 'message'; } + + /** + * Fetch the alert level. + */ + public function getLevel(): string + { + if (empty($this->level)) { + return $this->defaultLevel; + } + + return $this->level; + } + + /** + * Convert the message instance to an array. + */ + public function toArray(): array + { + return array_merge(parent::toArray(), [ + 'type' => $this->key(), + 'tag' => $this->getTag(), + 'level' => $this->getLevel(), + 'message' => $this->getMessage(), + 'title' => $this->getTitle(), + 'closable' => $this->isClosable(), + 'sticky' => $this->isSticky(), + ]); + } + + /** + * Fill the message alert from an array. + */ + public static function fill(array $alert): AlertInterface + { + $message = new static($alert['message']); + + $message->id($alert['id']); + $message->tag($alert['tag']); + $message->level($alert['level']); + $message->closable($alert['closable'] ?? false); + $message->sticky($alert['sticky'] ?? false); + + if ($alert['title']) { + $message->title($alert['title']); + } + + return $message; + } + + /** + * Flash field instance to store. + */ + public function flash(): void + { + if ($this->isSticky()) { + $this->flashSticky(); + + return; + } + + parent::flash(); + Flashed::dispatch($this); + } } diff --git a/src/Types/Modal.php b/src/Types/Modal.php index 169bd006..2ee82bc1 100644 --- a/src/Types/Modal.php +++ b/src/Types/Modal.php @@ -2,44 +2,38 @@ namespace Digitlimit\Alert\Types; -use Digitlimit\Alert\Component\Button; -use Digitlimit\Alert\Helpers\Helper; -use Digitlimit\Alert\Message\AbstractMessage; -use Digitlimit\Alert\Message\MessageInterface; -use Digitlimit\Alert\SessionInterface; -use Illuminate\View\View; - -class Modal extends AbstractMessage implements MessageInterface +use Digitlimit\Alert\Contracts\Closable; +use Digitlimit\Alert\Contracts\HasButton; +use Digitlimit\Alert\Contracts\HasMessage; +use Digitlimit\Alert\Contracts\HasTitle; +use Digitlimit\Alert\Contracts\HasView; +use Digitlimit\Alert\Contracts\Levelable; +use Digitlimit\Alert\Contracts\Scrollable; +use Digitlimit\Alert\Contracts\Sizable; +use Digitlimit\Alert\Contracts\Taggable; +use Digitlimit\Alert\Events\Modal\Flashed; +use Digitlimit\Alert\Foundation\AbstractAlert; +use Digitlimit\Alert\Foundation\AlertInterface; +use Digitlimit\Alert\Traits; +use Exception; +use Throwable; + +/** + * Modal alert class. + */ +class Modal extends AbstractAlert implements AlertInterface, Closable, HasButton, HasMessage, HasTitle, HasView, Levelable, Scrollable, Sizable, Taggable { - /** - * An instance of action button. - */ - public Button $action; - - /** - * An instance of cancel button. - */ - public Button $cancel; - - /** - * The modal size. - */ - public ?string $size = null; - - /** - * The scrollable class for modal if given. - */ - public ?string $scrollable = null; - - /** - * The position of the modal on the screen if given. - */ - public ?string $position = null; - - /** - * The view HTML string if given. - */ - public ?string $view = null; + use Traits\Closable; + use Traits\Levelable; + use Traits\Scrollable; + use Traits\Sizable; + use Traits\Taggable; + use Traits\WithActionButton; + use Traits\WithButton; + use Traits\WithCancelButton; + use Traits\WithMessage; + use Traits\WithTitle; + use Traits\WithView; /** * Create a new modal alert instance. @@ -47,12 +41,9 @@ class Modal extends AbstractMessage implements MessageInterface * @return void */ public function __construct( - protected SessionInterface $session, - public ?string $message + protected string $message ) { - $this->id($this->key().'-'.Helper::randomString()); - $this->action = new Button(); - $this->cancel = new Button(); + parent::__construct(); } /** @@ -64,113 +55,63 @@ public function key(): string } /** - * Set the action button. - */ - public function action(string $label, ?string $link = null, array $attributes = []): self - { - $this->action = new Button($label, $link, $attributes); - $this->flash(); - - return $this; - } - - /** - * Set the cancel button. + * Convert the modal alert to an array. */ - public function cancel(string $label, ?string $link = null, array $attributes = []): self + public function toArray(): array { - $this->cancel = new Button($label, $link, $attributes); - $this->flash(); - - return $this; + return array_merge(parent::toArray(), [ + 'type' => $this->key(), + 'level' => $this->getLevel(), + 'title' => $this->getTitle(), + 'message' => $this->getMessage(), + 'tag' => $this->getTag(), + 'size' => $this->getSize(), + 'scrollable' => $this->isScrollable(), + 'closable' => $this->isClosable(), + 'buttons' => $this->buttonsToArray(), + 'view' => $this->getView(), + ]); } /** - * Set modal to scrollable. - */ - public function scrollable( - string $class = 'modal-dialog-scrollable' - ): self { - $this->scrollable = $class; - $this->flash(); - - return $this; - } - - /** - * Set modal size to small. - */ - public function small(string $class = 'modal-sm'): self - { - $this->size = $class; - $this->flash(); - - return $this; - } - - /** - * Set modal size to large. - */ - public function large(string $class = 'modal-lg'): self - { - $this->size = $class; - $this->flash(); - - return $this; - } - - /** - * Set modal size to extra-large. - */ - public function extraLarge(string $class = 'modal-xl'): self - { - $this->size = $class; - $this->flash(); - - return $this; - } - - /** - * Set modal size to fullscreen. + * Fill the modal alert from an array. + * + * @throws Exception + * @throws Throwable */ - public function fullscreen(string $class = 'modal-fullscreen'): self + public static function fill(array $alert): AlertInterface { - $this->size = $class; - $this->flash(); + $modal = new static($alert['message']); - return $this; - } + $modal->id($alert['id']); + $modal->size($alert['size']); + $modal->level($alert['level']); + $modal->scrollable($alert['scrollable'] ?? false); + $modal->closable($alert['closable'] ?? false); + $modal->buttons($alert['buttons'] ?? []); - /** - * Set modal position to center. - */ - public function centered(string $class = 'modal-dialog-centered'): self - { - $this->position = $class; - $this->flash(); + if (isset($alert['tag']) && $alert['tag']) { + $modal->tag($alert['tag']); + } - return $this; - } + if (isset($alert['title']) && $alert['title']) { + $modal->title($alert['title']); + } - /** - * Set a view for the modal. - */ - public function view(View $view): self - { - $this->view = $view->render(); - $this->flash(); + if (isset($alert['view']) && $alert['view']) { + $modal->setView($alert['view']); + } - return $this; + return $modal; } /** - * Set HTML string for the modal. + * Flash field instance to store. */ - public function html(string $html): self + public function flash(): void { - $this->view = $html; - $this->flash(); + parent::flash(); - return $this; + Flashed::dispatch($this); } } diff --git a/src/Types/Notify.php b/src/Types/Notify.php index 7e4800ae..3fa2c941 100644 --- a/src/Types/Notify.php +++ b/src/Types/Notify.php @@ -2,17 +2,33 @@ namespace Digitlimit\Alert\Types; -use Digitlimit\Alert\Helpers\Helper; -use Digitlimit\Alert\Message\AbstractMessage; -use Digitlimit\Alert\Message\MessageInterface; -use Digitlimit\Alert\SessionInterface; - -class Notify extends AbstractMessage implements MessageInterface +use Digitlimit\Alert\Contracts\Closable; +use Digitlimit\Alert\Contracts\HasMessage; +use Digitlimit\Alert\Contracts\HasTimeout; +use Digitlimit\Alert\Contracts\HasTitle; +use Digitlimit\Alert\Contracts\Levelable; +use Digitlimit\Alert\Contracts\Positionable; +use Digitlimit\Alert\Contracts\Taggable; +use Digitlimit\Alert\Events\Notify\Flashed; +use Digitlimit\Alert\Foundation\AbstractAlert; +use Digitlimit\Alert\Foundation\AlertInterface; +use Digitlimit\Alert\Traits; +use Exception; + +/** + * Notify alert class. + */ +class Notify extends AbstractAlert implements AlertInterface, Closable, HasMessage, HasTimeout, HasTitle, Levelable, Positionable, Taggable { - /** - * The position of the notify. - */ - public ?string $position = null; + use Traits\Closable; + use Traits\Levelable; + use Traits\Positionable; + use Traits\Taggable; + use Traits\WithMessage; + use Traits\WithTimeout; + use Traits\WithTitle; + + protected string $defaultLevel = 'info'; /** * Create a new notify alert instance. @@ -20,95 +36,78 @@ class Notify extends AbstractMessage implements MessageInterface * @return void */ public function __construct( - protected SessionInterface $session, - public ?string $message + protected string $message ) { - $this->id($this->key().'-'.Helper::randomString()); - $this->bottomRight(); - } - - /** - * Message store key for the notify alert. - */ - public function key(): string - { - return 'notify'; - } - - /** - * Position notify on center of the screen. - */ - public function centered(string $class = 'top-50 start-50 translate-middle'): self - { - $this->position = $class; - $this->flash(); - - return $this; + parent::__construct(); } /** - * Position notify on the center of the screen. + * Fetch the alert level. */ - public function topLeft(string $class = 'top-0 start-0'): self + public function getLevel(): string { - $this->position = $class; - $this->flash(); + if (empty($this->level)) { + return $this->defaultLevel; + } - return $this; + return $this->level; } /** - * Position notify on the top right of the screen. + * Message store key for the notify alert. */ - public function topRight(string $class = 'top-0 end-0'): self + public function key(): string { - $this->position = $class; - $this->flash(); - - return $this; + return 'notify'; } /** - * Position notify on the top center of the screen. + * Convert the notify alert to an array. */ - public function topCenter(string $class = 'top-0 start-50 translate-middle-x'): self + public function toArray(): array { - $this->position = $class; - $this->flash(); - - return $this; + return array_merge(parent::toArray(), [ + 'type' => $this->key(), + 'title' => $this->getTitle(), + 'timeout' => $this->getTimeout(), + 'message' => $this->getMessage(), + 'tag' => $this->getTag(), + 'level' => $this->getLevel(), + 'position' => $this->getPosition(), + 'closable' => $this->isClosable(), + ]); } /** - * Position notify on the bottom left of the screen. + * Fill the notification alert from an array. + * + * @throws Exception */ - public function bottomLeft(string $class = 'bottom-0 start-0'): self + public static function fill(array $alert): AlertInterface { - $this->position = $class; - $this->flash(); + $notify = new static($alert['message']); + $notify->id($alert['id']); - return $this; - } + if ($alert['title']) { + $notify->title($alert['title']); + } - /** - * Position notify on the bottom right of the screen. - */ - public function bottomRight(string $class = 'bottom-0 end-0'): self - { - $this->position = $class; - $this->flash(); + $notify->tag($alert['tag']); + $notify->level($alert['level']); + $notify->position($alert['position']); + $notify->timeout($alert['timeout']); + $notify->closable($alert['closable']); - return $this; + return $notify; } /** - * Position notify on the bottom center of the screen. + * Flash field instance to store. */ - public function bottomCenter(string $class = 'bottom-0 start-50 translate-middle-x'): self + public function flash(): void { - $this->position = $class; - $this->flash(); + parent::flash(); - return $this; + Flashed::dispatch($this); } } diff --git a/src/Types/Sticky.php b/src/Types/Sticky.php deleted file mode 100644 index e2babc44..00000000 --- a/src/Types/Sticky.php +++ /dev/null @@ -1,75 +0,0 @@ -id($this->key().'-'.Helper::randomString()); - $this->action = new Button(); - } - - /** - * Message store key for the sticky alert. - */ - public function key(): string - { - return 'sticky'; - } - - /** - * Set the action button. - */ - public function action(string $label, ?string $link = null, array $attributes = []): self - { - $this->action = new Button($label, $link, $attributes); - $this->flash(); - - return $this; - } - - /** - * Put alert in the store. - */ - public function flash(): void - { - $sessionKey = SessionKey::key($this->key(), $this->getTag()); - $this->session->put($sessionKey, $this); - } - - /** - * Remove alert from the store. - */ - public function forget(?string $tag = null): void - { - $tag = $tag ?? $this->getTag(); - - if (empty($tag)) { - $tag = Alert::DEFAULT_TAG; - } - - $sessionKey = SessionKey::key($this->key(), $tag); - $this->session->forget($sessionKey); - } -} diff --git a/src/View/Components/Themes/Bootstrap5/Field.php b/src/View/Components/Themes/Bootstrap5/Field.php deleted file mode 100644 index 6274720b..00000000 --- a/src/View/Components/Themes/Bootstrap5/Field.php +++ /dev/null @@ -1,36 +0,0 @@ -alert = $alert; - } - - /** - * Get the view / contents that represent the component. - */ - public function render(): View - { - return view('alert::components.themes.bootstrap5.field'); - } -} diff --git a/src/View/Components/Themes/Bootstrap5/Message.php b/src/View/Components/Themes/Bootstrap5/Message.php deleted file mode 100644 index cd1e2112..00000000 --- a/src/View/Components/Themes/Bootstrap5/Message.php +++ /dev/null @@ -1,36 +0,0 @@ -alert = $alert; - } - - /** - * Get the view / contents that represent the component. - */ - public function render(): View - { - return view('alert::components.themes.bootstrap5.message'); - } -} diff --git a/src/View/Components/Themes/Bootstrap5/Modal.php b/src/View/Components/Themes/Bootstrap5/Modal.php deleted file mode 100644 index 3e48380b..00000000 --- a/src/View/Components/Themes/Bootstrap5/Modal.php +++ /dev/null @@ -1,80 +0,0 @@ - 'button', - 'class' => 'btn btn-primary', - ]; - - /** - * Default cancel button attributes. - */ - public array $cancelAttributes = [ - 'type' => 'button', - 'class' => 'btn btn-secondary', - 'data-bs-dismiss' => 'modal', - ]; - - /** - * Create a new component instance. - */ - public function __construct(Alert $alert) - { - $this->alert = $alert; - } - - /** - * Get the view / contents that represent the component. - */ - public function render(): View - { - return view('alert::components.themes.bootstrap5.modal'); - } - - /** - * Merge and convert array attributes to HTML string attributes. - */ - public function actionAttributes(array $attributes): string - { - $newAttributes = array_merge( - $this->actionAttributes, - $attributes - ); - - return Attribute::toString($newAttributes); - } - - /** - * Merge and convert array attributes to HTML string attributes. - */ - public function cancelAttributes(array $attributes): string - { - $newAttributes = array_merge( - $this->cancelAttributes, - $attributes - ); - - return Attribute::toString($newAttributes); - } -} diff --git a/src/View/Components/Themes/Bootstrap5/Notify.php b/src/View/Components/Themes/Bootstrap5/Notify.php deleted file mode 100644 index 7b250341..00000000 --- a/src/View/Components/Themes/Bootstrap5/Notify.php +++ /dev/null @@ -1,36 +0,0 @@ -alert = $alert; - } - - /** - * Get the view / contents that represent the component. - */ - public function render(): View - { - return view('alert::components.themes.bootstrap5.notify'); - } -} diff --git a/src/View/Components/Themes/Bootstrap5/Sticky.php b/src/View/Components/Themes/Bootstrap5/Sticky.php deleted file mode 100644 index 9153c449..00000000 --- a/src/View/Components/Themes/Bootstrap5/Sticky.php +++ /dev/null @@ -1,58 +0,0 @@ - 'button', - 'class' => 'btn btn-sm btn-primary float-end', - ]; - - /** - * Create a new component instance. - */ - public function __construct(Alert $alert) - { - $this->alert = $alert; - } - - /** - * Get the view / contents that represent the component. - */ - public function render(): View - { - return view('alert::components.themes.bootstrap5.sticky'); - } - - /** - * Merge and convert array attributes to HTML string attributes. - */ - public function actionAttributes(array $attributes): string - { - $newAttributes = array_merge( - $this->actionAttributes, - $attributes - ); - - return Attribute::toString($newAttributes); - } -} diff --git a/src/View/Components/Themes/Classic/Field.php b/src/View/Components/Themes/Classic/Field.php deleted file mode 100644 index 8779e962..00000000 --- a/src/View/Components/Themes/Classic/Field.php +++ /dev/null @@ -1,36 +0,0 @@ -alert = $alert; - } - - /** - * Get the view / contents that represent the component. - */ - public function render(): View - { - return view('alert::components.themes.classic.field'); - } -} diff --git a/src/View/Components/Themes/Classic/Message.php b/src/View/Components/Themes/Classic/Message.php deleted file mode 100644 index c22b4cfd..00000000 --- a/src/View/Components/Themes/Classic/Message.php +++ /dev/null @@ -1,36 +0,0 @@ -alert = $alert; - } - - /** - * Get the view / contents that represent the component. - */ - public function render(): View - { - return view('alert::components.themes.classic.message'); - } -} diff --git a/src/View/Components/Themes/Classic/Modal.php b/src/View/Components/Themes/Classic/Modal.php deleted file mode 100644 index 97a139bb..00000000 --- a/src/View/Components/Themes/Classic/Modal.php +++ /dev/null @@ -1,80 +0,0 @@ - 'button', - 'class' => 'btn btn-primary', - ]; - - /** - * Default cancel button attributes. - */ - public array $cancelAttributes = [ - 'type' => 'button', - 'class' => 'btn btn-secondary', - 'data-bs-dismiss' => 'modal', - ]; - - /** - * Create a new component instance. - */ - public function __construct(Alert $alert) - { - $this->alert = $alert; - } - - /** - * Get the view / contents that represent the component. - */ - public function render(): View - { - return view('alert::components.themes.classic.modal'); - } - - /** - * Merge and convert array attributes to HTML string attributes. - */ - public function actionAttributes(array $attributes): string - { - $newAttributes = array_merge( - $this->actionAttributes, - $attributes - ); - - return Attribute::toString($newAttributes); - } - - /** - * Merge and convert array attributes to HTML string attributes. - */ - public function cancelAttributes(array $attributes): string - { - $newAttributes = array_merge( - $this->cancelAttributes, - $attributes - ); - - return Attribute::toString($newAttributes); - } -} diff --git a/src/View/Components/Themes/Classic/Notify.php b/src/View/Components/Themes/Classic/Notify.php deleted file mode 100644 index 266f9da4..00000000 --- a/src/View/Components/Themes/Classic/Notify.php +++ /dev/null @@ -1,36 +0,0 @@ -alert = $alert; - } - - /** - * Get the view / contents that represent the component. - */ - public function render(): View - { - return view('alert::components.themes.classic.notify'); - } -} diff --git a/src/View/Components/Themes/Classic/Sticky.php b/src/View/Components/Themes/Classic/Sticky.php deleted file mode 100644 index 979203cf..00000000 --- a/src/View/Components/Themes/Classic/Sticky.php +++ /dev/null @@ -1,58 +0,0 @@ - 'button', - 'class' => 'btn btn-sm btn-primary float-end', - ]; - - /** - * Create a new component instance. - */ - public function __construct(Alert $alert) - { - $this->alert = $alert; - } - - /** - * Get the view / contents that represent the component. - */ - public function render(): View - { - return view('alert::components.themes.classic.sticky'); - } - - /** - * Merge and convert array attributes to HTML string attributes. - */ - public function actionAttributes(array $attributes): string - { - $newAttributes = array_merge( - $this->actionAttributes, - $attributes - ); - - return Attribute::toString($newAttributes); - } -} diff --git a/testbench.yaml b/testbench.yaml new file mode 100644 index 00000000..4390ace7 --- /dev/null +++ b/testbench.yaml @@ -0,0 +1,32 @@ +laravel: '@testbench' + +providers: + # - App\Providers\WorkbenchServiceProvider + +migrations: + - workbench/database/migrations + +seeders: + - Database\Seeders\DatabaseSeeder + +workbench: + start: '/' + install: true + health: false + discovers: + web: true + api: false + commands: false + components: false + views: false + build: + - asset-publish + - create-sqlite-db + - db-wipe + - migrate-fresh + assets: + - laravel-assets + sync: + - from: storage + to: workbench/storage + reverse: true diff --git a/tests/Feature/Component/ButtonTest.php b/tests/Feature/Component/ButtonTest.php deleted file mode 100644 index a543ea10..00000000 --- a/tests/Feature/Component/ButtonTest.php +++ /dev/null @@ -1,19 +0,0 @@ - 'btn-sm']); - - expect($button->label)->toEqual('Submit'); - expect($button->link)->toEqual('/about'); - expect($button->attributes)->toEqual(['class' => 'btn-sm']); - - $button->label('Register'); - $button->link('/register'); - $button->attributes(['id' => 'register']); - - expect($button->label)->toEqual('Register'); - expect($button->link)->toEqual('/register'); - expect($button->attributes)->toEqual(['id' => 'register']); -})->name('component', 'component-button'); diff --git a/tests/Feature/Components/FieldBagTest.php b/tests/Feature/Components/FieldBagTest.php deleted file mode 100644 index 01e0814d..00000000 --- a/tests/Feature/Components/FieldBagTest.php +++ /dev/null @@ -1,27 +0,0 @@ - '', 'lastname' => ''], - [ - 'firstname' => 'required', - 'lastname' => 'required', - ] - ); - - Alert::fieldBag($validator) - ->tag('contact') - ->error(); - - $this - ->blade('') - ->assertSee('class="form-text text-danger"', false) - ->assertSee('The firstname field is required'); - - $this - ->blade('') - ->assertSee('class="form-text text-danger"', false) - ->assertSee('The lastname field is required'); -})->group('view-component', 'view-component-field-bag'); diff --git a/tests/Feature/Components/FieldTest.php b/tests/Feature/Components/FieldTest.php deleted file mode 100644 index 952fd751..00000000 --- a/tests/Feature/Components/FieldTest.php +++ /dev/null @@ -1,46 +0,0 @@ -success(); - - $view = $this - ->blade(''); - - $view - ->assertSee('class="form-text text-success"', false) - ->assertSee('Username is available'); -})->group('view-component', 'view-component-field-default'); - -it('can render a tagged field view component', function () { - Alert::field('country', 'Please select a country') - ->tag('contact') - ->warning(); - - $view = $this - ->blade(''); - - $view - ->assertSee('class="form-text text-warning"', false) - ->assertSee('Please select a country'); -})->group('view-component', 'view-component-field-tagged'); - -it('can render a named field view component', function () { - Alert::field('country', 'Good, you chose a valid country') - ->tag('contact') - ->success(); - - Alert::field('state', 'Good, you chose a valid state') - ->tag('contact') - ->success(); - - $view = $this - ->blade(''); - - $view - ->assertSee('class="form-text text-success"', false) - ->assertSee('Good, you chose a valid country') - ->assertDontSee('Good, you chose a valid state'); -})->group('view-component', 'view-component-field-named-tagged'); diff --git a/tests/Feature/Components/MessageTest.php b/tests/Feature/Components/MessageTest.php deleted file mode 100644 index c5003c18..00000000 --- a/tests/Feature/Components/MessageTest.php +++ /dev/null @@ -1,12 +0,0 @@ -blade('') - ->assertSee('class="alert alert-dismissible alert-"', false) - ->assertSee('Thank you for joining us'); -})->group('view-component', 'view-component-message-default'); diff --git a/tests/Feature/Components/ModalTest.php b/tests/Feature/Components/ModalTest.php deleted file mode 100644 index d2b894be..00000000 --- a/tests/Feature/Components/ModalTest.php +++ /dev/null @@ -1,72 +0,0 @@ -blade('') - ->assertSee('class="modal"', false) - ->assertSee('Than you for joining us'); -})->group('view-component', 'view-component-modal-default'); - -it('can render a default modal with buttons and title', function () { - Alert::modal('Your message has been recieved, you will hear from us soon') - ->action('Yes') - ->cancel('Cancel') - ->centered() - ->title('Please login') - ->error(); - - $view = $this - ->blade(''); - - $view - ->assertSee('class="modal"', false) - ->assertSee('Yes') - ->assertSee('Cancel') - ->assertSee('Please login') - ->assertSee('Your message has been recieved, you will hear from us soon'); -})->group('view-component', 'view-component-modal-buttons-title'); - -it('can render a default modal a the right position', function () { - Alert::modal() - ->centered('centered'); - - $view = $this - ->blade(''); - - $view - ->assertSee('class="modal-dialog centered "', false); -})->group('view-component', 'view-component-modal-position'); - -it('can render a default modal a the right size', function () { - Alert::modal() - ->small(); - - $this - ->blade('') - ->assertSee('class="modal-dialog modal-sm "', false); - - Alert::modal() - ->large(); - - $this - ->blade('') - ->assertSee('class="modal-dialog modal-lg "', false); - - Alert::modal() - ->extraLarge(); - - $this - ->blade('') - ->assertSee('class="modal-dialog modal-xl "', false); - - Alert::modal() - ->fullscreen(); - - $this - ->blade('') - ->assertSee('class="modal-dialog modal-fullscreen "', false); -})->group('view-component', 'view-component-modal-size'); diff --git a/tests/Feature/Components/NotifyTest.php b/tests/Feature/Components/NotifyTest.php deleted file mode 100644 index 1da6d3e7..00000000 --- a/tests/Feature/Components/NotifyTest.php +++ /dev/null @@ -1,22 +0,0 @@ -blade('') - ->assertSee('class="position-fixed p-3 bottom-0 end-0"', false) - ->assertSee('Thank you for joining us'); -})->group('view-component', 'view-component-notify-default'); - -it('can render a tagged notify alert', function () { - Alert::notify('Thank you for joining us') - ->tag('contact'); - - $this - ->blade('') - ->assertSee('class="position-fixed p-3 bottom-0 end-0"', false) - ->assertSee('Thank you for joining us'); -})->group('view-component', 'view-component-notify-tagged'); diff --git a/tests/Feature/Components/StickyTest.php b/tests/Feature/Components/StickyTest.php deleted file mode 100644 index 14b0f79a..00000000 --- a/tests/Feature/Components/StickyTest.php +++ /dev/null @@ -1,32 +0,0 @@ -blade('') - ->assertSee('class="alert alert-dismissible alert-"', false) - ->assertSee('Thank you for joining us'); -})->group('view-component', 'view-component-sticky-default'); - -it('can render a tagged sticky alert', function () { - Alert::sticky('Thank you for joining us') - ->tag('contact'); - - $this - ->blade('') - ->assertSee('class="alert alert-dismissible alert-"', false) - ->assertSee('Thank you for joining us'); -})->group('view-component', 'view-component-sticky-tagged'); - -it('can render a tagged sticky alert button', function () { - Alert::sticky('Thank you for joining us') - ->action('Pay'); - - $this - ->blade('') - ->assertSee('class="alert alert-dismissible alert-"', false) - ->assertSee('Pay'); -})->group('view-component', 'view-component-sticky-button'); diff --git a/tests/Feature/Helpers/FieldTest.php b/tests/Feature/Helpers/FieldTest.php deleted file mode 100644 index 21289d0d..00000000 --- a/tests/Feature/Helpers/FieldTest.php +++ /dev/null @@ -1,18 +0,0 @@ -toBeInstanceOf(MessageInterface::class) - ->and($default) - ->toBeInstanceOf(Field::class) - ->and($default->message) - ->toEqual('Invalid firstname'); -})->group('types', 'types-field'); diff --git a/tests/Feature/Helpers/MessageTest.php b/tests/Feature/Helpers/MessageTest.php deleted file mode 100644 index 202769f9..00000000 --- a/tests/Feature/Helpers/MessageTest.php +++ /dev/null @@ -1,18 +0,0 @@ -toBeInstanceOf(MessageInterface::class) - ->and($default) - ->toBeInstanceOf(Message::class) - ->and($default->message) - ->toEqual('Thank you!'); -})->group('types', 'types-default', 'types-message'); diff --git a/tests/Feature/Helpers/ModalTest.php b/tests/Feature/Helpers/ModalTest.php deleted file mode 100644 index ed066367..00000000 --- a/tests/Feature/Helpers/ModalTest.php +++ /dev/null @@ -1,18 +0,0 @@ -toBeInstanceOf(MessageInterface::class) - ->and($default) - ->toBeInstanceOf(Modal::class) - ->and($default->message) - ->toEqual('Thank you!'); -})->group('types', 'types-modal', 'types-modal'); diff --git a/tests/Feature/Helpers/NotifyTest.php b/tests/Feature/Helpers/NotifyTest.php deleted file mode 100644 index 874923cb..00000000 --- a/tests/Feature/Helpers/NotifyTest.php +++ /dev/null @@ -1,20 +0,0 @@ -toBeInstanceOf(MessageInterface::class) - ->and($default) - ->toBeInstanceOf(Notify::class) - ->and($default->message) - ->toEqual('Thank you!') - ->and($default->key()) - ->toEqual('notify'); -})->group('types', 'types-notify', 'types-notify'); diff --git a/tests/Feature/Helpers/StickyTest.php b/tests/Feature/Helpers/StickyTest.php deleted file mode 100644 index 9eb4e66d..00000000 --- a/tests/Feature/Helpers/StickyTest.php +++ /dev/null @@ -1,18 +0,0 @@ -toBeInstanceOf(MessageInterface::class) - ->and($default) - ->toBeInstanceOf(Sticky::class) - ->and($default->message) - ->toEqual('Thank you!'); -})->group('types', 'types-sticky', 'types-sticky-message'); diff --git a/tests/Feature/Message/MessageInterfaceTest.php b/tests/Feature/Message/MessageInterfaceTest.php deleted file mode 100644 index b3d9bbc7..00000000 --- a/tests/Feature/Message/MessageInterfaceTest.php +++ /dev/null @@ -1 +0,0 @@ -primary(); - expect($alert->level)->toEqual('primary'); - - $alert = Alert::message('Thank you!')->secondary(); - expect($alert->level)->toEqual('secondary'); - - $alert = Alert::message('Thank you!')->success(); - expect($alert->level)->toEqual('success'); - - $alert = Alert::message('Thank you!')->info(); - expect($alert->level)->toEqual('info'); - - $alert = Alert::message('Thank you!')->error(); - expect($alert->level)->toEqual('danger'); - - $alert = Alert::message('Thank you!')->warning(); - expect($alert->level)->toEqual('warning'); - - $alert = Alert::message('Thank you!')->light(); - expect($alert->level)->toEqual('light'); - - $alert = Alert::message('Thank you!')->dark(); - expect($alert->level)->toEqual('dark'); -})->name('traits', 'traits-levelable'); diff --git a/tests/Feature/Types/FieldTest.php b/tests/Feature/Types/FieldTest.php deleted file mode 100644 index 656c2a3a..00000000 --- a/tests/Feature/Types/FieldTest.php +++ /dev/null @@ -1,18 +0,0 @@ -toBeInstanceOf(MessageInterface::class) - ->and($default) - ->toBeInstanceOf(Field::class) - ->and($default->message) - ->toEqual('Invalid firstname'); -})->group('types', 'types-field', 'types-field'); diff --git a/tests/Feature/Types/MessageTest.php b/tests/Feature/Types/MessageTest.php deleted file mode 100644 index ee429eb7..00000000 --- a/tests/Feature/Types/MessageTest.php +++ /dev/null @@ -1,18 +0,0 @@ -toBeInstanceOf(MessageInterface::class) - ->and($default) - ->toBeInstanceOf(Message::class) - ->and($default->message) - ->toEqual('Thank you!'); -})->group('types', 'types-default', 'types-message'); diff --git a/tests/Feature/Types/ModalTest.php b/tests/Feature/Types/ModalTest.php deleted file mode 100644 index 82a8d5c9..00000000 --- a/tests/Feature/Types/ModalTest.php +++ /dev/null @@ -1,18 +0,0 @@ -toBeInstanceOf(MessageInterface::class) - ->and($default) - ->toBeInstanceOf(Modal::class) - ->and($default->message) - ->toEqual('Thank you!'); -})->group('types', 'types-modal', 'types-modal'); diff --git a/tests/Feature/Types/NotifyTest.php b/tests/Feature/Types/NotifyTest.php deleted file mode 100644 index 2a6bee1b..00000000 --- a/tests/Feature/Types/NotifyTest.php +++ /dev/null @@ -1,63 +0,0 @@ -toBeInstanceOf(MessageInterface::class) - ->and($default)->toBeInstanceOf(Notify::class) - ->and($default->message) - ->toEqual('Thank you!') - ->and($default->key()) - ->toEqual('notify'); -})->group('types', 'types-notify', 'types-notify'); - -it('can create a notify alert position', function () { - // top right - Alert::notify('Thank you!') - ->topRight(); - - $default = Alert::default('notify'); - expect($default->position)->toEqual('top-0 end-0'); - - // top left - Alert::notify('Thank you!') - ->topLeft(); - - $default = Alert::default('notify'); - expect($default->position)->toEqual('top-0 start-0'); - - // bottom right - Alert::notify('Thank you!') - ->bottomRight(); - - $default = Alert::default('notify'); - expect($default->position)->toEqual('bottom-0 end-0'); - - // bottom left - Alert::notify('Thank you!') - ->bottomLeft(); - - $default = Alert::default('notify'); - expect($default->position)->toEqual('bottom-0 start-0'); - - // centered - Alert::notify('Thank you!') - ->centered(); - - $default = Alert::default('notify'); - expect($default->position)->toEqual('top-50 start-50 translate-middle'); - - // bottom center - Alert::notify('Thank you!') - ->bottomCenter(); - - $default = Alert::default('notify'); - expect($default->position)->toEqual('bottom-0 start-50 translate-middle-x'); -})->group('types', 'types-notify', 'types-notify-position'); diff --git a/tests/Feature/Types/StickyTest.php b/tests/Feature/Types/StickyTest.php deleted file mode 100644 index 0ffc45e3..00000000 --- a/tests/Feature/Types/StickyTest.php +++ /dev/null @@ -1,41 +0,0 @@ -toBeInstanceOf(MessageInterface::class) - ->and($default) - ->toBeInstanceOf(Sticky::class) - ->and($default->message) - ->toEqual('Thank you!'); -})->group('types', 'types-sticky', 'types-sticky-message'); - -it('can create a sticky alert title', function () { - Alert::sticky('Thank for ordering pizza!') - ->title('Order'); - - $default = Alert::default('sticky'); - - expect($default->title) - ->toEqual('Order') - ->and($default->message) - ->toEqual('Thank for ordering pizza!'); -})->group('types', 'types-sticky', 'types-sticky-title'); - -it('can create a sticky alert button', function () { - Alert::sticky() - ->action('Yes'); - - $default = Alert::default('sticky'); - - expect($default->action) - ->toBeInstanceOf(Button::class); -})->group('types', 'types-sticky', 'types-sticky-button'); diff --git a/tests/TestCase.php b/tests/TestCase.php index 9ae3ca2c..4fb91501 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -3,28 +3,31 @@ namespace Digitlimit\Alert\Tests; use Digitlimit\Alert\AlertServiceProvider; +use Illuminate\Foundation\Application; use Illuminate\Foundation\Testing\Concerns\InteractsWithViews; +use Illuminate\Support\Facades\Facade; use Orchestra\Testbench\TestCase as BaseTestCase; +use Livewire; class TestCase extends BaseTestCase { use InteractsWithViews; - protected function getPackageProviders($app) + protected function getPackageProviders($app): array { return [ AlertServiceProvider::class, + Livewire\LivewireServiceProvider::class, ]; } /** * Override application aliases. * - * @param \Illuminate\Foundation\Application $app - * - * @return array> + * @param Application $app + * @return array> */ - protected function getPackageAliases($app) + protected function getPackageAliases($app): array { return [ @@ -36,7 +39,7 @@ protected function getEnvironmentSetUp($app) // perform environment setup } - public function packagePath(string $path = '') + public function packagePath(string $path = ''): string { return __DIR__.'/../'.$path; } diff --git a/tests/Unit/Helpers/AttributeTest.php b/tests/Unit/Helpers/AttributeTest.php index be43bc79..da5fd972 100644 --- a/tests/Unit/Helpers/AttributeTest.php +++ b/tests/Unit/Helpers/AttributeTest.php @@ -3,11 +3,12 @@ use Digitlimit\Alert\Helpers\Attribute; it('can generate html element attribute from an array', function () { + $attributesString = Attribute::toString([ - 'id' => 'alert-id', - 'class' => 'alert alert-success', + 'id' => 'alert-id', + 'class' => 'hover:underline to-pink-500', ]); expect($attributesString) - ->toEqual('id="alert-id" class="alert alert-success"'); -})->name('helpers', 'helpers-to-string'); + ->toEqual('id="alert-id" class="hover:underline to-pink-500"'); +})->group('helpers', 'helpers-to-string'); diff --git a/tests/Unit/Helpers/SessionKeyTest.php b/tests/Unit/Helpers/SessionKeyTest.php index 38740bf1..972e3270 100644 --- a/tests/Unit/Helpers/SessionKeyTest.php +++ b/tests/Unit/Helpers/SessionKeyTest.php @@ -7,4 +7,4 @@ expect($key) ->toEqual(SessionKey::MAIN_KEY.'.notify.contact-form-1'); -})->name('helpers', 'helpers-session-key'); +})->group('helpers', 'helpers-session-key'); diff --git a/tests/Unit/Helpers/ThemeTest.php b/tests/Unit/Helpers/ThemeTest.php index 63244bb4..5b68f209 100644 --- a/tests/Unit/Helpers/ThemeTest.php +++ b/tests/Unit/Helpers/ThemeTest.php @@ -1,42 +1,47 @@ get('alert.theme'); + $theme = Config::get('alert.theme'); expect($theme) - ->toEqual('bootstrap5') - ->and(Theme::name())->toEqual('bootstrap5'); + ->toEqual('tailwind') + ->and(Theme::name())->toEqual('tailwind'); + })->group('theme', 'helpers', 'theme-name'); it('can get all themes', function () { - $themes = Helper::config()->get('alert.themes'); + $themes = Config::get('alert.themes'); $this->assertIsArray($themes); expect($themes) ->not()->toBeEmpty() ->toBeArray() ->toEqual(Theme::all()); + })->group('theme', 'helpers', 'theme-all'); -it('can get the correct theme based on config', function () { +it('can throw exception if theme is not found', function () { // set a non-existent theme config(['alert.theme' => 'none']); expect(Theme::name()) ->toEqual('none') - ->and(Theme::theme()) - ->toBeArray() - ->toBeEmpty(); + ->and(Theme::theme()); +})->throws( + Exception::class, + 'Theme none not found' +)->group('theme', 'helpers', 'theme-not-found'); +it('can get the correct theme instance', function () { // set a valid theme - config(['alert.theme' => 'classic']); + config(['alert.theme' => 'tailwind']); expect(Theme::name()) - ->toEqual('classic') + ->toEqual('tailwind') ->and(Theme::theme()) - ->toBeArray() - ->not()->toBeEmpty() - ->toEqual(config('alert.themes.classic')); -})->group('theme', 'helpers', 'theme-theme'); + ->toBeInstanceOf(ThemeInterface::class); + +})->group('theme', 'helpers', 'theme-instance'); diff --git a/tests/Unit/Helpers/TypeTest.php b/tests/Unit/Helpers/TypeTest.php index c74a93a0..3a23ffa5 100644 --- a/tests/Unit/Helpers/TypeTest.php +++ b/tests/Unit/Helpers/TypeTest.php @@ -9,7 +9,7 @@ ->toBeArray() ->and($types) ->not->toBeEmpty(); -}); +})->group('helpers', 'helpers-type'); it('should return prefixed alert type', function () { $type = 'success'; @@ -17,34 +17,7 @@ expect($prefixed) ->toEqual(Type::PREFIX.$type); -}); - -it('should check if alert type exists', function () { - $type = 'sticky'; - - expect(Type::exists($type)) - ->toBeTrue(); -}); - -it('should return alert type', function () { - $type = 'sticky'; - $alertType = Type::type($type); - - expect($alertType) - ->toBeArray() - ->toHaveKey('view') - ->toHaveKey('alert') - ->toHaveKey('component'); -}); - -it('should return alert class name', function () { - $type = 'sticky'; - $className = Type::classname($type); - - expect($className) - ->toBeString() - ->toEqual(Type::type($type)['alert']); -}); +})->group('helpers', 'helpers-type'); it('should throw exception if alert type does not exist', function () { $type = 'unknown'; @@ -53,4 +26,4 @@ })->throws( Exception::class, "The alert type 'unknown' does not exist in config" -); +)->group('helpers', 'helpers-type'); diff --git a/workbench/.gitignore b/workbench/.gitignore new file mode 100644 index 00000000..72603218 --- /dev/null +++ b/workbench/.gitignore @@ -0,0 +1,2 @@ +.env +.env.dusk diff --git a/workbench/app/Models/.gitkeep b/workbench/app/Models/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/workbench/app/Models/User.php b/workbench/app/Models/User.php new file mode 100644 index 00000000..3d48fd79 --- /dev/null +++ b/workbench/app/Models/User.php @@ -0,0 +1,45 @@ + + */ + protected $fillable = [ + 'name', + 'email', + 'password', + ]; + + /** + * The attributes that should be hidden for serialization. + * + * @var array + */ + protected $hidden = [ + 'password', + 'remember_token', + ]; + + /** + * The attributes that should be cast. + * + * @var array + */ + protected $casts = [ + 'email_verified_at' => 'datetime', + 'password' => 'hashed', + ]; +} diff --git a/workbench/app/Providers/WorkbenchServiceProvider.php b/workbench/app/Providers/WorkbenchServiceProvider.php new file mode 100644 index 00000000..41099fe3 --- /dev/null +++ b/workbench/app/Providers/WorkbenchServiceProvider.php @@ -0,0 +1,24 @@ +withRouting( + web: __DIR__.'/../routes/web.php', + commands: __DIR__.'/../routes/console.php', + ) + ->withMiddleware(function (Middleware $middleware) { + // + }) + ->withExceptions(function (Exceptions $exceptions) { + // + })->create(); diff --git a/workbench/database/factories/.gitkeep b/workbench/database/factories/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/workbench/database/factories/UserFactory.php b/workbench/database/factories/UserFactory.php new file mode 100644 index 00000000..636b6ea1 --- /dev/null +++ b/workbench/database/factories/UserFactory.php @@ -0,0 +1,54 @@ + + */ +class UserFactory extends Factory +{ + /** + * The current password being used by the factory. + */ + protected static ?string $password; + + /** + * The name of the factory's corresponding model. + * + * @var class-string + */ + protected $model = User::class; + + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'name' => fake()->name(), + 'email' => fake()->unique()->safeEmail(), + 'email_verified_at' => now(), + 'password' => static::$password ??= Hash::make('password'), + 'remember_token' => Str::random(10), + ]; + } + + /** + * Indicate that the model's email address should be unverified. + */ + public function unverified(): static + { + return $this->state(fn (array $attributes) => [ + 'email_verified_at' => null, + ]); + } +} diff --git a/workbench/database/migrations/.gitkeep b/workbench/database/migrations/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/workbench/database/seeders/DatabaseSeeder.php b/workbench/database/seeders/DatabaseSeeder.php new file mode 100644 index 00000000..57868a4e --- /dev/null +++ b/workbench/database/seeders/DatabaseSeeder.php @@ -0,0 +1,23 @@ +times(10)->create(); + + UserFactory::new()->create([ + 'name' => 'Test User', + 'email' => 'test@example.com', + ]); + } +} diff --git a/workbench/resources/views/.gitkeep b/workbench/resources/views/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/workbench/routes/console.php b/workbench/routes/console.php new file mode 100644 index 00000000..79297257 --- /dev/null +++ b/workbench/routes/console.php @@ -0,0 +1,8 @@ +comment(Inspiring::quote()); +// })->purpose('Display an inspiring quote'); diff --git a/workbench/routes/web.php b/workbench/routes/web.php new file mode 100644 index 00000000..86a06c53 --- /dev/null +++ b/workbench/routes/web.php @@ -0,0 +1,7 @@ +