From cd59ccd99bf2c5793de0f46cff6eb797bb922e28 Mon Sep 17 00:00:00 2001 From: fs Date: Wed, 4 Feb 2026 23:31:53 +0100 Subject: [PATCH] baseline --- .DS_Store | Bin 0 -> 8196 bytes .env.example | 19 + .gitignore | 9 + .htaccess | 5 + LICENSE.md | 21 + README.md | 41 + composer.json | 33 + composer.lock | 1847 +++ config/config.php.example | 69 + config/router.php | 16 + config/settings.php | 8 + db/init/init.sql | 425 + docker-compose.yml | 55 + docker/.DS_Store | Bin 0 -> 6148 bytes docker/nginx/default.conf | 29 + docker/php/Dockerfile | 22 + docker/php/php.ini | 4 + docs/ARCHITECTURE.md | 717 + docs/README-search.md | 25 + docs/conventions.md | 17 + docs/todo-editorjs-image.md | 63 + i18n/default_de.json | 481 + i18n/default_en.json | 481 + lib/.DS_Store | Bin 0 -> 6148 bytes lib/Http/AccessControl.php | 96 + lib/Http/AssetDetector.php | 56 + lib/Http/LocaleResolver.php | 142 + lib/Http/Request.php | 102 + lib/Repository/DepartmentRepository.php | 307 + .../EmailVerificationRepository.php | 71 + lib/Repository/MailLogRepository.php | 142 + lib/Repository/PageContentRepository.php | 59 + lib/Repository/PageRepository.php | 25 + lib/Repository/PasswordResetRepository.php | 71 + lib/Repository/PermissionRepository.php | 104 + lib/Repository/RememberTokenRepository.php | 55 + lib/Repository/RolePermissionRepository.php | 147 + lib/Repository/RoleRepository.php | 170 + lib/Repository/SettingRepository.php | 35 + lib/Repository/TenantDepartmentRepository.php | 69 + lib/Repository/TenantRepository.php | 249 + lib/Repository/UserDepartmentRepository.php | 54 + lib/Repository/UserRepository.php | 534 + lib/Repository/UserRoleRepository.php | 42 + lib/Repository/UserTenantRepository.php | 42 + lib/Service/AuthService.php | 163 + lib/Service/BrandingFaviconService.php | 238 + lib/Service/BrandingLogoService.php | 293 + lib/Service/DepartmentService.php | 161 + lib/Service/EmailVerificationService.php | 146 + lib/Service/MailLogService.php | 18 + lib/Service/MailService.php | 153 + lib/Service/PageService.php | 161 + lib/Service/PasswordResetService.php | 147 + lib/Service/PermissionService.php | 180 + lib/Service/RememberMeService.php | 157 + lib/Service/RoleService.php | 116 + lib/Service/SettingService.php | 340 + lib/Service/TenantAvatarService.php | 328 + lib/Service/TenantFaviconService.php | 214 + lib/Service/TenantScopeService.php | 118 + lib/Service/TenantService.php | 207 + lib/Service/UserAvatarService.php | 307 + lib/Service/UserService.php | 804 ++ lib/Support/Flash.php | 103 + lib/Support/Guard.php | 92 + lib/Support/Hello.php | 13 + lib/Support/SearchConfig.php | 230 + lib/Support/Tile.php | 28 + lib/Support/helpers.php | 6 + lib/Support/helpers/app.php | 208 + lib/Support/helpers/auth.php | 27 + lib/Support/helpers/i18n.php | 42 + lib/Support/helpers/ui.php | 178 + pages/.DS_Store | Bin 0 -> 6148 bytes pages/account/profile().php | 18 + pages/address-book/data().php | 92 + pages/address-book/index().php | 52 + pages/address-book/index(default).phtml | 156 + pages/address-book/view($id).php | 111 + pages/address-book/view(default).phtml | 277 + pages/admin/departments/_form.phtml | 55 + pages/admin/departments/create().php | 75 + pages/admin/departments/create(default).phtml | 44 + pages/admin/departments/data().php | 52 + pages/admin/departments/delete($id).php | 37 + pages/admin/departments/edit($id).php | 111 + pages/admin/departments/edit(default).phtml | 167 + pages/admin/departments/index().php | 39 + pages/admin/departments/index(default).phtml | 175 + pages/admin/index($slug).php | 16 + pages/admin/index().php | 10 + pages/admin/index(default).phtml | 25 + pages/admin/mail-log/data().php | 57 + pages/admin/mail-log/index().php | 23 + pages/admin/mail-log/index(default).phtml | 174 + pages/admin/mail-log/view($id).php | 25 + pages/admin/mail-log/view(default).phtml | 137 + pages/admin/permissions/_form.phtml | 38 + pages/admin/permissions/create().php | 42 + pages/admin/permissions/create(default).phtml | 44 + pages/admin/permissions/data().php | 41 + pages/admin/permissions/delete($id).php | 23 + pages/admin/permissions/edit($id).php | 64 + pages/admin/permissions/edit(default).phtml | 79 + pages/admin/permissions/index().php | 23 + pages/admin/permissions/index(default).phtml | 121 + pages/admin/roles/_form.phtml | 39 + pages/admin/roles/create().php | 61 + pages/admin/roles/create(default).phtml | 44 + pages/admin/roles/data().php | 43 + pages/admin/roles/delete($id).php | 29 + pages/admin/roles/edit($id).php | 87 + pages/admin/roles/edit(default).phtml | 167 + pages/admin/roles/index().php | 23 + pages/admin/roles/index(default).phtml | 159 + pages/admin/search/data().php | 92 + pages/admin/settings/favicon().php | 26 + pages/admin/settings/favicon-delete().php | 19 + pages/admin/settings/index().php | 130 + pages/admin/settings/index(default).phtml | 353 + pages/admin/settings/logo().php | 26 + pages/admin/settings/logo-delete().php | 19 + pages/admin/stats/index().php | 166 + pages/admin/stats/index(default).phtml | 283 + pages/admin/tenants/_form.phtml | 187 + pages/admin/tenants/avatar($id).php | 33 + pages/admin/tenants/avatar-delete($id).php | 26 + pages/admin/tenants/avatar-file(none).phtml | 28 + pages/admin/tenants/create().php | 62 + pages/admin/tenants/create(default).phtml | 44 + pages/admin/tenants/data().php | 43 + pages/admin/tenants/delete($id).php | 31 + pages/admin/tenants/edit($id).php | 82 + pages/admin/tenants/edit(default).phtml | 371 + pages/admin/tenants/favicon($id).php | 33 + pages/admin/tenants/favicon-delete($id).php | 26 + pages/admin/tenants/index().php | 23 + pages/admin/tenants/index(default).phtml | 159 + pages/admin/users/_form.phtml | 359 + pages/admin/users/activate($id).php | 41 + pages/admin/users/avatar($id).php | 41 + pages/admin/users/avatar-delete($id).php | 34 + pages/admin/users/avatar-file().php | 37 + pages/admin/users/avatar-file(none).phtml | 4 + pages/admin/users/bulk($action).php | 135 + pages/admin/users/create().php | 93 + pages/admin/users/create(default).phtml | 51 + pages/admin/users/data().php | 106 + pages/admin/users/deactivate($id).php | 53 + pages/admin/users/delete($id).php | 61 + pages/admin/users/edit($id).php | 160 + pages/admin/users/edit(default).phtml | 312 + pages/admin/users/export().php | 49 + pages/admin/users/export(none).phtml | 75 + pages/admin/users/forget-tokens($id).php | 39 + pages/admin/users/index().php | 48 + pages/admin/users/index(default).phtml | 389 + pages/admin/users/send-access($id).php | 73 + pages/admin/users/switch-tenant().php | 83 + pages/admin/users/theme().php | 66 + pages/auth/forgot().php | 31 + pages/auth/forgot(login).phtml | 43 + pages/auth/login().php | 19 + pages/auth/login(login).phtml | 46 + pages/auth/logout().php | 5 + pages/auth/register().php | 31 + pages/auth/register(login).phtml | 74 + pages/auth/reset().php | 40 + pages/auth/reset(login).phtml | 69 + pages/auth/verify().php | 35 + pages/auth/verify(login).phtml | 51 + pages/auth/verify-email().php | 60 + pages/auth/verify-email(login).phtml | 55 + pages/branding/logo(none).phtml | 19 + pages/error/forbidden(error).phtml | 24 + pages/error/method_not_allowed(error).phtml | 6 + pages/error/not_found(error).phtml | 21 + pages/flash/dismiss($id).php | 14 + pages/index().php | 9 + pages/lang().php | 35 + pages/page/copy-language().php | 41 + pages/page/index($slug).php | 96 + pages/page/index(default).phtml | 113 + pages/search/data().php | 121 + pages/search/index().php | 17 + pages/search/index(default).phtml | 86 + phpstan.neon | 13 + storage/.gitkeep | 1 + templates/.DS_Store | Bin 0 -> 8196 bytes templates/default.phtml | 104 + templates/emails/de/access_info.html | 18 + templates/emails/de/access_info.txt | 17 + templates/emails/de/email_verification.html | 15 + templates/emails/de/email_verification.txt | 18 + templates/emails/de/partials/footer.html | 16 + templates/emails/de/partials/footer.txt | 2 + templates/emails/de/partials/header.html | 14 + templates/emails/de/partials/header.txt | 2 + templates/emails/de/reset_code.html | 15 + templates/emails/de/reset_code.txt | 18 + templates/emails/en/access_info.html | 18 + templates/emails/en/access_info.txt | 17 + templates/emails/en/email_verification.html | 15 + templates/emails/en/email_verification.txt | 18 + templates/emails/en/partials/footer.html | 16 + templates/emails/en/partials/footer.txt | 2 + templates/emails/en/partials/header.html | 14 + templates/emails/en/partials/header.txt | 2 + templates/emails/en/reset_code.html | 15 + templates/emails/en/reset_code.txt | 18 + templates/error.phtml | 13 + templates/login.phtml | 49 + templates/partials/.DS_Store | Bin 0 -> 6148 bytes templates/partials/app-aside-icon-bar.phtml | 69 + templates/partials/app-aside.phtml | 399 + templates/partials/app-flash.phtml | 34 + templates/partials/app-footer.phtml | 24 + .../partials/app-language-switcher.phtml | 66 + templates/partials/app-tile.phtml | 44 + templates/partials/app-topbar.phtml | 106 + tests/.DS_Store | Bin 0 -> 6148 bytes tests/Http/RequestTest.php | 54 + tests/Service/UserServicePasswordTest.php | 49 + web/.DS_Store | Bin 0 -> 6148 bytes web/.htaccess | 9 + web/brand/logo.svg | 35 + web/css/base/variables.css | 713 + web/css/components/app-badges.css | 127 + web/css/components/app-blockquote.css | 66 + web/css/components/app-brand.css | 31 + web/css/components/app-breadcrumb.css | 12 + web/css/components/app-buttons.css | 44 + web/css/components/app-dashboard-titlebar.css | 55 + web/css/components/app-details-titlebar.css | 87 + web/css/components/app-details.css | 137 + web/css/components/app-flash.css | 119 + web/css/components/app-forms.css | 62 + web/css/components/app-list-table.css | 7 + web/css/components/app-list-tabs.css | 37 + web/css/components/app-list-titlebar.css | 79 + web/css/components/app-list-toolbar.css | 69 + web/css/components/app-page-copy.css | 10 + web/css/components/app-page-editor.css | 74 + web/css/components/app-profile.css | 570 + web/css/components/app-search.css | 137 + web/css/components/app-tabs.css | 53 + web/css/components/app-tile.css | 111 + web/css/components/app-tooltips.css | 108 + web/css/components/vendor-editorjs.css | 74 + web/css/components/vendor-gridjs.css | 207 + web/css/components/vendor-multi-select.css | 130 + web/css/layout/app-aside-icon-bar.css | 60 + web/css/layout/app-shell.css | 2978 ++++ web/css/layout/app-sidebar.css | 208 + web/css/layout/app-topbar.css | 87 + web/css/pages/app-login.css | 10 + web/favicon/apple-touch-icon.png | Bin 0 -> 4827 bytes web/favicon/favicon-16x16.png | Bin 0 -> 451 bytes web/favicon/favicon-32x32.png | Bin 0 -> 816 bytes web/favicon/favicon-96x96.png | Bin 0 -> 2474 bytes web/favicon/favicon.ico | Bin 0 -> 15086 bytes web/favicon/favicon.svg | 36 + web/favicon/site.webmanifest | 21 + .../apple-touch-icon.png | Bin 0 -> 6025 bytes .../favicon-16x16.png | Bin 0 -> 521 bytes .../favicon-32x32.png | Bin 0 -> 1005 bytes .../favicon-96x96.png | Bin 0 -> 2881 bytes .../web-app-manifest-192x192.png | Bin 0 -> 5938 bytes .../web-app-manifest-512x512.png | Bin 0 -> 22668 bytes web/favicon/web-app-manifest-192x192.png | Bin 0 -> 5226 bytes web/favicon/web-app-manifest-512x512.png | Bin 0 -> 16667 bytes web/img/favicon.ico | Bin 0 -> 1150 bytes web/img/forkme_right_red_aa0000.png | Bin 0 -> 7927 bytes web/img/minty_square.png | Bin 0 -> 132166 bytes web/img/mintyphp_logo.png | Bin 0 -> 227245 bytes web/index.php | 159 + web/js/app-init.js | 21 + web/js/app-login-init.js | 2 + web/js/components/app-async-flash.js | 89 + web/js/components/app-bulk-selection.js | 26 + web/js/components/app-color-default-toggle.js | 43 + web/js/components/app-copy-badge.js | 66 + web/js/components/app-flash-auto-dismiss.js | 53 + web/js/components/app-fslightbox-refresh.js | 48 + web/js/components/app-global-search.js | 168 + web/js/components/app-multiselect-init.js | 109 + web/js/components/app-nav-history.js | 48 + web/js/components/app-page-editor.js | 185 + web/js/components/app-password-hints.js | 76 + web/js/components/app-tabs.js | 118 + web/js/components/app-tenant-switcher.js | 71 + web/js/components/app-theme-toggle.js | 57 + web/js/components/app-toggle-aside-panels.js | 191 + web/js/components/app-toggle-details-aside.js | 66 + web/js/components/app-toggle-sidebar.js | 95 + web/js/components/app-toggle-toolbar.js | 86 + web/js/core/app-grid-factory.js | 604 + web/js/pages/app-list-utils.js | 19 + web/js/pages/app-users-list.js | 127 + web/vendor/bootstrap-icons/0-circle-fill.svg | 4 + web/vendor/bootstrap-icons/0-circle.svg | 4 + web/vendor/bootstrap-icons/0-square-fill.svg | 4 + web/vendor/bootstrap-icons/0-square.svg | 4 + web/vendor/bootstrap-icons/1-circle-fill.svg | 3 + web/vendor/bootstrap-icons/1-circle.svg | 3 + web/vendor/bootstrap-icons/1-square-fill.svg | 3 + web/vendor/bootstrap-icons/1-square.svg | 4 + web/vendor/bootstrap-icons/123.svg | 3 + web/vendor/bootstrap-icons/2-circle-fill.svg | 3 + web/vendor/bootstrap-icons/2-circle.svg | 3 + web/vendor/bootstrap-icons/2-square-fill.svg | 3 + web/vendor/bootstrap-icons/2-square.svg | 4 + web/vendor/bootstrap-icons/3-circle-fill.svg | 3 + web/vendor/bootstrap-icons/3-circle.svg | 4 + web/vendor/bootstrap-icons/3-square-fill.svg | 3 + web/vendor/bootstrap-icons/3-square.svg | 4 + web/vendor/bootstrap-icons/4-circle-fill.svg | 3 + web/vendor/bootstrap-icons/4-circle.svg | 4 + web/vendor/bootstrap-icons/4-square-fill.svg | 4 + web/vendor/bootstrap-icons/4-square.svg | 4 + web/vendor/bootstrap-icons/5-circle-fill.svg | 3 + web/vendor/bootstrap-icons/5-circle.svg | 3 + web/vendor/bootstrap-icons/5-square-fill.svg | 3 + web/vendor/bootstrap-icons/5-square.svg | 4 + web/vendor/bootstrap-icons/6-circle-fill.svg | 3 + web/vendor/bootstrap-icons/6-circle.svg | 3 + web/vendor/bootstrap-icons/6-square-fill.svg | 4 + web/vendor/bootstrap-icons/6-square.svg | 4 + web/vendor/bootstrap-icons/7-circle-fill.svg | 3 + web/vendor/bootstrap-icons/7-circle.svg | 3 + web/vendor/bootstrap-icons/7-square-fill.svg | 3 + web/vendor/bootstrap-icons/7-square.svg | 4 + web/vendor/bootstrap-icons/8-circle-fill.svg | 3 + web/vendor/bootstrap-icons/8-circle.svg | 3 + web/vendor/bootstrap-icons/8-square-fill.svg | 4 + web/vendor/bootstrap-icons/8-square.svg | 4 + web/vendor/bootstrap-icons/9-circle-fill.svg | 3 + web/vendor/bootstrap-icons/9-circle.svg | 3 + web/vendor/bootstrap-icons/9-square-fill.svg | 4 + web/vendor/bootstrap-icons/9-square.svg | 4 + web/vendor/bootstrap-icons/activity.svg | 3 + .../bootstrap-icons/airplane-engines-fill.svg | 3 + .../bootstrap-icons/airplane-engines.svg | 3 + web/vendor/bootstrap-icons/airplane-fill.svg | 3 + web/vendor/bootstrap-icons/airplane.svg | 3 + web/vendor/bootstrap-icons/alarm-fill.svg | 3 + web/vendor/bootstrap-icons/alarm.svg | 4 + web/vendor/bootstrap-icons/alexa.svg | 3 + web/vendor/bootstrap-icons/align-bottom.svg | 4 + web/vendor/bootstrap-icons/align-center.svg | 3 + web/vendor/bootstrap-icons/align-end.svg | 4 + web/vendor/bootstrap-icons/align-middle.svg | 3 + web/vendor/bootstrap-icons/align-start.svg | 4 + web/vendor/bootstrap-icons/align-top.svg | 4 + web/vendor/bootstrap-icons/alipay.svg | 4 + .../bootstrap-icons/alphabet-uppercase.svg | 3 + web/vendor/bootstrap-icons/alphabet.svg | 3 + web/vendor/bootstrap-icons/alt.svg | 3 + web/vendor/bootstrap-icons/amazon.svg | 4 + web/vendor/bootstrap-icons/amd.svg | 3 + web/vendor/bootstrap-icons/android.svg | 3 + web/vendor/bootstrap-icons/android2.svg | 3 + web/vendor/bootstrap-icons/anthropic.svg | 3 + web/vendor/bootstrap-icons/app-indicator.svg | 4 + web/vendor/bootstrap-icons/app.svg | 3 + web/vendor/bootstrap-icons/apple-music.svg | 3 + web/vendor/bootstrap-icons/apple.svg | 4 + web/vendor/bootstrap-icons/archive-fill.svg | 3 + web/vendor/bootstrap-icons/archive.svg | 3 + .../bootstrap-icons/arrow-90deg-down.svg | 3 + .../bootstrap-icons/arrow-90deg-left.svg | 3 + .../bootstrap-icons/arrow-90deg-right.svg | 3 + web/vendor/bootstrap-icons/arrow-90deg-up.svg | 3 + web/vendor/bootstrap-icons/arrow-bar-down.svg | 3 + web/vendor/bootstrap-icons/arrow-bar-left.svg | 3 + .../bootstrap-icons/arrow-bar-right.svg | 3 + web/vendor/bootstrap-icons/arrow-bar-up.svg | 3 + .../bootstrap-icons/arrow-clockwise.svg | 4 + .../arrow-counterclockwise.svg | 4 + .../arrow-down-circle-fill.svg | 3 + .../bootstrap-icons/arrow-down-circle.svg | 3 + .../arrow-down-left-circle-fill.svg | 3 + .../arrow-down-left-circle.svg | 3 + .../arrow-down-left-square-fill.svg | 3 + .../arrow-down-left-square.svg | 3 + .../bootstrap-icons/arrow-down-left.svg | 3 + .../arrow-down-right-circle-fill.svg | 3 + .../arrow-down-right-circle.svg | 3 + .../arrow-down-right-square-fill.svg | 3 + .../arrow-down-right-square.svg | 3 + .../bootstrap-icons/arrow-down-right.svg | 3 + .../bootstrap-icons/arrow-down-short.svg | 3 + .../arrow-down-square-fill.svg | 3 + .../bootstrap-icons/arrow-down-square.svg | 3 + web/vendor/bootstrap-icons/arrow-down-up.svg | 3 + web/vendor/bootstrap-icons/arrow-down.svg | 3 + .../arrow-left-circle-fill.svg | 3 + .../bootstrap-icons/arrow-left-circle.svg | 3 + .../bootstrap-icons/arrow-left-right.svg | 3 + .../bootstrap-icons/arrow-left-short.svg | 3 + .../arrow-left-square-fill.svg | 3 + .../bootstrap-icons/arrow-left-square.svg | 3 + web/vendor/bootstrap-icons/arrow-left.svg | 3 + web/vendor/bootstrap-icons/arrow-repeat.svg | 4 + .../bootstrap-icons/arrow-return-left.svg | 3 + .../bootstrap-icons/arrow-return-right.svg | 3 + .../arrow-right-circle-fill.svg | 3 + .../bootstrap-icons/arrow-right-circle.svg | 3 + .../bootstrap-icons/arrow-right-short.svg | 3 + .../arrow-right-square-fill.svg | 3 + .../bootstrap-icons/arrow-right-square.svg | 3 + web/vendor/bootstrap-icons/arrow-right.svg | 3 + .../arrow-through-heart-fill.svg | 3 + .../bootstrap-icons/arrow-through-heart.svg | 3 + .../bootstrap-icons/arrow-up-circle-fill.svg | 3 + .../bootstrap-icons/arrow-up-circle.svg | 3 + .../arrow-up-left-circle-fill.svg | 3 + .../bootstrap-icons/arrow-up-left-circle.svg | 3 + .../arrow-up-left-square-fill.svg | 3 + .../bootstrap-icons/arrow-up-left-square.svg | 3 + web/vendor/bootstrap-icons/arrow-up-left.svg | 3 + .../arrow-up-right-circle-fill.svg | 3 + .../bootstrap-icons/arrow-up-right-circle.svg | 3 + .../arrow-up-right-square-fill.svg | 3 + .../bootstrap-icons/arrow-up-right-square.svg | 3 + web/vendor/bootstrap-icons/arrow-up-right.svg | 3 + web/vendor/bootstrap-icons/arrow-up-short.svg | 3 + .../bootstrap-icons/arrow-up-square-fill.svg | 3 + .../bootstrap-icons/arrow-up-square.svg | 3 + web/vendor/bootstrap-icons/arrow-up.svg | 3 + .../bootstrap-icons/arrows-angle-contract.svg | 3 + .../bootstrap-icons/arrows-angle-expand.svg | 3 + .../arrows-collapse-vertical.svg | 3 + .../bootstrap-icons/arrows-collapse.svg | 3 + .../arrows-expand-vertical.svg | 3 + web/vendor/bootstrap-icons/arrows-expand.svg | 3 + .../bootstrap-icons/arrows-fullscreen.svg | 3 + web/vendor/bootstrap-icons/arrows-move.svg | 3 + .../bootstrap-icons/arrows-vertical.svg | 3 + web/vendor/bootstrap-icons/arrows.svg | 3 + .../bootstrap-icons/aspect-ratio-fill.svg | 3 + web/vendor/bootstrap-icons/aspect-ratio.svg | 4 + web/vendor/bootstrap-icons/asterisk.svg | 3 + web/vendor/bootstrap-icons/at.svg | 3 + web/vendor/bootstrap-icons/award-fill.svg | 4 + web/vendor/bootstrap-icons/award.svg | 4 + web/vendor/bootstrap-icons/back.svg | 3 + web/vendor/bootstrap-icons/backpack-fill.svg | 4 + web/vendor/bootstrap-icons/backpack.svg | 4 + web/vendor/bootstrap-icons/backpack2-fill.svg | 4 + web/vendor/bootstrap-icons/backpack2.svg | 5 + web/vendor/bootstrap-icons/backpack3-fill.svg | 4 + web/vendor/bootstrap-icons/backpack3.svg | 4 + web/vendor/bootstrap-icons/backpack4-fill.svg | 4 + web/vendor/bootstrap-icons/backpack4.svg | 4 + web/vendor/bootstrap-icons/backspace-fill.svg | 3 + .../backspace-reverse-fill.svg | 3 + .../bootstrap-icons/backspace-reverse.svg | 4 + web/vendor/bootstrap-icons/backspace.svg | 4 + web/vendor/bootstrap-icons/badge-3d-fill.svg | 4 + web/vendor/bootstrap-icons/badge-3d.svg | 4 + web/vendor/bootstrap-icons/badge-4k-fill.svg | 4 + web/vendor/bootstrap-icons/badge-4k.svg | 4 + web/vendor/bootstrap-icons/badge-8k-fill.svg | 4 + web/vendor/bootstrap-icons/badge-8k.svg | 4 + web/vendor/bootstrap-icons/badge-ad-fill.svg | 4 + web/vendor/bootstrap-icons/badge-ad.svg | 4 + web/vendor/bootstrap-icons/badge-ar-fill.svg | 4 + web/vendor/bootstrap-icons/badge-ar.svg | 4 + web/vendor/bootstrap-icons/badge-cc-fill.svg | 3 + web/vendor/bootstrap-icons/badge-cc.svg | 4 + web/vendor/bootstrap-icons/badge-hd-fill.svg | 4 + web/vendor/bootstrap-icons/badge-hd.svg | 4 + web/vendor/bootstrap-icons/badge-sd-fill.svg | 4 + web/vendor/bootstrap-icons/badge-sd.svg | 3 + web/vendor/bootstrap-icons/badge-tm-fill.svg | 3 + web/vendor/bootstrap-icons/badge-tm.svg | 4 + web/vendor/bootstrap-icons/badge-vo-fill.svg | 4 + web/vendor/bootstrap-icons/badge-vo.svg | 4 + web/vendor/bootstrap-icons/badge-vr-fill.svg | 4 + web/vendor/bootstrap-icons/badge-vr.svg | 4 + web/vendor/bootstrap-icons/badge-wc-fill.svg | 3 + web/vendor/bootstrap-icons/badge-wc.svg | 4 + web/vendor/bootstrap-icons/bag-check-fill.svg | 3 + web/vendor/bootstrap-icons/bag-check.svg | 4 + web/vendor/bootstrap-icons/bag-dash-fill.svg | 3 + web/vendor/bootstrap-icons/bag-dash.svg | 4 + web/vendor/bootstrap-icons/bag-fill.svg | 3 + web/vendor/bootstrap-icons/bag-heart-fill.svg | 3 + web/vendor/bootstrap-icons/bag-heart.svg | 3 + web/vendor/bootstrap-icons/bag-plus-fill.svg | 3 + web/vendor/bootstrap-icons/bag-plus.svg | 4 + web/vendor/bootstrap-icons/bag-x-fill.svg | 3 + web/vendor/bootstrap-icons/bag-x.svg | 4 + web/vendor/bootstrap-icons/bag.svg | 3 + web/vendor/bootstrap-icons/balloon-fill.svg | 3 + .../bootstrap-icons/balloon-heart-fill.svg | 3 + web/vendor/bootstrap-icons/balloon-heart.svg | 3 + web/vendor/bootstrap-icons/balloon.svg | 3 + web/vendor/bootstrap-icons/ban-fill.svg | 3 + web/vendor/bootstrap-icons/ban.svg | 3 + web/vendor/bootstrap-icons/bandaid-fill.svg | 3 + web/vendor/bootstrap-icons/bandaid.svg | 4 + web/vendor/bootstrap-icons/bank.svg | 3 + web/vendor/bootstrap-icons/bank2.svg | 3 + web/vendor/bootstrap-icons/bar-chart-fill.svg | 3 + .../bootstrap-icons/bar-chart-line-fill.svg | 3 + web/vendor/bootstrap-icons/bar-chart-line.svg | 3 + .../bootstrap-icons/bar-chart-steps.svg | 3 + web/vendor/bootstrap-icons/bar-chart.svg | 3 + web/vendor/bootstrap-icons/basket-fill.svg | 3 + web/vendor/bootstrap-icons/basket.svg | 3 + web/vendor/bootstrap-icons/basket2-fill.svg | 3 + web/vendor/bootstrap-icons/basket2.svg | 4 + web/vendor/bootstrap-icons/basket3-fill.svg | 3 + web/vendor/bootstrap-icons/basket3.svg | 3 + .../bootstrap-icons/battery-charging.svg | 6 + web/vendor/bootstrap-icons/battery-full.svg | 4 + web/vendor/bootstrap-icons/battery-half.svg | 4 + web/vendor/bootstrap-icons/battery-low.svg | 4 + web/vendor/bootstrap-icons/battery.svg | 3 + web/vendor/bootstrap-icons/beaker-fill.svg | 3 + web/vendor/bootstrap-icons/beaker.svg | 4 + web/vendor/bootstrap-icons/behance.svg | 3 + web/vendor/bootstrap-icons/bell-fill.svg | 3 + .../bootstrap-icons/bell-slash-fill.svg | 3 + web/vendor/bootstrap-icons/bell-slash.svg | 3 + web/vendor/bootstrap-icons/bell.svg | 3 + web/vendor/bootstrap-icons/bezier.svg | 4 + web/vendor/bootstrap-icons/bezier2.svg | 3 + web/vendor/bootstrap-icons/bicycle.svg | 3 + web/vendor/bootstrap-icons/bing.svg | 5 + .../bootstrap-icons/binoculars-fill.svg | 3 + web/vendor/bootstrap-icons/binoculars.svg | 3 + .../bootstrap-icons/blockquote-left.svg | 3 + .../bootstrap-icons/blockquote-right.svg | 3 + web/vendor/bootstrap-icons/bluesky.svg | 3 + web/vendor/bootstrap-icons/bluetooth.svg | 3 + web/vendor/bootstrap-icons/body-text.svg | 3 + web/vendor/bootstrap-icons/book-fill.svg | 3 + web/vendor/bootstrap-icons/book-half.svg | 3 + web/vendor/bootstrap-icons/book.svg | 3 + .../bootstrap-icons/bookmark-check-fill.svg | 3 + web/vendor/bootstrap-icons/bookmark-check.svg | 4 + .../bootstrap-icons/bookmark-dash-fill.svg | 3 + web/vendor/bootstrap-icons/bookmark-dash.svg | 4 + web/vendor/bootstrap-icons/bookmark-fill.svg | 3 + .../bootstrap-icons/bookmark-heart-fill.svg | 3 + web/vendor/bootstrap-icons/bookmark-heart.svg | 4 + .../bootstrap-icons/bookmark-plus-fill.svg | 3 + web/vendor/bootstrap-icons/bookmark-plus.svg | 4 + .../bootstrap-icons/bookmark-star-fill.svg | 3 + web/vendor/bootstrap-icons/bookmark-star.svg | 4 + .../bootstrap-icons/bookmark-x-fill.svg | 3 + web/vendor/bootstrap-icons/bookmark-x.svg | 4 + web/vendor/bootstrap-icons/bookmark.svg | 3 + web/vendor/bootstrap-icons/bookmarks-fill.svg | 4 + web/vendor/bootstrap-icons/bookmarks.svg | 4 + web/vendor/bootstrap-icons/bookshelf.svg | 3 + web/vendor/bootstrap-icons/boombox-fill.svg | 4 + web/vendor/bootstrap-icons/boombox.svg | 6 + web/vendor/bootstrap-icons/bootstrap-fill.svg | 4 + .../bootstrap-icons/bootstrap-icons.css | 2106 +++ .../bootstrap-icons/bootstrap-icons.json | 2080 +++ .../bootstrap-icons/bootstrap-icons.min.css | 5 + .../bootstrap-icons/bootstrap-icons.scss | 2118 +++ .../bootstrap-icons/bootstrap-icons.svg | 1 + .../bootstrap-icons/bootstrap-reboot.svg | 4 + web/vendor/bootstrap-icons/bootstrap.svg | 4 + web/vendor/bootstrap-icons/border-all.svg | 3 + web/vendor/bootstrap-icons/border-bottom.svg | 3 + web/vendor/bootstrap-icons/border-center.svg | 3 + web/vendor/bootstrap-icons/border-inner.svg | 5 + web/vendor/bootstrap-icons/border-left.svg | 3 + web/vendor/bootstrap-icons/border-middle.svg | 3 + web/vendor/bootstrap-icons/border-outer.svg | 4 + web/vendor/bootstrap-icons/border-right.svg | 3 + web/vendor/bootstrap-icons/border-style.svg | 3 + web/vendor/bootstrap-icons/border-top.svg | 3 + web/vendor/bootstrap-icons/border-width.svg | 3 + web/vendor/bootstrap-icons/border.svg | 3 + .../bootstrap-icons/bounding-box-circles.svg | 3 + web/vendor/bootstrap-icons/bounding-box.svg | 3 + .../bootstrap-icons/box-arrow-down-left.svg | 4 + .../bootstrap-icons/box-arrow-down-right.svg | 4 + web/vendor/bootstrap-icons/box-arrow-down.svg | 4 + .../box-arrow-in-down-left.svg | 4 + .../box-arrow-in-down-right.svg | 4 + .../bootstrap-icons/box-arrow-in-down.svg | 4 + .../bootstrap-icons/box-arrow-in-left.svg | 4 + .../bootstrap-icons/box-arrow-in-right.svg | 4 + .../bootstrap-icons/box-arrow-in-up-left.svg | 4 + .../bootstrap-icons/box-arrow-in-up-right.svg | 4 + .../bootstrap-icons/box-arrow-in-up.svg | 4 + web/vendor/bootstrap-icons/box-arrow-left.svg | 4 + .../bootstrap-icons/box-arrow-right.svg | 4 + .../bootstrap-icons/box-arrow-up-left.svg | 4 + .../bootstrap-icons/box-arrow-up-right.svg | 4 + web/vendor/bootstrap-icons/box-arrow-up.svg | 4 + web/vendor/bootstrap-icons/box-fill.svg | 3 + web/vendor/bootstrap-icons/box-seam-fill.svg | 3 + web/vendor/bootstrap-icons/box-seam.svg | 3 + web/vendor/bootstrap-icons/box.svg | 3 + web/vendor/bootstrap-icons/box2-fill.svg | 3 + .../bootstrap-icons/box2-heart-fill.svg | 3 + web/vendor/bootstrap-icons/box2-heart.svg | 4 + web/vendor/bootstrap-icons/box2.svg | 3 + web/vendor/bootstrap-icons/boxes.svg | 3 + .../bootstrap-icons/braces-asterisk.svg | 3 + web/vendor/bootstrap-icons/braces.svg | 3 + web/vendor/bootstrap-icons/bricks.svg | 3 + web/vendor/bootstrap-icons/briefcase-fill.svg | 4 + web/vendor/bootstrap-icons/briefcase.svg | 3 + .../brightness-alt-high-fill.svg | 3 + .../bootstrap-icons/brightness-alt-high.svg | 3 + .../brightness-alt-low-fill.svg | 3 + .../bootstrap-icons/brightness-alt-low.svg | 3 + .../bootstrap-icons/brightness-high-fill.svg | 3 + .../bootstrap-icons/brightness-high.svg | 3 + .../bootstrap-icons/brightness-low-fill.svg | 3 + web/vendor/bootstrap-icons/brightness-low.svg | 3 + web/vendor/bootstrap-icons/brilliance.svg | 3 + web/vendor/bootstrap-icons/broadcast-pin.svg | 3 + web/vendor/bootstrap-icons/broadcast.svg | 3 + web/vendor/bootstrap-icons/browser-chrome.svg | 3 + web/vendor/bootstrap-icons/browser-edge.svg | 5 + .../bootstrap-icons/browser-firefox.svg | 3 + web/vendor/bootstrap-icons/browser-safari.svg | 3 + web/vendor/bootstrap-icons/brush-fill.svg | 3 + web/vendor/bootstrap-icons/brush.svg | 3 + web/vendor/bootstrap-icons/bucket-fill.svg | 3 + web/vendor/bootstrap-icons/bucket.svg | 3 + web/vendor/bootstrap-icons/bug-fill.svg | 4 + web/vendor/bootstrap-icons/bug.svg | 3 + web/vendor/bootstrap-icons/building-add.svg | 5 + web/vendor/bootstrap-icons/building-check.svg | 5 + web/vendor/bootstrap-icons/building-dash.svg | 5 + web/vendor/bootstrap-icons/building-down.svg | 5 + .../bootstrap-icons/building-exclamation.svg | 4 + .../bootstrap-icons/building-fill-add.svg | 4 + .../bootstrap-icons/building-fill-check.svg | 4 + .../bootstrap-icons/building-fill-dash.svg | 4 + .../bootstrap-icons/building-fill-down.svg | 4 + .../building-fill-exclamation.svg | 4 + .../bootstrap-icons/building-fill-gear.svg | 4 + .../bootstrap-icons/building-fill-lock.svg | 4 + .../bootstrap-icons/building-fill-slash.svg | 4 + .../bootstrap-icons/building-fill-up.svg | 4 + .../bootstrap-icons/building-fill-x.svg | 4 + web/vendor/bootstrap-icons/building-fill.svg | 3 + web/vendor/bootstrap-icons/building-gear.svg | 4 + web/vendor/bootstrap-icons/building-lock.svg | 4 + web/vendor/bootstrap-icons/building-slash.svg | 5 + web/vendor/bootstrap-icons/building-up.svg | 5 + web/vendor/bootstrap-icons/building-x.svg | 4 + web/vendor/bootstrap-icons/building.svg | 4 + web/vendor/bootstrap-icons/buildings-fill.svg | 3 + web/vendor/bootstrap-icons/buildings.svg | 4 + web/vendor/bootstrap-icons/bullseye.svg | 6 + web/vendor/bootstrap-icons/bus-front-fill.svg | 3 + web/vendor/bootstrap-icons/bus-front.svg | 4 + web/vendor/bootstrap-icons/c-circle-fill.svg | 3 + web/vendor/bootstrap-icons/c-circle.svg | 3 + web/vendor/bootstrap-icons/c-square-fill.svg | 3 + web/vendor/bootstrap-icons/c-square.svg | 4 + web/vendor/bootstrap-icons/cake-fill.svg | 3 + web/vendor/bootstrap-icons/cake.svg | 3 + web/vendor/bootstrap-icons/cake2-fill.svg | 4 + web/vendor/bootstrap-icons/cake2.svg | 3 + .../bootstrap-icons/calculator-fill.svg | 3 + web/vendor/bootstrap-icons/calculator.svg | 4 + .../bootstrap-icons/calendar-check-fill.svg | 3 + web/vendor/bootstrap-icons/calendar-check.svg | 4 + .../bootstrap-icons/calendar-date-fill.svg | 4 + web/vendor/bootstrap-icons/calendar-date.svg | 4 + .../bootstrap-icons/calendar-day-fill.svg | 3 + web/vendor/bootstrap-icons/calendar-day.svg | 4 + .../bootstrap-icons/calendar-event-fill.svg | 3 + web/vendor/bootstrap-icons/calendar-event.svg | 4 + web/vendor/bootstrap-icons/calendar-fill.svg | 3 + .../bootstrap-icons/calendar-heart-fill.svg | 3 + web/vendor/bootstrap-icons/calendar-heart.svg | 3 + .../bootstrap-icons/calendar-minus-fill.svg | 3 + web/vendor/bootstrap-icons/calendar-minus.svg | 4 + .../bootstrap-icons/calendar-month-fill.svg | 4 + web/vendor/bootstrap-icons/calendar-month.svg | 4 + .../bootstrap-icons/calendar-plus-fill.svg | 3 + web/vendor/bootstrap-icons/calendar-plus.svg | 4 + .../bootstrap-icons/calendar-range-fill.svg | 3 + web/vendor/bootstrap-icons/calendar-range.svg | 4 + .../bootstrap-icons/calendar-week-fill.svg | 3 + web/vendor/bootstrap-icons/calendar-week.svg | 4 + .../bootstrap-icons/calendar-x-fill.svg | 3 + web/vendor/bootstrap-icons/calendar-x.svg | 4 + web/vendor/bootstrap-icons/calendar.svg | 3 + .../bootstrap-icons/calendar2-check-fill.svg | 3 + .../bootstrap-icons/calendar2-check.svg | 5 + .../bootstrap-icons/calendar2-date-fill.svg | 4 + web/vendor/bootstrap-icons/calendar2-date.svg | 5 + .../bootstrap-icons/calendar2-day-fill.svg | 3 + web/vendor/bootstrap-icons/calendar2-day.svg | 5 + .../bootstrap-icons/calendar2-event-fill.svg | 3 + .../bootstrap-icons/calendar2-event.svg | 5 + web/vendor/bootstrap-icons/calendar2-fill.svg | 3 + .../bootstrap-icons/calendar2-heart-fill.svg | 3 + .../bootstrap-icons/calendar2-heart.svg | 3 + .../bootstrap-icons/calendar2-minus-fill.svg | 3 + .../bootstrap-icons/calendar2-minus.svg | 5 + .../bootstrap-icons/calendar2-month-fill.svg | 4 + .../bootstrap-icons/calendar2-month.svg | 5 + .../bootstrap-icons/calendar2-plus-fill.svg | 3 + web/vendor/bootstrap-icons/calendar2-plus.svg | 4 + .../bootstrap-icons/calendar2-range-fill.svg | 3 + .../bootstrap-icons/calendar2-range.svg | 4 + .../bootstrap-icons/calendar2-week-fill.svg | 3 + web/vendor/bootstrap-icons/calendar2-week.svg | 4 + .../bootstrap-icons/calendar2-x-fill.svg | 3 + web/vendor/bootstrap-icons/calendar2-x.svg | 5 + web/vendor/bootstrap-icons/calendar2.svg | 4 + .../bootstrap-icons/calendar3-event-fill.svg | 3 + .../bootstrap-icons/calendar3-event.svg | 4 + web/vendor/bootstrap-icons/calendar3-fill.svg | 3 + .../bootstrap-icons/calendar3-range-fill.svg | 3 + .../bootstrap-icons/calendar3-range.svg | 4 + .../bootstrap-icons/calendar3-week-fill.svg | 3 + web/vendor/bootstrap-icons/calendar3-week.svg | 4 + web/vendor/bootstrap-icons/calendar3.svg | 4 + .../bootstrap-icons/calendar4-event.svg | 4 + .../bootstrap-icons/calendar4-range.svg | 4 + web/vendor/bootstrap-icons/calendar4-week.svg | 4 + web/vendor/bootstrap-icons/calendar4.svg | 3 + web/vendor/bootstrap-icons/camera-fill.svg | 4 + .../bootstrap-icons/camera-reels-fill.svg | 5 + web/vendor/bootstrap-icons/camera-reels.svg | 5 + .../bootstrap-icons/camera-video-fill.svg | 3 + .../bootstrap-icons/camera-video-off-fill.svg | 3 + .../bootstrap-icons/camera-video-off.svg | 3 + web/vendor/bootstrap-icons/camera-video.svg | 3 + web/vendor/bootstrap-icons/camera.svg | 4 + web/vendor/bootstrap-icons/camera2.svg | 4 + web/vendor/bootstrap-icons/capslock-fill.svg | 3 + web/vendor/bootstrap-icons/capslock.svg | 3 + web/vendor/bootstrap-icons/capsule-pill.svg | 3 + web/vendor/bootstrap-icons/capsule.svg | 3 + web/vendor/bootstrap-icons/car-front-fill.svg | 3 + web/vendor/bootstrap-icons/car-front.svg | 4 + web/vendor/bootstrap-icons/card-checklist.svg | 4 + web/vendor/bootstrap-icons/card-heading.svg | 4 + web/vendor/bootstrap-icons/card-image.svg | 4 + web/vendor/bootstrap-icons/card-list.svg | 4 + web/vendor/bootstrap-icons/card-text.svg | 4 + .../bootstrap-icons/caret-down-fill.svg | 3 + .../caret-down-square-fill.svg | 3 + .../bootstrap-icons/caret-down-square.svg | 4 + web/vendor/bootstrap-icons/caret-down.svg | 3 + .../bootstrap-icons/caret-left-fill.svg | 3 + .../caret-left-square-fill.svg | 3 + .../bootstrap-icons/caret-left-square.svg | 4 + web/vendor/bootstrap-icons/caret-left.svg | 3 + .../bootstrap-icons/caret-right-fill.svg | 3 + .../caret-right-square-fill.svg | 3 + .../bootstrap-icons/caret-right-square.svg | 4 + web/vendor/bootstrap-icons/caret-right.svg | 3 + web/vendor/bootstrap-icons/caret-up-fill.svg | 3 + .../bootstrap-icons/caret-up-square-fill.svg | 3 + .../bootstrap-icons/caret-up-square.svg | 4 + web/vendor/bootstrap-icons/caret-up.svg | 3 + .../bootstrap-icons/cart-check-fill.svg | 3 + web/vendor/bootstrap-icons/cart-check.svg | 4 + web/vendor/bootstrap-icons/cart-dash-fill.svg | 3 + web/vendor/bootstrap-icons/cart-dash.svg | 4 + web/vendor/bootstrap-icons/cart-fill.svg | 3 + web/vendor/bootstrap-icons/cart-plus-fill.svg | 3 + web/vendor/bootstrap-icons/cart-plus.svg | 4 + web/vendor/bootstrap-icons/cart-x-fill.svg | 3 + web/vendor/bootstrap-icons/cart-x.svg | 4 + web/vendor/bootstrap-icons/cart.svg | 3 + web/vendor/bootstrap-icons/cart2.svg | 3 + web/vendor/bootstrap-icons/cart3.svg | 3 + web/vendor/bootstrap-icons/cart4.svg | 3 + web/vendor/bootstrap-icons/cash-coin.svg | 6 + web/vendor/bootstrap-icons/cash-stack.svg | 4 + web/vendor/bootstrap-icons/cash.svg | 4 + web/vendor/bootstrap-icons/cassette-fill.svg | 4 + web/vendor/bootstrap-icons/cassette.svg | 4 + web/vendor/bootstrap-icons/cast.svg | 4 + web/vendor/bootstrap-icons/cc-circle-fill.svg | 3 + web/vendor/bootstrap-icons/cc-circle.svg | 3 + web/vendor/bootstrap-icons/cc-square-fill.svg | 3 + web/vendor/bootstrap-icons/cc-square.svg | 4 + web/vendor/bootstrap-icons/chat-dots-fill.svg | 3 + web/vendor/bootstrap-icons/chat-dots.svg | 4 + web/vendor/bootstrap-icons/chat-fill.svg | 3 + .../bootstrap-icons/chat-heart-fill.svg | 3 + web/vendor/bootstrap-icons/chat-heart.svg | 3 + .../bootstrap-icons/chat-left-dots-fill.svg | 3 + web/vendor/bootstrap-icons/chat-left-dots.svg | 4 + web/vendor/bootstrap-icons/chat-left-fill.svg | 3 + .../bootstrap-icons/chat-left-heart-fill.svg | 3 + .../bootstrap-icons/chat-left-heart.svg | 4 + .../bootstrap-icons/chat-left-quote-fill.svg | 3 + .../bootstrap-icons/chat-left-quote.svg | 4 + .../bootstrap-icons/chat-left-text-fill.svg | 3 + web/vendor/bootstrap-icons/chat-left-text.svg | 4 + web/vendor/bootstrap-icons/chat-left.svg | 3 + .../bootstrap-icons/chat-quote-fill.svg | 3 + web/vendor/bootstrap-icons/chat-quote.svg | 4 + .../bootstrap-icons/chat-right-dots-fill.svg | 3 + .../bootstrap-icons/chat-right-dots.svg | 4 + .../bootstrap-icons/chat-right-fill.svg | 3 + .../bootstrap-icons/chat-right-heart-fill.svg | 3 + .../bootstrap-icons/chat-right-heart.svg | 4 + .../bootstrap-icons/chat-right-quote-fill.svg | 3 + .../bootstrap-icons/chat-right-quote.svg | 4 + .../bootstrap-icons/chat-right-text-fill.svg | 3 + .../bootstrap-icons/chat-right-text.svg | 4 + web/vendor/bootstrap-icons/chat-right.svg | 3 + .../bootstrap-icons/chat-square-dots-fill.svg | 3 + .../bootstrap-icons/chat-square-dots.svg | 4 + .../bootstrap-icons/chat-square-fill.svg | 3 + .../chat-square-heart-fill.svg | 3 + .../bootstrap-icons/chat-square-heart.svg | 4 + .../chat-square-quote-fill.svg | 3 + .../bootstrap-icons/chat-square-quote.svg | 4 + .../bootstrap-icons/chat-square-text-fill.svg | 3 + .../bootstrap-icons/chat-square-text.svg | 4 + web/vendor/bootstrap-icons/chat-square.svg | 3 + web/vendor/bootstrap-icons/chat-text-fill.svg | 3 + web/vendor/bootstrap-icons/chat-text.svg | 4 + web/vendor/bootstrap-icons/chat.svg | 3 + web/vendor/bootstrap-icons/check-all.svg | 3 + .../bootstrap-icons/check-circle-fill.svg | 3 + web/vendor/bootstrap-icons/check-circle.svg | 4 + web/vendor/bootstrap-icons/check-lg.svg | 3 + .../bootstrap-icons/check-square-fill.svg | 3 + web/vendor/bootstrap-icons/check-square.svg | 4 + web/vendor/bootstrap-icons/check.svg | 3 + web/vendor/bootstrap-icons/check2-all.svg | 4 + web/vendor/bootstrap-icons/check2-circle.svg | 4 + web/vendor/bootstrap-icons/check2-square.svg | 4 + web/vendor/bootstrap-icons/check2.svg | 3 + .../bootstrap-icons/chevron-bar-contract.svg | 3 + .../bootstrap-icons/chevron-bar-down.svg | 3 + .../bootstrap-icons/chevron-bar-expand.svg | 3 + .../bootstrap-icons/chevron-bar-left.svg | 3 + .../bootstrap-icons/chevron-bar-right.svg | 3 + web/vendor/bootstrap-icons/chevron-bar-up.svg | 3 + .../bootstrap-icons/chevron-compact-down.svg | 3 + .../bootstrap-icons/chevron-compact-left.svg | 3 + .../bootstrap-icons/chevron-compact-right.svg | 3 + .../bootstrap-icons/chevron-compact-up.svg | 3 + .../bootstrap-icons/chevron-contract.svg | 3 + .../bootstrap-icons/chevron-double-down.svg | 4 + .../bootstrap-icons/chevron-double-left.svg | 4 + .../bootstrap-icons/chevron-double-right.svg | 4 + .../bootstrap-icons/chevron-double-up.svg | 4 + web/vendor/bootstrap-icons/chevron-down.svg | 3 + web/vendor/bootstrap-icons/chevron-expand.svg | 3 + web/vendor/bootstrap-icons/chevron-left.svg | 3 + web/vendor/bootstrap-icons/chevron-right.svg | 3 + web/vendor/bootstrap-icons/chevron-up.svg | 3 + web/vendor/bootstrap-icons/circle-fill.svg | 3 + web/vendor/bootstrap-icons/circle-half.svg | 3 + web/vendor/bootstrap-icons/circle-square.svg | 4 + web/vendor/bootstrap-icons/circle.svg | 3 + web/vendor/bootstrap-icons/claude.svg | 3 + .../bootstrap-icons/clipboard-check-fill.svg | 4 + .../bootstrap-icons/clipboard-check.svg | 5 + .../bootstrap-icons/clipboard-data-fill.svg | 4 + web/vendor/bootstrap-icons/clipboard-data.svg | 5 + web/vendor/bootstrap-icons/clipboard-fill.svg | 3 + .../bootstrap-icons/clipboard-heart-fill.svg | 4 + .../bootstrap-icons/clipboard-heart.svg | 5 + .../bootstrap-icons/clipboard-minus-fill.svg | 4 + .../bootstrap-icons/clipboard-minus.svg | 5 + .../bootstrap-icons/clipboard-plus-fill.svg | 4 + web/vendor/bootstrap-icons/clipboard-plus.svg | 5 + .../bootstrap-icons/clipboard-pulse.svg | 3 + .../bootstrap-icons/clipboard-x-fill.svg | 4 + web/vendor/bootstrap-icons/clipboard-x.svg | 5 + web/vendor/bootstrap-icons/clipboard.svg | 4 + .../bootstrap-icons/clipboard2-check-fill.svg | 4 + .../bootstrap-icons/clipboard2-check.svg | 5 + .../bootstrap-icons/clipboard2-data-fill.svg | 4 + .../bootstrap-icons/clipboard2-data.svg | 5 + .../bootstrap-icons/clipboard2-fill.svg | 4 + .../bootstrap-icons/clipboard2-heart-fill.svg | 4 + .../bootstrap-icons/clipboard2-heart.svg | 5 + .../bootstrap-icons/clipboard2-minus-fill.svg | 4 + .../bootstrap-icons/clipboard2-minus.svg | 5 + .../bootstrap-icons/clipboard2-plus-fill.svg | 4 + .../bootstrap-icons/clipboard2-plus.svg | 5 + .../bootstrap-icons/clipboard2-pulse-fill.svg | 4 + .../bootstrap-icons/clipboard2-pulse.svg | 5 + .../bootstrap-icons/clipboard2-x-fill.svg | 4 + web/vendor/bootstrap-icons/clipboard2-x.svg | 5 + web/vendor/bootstrap-icons/clipboard2.svg | 4 + web/vendor/bootstrap-icons/clock-fill.svg | 3 + web/vendor/bootstrap-icons/clock-history.svg | 5 + web/vendor/bootstrap-icons/clock.svg | 4 + .../bootstrap-icons/cloud-arrow-down-fill.svg | 3 + .../bootstrap-icons/cloud-arrow-down.svg | 4 + .../bootstrap-icons/cloud-arrow-up-fill.svg | 3 + web/vendor/bootstrap-icons/cloud-arrow-up.svg | 4 + .../bootstrap-icons/cloud-check-fill.svg | 3 + web/vendor/bootstrap-icons/cloud-check.svg | 4 + .../bootstrap-icons/cloud-download-fill.svg | 3 + web/vendor/bootstrap-icons/cloud-download.svg | 4 + .../bootstrap-icons/cloud-drizzle-fill.svg | 3 + web/vendor/bootstrap-icons/cloud-drizzle.svg | 3 + web/vendor/bootstrap-icons/cloud-fill.svg | 3 + web/vendor/bootstrap-icons/cloud-fog-fill.svg | 3 + web/vendor/bootstrap-icons/cloud-fog.svg | 3 + .../bootstrap-icons/cloud-fog2-fill.svg | 3 + web/vendor/bootstrap-icons/cloud-fog2.svg | 3 + .../bootstrap-icons/cloud-hail-fill.svg | 3 + web/vendor/bootstrap-icons/cloud-hail.svg | 3 + .../bootstrap-icons/cloud-haze-fill.svg | 3 + web/vendor/bootstrap-icons/cloud-haze.svg | 3 + .../bootstrap-icons/cloud-haze2-fill.svg | 3 + web/vendor/bootstrap-icons/cloud-haze2.svg | 3 + .../bootstrap-icons/cloud-lightning-fill.svg | 3 + .../cloud-lightning-rain-fill.svg | 3 + .../bootstrap-icons/cloud-lightning-rain.svg | 3 + .../bootstrap-icons/cloud-lightning.svg | 3 + .../bootstrap-icons/cloud-minus-fill.svg | 3 + web/vendor/bootstrap-icons/cloud-minus.svg | 4 + .../bootstrap-icons/cloud-moon-fill.svg | 4 + web/vendor/bootstrap-icons/cloud-moon.svg | 4 + .../bootstrap-icons/cloud-plus-fill.svg | 3 + web/vendor/bootstrap-icons/cloud-plus.svg | 4 + .../bootstrap-icons/cloud-rain-fill.svg | 3 + .../bootstrap-icons/cloud-rain-heavy-fill.svg | 3 + .../bootstrap-icons/cloud-rain-heavy.svg | 3 + web/vendor/bootstrap-icons/cloud-rain.svg | 3 + .../bootstrap-icons/cloud-slash-fill.svg | 3 + web/vendor/bootstrap-icons/cloud-slash.svg | 4 + .../bootstrap-icons/cloud-sleet-fill.svg | 3 + web/vendor/bootstrap-icons/cloud-sleet.svg | 3 + .../bootstrap-icons/cloud-snow-fill.svg | 3 + web/vendor/bootstrap-icons/cloud-snow.svg | 3 + web/vendor/bootstrap-icons/cloud-sun-fill.svg | 4 + web/vendor/bootstrap-icons/cloud-sun.svg | 4 + .../bootstrap-icons/cloud-upload-fill.svg | 3 + web/vendor/bootstrap-icons/cloud-upload.svg | 4 + web/vendor/bootstrap-icons/cloud.svg | 3 + web/vendor/bootstrap-icons/clouds-fill.svg | 4 + web/vendor/bootstrap-icons/clouds.svg | 4 + web/vendor/bootstrap-icons/cloudy-fill.svg | 3 + web/vendor/bootstrap-icons/cloudy.svg | 3 + web/vendor/bootstrap-icons/code-slash.svg | 3 + web/vendor/bootstrap-icons/code-square.svg | 4 + web/vendor/bootstrap-icons/code.svg | 3 + web/vendor/bootstrap-icons/coin.svg | 5 + .../bootstrap-icons/collection-fill.svg | 3 + .../bootstrap-icons/collection-play-fill.svg | 3 + .../bootstrap-icons/collection-play.svg | 4 + web/vendor/bootstrap-icons/collection.svg | 3 + web/vendor/bootstrap-icons/columns-gap.svg | 3 + web/vendor/bootstrap-icons/columns.svg | 3 + web/vendor/bootstrap-icons/command.svg | 3 + web/vendor/bootstrap-icons/compass-fill.svg | 3 + web/vendor/bootstrap-icons/compass.svg | 4 + web/vendor/bootstrap-icons/cone-striped.svg | 3 + web/vendor/bootstrap-icons/cone.svg | 3 + web/vendor/bootstrap-icons/controller.svg | 4 + web/vendor/bootstrap-icons/cookie.svg | 4 + web/vendor/bootstrap-icons/copy.svg | 3 + web/vendor/bootstrap-icons/cpu-fill.svg | 4 + web/vendor/bootstrap-icons/cpu.svg | 3 + .../credit-card-2-back-fill.svg | 3 + .../bootstrap-icons/credit-card-2-back.svg | 4 + .../credit-card-2-front-fill.svg | 3 + .../bootstrap-icons/credit-card-2-front.svg | 4 + .../bootstrap-icons/credit-card-fill.svg | 3 + web/vendor/bootstrap-icons/credit-card.svg | 4 + web/vendor/bootstrap-icons/crop.svg | 3 + web/vendor/bootstrap-icons/crosshair.svg | 3 + web/vendor/bootstrap-icons/crosshair2.svg | 3 + web/vendor/bootstrap-icons/css.svg | 3 + web/vendor/bootstrap-icons/cup-fill.svg | 3 + web/vendor/bootstrap-icons/cup-hot-fill.svg | 4 + web/vendor/bootstrap-icons/cup-hot.svg | 4 + web/vendor/bootstrap-icons/cup-straw.svg | 3 + web/vendor/bootstrap-icons/cup.svg | 3 + .../bootstrap-icons/currency-bitcoin.svg | 3 + .../bootstrap-icons/currency-dollar.svg | 3 + web/vendor/bootstrap-icons/currency-euro.svg | 3 + .../bootstrap-icons/currency-exchange.svg | 3 + web/vendor/bootstrap-icons/currency-pound.svg | 3 + web/vendor/bootstrap-icons/currency-rupee.svg | 3 + web/vendor/bootstrap-icons/currency-yen.svg | 3 + web/vendor/bootstrap-icons/cursor-fill.svg | 3 + web/vendor/bootstrap-icons/cursor-text.svg | 3 + web/vendor/bootstrap-icons/cursor.svg | 3 + .../bootstrap-icons/dash-circle-dotted.svg | 3 + .../bootstrap-icons/dash-circle-fill.svg | 3 + web/vendor/bootstrap-icons/dash-circle.svg | 4 + web/vendor/bootstrap-icons/dash-lg.svg | 3 + .../bootstrap-icons/dash-square-dotted.svg | 3 + .../bootstrap-icons/dash-square-fill.svg | 3 + web/vendor/bootstrap-icons/dash-square.svg | 4 + web/vendor/bootstrap-icons/dash.svg | 3 + web/vendor/bootstrap-icons/database-add.svg | 4 + web/vendor/bootstrap-icons/database-check.svg | 4 + web/vendor/bootstrap-icons/database-dash.svg | 4 + web/vendor/bootstrap-icons/database-down.svg | 4 + .../bootstrap-icons/database-exclamation.svg | 4 + .../bootstrap-icons/database-fill-add.svg | 4 + .../bootstrap-icons/database-fill-check.svg | 4 + .../bootstrap-icons/database-fill-dash.svg | 4 + .../bootstrap-icons/database-fill-down.svg | 4 + .../database-fill-exclamation.svg | 5 + .../bootstrap-icons/database-fill-gear.svg | 4 + .../bootstrap-icons/database-fill-lock.svg | 5 + .../bootstrap-icons/database-fill-slash.svg | 4 + .../bootstrap-icons/database-fill-up.svg | 4 + .../bootstrap-icons/database-fill-x.svg | 5 + web/vendor/bootstrap-icons/database-fill.svg | 6 + web/vendor/bootstrap-icons/database-gear.svg | 4 + web/vendor/bootstrap-icons/database-lock.svg | 4 + web/vendor/bootstrap-icons/database-slash.svg | 4 + web/vendor/bootstrap-icons/database-up.svg | 4 + web/vendor/bootstrap-icons/database-x.svg | 4 + web/vendor/bootstrap-icons/database.svg | 3 + .../bootstrap-icons/device-hdd-fill.svg | 4 + web/vendor/bootstrap-icons/device-hdd.svg | 5 + .../bootstrap-icons/device-ssd-fill.svg | 4 + web/vendor/bootstrap-icons/device-ssd.svg | 4 + web/vendor/bootstrap-icons/diagram-2-fill.svg | 3 + web/vendor/bootstrap-icons/diagram-2.svg | 3 + web/vendor/bootstrap-icons/diagram-3-fill.svg | 3 + web/vendor/bootstrap-icons/diagram-3.svg | 3 + web/vendor/bootstrap-icons/diamond-fill.svg | 3 + web/vendor/bootstrap-icons/diamond-half.svg | 3 + web/vendor/bootstrap-icons/diamond.svg | 3 + web/vendor/bootstrap-icons/dice-1-fill.svg | 3 + web/vendor/bootstrap-icons/dice-1.svg | 4 + web/vendor/bootstrap-icons/dice-2-fill.svg | 3 + web/vendor/bootstrap-icons/dice-2.svg | 4 + web/vendor/bootstrap-icons/dice-3-fill.svg | 3 + web/vendor/bootstrap-icons/dice-3.svg | 4 + web/vendor/bootstrap-icons/dice-4-fill.svg | 3 + web/vendor/bootstrap-icons/dice-4.svg | 4 + web/vendor/bootstrap-icons/dice-5-fill.svg | 3 + web/vendor/bootstrap-icons/dice-5.svg | 4 + web/vendor/bootstrap-icons/dice-6-fill.svg | 3 + web/vendor/bootstrap-icons/dice-6.svg | 4 + web/vendor/bootstrap-icons/disc-fill.svg | 3 + web/vendor/bootstrap-icons/disc.svg | 4 + web/vendor/bootstrap-icons/discord.svg | 3 + web/vendor/bootstrap-icons/display-fill.svg | 3 + web/vendor/bootstrap-icons/display.svg | 3 + .../bootstrap-icons/displayport-fill.svg | 3 + web/vendor/bootstrap-icons/displayport.svg | 4 + .../bootstrap-icons/distribute-horizontal.svg | 4 + .../bootstrap-icons/distribute-vertical.svg | 4 + .../bootstrap-icons/door-closed-fill.svg | 3 + web/vendor/bootstrap-icons/door-closed.svg | 4 + web/vendor/bootstrap-icons/door-open-fill.svg | 3 + web/vendor/bootstrap-icons/door-open.svg | 4 + web/vendor/bootstrap-icons/dot.svg | 3 + web/vendor/bootstrap-icons/download.svg | 4 + web/vendor/bootstrap-icons/dpad-fill.svg | 3 + web/vendor/bootstrap-icons/dpad.svg | 4 + web/vendor/bootstrap-icons/dribbble.svg | 3 + web/vendor/bootstrap-icons/dropbox.svg | 3 + web/vendor/bootstrap-icons/droplet-fill.svg | 3 + web/vendor/bootstrap-icons/droplet-half.svg | 4 + web/vendor/bootstrap-icons/droplet.svg | 4 + web/vendor/bootstrap-icons/duffle-fill.svg | 3 + web/vendor/bootstrap-icons/duffle.svg | 4 + web/vendor/bootstrap-icons/ear-fill.svg | 3 + web/vendor/bootstrap-icons/ear.svg | 3 + web/vendor/bootstrap-icons/earbuds.svg | 3 + web/vendor/bootstrap-icons/easel-fill.svg | 3 + web/vendor/bootstrap-icons/easel.svg | 3 + web/vendor/bootstrap-icons/easel2-fill.svg | 4 + web/vendor/bootstrap-icons/easel2.svg | 3 + web/vendor/bootstrap-icons/easel3-fill.svg | 3 + web/vendor/bootstrap-icons/easel3.svg | 3 + web/vendor/bootstrap-icons/egg-fill.svg | 3 + web/vendor/bootstrap-icons/egg-fried.svg | 4 + web/vendor/bootstrap-icons/egg.svg | 3 + web/vendor/bootstrap-icons/eject-fill.svg | 3 + web/vendor/bootstrap-icons/eject.svg | 3 + .../bootstrap-icons/emoji-angry-fill.svg | 3 + web/vendor/bootstrap-icons/emoji-angry.svg | 4 + .../bootstrap-icons/emoji-astonished-fill.svg | 3 + .../bootstrap-icons/emoji-astonished.svg | 4 + .../bootstrap-icons/emoji-dizzy-fill.svg | 3 + web/vendor/bootstrap-icons/emoji-dizzy.svg | 4 + .../emoji-expressionless-fill.svg | 3 + .../bootstrap-icons/emoji-expressionless.svg | 4 + .../bootstrap-icons/emoji-frown-fill.svg | 3 + web/vendor/bootstrap-icons/emoji-frown.svg | 4 + .../bootstrap-icons/emoji-grimace-fill.svg | 3 + web/vendor/bootstrap-icons/emoji-grimace.svg | 4 + .../bootstrap-icons/emoji-grin-fill.svg | 3 + web/vendor/bootstrap-icons/emoji-grin.svg | 4 + .../bootstrap-icons/emoji-heart-eyes-fill.svg | 3 + .../bootstrap-icons/emoji-heart-eyes.svg | 4 + .../bootstrap-icons/emoji-kiss-fill.svg | 3 + web/vendor/bootstrap-icons/emoji-kiss.svg | 3 + .../bootstrap-icons/emoji-laughing-fill.svg | 3 + web/vendor/bootstrap-icons/emoji-laughing.svg | 4 + .../bootstrap-icons/emoji-neutral-fill.svg | 3 + web/vendor/bootstrap-icons/emoji-neutral.svg | 4 + .../bootstrap-icons/emoji-smile-fill.svg | 3 + .../emoji-smile-upside-down-fill.svg | 3 + .../emoji-smile-upside-down.svg | 4 + web/vendor/bootstrap-icons/emoji-smile.svg | 4 + .../bootstrap-icons/emoji-sunglasses-fill.svg | 3 + .../bootstrap-icons/emoji-sunglasses.svg | 4 + .../bootstrap-icons/emoji-surprise-fill.svg | 3 + web/vendor/bootstrap-icons/emoji-surprise.svg | 4 + .../bootstrap-icons/emoji-tear-fill.svg | 3 + web/vendor/bootstrap-icons/emoji-tear.svg | 4 + .../bootstrap-icons/emoji-wink-fill.svg | 3 + web/vendor/bootstrap-icons/emoji-wink.svg | 4 + .../envelope-arrow-down-fill.svg | 4 + .../bootstrap-icons/envelope-arrow-down.svg | 4 + .../envelope-arrow-up-fill.svg | 4 + .../bootstrap-icons/envelope-arrow-up.svg | 4 + .../bootstrap-icons/envelope-at-fill.svg | 4 + web/vendor/bootstrap-icons/envelope-at.svg | 4 + .../bootstrap-icons/envelope-check-fill.svg | 4 + web/vendor/bootstrap-icons/envelope-check.svg | 4 + .../bootstrap-icons/envelope-dash-fill.svg | 4 + web/vendor/bootstrap-icons/envelope-dash.svg | 4 + .../envelope-exclamation-fill.svg | 4 + .../bootstrap-icons/envelope-exclamation.svg | 4 + web/vendor/bootstrap-icons/envelope-fill.svg | 3 + .../bootstrap-icons/envelope-heart-fill.svg | 4 + web/vendor/bootstrap-icons/envelope-heart.svg | 3 + .../bootstrap-icons/envelope-open-fill.svg | 3 + .../envelope-open-heart-fill.svg | 4 + .../bootstrap-icons/envelope-open-heart.svg | 3 + web/vendor/bootstrap-icons/envelope-open.svg | 3 + .../bootstrap-icons/envelope-paper-fill.svg | 3 + .../envelope-paper-heart-fill.svg | 3 + .../bootstrap-icons/envelope-paper-heart.svg | 3 + web/vendor/bootstrap-icons/envelope-paper.svg | 3 + .../bootstrap-icons/envelope-plus-fill.svg | 4 + web/vendor/bootstrap-icons/envelope-plus.svg | 4 + .../bootstrap-icons/envelope-slash-fill.svg | 4 + web/vendor/bootstrap-icons/envelope-slash.svg | 4 + .../bootstrap-icons/envelope-x-fill.svg | 4 + web/vendor/bootstrap-icons/envelope-x.svg | 4 + web/vendor/bootstrap-icons/envelope.svg | 3 + web/vendor/bootstrap-icons/eraser-fill.svg | 3 + web/vendor/bootstrap-icons/eraser.svg | 3 + web/vendor/bootstrap-icons/escape.svg | 4 + web/vendor/bootstrap-icons/ethernet.svg | 4 + web/vendor/bootstrap-icons/ev-front-fill.svg | 3 + web/vendor/bootstrap-icons/ev-front.svg | 4 + .../bootstrap-icons/ev-station-fill.svg | 3 + web/vendor/bootstrap-icons/ev-station.svg | 4 + .../exclamation-circle-fill.svg | 3 + .../bootstrap-icons/exclamation-circle.svg | 4 + .../exclamation-diamond-fill.svg | 3 + .../bootstrap-icons/exclamation-diamond.svg | 4 + web/vendor/bootstrap-icons/exclamation-lg.svg | 3 + .../exclamation-octagon-fill.svg | 3 + .../bootstrap-icons/exclamation-octagon.svg | 4 + .../exclamation-square-fill.svg | 3 + .../bootstrap-icons/exclamation-square.svg | 4 + .../exclamation-triangle-fill.svg | 3 + .../bootstrap-icons/exclamation-triangle.svg | 4 + web/vendor/bootstrap-icons/exclamation.svg | 3 + web/vendor/bootstrap-icons/exclude.svg | 3 + web/vendor/bootstrap-icons/explicit-fill.svg | 3 + web/vendor/bootstrap-icons/explicit.svg | 4 + web/vendor/bootstrap-icons/exposure.svg | 4 + web/vendor/bootstrap-icons/eye-fill.svg | 4 + web/vendor/bootstrap-icons/eye-slash-fill.svg | 4 + web/vendor/bootstrap-icons/eye-slash.svg | 5 + web/vendor/bootstrap-icons/eye.svg | 4 + web/vendor/bootstrap-icons/eyedropper.svg | 3 + web/vendor/bootstrap-icons/eyeglasses.svg | 3 + web/vendor/bootstrap-icons/facebook.svg | 3 + web/vendor/bootstrap-icons/fan.svg | 4 + .../bootstrap-icons/fast-forward-btn-fill.svg | 3 + .../bootstrap-icons/fast-forward-btn.svg | 4 + .../fast-forward-circle-fill.svg | 3 + .../bootstrap-icons/fast-forward-circle.svg | 4 + .../bootstrap-icons/fast-forward-fill.svg | 4 + web/vendor/bootstrap-icons/fast-forward.svg | 4 + web/vendor/bootstrap-icons/feather.svg | 3 + web/vendor/bootstrap-icons/feather2.svg | 3 + .../bootstrap-icons/file-arrow-down-fill.svg | 3 + .../bootstrap-icons/file-arrow-down.svg | 4 + .../bootstrap-icons/file-arrow-up-fill.svg | 3 + web/vendor/bootstrap-icons/file-arrow-up.svg | 4 + .../bootstrap-icons/file-bar-graph-fill.svg | 3 + web/vendor/bootstrap-icons/file-bar-graph.svg | 4 + .../bootstrap-icons/file-binary-fill.svg | 4 + web/vendor/bootstrap-icons/file-binary.svg | 4 + .../bootstrap-icons/file-break-fill.svg | 3 + web/vendor/bootstrap-icons/file-break.svg | 3 + .../bootstrap-icons/file-check-fill.svg | 3 + web/vendor/bootstrap-icons/file-check.svg | 4 + web/vendor/bootstrap-icons/file-code-fill.svg | 3 + web/vendor/bootstrap-icons/file-code.svg | 4 + web/vendor/bootstrap-icons/file-diff-fill.svg | 3 + web/vendor/bootstrap-icons/file-diff.svg | 4 + .../file-earmark-arrow-down-fill.svg | 3 + .../file-earmark-arrow-down.svg | 4 + .../file-earmark-arrow-up-fill.svg | 3 + .../bootstrap-icons/file-earmark-arrow-up.svg | 4 + .../file-earmark-bar-graph-fill.svg | 3 + .../file-earmark-bar-graph.svg | 4 + .../file-earmark-binary-fill.svg | 4 + .../bootstrap-icons/file-earmark-binary.svg | 4 + .../file-earmark-break-fill.svg | 3 + .../bootstrap-icons/file-earmark-break.svg | 3 + .../file-earmark-check-fill.svg | 3 + .../bootstrap-icons/file-earmark-check.svg | 4 + .../file-earmark-code-fill.svg | 3 + .../bootstrap-icons/file-earmark-code.svg | 4 + .../file-earmark-diff-fill.svg | 3 + .../bootstrap-icons/file-earmark-diff.svg | 4 + .../file-earmark-easel-fill.svg | 4 + .../bootstrap-icons/file-earmark-easel.svg | 4 + .../file-earmark-excel-fill.svg | 3 + .../bootstrap-icons/file-earmark-excel.svg | 4 + .../bootstrap-icons/file-earmark-fill.svg | 3 + .../file-earmark-font-fill.svg | 3 + .../bootstrap-icons/file-earmark-font.svg | 4 + .../file-earmark-image-fill.svg | 4 + .../bootstrap-icons/file-earmark-image.svg | 4 + .../file-earmark-lock-fill.svg | 4 + .../bootstrap-icons/file-earmark-lock.svg | 4 + .../file-earmark-lock2-fill.svg | 4 + .../bootstrap-icons/file-earmark-lock2.svg | 4 + .../file-earmark-medical-fill.svg | 3 + .../bootstrap-icons/file-earmark-medical.svg | 4 + .../file-earmark-minus-fill.svg | 3 + .../bootstrap-icons/file-earmark-minus.svg | 4 + .../file-earmark-music-fill.svg | 3 + .../bootstrap-icons/file-earmark-music.svg | 4 + .../bootstrap-icons/file-earmark-pdf-fill.svg | 4 + .../bootstrap-icons/file-earmark-pdf.svg | 4 + .../file-earmark-person-fill.svg | 3 + .../bootstrap-icons/file-earmark-person.svg | 4 + .../file-earmark-play-fill.svg | 3 + .../bootstrap-icons/file-earmark-play.svg | 4 + .../file-earmark-plus-fill.svg | 3 + .../bootstrap-icons/file-earmark-plus.svg | 4 + .../file-earmark-post-fill.svg | 3 + .../bootstrap-icons/file-earmark-post.svg | 4 + .../bootstrap-icons/file-earmark-ppt-fill.svg | 4 + .../bootstrap-icons/file-earmark-ppt.svg | 4 + .../file-earmark-richtext-fill.svg | 3 + .../bootstrap-icons/file-earmark-richtext.svg | 4 + .../file-earmark-ruled-fill.svg | 3 + .../bootstrap-icons/file-earmark-ruled.svg | 3 + .../file-earmark-slides-fill.svg | 4 + .../bootstrap-icons/file-earmark-slides.svg | 4 + .../file-earmark-spreadsheet-fill.svg | 4 + .../file-earmark-spreadsheet.svg | 3 + .../file-earmark-text-fill.svg | 3 + .../bootstrap-icons/file-earmark-text.svg | 4 + .../file-earmark-word-fill.svg | 3 + .../bootstrap-icons/file-earmark-word.svg | 4 + .../bootstrap-icons/file-earmark-x-fill.svg | 3 + web/vendor/bootstrap-icons/file-earmark-x.svg | 4 + .../bootstrap-icons/file-earmark-zip-fill.svg | 4 + .../bootstrap-icons/file-earmark-zip.svg | 4 + web/vendor/bootstrap-icons/file-earmark.svg | 3 + .../bootstrap-icons/file-easel-fill.svg | 4 + web/vendor/bootstrap-icons/file-easel.svg | 4 + .../bootstrap-icons/file-excel-fill.svg | 3 + web/vendor/bootstrap-icons/file-excel.svg | 4 + web/vendor/bootstrap-icons/file-fill.svg | 3 + web/vendor/bootstrap-icons/file-font-fill.svg | 3 + web/vendor/bootstrap-icons/file-font.svg | 4 + .../bootstrap-icons/file-image-fill.svg | 4 + web/vendor/bootstrap-icons/file-image.svg | 4 + web/vendor/bootstrap-icons/file-lock-fill.svg | 4 + web/vendor/bootstrap-icons/file-lock.svg | 4 + .../bootstrap-icons/file-lock2-fill.svg | 4 + web/vendor/bootstrap-icons/file-lock2.svg | 4 + .../bootstrap-icons/file-medical-fill.svg | 3 + web/vendor/bootstrap-icons/file-medical.svg | 4 + .../bootstrap-icons/file-minus-fill.svg | 3 + web/vendor/bootstrap-icons/file-minus.svg | 4 + .../bootstrap-icons/file-music-fill.svg | 3 + web/vendor/bootstrap-icons/file-music.svg | 4 + web/vendor/bootstrap-icons/file-pdf-fill.svg | 4 + web/vendor/bootstrap-icons/file-pdf.svg | 4 + .../bootstrap-icons/file-person-fill.svg | 3 + web/vendor/bootstrap-icons/file-person.svg | 4 + web/vendor/bootstrap-icons/file-play-fill.svg | 3 + web/vendor/bootstrap-icons/file-play.svg | 4 + web/vendor/bootstrap-icons/file-plus-fill.svg | 3 + web/vendor/bootstrap-icons/file-plus.svg | 4 + web/vendor/bootstrap-icons/file-post-fill.svg | 3 + web/vendor/bootstrap-icons/file-post.svg | 4 + web/vendor/bootstrap-icons/file-ppt-fill.svg | 4 + web/vendor/bootstrap-icons/file-ppt.svg | 4 + .../bootstrap-icons/file-richtext-fill.svg | 3 + web/vendor/bootstrap-icons/file-richtext.svg | 4 + .../bootstrap-icons/file-ruled-fill.svg | 3 + web/vendor/bootstrap-icons/file-ruled.svg | 3 + .../bootstrap-icons/file-slides-fill.svg | 4 + web/vendor/bootstrap-icons/file-slides.svg | 4 + .../bootstrap-icons/file-spreadsheet-fill.svg | 3 + .../bootstrap-icons/file-spreadsheet.svg | 3 + web/vendor/bootstrap-icons/file-text-fill.svg | 3 + web/vendor/bootstrap-icons/file-text.svg | 4 + web/vendor/bootstrap-icons/file-word-fill.svg | 3 + web/vendor/bootstrap-icons/file-word.svg | 4 + web/vendor/bootstrap-icons/file-x-fill.svg | 3 + web/vendor/bootstrap-icons/file-x.svg | 4 + web/vendor/bootstrap-icons/file-zip-fill.svg | 4 + web/vendor/bootstrap-icons/file-zip.svg | 4 + web/vendor/bootstrap-icons/file.svg | 3 + web/vendor/bootstrap-icons/files-alt.svg | 3 + web/vendor/bootstrap-icons/files.svg | 3 + web/vendor/bootstrap-icons/filetype-aac.svg | 3 + web/vendor/bootstrap-icons/filetype-ai.svg | 3 + web/vendor/bootstrap-icons/filetype-bmp.svg | 3 + web/vendor/bootstrap-icons/filetype-cs.svg | 3 + web/vendor/bootstrap-icons/filetype-css.svg | 3 + web/vendor/bootstrap-icons/filetype-csv.svg | 3 + web/vendor/bootstrap-icons/filetype-doc.svg | 3 + web/vendor/bootstrap-icons/filetype-docx.svg | 3 + web/vendor/bootstrap-icons/filetype-exe.svg | 3 + web/vendor/bootstrap-icons/filetype-gif.svg | 3 + web/vendor/bootstrap-icons/filetype-heic.svg | 3 + web/vendor/bootstrap-icons/filetype-html.svg | 3 + web/vendor/bootstrap-icons/filetype-java.svg | 3 + web/vendor/bootstrap-icons/filetype-jpg.svg | 3 + web/vendor/bootstrap-icons/filetype-js.svg | 3 + web/vendor/bootstrap-icons/filetype-json.svg | 3 + web/vendor/bootstrap-icons/filetype-jsx.svg | 3 + web/vendor/bootstrap-icons/filetype-key.svg | 3 + web/vendor/bootstrap-icons/filetype-m4p.svg | 3 + web/vendor/bootstrap-icons/filetype-md.svg | 3 + web/vendor/bootstrap-icons/filetype-mdx.svg | 3 + web/vendor/bootstrap-icons/filetype-mov.svg | 3 + web/vendor/bootstrap-icons/filetype-mp3.svg | 3 + web/vendor/bootstrap-icons/filetype-mp4.svg | 3 + web/vendor/bootstrap-icons/filetype-otf.svg | 3 + web/vendor/bootstrap-icons/filetype-pdf.svg | 3 + web/vendor/bootstrap-icons/filetype-php.svg | 3 + web/vendor/bootstrap-icons/filetype-png.svg | 3 + web/vendor/bootstrap-icons/filetype-ppt.svg | 3 + web/vendor/bootstrap-icons/filetype-pptx.svg | 3 + web/vendor/bootstrap-icons/filetype-psd.svg | 3 + web/vendor/bootstrap-icons/filetype-py.svg | 3 + web/vendor/bootstrap-icons/filetype-raw.svg | 3 + web/vendor/bootstrap-icons/filetype-rb.svg | 3 + web/vendor/bootstrap-icons/filetype-sass.svg | 3 + web/vendor/bootstrap-icons/filetype-scss.svg | 3 + web/vendor/bootstrap-icons/filetype-sh.svg | 3 + web/vendor/bootstrap-icons/filetype-sql.svg | 3 + web/vendor/bootstrap-icons/filetype-svg.svg | 3 + web/vendor/bootstrap-icons/filetype-tiff.svg | 3 + web/vendor/bootstrap-icons/filetype-tsx.svg | 3 + web/vendor/bootstrap-icons/filetype-ttf.svg | 3 + web/vendor/bootstrap-icons/filetype-txt.svg | 3 + web/vendor/bootstrap-icons/filetype-wav.svg | 3 + web/vendor/bootstrap-icons/filetype-woff.svg | 3 + web/vendor/bootstrap-icons/filetype-xls.svg | 3 + web/vendor/bootstrap-icons/filetype-xlsx.svg | 3 + web/vendor/bootstrap-icons/filetype-xml.svg | 3 + web/vendor/bootstrap-icons/filetype-yml.svg | 3 + web/vendor/bootstrap-icons/film.svg | 3 + .../bootstrap-icons/filter-circle-fill.svg | 3 + web/vendor/bootstrap-icons/filter-circle.svg | 4 + web/vendor/bootstrap-icons/filter-left.svg | 3 + web/vendor/bootstrap-icons/filter-right.svg | 3 + .../bootstrap-icons/filter-square-fill.svg | 3 + web/vendor/bootstrap-icons/filter-square.svg | 4 + web/vendor/bootstrap-icons/filter.svg | 3 + web/vendor/bootstrap-icons/fingerprint.svg | 7 + web/vendor/bootstrap-icons/fire.svg | 3 + web/vendor/bootstrap-icons/flag-fill.svg | 3 + web/vendor/bootstrap-icons/flag.svg | 3 + web/vendor/bootstrap-icons/flask-fill.svg | 3 + .../bootstrap-icons/flask-florence-fill.svg | 3 + web/vendor/bootstrap-icons/flask-florence.svg | 3 + web/vendor/bootstrap-icons/flask.svg | 3 + web/vendor/bootstrap-icons/floppy-fill.svg | 4 + web/vendor/bootstrap-icons/floppy.svg | 4 + web/vendor/bootstrap-icons/floppy2-fill.svg | 4 + web/vendor/bootstrap-icons/floppy2.svg | 3 + web/vendor/bootstrap-icons/flower1.svg | 3 + web/vendor/bootstrap-icons/flower2.svg | 3 + web/vendor/bootstrap-icons/flower3.svg | 3 + web/vendor/bootstrap-icons/folder-check.svg | 4 + web/vendor/bootstrap-icons/folder-fill.svg | 3 + web/vendor/bootstrap-icons/folder-minus.svg | 4 + web/vendor/bootstrap-icons/folder-plus.svg | 4 + .../bootstrap-icons/folder-symlink-fill.svg | 3 + web/vendor/bootstrap-icons/folder-symlink.svg | 4 + web/vendor/bootstrap-icons/folder-x.svg | 4 + web/vendor/bootstrap-icons/folder.svg | 3 + web/vendor/bootstrap-icons/folder2-open.svg | 3 + web/vendor/bootstrap-icons/folder2.svg | 3 + web/vendor/bootstrap-icons/fonts.svg | 3 + .../fonts/bootstrap-icons.woff | Bin 0 -> 180288 bytes .../fonts/bootstrap-icons.woff2 | Bin 0 -> 134044 bytes web/vendor/bootstrap-icons/fork-knife.svg | 3 + web/vendor/bootstrap-icons/forward-fill.svg | 3 + web/vendor/bootstrap-icons/forward.svg | 3 + web/vendor/bootstrap-icons/front.svg | 3 + .../bootstrap-icons/fuel-pump-diesel-fill.svg | 4 + .../bootstrap-icons/fuel-pump-diesel.svg | 4 + web/vendor/bootstrap-icons/fuel-pump-fill.svg | 3 + web/vendor/bootstrap-icons/fuel-pump.svg | 4 + .../bootstrap-icons/fullscreen-exit.svg | 3 + web/vendor/bootstrap-icons/fullscreen.svg | 3 + web/vendor/bootstrap-icons/funnel-fill.svg | 3 + web/vendor/bootstrap-icons/funnel.svg | 3 + web/vendor/bootstrap-icons/gear-fill.svg | 3 + .../bootstrap-icons/gear-wide-connected.svg | 3 + web/vendor/bootstrap-icons/gear-wide.svg | 3 + web/vendor/bootstrap-icons/gear.svg | 4 + web/vendor/bootstrap-icons/gem.svg | 3 + .../bootstrap-icons/gender-ambiguous.svg | 3 + web/vendor/bootstrap-icons/gender-female.svg | 3 + web/vendor/bootstrap-icons/gender-male.svg | 3 + web/vendor/bootstrap-icons/gender-neuter.svg | 3 + web/vendor/bootstrap-icons/gender-trans.svg | 3 + web/vendor/bootstrap-icons/geo-alt-fill.svg | 3 + web/vendor/bootstrap-icons/geo-alt.svg | 4 + web/vendor/bootstrap-icons/geo-fill.svg | 3 + web/vendor/bootstrap-icons/geo.svg | 3 + web/vendor/bootstrap-icons/gift-fill.svg | 3 + web/vendor/bootstrap-icons/gift.svg | 3 + web/vendor/bootstrap-icons/git.svg | 3 + web/vendor/bootstrap-icons/github.svg | 3 + web/vendor/bootstrap-icons/gitlab.svg | 3 + .../bootstrap-icons/globe-americas-fill.svg | 3 + web/vendor/bootstrap-icons/globe-americas.svg | 3 + .../globe-asia-australia-fill.svg | 3 + .../bootstrap-icons/globe-asia-australia.svg | 4 + .../globe-central-south-asia-fill.svg | 3 + .../globe-central-south-asia.svg | 3 + .../globe-europe-africa-fill.svg | 3 + .../bootstrap-icons/globe-europe-africa.svg | 3 + web/vendor/bootstrap-icons/globe.svg | 3 + web/vendor/bootstrap-icons/globe2.svg | 3 + web/vendor/bootstrap-icons/google-play.svg | 3 + web/vendor/bootstrap-icons/google.svg | 3 + web/vendor/bootstrap-icons/gpu-card.svg | 5 + .../bootstrap-icons/graph-down-arrow.svg | 3 + web/vendor/bootstrap-icons/graph-down.svg | 3 + web/vendor/bootstrap-icons/graph-up-arrow.svg | 3 + web/vendor/bootstrap-icons/graph-up.svg | 3 + web/vendor/bootstrap-icons/grid-1x2-fill.svg | 3 + web/vendor/bootstrap-icons/grid-1x2.svg | 3 + .../bootstrap-icons/grid-3x2-gap-fill.svg | 3 + web/vendor/bootstrap-icons/grid-3x2-gap.svg | 3 + web/vendor/bootstrap-icons/grid-3x2.svg | 3 + .../bootstrap-icons/grid-3x3-gap-fill.svg | 3 + web/vendor/bootstrap-icons/grid-3x3-gap.svg | 3 + web/vendor/bootstrap-icons/grid-3x3.svg | 3 + web/vendor/bootstrap-icons/grid-fill.svg | 3 + web/vendor/bootstrap-icons/grid.svg | 3 + .../bootstrap-icons/grip-horizontal.svg | 3 + web/vendor/bootstrap-icons/grip-vertical.svg | 3 + web/vendor/bootstrap-icons/h-circle-fill.svg | 3 + web/vendor/bootstrap-icons/h-circle.svg | 3 + web/vendor/bootstrap-icons/h-square-fill.svg | 3 + web/vendor/bootstrap-icons/h-square.svg | 4 + web/vendor/bootstrap-icons/hammer.svg | 3 + .../bootstrap-icons/hand-index-fill.svg | 3 + .../bootstrap-icons/hand-index-thumb-fill.svg | 3 + .../bootstrap-icons/hand-index-thumb.svg | 3 + web/vendor/bootstrap-icons/hand-index.svg | 3 + .../bootstrap-icons/hand-thumbs-down-fill.svg | 3 + .../bootstrap-icons/hand-thumbs-down.svg | 3 + .../bootstrap-icons/hand-thumbs-up-fill.svg | 3 + web/vendor/bootstrap-icons/hand-thumbs-up.svg | 3 + web/vendor/bootstrap-icons/handbag-fill.svg | 3 + web/vendor/bootstrap-icons/handbag.svg | 3 + web/vendor/bootstrap-icons/hash.svg | 3 + web/vendor/bootstrap-icons/hdd-fill.svg | 3 + .../bootstrap-icons/hdd-network-fill.svg | 3 + web/vendor/bootstrap-icons/hdd-network.svg | 4 + web/vendor/bootstrap-icons/hdd-rack-fill.svg | 3 + web/vendor/bootstrap-icons/hdd-rack.svg | 4 + web/vendor/bootstrap-icons/hdd-stack-fill.svg | 3 + web/vendor/bootstrap-icons/hdd-stack.svg | 5 + web/vendor/bootstrap-icons/hdd.svg | 4 + web/vendor/bootstrap-icons/hdmi-fill.svg | 3 + web/vendor/bootstrap-icons/hdmi.svg | 4 + web/vendor/bootstrap-icons/headphones.svg | 3 + web/vendor/bootstrap-icons/headset-vr.svg | 4 + web/vendor/bootstrap-icons/headset.svg | 3 + web/vendor/bootstrap-icons/heart-arrow.svg | 3 + web/vendor/bootstrap-icons/heart-fill.svg | 3 + web/vendor/bootstrap-icons/heart-half.svg | 3 + .../bootstrap-icons/heart-pulse-fill.svg | 4 + web/vendor/bootstrap-icons/heart-pulse.svg | 4 + web/vendor/bootstrap-icons/heart.svg | 3 + .../bootstrap-icons/heartbreak-fill.svg | 3 + web/vendor/bootstrap-icons/heartbreak.svg | 3 + web/vendor/bootstrap-icons/hearts.svg | 3 + web/vendor/bootstrap-icons/heptagon-fill.svg | 3 + web/vendor/bootstrap-icons/heptagon-half.svg | 3 + web/vendor/bootstrap-icons/heptagon.svg | 3 + web/vendor/bootstrap-icons/hexagon-fill.svg | 3 + web/vendor/bootstrap-icons/hexagon-half.svg | 3 + web/vendor/bootstrap-icons/hexagon.svg | 3 + web/vendor/bootstrap-icons/highlighter.svg | 3 + web/vendor/bootstrap-icons/highlights.svg | 3 + web/vendor/bootstrap-icons/hospital-fill.svg | 3 + web/vendor/bootstrap-icons/hospital.svg | 4 + .../bootstrap-icons/hourglass-bottom.svg | 3 + .../bootstrap-icons/hourglass-split.svg | 3 + web/vendor/bootstrap-icons/hourglass-top.svg | 3 + web/vendor/bootstrap-icons/hourglass.svg | 3 + web/vendor/bootstrap-icons/house-add-fill.svg | 5 + web/vendor/bootstrap-icons/house-add.svg | 4 + .../bootstrap-icons/house-check-fill.svg | 5 + web/vendor/bootstrap-icons/house-check.svg | 4 + .../bootstrap-icons/house-dash-fill.svg | 5 + web/vendor/bootstrap-icons/house-dash.svg | 4 + .../bootstrap-icons/house-door-fill.svg | 3 + web/vendor/bootstrap-icons/house-door.svg | 3 + .../bootstrap-icons/house-down-fill.svg | 5 + web/vendor/bootstrap-icons/house-down.svg | 4 + .../house-exclamation-fill.svg | 5 + .../bootstrap-icons/house-exclamation.svg | 4 + web/vendor/bootstrap-icons/house-fill.svg | 4 + .../bootstrap-icons/house-gear-fill.svg | 5 + web/vendor/bootstrap-icons/house-gear.svg | 4 + .../bootstrap-icons/house-heart-fill.svg | 4 + web/vendor/bootstrap-icons/house-heart.svg | 4 + .../bootstrap-icons/house-lock-fill.svg | 5 + web/vendor/bootstrap-icons/house-lock.svg | 4 + .../bootstrap-icons/house-slash-fill.svg | 5 + web/vendor/bootstrap-icons/house-slash.svg | 4 + web/vendor/bootstrap-icons/house-up-fill.svg | 5 + web/vendor/bootstrap-icons/house-up.svg | 4 + web/vendor/bootstrap-icons/house-x-fill.svg | 5 + web/vendor/bootstrap-icons/house-x.svg | 4 + web/vendor/bootstrap-icons/house.svg | 3 + web/vendor/bootstrap-icons/houses-fill.svg | 4 + web/vendor/bootstrap-icons/houses.svg | 3 + web/vendor/bootstrap-icons/hr.svg | 3 + web/vendor/bootstrap-icons/hurricane.svg | 3 + web/vendor/bootstrap-icons/hypnotize.svg | 4 + web/vendor/bootstrap-icons/image-alt.svg | 3 + web/vendor/bootstrap-icons/image-fill.svg | 3 + web/vendor/bootstrap-icons/image.svg | 4 + web/vendor/bootstrap-icons/images.svg | 4 + web/vendor/bootstrap-icons/inbox-fill.svg | 3 + web/vendor/bootstrap-icons/inbox.svg | 3 + web/vendor/bootstrap-icons/inboxes-fill.svg | 3 + web/vendor/bootstrap-icons/inboxes.svg | 3 + web/vendor/bootstrap-icons/incognito.svg | 3 + web/vendor/bootstrap-icons/indent.svg | 4 + web/vendor/bootstrap-icons/infinity.svg | 3 + .../bootstrap-icons/info-circle-fill.svg | 3 + web/vendor/bootstrap-icons/info-circle.svg | 4 + web/vendor/bootstrap-icons/info-lg.svg | 3 + .../bootstrap-icons/info-square-fill.svg | 3 + web/vendor/bootstrap-icons/info-square.svg | 4 + web/vendor/bootstrap-icons/info.svg | 3 + .../bootstrap-icons/input-cursor-text.svg | 4 + web/vendor/bootstrap-icons/input-cursor.svg | 4 + web/vendor/bootstrap-icons/instagram.svg | 3 + web/vendor/bootstrap-icons/intersect.svg | 3 + web/vendor/bootstrap-icons/javascript.svg | 3 + web/vendor/bootstrap-icons/journal-album.svg | 5 + .../bootstrap-icons/journal-arrow-down.svg | 5 + .../bootstrap-icons/journal-arrow-up.svg | 5 + .../bootstrap-icons/journal-bookmark-fill.svg | 5 + .../bootstrap-icons/journal-bookmark.svg | 5 + web/vendor/bootstrap-icons/journal-check.svg | 5 + web/vendor/bootstrap-icons/journal-code.svg | 5 + .../bootstrap-icons/journal-medical.svg | 5 + web/vendor/bootstrap-icons/journal-minus.svg | 5 + web/vendor/bootstrap-icons/journal-plus.svg | 5 + .../bootstrap-icons/journal-richtext.svg | 5 + web/vendor/bootstrap-icons/journal-text.svg | 5 + web/vendor/bootstrap-icons/journal-x.svg | 5 + web/vendor/bootstrap-icons/journal.svg | 4 + web/vendor/bootstrap-icons/journals.svg | 4 + web/vendor/bootstrap-icons/joystick.svg | 4 + web/vendor/bootstrap-icons/justify-left.svg | 3 + web/vendor/bootstrap-icons/justify-right.svg | 3 + web/vendor/bootstrap-icons/justify.svg | 3 + web/vendor/bootstrap-icons/kanban-fill.svg | 3 + web/vendor/bootstrap-icons/kanban.svg | 4 + web/vendor/bootstrap-icons/key-fill.svg | 3 + web/vendor/bootstrap-icons/key.svg | 4 + web/vendor/bootstrap-icons/keyboard-fill.svg | 3 + web/vendor/bootstrap-icons/keyboard.svg | 4 + web/vendor/bootstrap-icons/ladder.svg | 3 + web/vendor/bootstrap-icons/lamp-fill.svg | 4 + web/vendor/bootstrap-icons/lamp.svg | 4 + web/vendor/bootstrap-icons/laptop-fill.svg | 3 + web/vendor/bootstrap-icons/laptop.svg | 3 + web/vendor/bootstrap-icons/layer-backward.svg | 4 + web/vendor/bootstrap-icons/layer-forward.svg | 4 + web/vendor/bootstrap-icons/layers-fill.svg | 4 + web/vendor/bootstrap-icons/layers-half.svg | 3 + web/vendor/bootstrap-icons/layers.svg | 3 + .../layout-sidebar-inset-reverse.svg | 4 + .../bootstrap-icons/layout-sidebar-inset.svg | 4 + .../layout-sidebar-reverse.svg | 3 + web/vendor/bootstrap-icons/layout-sidebar.svg | 3 + web/vendor/bootstrap-icons/layout-split.svg | 3 + .../layout-text-sidebar-reverse.svg | 4 + .../bootstrap-icons/layout-text-sidebar.svg | 4 + .../layout-text-window-reverse.svg | 4 + .../bootstrap-icons/layout-text-window.svg | 4 + .../bootstrap-icons/layout-three-columns.svg | 3 + web/vendor/bootstrap-icons/layout-wtf.svg | 3 + web/vendor/bootstrap-icons/leaf-fill.svg | 3 + web/vendor/bootstrap-icons/leaf.svg | 3 + web/vendor/bootstrap-icons/life-preserver.svg | 3 + web/vendor/bootstrap-icons/lightbulb-fill.svg | 3 + .../bootstrap-icons/lightbulb-off-fill.svg | 3 + web/vendor/bootstrap-icons/lightbulb-off.svg | 3 + web/vendor/bootstrap-icons/lightbulb.svg | 3 + .../bootstrap-icons/lightning-charge-fill.svg | 3 + .../bootstrap-icons/lightning-charge.svg | 3 + web/vendor/bootstrap-icons/lightning-fill.svg | 3 + web/vendor/bootstrap-icons/lightning.svg | 3 + web/vendor/bootstrap-icons/line.svg | 3 + web/vendor/bootstrap-icons/link-45deg.svg | 4 + web/vendor/bootstrap-icons/link.svg | 4 + web/vendor/bootstrap-icons/linkedin.svg | 3 + web/vendor/bootstrap-icons/list-check.svg | 3 + .../bootstrap-icons/list-columns-reverse.svg | 3 + web/vendor/bootstrap-icons/list-columns.svg | 3 + web/vendor/bootstrap-icons/list-nested.svg | 3 + web/vendor/bootstrap-icons/list-ol.svg | 4 + web/vendor/bootstrap-icons/list-stars.svg | 4 + web/vendor/bootstrap-icons/list-task.svg | 5 + web/vendor/bootstrap-icons/list-ul.svg | 3 + web/vendor/bootstrap-icons/list.svg | 3 + web/vendor/bootstrap-icons/lock-fill.svg | 3 + web/vendor/bootstrap-icons/lock.svg | 3 + web/vendor/bootstrap-icons/luggage-fill.svg | 4 + web/vendor/bootstrap-icons/luggage.svg | 4 + web/vendor/bootstrap-icons/lungs-fill.svg | 3 + web/vendor/bootstrap-icons/lungs.svg | 3 + web/vendor/bootstrap-icons/magic.svg | 3 + web/vendor/bootstrap-icons/magnet-fill.svg | 3 + web/vendor/bootstrap-icons/magnet.svg | 3 + web/vendor/bootstrap-icons/mailbox-flag.svg | 4 + web/vendor/bootstrap-icons/mailbox.svg | 4 + web/vendor/bootstrap-icons/mailbox2-flag.svg | 4 + web/vendor/bootstrap-icons/mailbox2.svg | 4 + web/vendor/bootstrap-icons/map-fill.svg | 3 + web/vendor/bootstrap-icons/map.svg | 3 + web/vendor/bootstrap-icons/markdown-fill.svg | 3 + web/vendor/bootstrap-icons/markdown.svg | 6 + web/vendor/bootstrap-icons/marker-tip.svg | 3 + web/vendor/bootstrap-icons/mask.svg | 3 + web/vendor/bootstrap-icons/mastodon.svg | 3 + .../bootstrap-icons/measuring-cup-fill.svg | 3 + web/vendor/bootstrap-icons/measuring-cup.svg | 3 + web/vendor/bootstrap-icons/medium.svg | 3 + web/vendor/bootstrap-icons/megaphone-fill.svg | 3 + web/vendor/bootstrap-icons/megaphone.svg | 3 + web/vendor/bootstrap-icons/memory.svg | 3 + web/vendor/bootstrap-icons/menu-app-fill.svg | 3 + web/vendor/bootstrap-icons/menu-app.svg | 3 + .../bootstrap-icons/menu-button-fill.svg | 3 + .../bootstrap-icons/menu-button-wide-fill.svg | 3 + .../bootstrap-icons/menu-button-wide.svg | 4 + web/vendor/bootstrap-icons/menu-button.svg | 4 + web/vendor/bootstrap-icons/menu-down.svg | 3 + web/vendor/bootstrap-icons/menu-up.svg | 3 + web/vendor/bootstrap-icons/messenger.svg | 3 + web/vendor/bootstrap-icons/meta.svg | 3 + web/vendor/bootstrap-icons/mic-fill.svg | 4 + web/vendor/bootstrap-icons/mic-mute-fill.svg | 4 + web/vendor/bootstrap-icons/mic-mute.svg | 4 + web/vendor/bootstrap-icons/mic.svg | 4 + .../bootstrap-icons/microsoft-teams.svg | 4 + web/vendor/bootstrap-icons/microsoft.svg | 3 + .../bootstrap-icons/minecart-loaded.svg | 4 + web/vendor/bootstrap-icons/minecart.svg | 3 + web/vendor/bootstrap-icons/modem-fill.svg | 3 + web/vendor/bootstrap-icons/modem.svg | 4 + web/vendor/bootstrap-icons/moisture.svg | 3 + web/vendor/bootstrap-icons/moon-fill.svg | 3 + .../bootstrap-icons/moon-stars-fill.svg | 4 + web/vendor/bootstrap-icons/moon-stars.svg | 4 + web/vendor/bootstrap-icons/moon.svg | 3 + .../bootstrap-icons/mortarboard-fill.svg | 4 + web/vendor/bootstrap-icons/mortarboard.svg | 4 + .../bootstrap-icons/motherboard-fill.svg | 4 + web/vendor/bootstrap-icons/motherboard.svg | 4 + web/vendor/bootstrap-icons/mouse-fill.svg | 3 + web/vendor/bootstrap-icons/mouse.svg | 3 + web/vendor/bootstrap-icons/mouse2-fill.svg | 3 + web/vendor/bootstrap-icons/mouse2.svg | 3 + web/vendor/bootstrap-icons/mouse3-fill.svg | 3 + web/vendor/bootstrap-icons/mouse3.svg | 3 + .../bootstrap-icons/music-note-beamed.svg | 5 + .../bootstrap-icons/music-note-list.svg | 6 + web/vendor/bootstrap-icons/music-note.svg | 5 + .../bootstrap-icons/music-player-fill.svg | 4 + web/vendor/bootstrap-icons/music-player.svg | 5 + web/vendor/bootstrap-icons/newspaper.svg | 4 + .../bootstrap-icons/nintendo-switch.svg | 4 + .../bootstrap-icons/node-minus-fill.svg | 3 + web/vendor/bootstrap-icons/node-minus.svg | 3 + web/vendor/bootstrap-icons/node-plus-fill.svg | 3 + web/vendor/bootstrap-icons/node-plus.svg | 3 + .../bootstrap-icons/noise-reduction.svg | 4 + web/vendor/bootstrap-icons/nut-fill.svg | 3 + web/vendor/bootstrap-icons/nut.svg | 4 + web/vendor/bootstrap-icons/nvidia.svg | 3 + web/vendor/bootstrap-icons/nvme-fill.svg | 4 + web/vendor/bootstrap-icons/nvme.svg | 4 + web/vendor/bootstrap-icons/octagon-fill.svg | 3 + web/vendor/bootstrap-icons/octagon-half.svg | 3 + web/vendor/bootstrap-icons/octagon.svg | 3 + web/vendor/bootstrap-icons/openai.svg | 3 + web/vendor/bootstrap-icons/opencollective.svg | 4 + .../bootstrap-icons/optical-audio-fill.svg | 4 + web/vendor/bootstrap-icons/optical-audio.svg | 5 + web/vendor/bootstrap-icons/option.svg | 3 + web/vendor/bootstrap-icons/outlet.svg | 4 + web/vendor/bootstrap-icons/p-circle-fill.svg | 3 + web/vendor/bootstrap-icons/p-circle.svg | 3 + web/vendor/bootstrap-icons/p-square-fill.svg | 4 + web/vendor/bootstrap-icons/p-square.svg | 4 + web/vendor/bootstrap-icons/paint-bucket.svg | 3 + web/vendor/bootstrap-icons/palette-fill.svg | 3 + web/vendor/bootstrap-icons/palette.svg | 4 + web/vendor/bootstrap-icons/palette2.svg | 3 + web/vendor/bootstrap-icons/paperclip.svg | 3 + web/vendor/bootstrap-icons/paragraph.svg | 3 + web/vendor/bootstrap-icons/pass-fill.svg | 3 + web/vendor/bootstrap-icons/pass.svg | 4 + web/vendor/bootstrap-icons/passport-fill.svg | 4 + web/vendor/bootstrap-icons/passport.svg | 4 + .../bootstrap-icons/patch-check-fill.svg | 3 + web/vendor/bootstrap-icons/patch-check.svg | 4 + .../patch-exclamation-fill.svg | 3 + .../bootstrap-icons/patch-exclamation.svg | 4 + .../bootstrap-icons/patch-minus-fill.svg | 3 + web/vendor/bootstrap-icons/patch-minus.svg | 4 + .../bootstrap-icons/patch-plus-fill.svg | 3 + web/vendor/bootstrap-icons/patch-plus.svg | 4 + .../bootstrap-icons/patch-question-fill.svg | 3 + web/vendor/bootstrap-icons/patch-question.svg | 5 + web/vendor/bootstrap-icons/pause-btn-fill.svg | 3 + web/vendor/bootstrap-icons/pause-btn.svg | 4 + .../bootstrap-icons/pause-circle-fill.svg | 3 + web/vendor/bootstrap-icons/pause-circle.svg | 4 + web/vendor/bootstrap-icons/pause-fill.svg | 3 + web/vendor/bootstrap-icons/pause.svg | 3 + web/vendor/bootstrap-icons/paypal.svg | 3 + .../bootstrap-icons/pc-display-horizontal.svg | 3 + web/vendor/bootstrap-icons/pc-display.svg | 3 + web/vendor/bootstrap-icons/pc-horizontal.svg | 3 + web/vendor/bootstrap-icons/pc.svg | 3 + .../bootstrap-icons/pci-card-network.svg | 5 + web/vendor/bootstrap-icons/pci-card-sound.svg | 5 + web/vendor/bootstrap-icons/pci-card.svg | 4 + web/vendor/bootstrap-icons/peace-fill.svg | 3 + web/vendor/bootstrap-icons/peace.svg | 3 + web/vendor/bootstrap-icons/pen-fill.svg | 3 + web/vendor/bootstrap-icons/pen.svg | 3 + web/vendor/bootstrap-icons/pencil-fill.svg | 3 + web/vendor/bootstrap-icons/pencil-square.svg | 4 + web/vendor/bootstrap-icons/pencil.svg | 3 + web/vendor/bootstrap-icons/pentagon-fill.svg | 3 + web/vendor/bootstrap-icons/pentagon-half.svg | 3 + web/vendor/bootstrap-icons/pentagon.svg | 3 + web/vendor/bootstrap-icons/people-fill.svg | 3 + web/vendor/bootstrap-icons/people.svg | 3 + web/vendor/bootstrap-icons/percent.svg | 3 + web/vendor/bootstrap-icons/perplexity.svg | 3 + web/vendor/bootstrap-icons/person-add.svg | 4 + web/vendor/bootstrap-icons/person-arms-up.svg | 4 + .../bootstrap-icons/person-badge-fill.svg | 3 + web/vendor/bootstrap-icons/person-badge.svg | 4 + .../bootstrap-icons/person-bounding-box.svg | 4 + .../bootstrap-icons/person-check-fill.svg | 4 + web/vendor/bootstrap-icons/person-check.svg | 4 + web/vendor/bootstrap-icons/person-circle.svg | 4 + .../bootstrap-icons/person-dash-fill.svg | 4 + web/vendor/bootstrap-icons/person-dash.svg | 4 + web/vendor/bootstrap-icons/person-down.svg | 4 + .../bootstrap-icons/person-exclamation.svg | 4 + .../bootstrap-icons/person-fill-add.svg | 4 + .../bootstrap-icons/person-fill-check.svg | 4 + .../bootstrap-icons/person-fill-dash.svg | 4 + .../bootstrap-icons/person-fill-down.svg | 4 + .../person-fill-exclamation.svg | 4 + .../bootstrap-icons/person-fill-gear.svg | 3 + .../bootstrap-icons/person-fill-lock.svg | 3 + .../bootstrap-icons/person-fill-slash.svg | 3 + web/vendor/bootstrap-icons/person-fill-up.svg | 4 + web/vendor/bootstrap-icons/person-fill-x.svg | 4 + web/vendor/bootstrap-icons/person-fill.svg | 3 + web/vendor/bootstrap-icons/person-gear.svg | 3 + web/vendor/bootstrap-icons/person-heart.svg | 3 + web/vendor/bootstrap-icons/person-hearts.svg | 3 + .../bootstrap-icons/person-lines-fill.svg | 3 + web/vendor/bootstrap-icons/person-lock.svg | 3 + .../bootstrap-icons/person-plus-fill.svg | 4 + web/vendor/bootstrap-icons/person-plus.svg | 4 + .../bootstrap-icons/person-raised-hand.svg | 4 + web/vendor/bootstrap-icons/person-rolodex.svg | 4 + web/vendor/bootstrap-icons/person-slash.svg | 3 + web/vendor/bootstrap-icons/person-square.svg | 4 + .../bootstrap-icons/person-standing-dress.svg | 3 + .../bootstrap-icons/person-standing.svg | 3 + web/vendor/bootstrap-icons/person-up.svg | 4 + .../bootstrap-icons/person-vcard-fill.svg | 3 + web/vendor/bootstrap-icons/person-vcard.svg | 4 + web/vendor/bootstrap-icons/person-video.svg | 4 + web/vendor/bootstrap-icons/person-video2.svg | 4 + web/vendor/bootstrap-icons/person-video3.svg | 4 + web/vendor/bootstrap-icons/person-walking.svg | 4 + .../bootstrap-icons/person-wheelchair.svg | 3 + .../bootstrap-icons/person-workspace.svg | 4 + web/vendor/bootstrap-icons/person-x-fill.svg | 3 + web/vendor/bootstrap-icons/person-x.svg | 4 + web/vendor/bootstrap-icons/person.svg | 3 + web/vendor/bootstrap-icons/phone-fill.svg | 3 + web/vendor/bootstrap-icons/phone-flip.svg | 3 + .../bootstrap-icons/phone-landscape-fill.svg | 3 + .../bootstrap-icons/phone-landscape.svg | 4 + .../bootstrap-icons/phone-vibrate-fill.svg | 3 + web/vendor/bootstrap-icons/phone-vibrate.svg | 4 + web/vendor/bootstrap-icons/phone.svg | 4 + web/vendor/bootstrap-icons/pie-chart-fill.svg | 3 + web/vendor/bootstrap-icons/pie-chart.svg | 3 + .../bootstrap-icons/piggy-bank-fill.svg | 3 + web/vendor/bootstrap-icons/piggy-bank.svg | 4 + web/vendor/bootstrap-icons/pin-angle-fill.svg | 3 + web/vendor/bootstrap-icons/pin-angle.svg | 3 + web/vendor/bootstrap-icons/pin-fill.svg | 3 + web/vendor/bootstrap-icons/pin-map-fill.svg | 4 + web/vendor/bootstrap-icons/pin-map.svg | 4 + web/vendor/bootstrap-icons/pin.svg | 3 + web/vendor/bootstrap-icons/pinterest.svg | 3 + web/vendor/bootstrap-icons/pip-fill.svg | 3 + web/vendor/bootstrap-icons/pip.svg | 4 + web/vendor/bootstrap-icons/play-btn-fill.svg | 3 + web/vendor/bootstrap-icons/play-btn.svg | 4 + .../bootstrap-icons/play-circle-fill.svg | 3 + web/vendor/bootstrap-icons/play-circle.svg | 4 + web/vendor/bootstrap-icons/play-fill.svg | 3 + web/vendor/bootstrap-icons/play.svg | 3 + web/vendor/bootstrap-icons/playstation.svg | 3 + web/vendor/bootstrap-icons/plug-fill.svg | 3 + web/vendor/bootstrap-icons/plug.svg | 3 + web/vendor/bootstrap-icons/plugin.svg | 3 + .../bootstrap-icons/plus-circle-dotted.svg | 3 + .../bootstrap-icons/plus-circle-fill.svg | 3 + web/vendor/bootstrap-icons/plus-circle.svg | 4 + web/vendor/bootstrap-icons/plus-lg.svg | 3 + .../bootstrap-icons/plus-slash-minus.svg | 3 + .../bootstrap-icons/plus-square-dotted.svg | 3 + .../bootstrap-icons/plus-square-fill.svg | 3 + web/vendor/bootstrap-icons/plus-square.svg | 4 + web/vendor/bootstrap-icons/plus.svg | 3 + web/vendor/bootstrap-icons/postage-fill.svg | 4 + .../bootstrap-icons/postage-heart-fill.svg | 4 + web/vendor/bootstrap-icons/postage-heart.svg | 4 + web/vendor/bootstrap-icons/postage.svg | 4 + web/vendor/bootstrap-icons/postcard-fill.svg | 4 + .../bootstrap-icons/postcard-heart-fill.svg | 3 + web/vendor/bootstrap-icons/postcard-heart.svg | 4 + web/vendor/bootstrap-icons/postcard.svg | 3 + web/vendor/bootstrap-icons/power.svg | 4 + web/vendor/bootstrap-icons/prescription.svg | 4 + web/vendor/bootstrap-icons/prescription2.svg | 4 + web/vendor/bootstrap-icons/printer-fill.svg | 4 + web/vendor/bootstrap-icons/printer.svg | 4 + web/vendor/bootstrap-icons/projector-fill.svg | 3 + web/vendor/bootstrap-icons/projector.svg | 4 + web/vendor/bootstrap-icons/puzzle-fill.svg | 3 + web/vendor/bootstrap-icons/puzzle.svg | 3 + web/vendor/bootstrap-icons/qr-code-scan.svg | 7 + web/vendor/bootstrap-icons/qr-code.svg | 7 + .../bootstrap-icons/question-circle-fill.svg | 3 + .../bootstrap-icons/question-circle.svg | 4 + .../bootstrap-icons/question-diamond-fill.svg | 3 + .../bootstrap-icons/question-diamond.svg | 4 + web/vendor/bootstrap-icons/question-lg.svg | 3 + .../bootstrap-icons/question-octagon-fill.svg | 3 + .../bootstrap-icons/question-octagon.svg | 4 + .../bootstrap-icons/question-square-fill.svg | 3 + .../bootstrap-icons/question-square.svg | 4 + web/vendor/bootstrap-icons/question.svg | 3 + web/vendor/bootstrap-icons/quora.svg | 3 + web/vendor/bootstrap-icons/quote.svg | 3 + web/vendor/bootstrap-icons/r-circle-fill.svg | 3 + web/vendor/bootstrap-icons/r-circle.svg | 3 + web/vendor/bootstrap-icons/r-square-fill.svg | 4 + web/vendor/bootstrap-icons/r-square.svg | 4 + web/vendor/bootstrap-icons/radar.svg | 3 + web/vendor/bootstrap-icons/radioactive.svg | 4 + web/vendor/bootstrap-icons/rainbow.svg | 3 + web/vendor/bootstrap-icons/receipt-cutoff.svg | 4 + web/vendor/bootstrap-icons/receipt.svg | 4 + web/vendor/bootstrap-icons/reception-0.svg | 3 + web/vendor/bootstrap-icons/reception-1.svg | 3 + web/vendor/bootstrap-icons/reception-2.svg | 3 + web/vendor/bootstrap-icons/reception-3.svg | 3 + web/vendor/bootstrap-icons/reception-4.svg | 3 + .../bootstrap-icons/record-btn-fill.svg | 3 + web/vendor/bootstrap-icons/record-btn.svg | 4 + .../bootstrap-icons/record-circle-fill.svg | 3 + web/vendor/bootstrap-icons/record-circle.svg | 4 + web/vendor/bootstrap-icons/record-fill.svg | 3 + web/vendor/bootstrap-icons/record.svg | 3 + web/vendor/bootstrap-icons/record2-fill.svg | 4 + web/vendor/bootstrap-icons/record2.svg | 4 + web/vendor/bootstrap-icons/recycle.svg | 3 + web/vendor/bootstrap-icons/reddit.svg | 4 + web/vendor/bootstrap-icons/regex.svg | 3 + web/vendor/bootstrap-icons/repeat-1.svg | 4 + web/vendor/bootstrap-icons/repeat.svg | 3 + web/vendor/bootstrap-icons/reply-all-fill.svg | 4 + web/vendor/bootstrap-icons/reply-all.svg | 4 + web/vendor/bootstrap-icons/reply-fill.svg | 3 + web/vendor/bootstrap-icons/reply.svg | 3 + .../bootstrap-icons/rewind-btn-fill.svg | 3 + web/vendor/bootstrap-icons/rewind-btn.svg | 4 + .../bootstrap-icons/rewind-circle-fill.svg | 3 + web/vendor/bootstrap-icons/rewind-circle.svg | 4 + web/vendor/bootstrap-icons/rewind-fill.svg | 4 + web/vendor/bootstrap-icons/rewind.svg | 4 + web/vendor/bootstrap-icons/robot.svg | 4 + web/vendor/bootstrap-icons/rocket-fill.svg | 4 + .../bootstrap-icons/rocket-takeoff-fill.svg | 4 + web/vendor/bootstrap-icons/rocket-takeoff.svg | 5 + web/vendor/bootstrap-icons/rocket.svg | 5 + web/vendor/bootstrap-icons/router-fill.svg | 6 + web/vendor/bootstrap-icons/router.svg | 6 + web/vendor/bootstrap-icons/rss-fill.svg | 3 + web/vendor/bootstrap-icons/rss.svg | 4 + web/vendor/bootstrap-icons/rulers.svg | 3 + web/vendor/bootstrap-icons/safe-fill.svg | 4 + web/vendor/bootstrap-icons/safe.svg | 4 + web/vendor/bootstrap-icons/safe2-fill.svg | 4 + web/vendor/bootstrap-icons/safe2.svg | 4 + web/vendor/bootstrap-icons/save-fill.svg | 3 + web/vendor/bootstrap-icons/save.svg | 3 + web/vendor/bootstrap-icons/save2-fill.svg | 3 + web/vendor/bootstrap-icons/save2.svg | 3 + web/vendor/bootstrap-icons/scissors.svg | 3 + web/vendor/bootstrap-icons/scooter.svg | 3 + web/vendor/bootstrap-icons/screwdriver.svg | 3 + web/vendor/bootstrap-icons/sd-card-fill.svg | 3 + web/vendor/bootstrap-icons/sd-card.svg | 4 + .../bootstrap-icons/search-heart-fill.svg | 3 + web/vendor/bootstrap-icons/search-heart.svg | 4 + web/vendor/bootstrap-icons/search.svg | 3 + web/vendor/bootstrap-icons/segmented-nav.svg | 3 + .../bootstrap-icons/send-arrow-down-fill.svg | 4 + .../bootstrap-icons/send-arrow-down.svg | 4 + .../bootstrap-icons/send-arrow-up-fill.svg | 4 + web/vendor/bootstrap-icons/send-arrow-up.svg | 4 + .../bootstrap-icons/send-check-fill.svg | 4 + web/vendor/bootstrap-icons/send-check.svg | 4 + web/vendor/bootstrap-icons/send-dash-fill.svg | 4 + web/vendor/bootstrap-icons/send-dash.svg | 4 + .../bootstrap-icons/send-exclamation-fill.svg | 4 + .../bootstrap-icons/send-exclamation.svg | 4 + web/vendor/bootstrap-icons/send-fill.svg | 3 + web/vendor/bootstrap-icons/send-plus-fill.svg | 4 + web/vendor/bootstrap-icons/send-plus.svg | 4 + .../bootstrap-icons/send-slash-fill.svg | 4 + web/vendor/bootstrap-icons/send-slash.svg | 4 + web/vendor/bootstrap-icons/send-x-fill.svg | 4 + web/vendor/bootstrap-icons/send-x.svg | 4 + web/vendor/bootstrap-icons/send.svg | 3 + web/vendor/bootstrap-icons/server.svg | 5 + web/vendor/bootstrap-icons/shadows.svg | 3 + web/vendor/bootstrap-icons/share-fill.svg | 3 + web/vendor/bootstrap-icons/share.svg | 3 + web/vendor/bootstrap-icons/shield-check.svg | 4 + .../bootstrap-icons/shield-exclamation.svg | 4 + .../bootstrap-icons/shield-fill-check.svg | 3 + .../shield-fill-exclamation.svg | 3 + .../bootstrap-icons/shield-fill-minus.svg | 3 + .../bootstrap-icons/shield-fill-plus.svg | 3 + web/vendor/bootstrap-icons/shield-fill-x.svg | 3 + web/vendor/bootstrap-icons/shield-fill.svg | 3 + .../bootstrap-icons/shield-lock-fill.svg | 3 + web/vendor/bootstrap-icons/shield-lock.svg | 4 + web/vendor/bootstrap-icons/shield-minus.svg | 4 + web/vendor/bootstrap-icons/shield-plus.svg | 4 + web/vendor/bootstrap-icons/shield-shaded.svg | 3 + .../bootstrap-icons/shield-slash-fill.svg | 3 + web/vendor/bootstrap-icons/shield-slash.svg | 3 + web/vendor/bootstrap-icons/shield-x.svg | 4 + web/vendor/bootstrap-icons/shield.svg | 3 + web/vendor/bootstrap-icons/shift-fill.svg | 3 + web/vendor/bootstrap-icons/shift.svg | 3 + web/vendor/bootstrap-icons/shop-window.svg | 3 + web/vendor/bootstrap-icons/shop.svg | 3 + web/vendor/bootstrap-icons/shuffle.svg | 4 + .../bootstrap-icons/sign-dead-end-fill.svg | 4 + web/vendor/bootstrap-icons/sign-dead-end.svg | 4 + .../sign-do-not-enter-fill.svg | 4 + .../bootstrap-icons/sign-do-not-enter.svg | 4 + .../sign-intersection-fill.svg | 3 + .../sign-intersection-side-fill.svg | 3 + .../sign-intersection-side.svg | 4 + .../sign-intersection-t-fill.svg | 3 + .../bootstrap-icons/sign-intersection-t.svg | 4 + .../sign-intersection-y-fill.svg | 3 + .../bootstrap-icons/sign-intersection-y.svg | 4 + .../bootstrap-icons/sign-intersection.svg | 4 + .../bootstrap-icons/sign-merge-left-fill.svg | 3 + .../bootstrap-icons/sign-merge-left.svg | 4 + .../bootstrap-icons/sign-merge-right-fill.svg | 3 + .../bootstrap-icons/sign-merge-right.svg | 4 + .../sign-no-left-turn-fill.svg | 4 + .../bootstrap-icons/sign-no-left-turn.svg | 3 + .../bootstrap-icons/sign-no-parking-fill.svg | 4 + .../bootstrap-icons/sign-no-parking.svg | 3 + .../sign-no-right-turn-fill.svg | 4 + .../bootstrap-icons/sign-no-right-turn.svg | 3 + .../bootstrap-icons/sign-railroad-fill.svg | 5 + web/vendor/bootstrap-icons/sign-railroad.svg | 4 + web/vendor/bootstrap-icons/sign-stop-fill.svg | 4 + .../bootstrap-icons/sign-stop-lights-fill.svg | 4 + .../bootstrap-icons/sign-stop-lights.svg | 4 + web/vendor/bootstrap-icons/sign-stop.svg | 5 + .../bootstrap-icons/sign-turn-left-fill.svg | 3 + web/vendor/bootstrap-icons/sign-turn-left.svg | 4 + .../bootstrap-icons/sign-turn-right-fill.svg | 3 + .../bootstrap-icons/sign-turn-right.svg | 4 + .../sign-turn-slight-left-fill.svg | 3 + .../bootstrap-icons/sign-turn-slight-left.svg | 4 + .../sign-turn-slight-right-fill.svg | 3 + .../sign-turn-slight-right.svg | 4 + .../bootstrap-icons/sign-yield-fill.svg | 4 + web/vendor/bootstrap-icons/sign-yield.svg | 5 + web/vendor/bootstrap-icons/signal.svg | 3 + .../bootstrap-icons/signpost-2-fill.svg | 3 + web/vendor/bootstrap-icons/signpost-2.svg | 3 + web/vendor/bootstrap-icons/signpost-fill.svg | 3 + .../bootstrap-icons/signpost-split-fill.svg | 3 + web/vendor/bootstrap-icons/signpost-split.svg | 3 + web/vendor/bootstrap-icons/signpost.svg | 3 + web/vendor/bootstrap-icons/sim-fill.svg | 4 + web/vendor/bootstrap-icons/sim-slash-fill.svg | 3 + web/vendor/bootstrap-icons/sim-slash.svg | 3 + web/vendor/bootstrap-icons/sim.svg | 4 + web/vendor/bootstrap-icons/sina-weibo.svg | 4 + .../skip-backward-btn-fill.svg | 3 + .../bootstrap-icons/skip-backward-btn.svg | 4 + .../skip-backward-circle-fill.svg | 3 + .../bootstrap-icons/skip-backward-circle.svg | 4 + .../bootstrap-icons/skip-backward-fill.svg | 3 + web/vendor/bootstrap-icons/skip-backward.svg | 3 + .../bootstrap-icons/skip-end-btn-fill.svg | 3 + web/vendor/bootstrap-icons/skip-end-btn.svg | 4 + .../bootstrap-icons/skip-end-circle-fill.svg | 3 + .../bootstrap-icons/skip-end-circle.svg | 4 + web/vendor/bootstrap-icons/skip-end-fill.svg | 3 + web/vendor/bootstrap-icons/skip-end.svg | 3 + .../bootstrap-icons/skip-forward-btn-fill.svg | 3 + .../bootstrap-icons/skip-forward-btn.svg | 4 + .../skip-forward-circle-fill.svg | 3 + .../bootstrap-icons/skip-forward-circle.svg | 4 + .../bootstrap-icons/skip-forward-fill.svg | 3 + web/vendor/bootstrap-icons/skip-forward.svg | 3 + .../bootstrap-icons/skip-start-btn-fill.svg | 3 + web/vendor/bootstrap-icons/skip-start-btn.svg | 4 + .../skip-start-circle-fill.svg | 3 + .../bootstrap-icons/skip-start-circle.svg | 4 + .../bootstrap-icons/skip-start-fill.svg | 3 + web/vendor/bootstrap-icons/skip-start.svg | 3 + web/vendor/bootstrap-icons/skype.svg | 3 + web/vendor/bootstrap-icons/slack.svg | 3 + .../bootstrap-icons/slash-circle-fill.svg | 3 + web/vendor/bootstrap-icons/slash-circle.svg | 4 + web/vendor/bootstrap-icons/slash-lg.svg | 3 + .../bootstrap-icons/slash-square-fill.svg | 3 + web/vendor/bootstrap-icons/slash-square.svg | 4 + web/vendor/bootstrap-icons/slash.svg | 3 + web/vendor/bootstrap-icons/sliders.svg | 3 + .../bootstrap-icons/sliders2-vertical.svg | 3 + web/vendor/bootstrap-icons/sliders2.svg | 3 + web/vendor/bootstrap-icons/smartwatch.svg | 4 + web/vendor/bootstrap-icons/snapchat.svg | 3 + web/vendor/bootstrap-icons/snow.svg | 3 + web/vendor/bootstrap-icons/snow2.svg | 3 + web/vendor/bootstrap-icons/snow3.svg | 4 + .../bootstrap-icons/sort-alpha-down-alt.svg | 5 + .../bootstrap-icons/sort-alpha-down.svg | 4 + .../bootstrap-icons/sort-alpha-up-alt.svg | 5 + web/vendor/bootstrap-icons/sort-alpha-up.svg | 4 + web/vendor/bootstrap-icons/sort-down-alt.svg | 3 + web/vendor/bootstrap-icons/sort-down.svg | 3 + .../bootstrap-icons/sort-numeric-down-alt.svg | 4 + .../bootstrap-icons/sort-numeric-down.svg | 5 + .../bootstrap-icons/sort-numeric-up-alt.svg | 4 + .../bootstrap-icons/sort-numeric-up.svg | 5 + web/vendor/bootstrap-icons/sort-up-alt.svg | 3 + web/vendor/bootstrap-icons/sort-up.svg | 3 + web/vendor/bootstrap-icons/soundwave.svg | 3 + web/vendor/bootstrap-icons/sourceforge.svg | 4 + web/vendor/bootstrap-icons/speaker-fill.svg | 4 + web/vendor/bootstrap-icons/speaker.svg | 4 + web/vendor/bootstrap-icons/speedometer.svg | 4 + web/vendor/bootstrap-icons/speedometer2.svg | 4 + web/vendor/bootstrap-icons/spellcheck.svg | 4 + web/vendor/bootstrap-icons/spotify.svg | 3 + web/vendor/bootstrap-icons/square-fill.svg | 3 + web/vendor/bootstrap-icons/square-half.svg | 3 + web/vendor/bootstrap-icons/square.svg | 3 + web/vendor/bootstrap-icons/stack-overflow.svg | 4 + web/vendor/bootstrap-icons/stack.svg | 4 + web/vendor/bootstrap-icons/star-fill.svg | 3 + web/vendor/bootstrap-icons/star-half.svg | 3 + web/vendor/bootstrap-icons/star.svg | 3 + web/vendor/bootstrap-icons/stars.svg | 3 + web/vendor/bootstrap-icons/steam.svg | 4 + web/vendor/bootstrap-icons/stickies-fill.svg | 4 + web/vendor/bootstrap-icons/stickies.svg | 4 + web/vendor/bootstrap-icons/sticky-fill.svg | 3 + web/vendor/bootstrap-icons/sticky.svg | 3 + web/vendor/bootstrap-icons/stop-btn-fill.svg | 3 + web/vendor/bootstrap-icons/stop-btn.svg | 4 + .../bootstrap-icons/stop-circle-fill.svg | 3 + web/vendor/bootstrap-icons/stop-circle.svg | 4 + web/vendor/bootstrap-icons/stop-fill.svg | 3 + web/vendor/bootstrap-icons/stop.svg | 3 + .../bootstrap-icons/stoplights-fill.svg | 3 + web/vendor/bootstrap-icons/stoplights.svg | 4 + web/vendor/bootstrap-icons/stopwatch-fill.svg | 3 + web/vendor/bootstrap-icons/stopwatch.svg | 4 + web/vendor/bootstrap-icons/strava.svg | 3 + web/vendor/bootstrap-icons/stripe.svg | 3 + web/vendor/bootstrap-icons/subscript.svg | 3 + web/vendor/bootstrap-icons/substack.svg | 3 + web/vendor/bootstrap-icons/subtract.svg | 3 + web/vendor/bootstrap-icons/suit-club-fill.svg | 3 + web/vendor/bootstrap-icons/suit-club.svg | 3 + .../bootstrap-icons/suit-diamond-fill.svg | 3 + web/vendor/bootstrap-icons/suit-diamond.svg | 3 + .../bootstrap-icons/suit-heart-fill.svg | 3 + web/vendor/bootstrap-icons/suit-heart.svg | 3 + .../bootstrap-icons/suit-spade-fill.svg | 3 + web/vendor/bootstrap-icons/suit-spade.svg | 3 + web/vendor/bootstrap-icons/suitcase-fill.svg | 3 + .../bootstrap-icons/suitcase-lg-fill.svg | 3 + web/vendor/bootstrap-icons/suitcase-lg.svg | 3 + web/vendor/bootstrap-icons/suitcase.svg | 4 + web/vendor/bootstrap-icons/suitcase2-fill.svg | 3 + web/vendor/bootstrap-icons/suitcase2.svg | 3 + web/vendor/bootstrap-icons/sun-fill.svg | 3 + web/vendor/bootstrap-icons/sun.svg | 3 + web/vendor/bootstrap-icons/sunglasses.svg | 3 + web/vendor/bootstrap-icons/sunrise-fill.svg | 3 + web/vendor/bootstrap-icons/sunrise.svg | 3 + web/vendor/bootstrap-icons/sunset-fill.svg | 3 + web/vendor/bootstrap-icons/sunset.svg | 3 + web/vendor/bootstrap-icons/superscript.svg | 3 + .../bootstrap-icons/symmetry-horizontal.svg | 3 + .../bootstrap-icons/symmetry-vertical.svg | 3 + web/vendor/bootstrap-icons/table.svg | 3 + web/vendor/bootstrap-icons/tablet-fill.svg | 3 + .../bootstrap-icons/tablet-landscape-fill.svg | 3 + .../bootstrap-icons/tablet-landscape.svg | 4 + web/vendor/bootstrap-icons/tablet.svg | 4 + web/vendor/bootstrap-icons/tag-fill.svg | 3 + web/vendor/bootstrap-icons/tag.svg | 4 + web/vendor/bootstrap-icons/tags-fill.svg | 4 + web/vendor/bootstrap-icons/tags.svg | 4 + .../bootstrap-icons/taxi-front-fill.svg | 3 + web/vendor/bootstrap-icons/taxi-front.svg | 4 + web/vendor/bootstrap-icons/telegram.svg | 3 + web/vendor/bootstrap-icons/telephone-fill.svg | 3 + .../telephone-forward-fill.svg | 3 + .../bootstrap-icons/telephone-forward.svg | 3 + .../telephone-inbound-fill.svg | 3 + .../bootstrap-icons/telephone-inbound.svg | 3 + .../bootstrap-icons/telephone-minus-fill.svg | 3 + .../bootstrap-icons/telephone-minus.svg | 4 + .../telephone-outbound-fill.svg | 3 + .../bootstrap-icons/telephone-outbound.svg | 3 + .../bootstrap-icons/telephone-plus-fill.svg | 3 + web/vendor/bootstrap-icons/telephone-plus.svg | 4 + .../bootstrap-icons/telephone-x-fill.svg | 3 + web/vendor/bootstrap-icons/telephone-x.svg | 4 + web/vendor/bootstrap-icons/telephone.svg | 3 + web/vendor/bootstrap-icons/tencent-qq.svg | 4 + web/vendor/bootstrap-icons/terminal-dash.svg | 4 + web/vendor/bootstrap-icons/terminal-fill.svg | 3 + web/vendor/bootstrap-icons/terminal-plus.svg | 4 + web/vendor/bootstrap-icons/terminal-split.svg | 4 + web/vendor/bootstrap-icons/terminal-x.svg | 4 + web/vendor/bootstrap-icons/terminal.svg | 4 + web/vendor/bootstrap-icons/text-center.svg | 3 + .../bootstrap-icons/text-indent-left.svg | 3 + .../bootstrap-icons/text-indent-right.svg | 3 + web/vendor/bootstrap-icons/text-left.svg | 3 + web/vendor/bootstrap-icons/text-paragraph.svg | 3 + web/vendor/bootstrap-icons/text-right.svg | 3 + web/vendor/bootstrap-icons/text-wrap.svg | 3 + .../bootstrap-icons/textarea-resize.svg | 3 + web/vendor/bootstrap-icons/textarea-t.svg | 4 + web/vendor/bootstrap-icons/textarea.svg | 3 + .../bootstrap-icons/thermometer-half.svg | 4 + .../bootstrap-icons/thermometer-high.svg | 4 + .../bootstrap-icons/thermometer-low.svg | 4 + .../bootstrap-icons/thermometer-snow.svg | 4 + .../bootstrap-icons/thermometer-sun.svg | 4 + web/vendor/bootstrap-icons/thermometer.svg | 4 + web/vendor/bootstrap-icons/threads-fill.svg | 4 + web/vendor/bootstrap-icons/threads.svg | 3 + .../bootstrap-icons/three-dots-vertical.svg | 3 + web/vendor/bootstrap-icons/three-dots.svg | 3 + .../bootstrap-icons/thunderbolt-fill.svg | 3 + web/vendor/bootstrap-icons/thunderbolt.svg | 4 + .../bootstrap-icons/ticket-detailed-fill.svg | 3 + .../bootstrap-icons/ticket-detailed.svg | 4 + web/vendor/bootstrap-icons/ticket-fill.svg | 3 + .../ticket-perforated-fill.svg | 3 + .../bootstrap-icons/ticket-perforated.svg | 4 + web/vendor/bootstrap-icons/ticket.svg | 3 + web/vendor/bootstrap-icons/tiktok.svg | 3 + web/vendor/bootstrap-icons/toggle-off.svg | 3 + web/vendor/bootstrap-icons/toggle-on.svg | 3 + web/vendor/bootstrap-icons/toggle2-off.svg | 4 + web/vendor/bootstrap-icons/toggle2-on.svg | 4 + web/vendor/bootstrap-icons/toggles.svg | 3 + web/vendor/bootstrap-icons/toggles2.svg | 5 + web/vendor/bootstrap-icons/tools.svg | 3 + web/vendor/bootstrap-icons/tornado.svg | 3 + .../train-freight-front-fill.svg | 3 + .../bootstrap-icons/train-freight-front.svg | 3 + .../bootstrap-icons/train-front-fill.svg | 3 + web/vendor/bootstrap-icons/train-front.svg | 3 + .../train-lightrail-front-fill.svg | 3 + .../bootstrap-icons/train-lightrail-front.svg | 3 + web/vendor/bootstrap-icons/translate.svg | 4 + web/vendor/bootstrap-icons/transparency.svg | 3 + web/vendor/bootstrap-icons/trash-fill.svg | 3 + web/vendor/bootstrap-icons/trash.svg | 4 + web/vendor/bootstrap-icons/trash2-fill.svg | 3 + web/vendor/bootstrap-icons/trash2.svg | 3 + web/vendor/bootstrap-icons/trash3-fill.svg | 3 + web/vendor/bootstrap-icons/trash3.svg | 3 + web/vendor/bootstrap-icons/tree-fill.svg | 3 + web/vendor/bootstrap-icons/tree.svg | 3 + web/vendor/bootstrap-icons/trello.svg | 3 + web/vendor/bootstrap-icons/triangle-fill.svg | 3 + web/vendor/bootstrap-icons/triangle-half.svg | 3 + web/vendor/bootstrap-icons/triangle.svg | 3 + web/vendor/bootstrap-icons/trophy-fill.svg | 3 + web/vendor/bootstrap-icons/trophy.svg | 3 + web/vendor/bootstrap-icons/tropical-storm.svg | 4 + web/vendor/bootstrap-icons/truck-flatbed.svg | 3 + .../bootstrap-icons/truck-front-fill.svg | 3 + web/vendor/bootstrap-icons/truck-front.svg | 4 + web/vendor/bootstrap-icons/truck.svg | 3 + web/vendor/bootstrap-icons/tsunami.svg | 3 + web/vendor/bootstrap-icons/tux.svg | 4 + web/vendor/bootstrap-icons/tv-fill.svg | 3 + web/vendor/bootstrap-icons/tv.svg | 3 + web/vendor/bootstrap-icons/twitch.svg | 4 + web/vendor/bootstrap-icons/twitter-x.svg | 3 + web/vendor/bootstrap-icons/twitter.svg | 3 + web/vendor/bootstrap-icons/type-bold.svg | 3 + web/vendor/bootstrap-icons/type-h1.svg | 3 + web/vendor/bootstrap-icons/type-h2.svg | 3 + web/vendor/bootstrap-icons/type-h3.svg | 3 + web/vendor/bootstrap-icons/type-h4.svg | 3 + web/vendor/bootstrap-icons/type-h5.svg | 3 + web/vendor/bootstrap-icons/type-h6.svg | 3 + web/vendor/bootstrap-icons/type-italic.svg | 3 + .../bootstrap-icons/type-strikethrough.svg | 3 + web/vendor/bootstrap-icons/type-underline.svg | 3 + web/vendor/bootstrap-icons/type.svg | 3 + web/vendor/bootstrap-icons/typescript.svg | 3 + web/vendor/bootstrap-icons/ubuntu.svg | 3 + web/vendor/bootstrap-icons/ui-checks-grid.svg | 3 + web/vendor/bootstrap-icons/ui-checks.svg | 3 + web/vendor/bootstrap-icons/ui-radios-grid.svg | 3 + web/vendor/bootstrap-icons/ui-radios.svg | 3 + web/vendor/bootstrap-icons/umbrella-fill.svg | 3 + web/vendor/bootstrap-icons/umbrella.svg | 3 + web/vendor/bootstrap-icons/unindent.svg | 4 + web/vendor/bootstrap-icons/union.svg | 3 + web/vendor/bootstrap-icons/unity.svg | 3 + .../universal-access-circle.svg | 4 + .../bootstrap-icons/universal-access.svg | 3 + web/vendor/bootstrap-icons/unlock-fill.svg | 3 + web/vendor/bootstrap-icons/unlock.svg | 3 + web/vendor/bootstrap-icons/unlock2-fill.svg | 3 + web/vendor/bootstrap-icons/unlock2.svg | 3 + web/vendor/bootstrap-icons/upc-scan.svg | 3 + web/vendor/bootstrap-icons/upc.svg | 3 + web/vendor/bootstrap-icons/upload.svg | 4 + web/vendor/bootstrap-icons/usb-c-fill.svg | 3 + web/vendor/bootstrap-icons/usb-c.svg | 4 + web/vendor/bootstrap-icons/usb-drive-fill.svg | 3 + web/vendor/bootstrap-icons/usb-drive.svg | 3 + web/vendor/bootstrap-icons/usb-fill.svg | 3 + web/vendor/bootstrap-icons/usb-micro-fill.svg | 3 + web/vendor/bootstrap-icons/usb-micro.svg | 4 + web/vendor/bootstrap-icons/usb-mini-fill.svg | 3 + web/vendor/bootstrap-icons/usb-mini.svg | 4 + web/vendor/bootstrap-icons/usb-plug-fill.svg | 3 + web/vendor/bootstrap-icons/usb-plug.svg | 3 + web/vendor/bootstrap-icons/usb-symbol.svg | 3 + web/vendor/bootstrap-icons/usb.svg | 4 + web/vendor/bootstrap-icons/valentine.svg | 4 + web/vendor/bootstrap-icons/valentine2.svg | 4 + web/vendor/bootstrap-icons/vector-pen.svg | 4 + web/vendor/bootstrap-icons/view-list.svg | 3 + web/vendor/bootstrap-icons/view-stacked.svg | 3 + web/vendor/bootstrap-icons/vignette.svg | 4 + web/vendor/bootstrap-icons/vimeo.svg | 3 + web/vendor/bootstrap-icons/vinyl-fill.svg | 4 + web/vendor/bootstrap-icons/vinyl.svg | 5 + web/vendor/bootstrap-icons/virus.svg | 3 + web/vendor/bootstrap-icons/virus2.svg | 3 + web/vendor/bootstrap-icons/voicemail.svg | 3 + .../bootstrap-icons/volume-down-fill.svg | 3 + web/vendor/bootstrap-icons/volume-down.svg | 3 + .../bootstrap-icons/volume-mute-fill.svg | 3 + web/vendor/bootstrap-icons/volume-mute.svg | 3 + .../bootstrap-icons/volume-off-fill.svg | 3 + web/vendor/bootstrap-icons/volume-off.svg | 3 + web/vendor/bootstrap-icons/volume-up-fill.svg | 5 + web/vendor/bootstrap-icons/volume-up.svg | 5 + web/vendor/bootstrap-icons/vr.svg | 3 + web/vendor/bootstrap-icons/wallet-fill.svg | 4 + web/vendor/bootstrap-icons/wallet.svg | 3 + web/vendor/bootstrap-icons/wallet2.svg | 3 + web/vendor/bootstrap-icons/watch.svg | 4 + web/vendor/bootstrap-icons/water.svg | 3 + web/vendor/bootstrap-icons/webcam-fill.svg | 4 + web/vendor/bootstrap-icons/webcam.svg | 4 + web/vendor/bootstrap-icons/wechat.svg | 4 + web/vendor/bootstrap-icons/whatsapp.svg | 3 + web/vendor/bootstrap-icons/wifi-1.svg | 3 + web/vendor/bootstrap-icons/wifi-2.svg | 3 + web/vendor/bootstrap-icons/wifi-off.svg | 3 + web/vendor/bootstrap-icons/wifi.svg | 4 + web/vendor/bootstrap-icons/wikipedia.svg | 3 + web/vendor/bootstrap-icons/wind.svg | 3 + web/vendor/bootstrap-icons/window-dash.svg | 5 + web/vendor/bootstrap-icons/window-desktop.svg | 4 + web/vendor/bootstrap-icons/window-dock.svg | 4 + .../bootstrap-icons/window-fullscreen.svg | 4 + web/vendor/bootstrap-icons/window-plus.svg | 5 + web/vendor/bootstrap-icons/window-sidebar.svg | 4 + web/vendor/bootstrap-icons/window-split.svg | 4 + web/vendor/bootstrap-icons/window-stack.svg | 4 + web/vendor/bootstrap-icons/window-x.svg | 5 + web/vendor/bootstrap-icons/window.svg | 4 + web/vendor/bootstrap-icons/windows.svg | 3 + web/vendor/bootstrap-icons/wordpress.svg | 5 + .../wrench-adjustable-circle-fill.svg | 4 + .../wrench-adjustable-circle.svg | 4 + .../bootstrap-icons/wrench-adjustable.svg | 4 + web/vendor/bootstrap-icons/wrench.svg | 3 + web/vendor/bootstrap-icons/x-circle-fill.svg | 3 + web/vendor/bootstrap-icons/x-circle.svg | 4 + web/vendor/bootstrap-icons/x-diamond-fill.svg | 3 + web/vendor/bootstrap-icons/x-diamond.svg | 3 + web/vendor/bootstrap-icons/x-lg.svg | 3 + web/vendor/bootstrap-icons/x-octagon-fill.svg | 3 + web/vendor/bootstrap-icons/x-octagon.svg | 4 + web/vendor/bootstrap-icons/x-square-fill.svg | 3 + web/vendor/bootstrap-icons/x-square.svg | 4 + web/vendor/bootstrap-icons/x.svg | 3 + web/vendor/bootstrap-icons/xbox.svg | 3 + web/vendor/bootstrap-icons/yelp.svg | 3 + web/vendor/bootstrap-icons/yin-yang.svg | 4 + web/vendor/bootstrap-icons/youtube.svg | 3 + web/vendor/bootstrap-icons/zoom-in.svg | 5 + web/vendor/bootstrap-icons/zoom-out.svg | 5 + web/vendor/editorjs/editorjs.mjs | 11208 ++++++++++++++++ web/vendor/editorjs/editorjs.umd.js | 51 + web/vendor/editorjs/tools/checklist.umd.js | 1 + web/vendor/editorjs/tools/columns.js | 8 + web/vendor/editorjs/tools/header.umd.js | 10 + web/vendor/editorjs/tools/list.umd.js | 1 + web/vendor/editorjs/tools/marker.umd.js | 1 + web/vendor/editorjs/tools/table.umd.js | 8 + web/vendor/fslightbox/README.md | 55 + web/vendor/fslightbox/fslightbox.js | 1 + web/vendor/fslightbox/package.json | 22 + web/vendor/gridjs/gridjs.umd.js | 2 + web/vendor/gridjs/mermaid.min.css | 1 + .../gridjs/plugins/selection/selection.umd.js | 2 + web/vendor/multi-select/MultiSelect.css | 206 + web/vendor/multi-select/MultiSelect.js | 399 + 2401 files changed, 56808 insertions(+) create mode 100644 .DS_Store create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 .htaccess create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 config/config.php.example create mode 100644 config/router.php create mode 100644 config/settings.php create mode 100644 db/init/init.sql create mode 100644 docker-compose.yml create mode 100644 docker/.DS_Store create mode 100644 docker/nginx/default.conf create mode 100644 docker/php/Dockerfile create mode 100644 docker/php/php.ini create mode 100644 docs/ARCHITECTURE.md create mode 100644 docs/README-search.md create mode 100644 docs/conventions.md create mode 100644 docs/todo-editorjs-image.md create mode 100644 i18n/default_de.json create mode 100644 i18n/default_en.json create mode 100644 lib/.DS_Store create mode 100644 lib/Http/AccessControl.php create mode 100644 lib/Http/AssetDetector.php create mode 100644 lib/Http/LocaleResolver.php create mode 100644 lib/Http/Request.php create mode 100644 lib/Repository/DepartmentRepository.php create mode 100644 lib/Repository/EmailVerificationRepository.php create mode 100644 lib/Repository/MailLogRepository.php create mode 100644 lib/Repository/PageContentRepository.php create mode 100644 lib/Repository/PageRepository.php create mode 100644 lib/Repository/PasswordResetRepository.php create mode 100644 lib/Repository/PermissionRepository.php create mode 100644 lib/Repository/RememberTokenRepository.php create mode 100644 lib/Repository/RolePermissionRepository.php create mode 100644 lib/Repository/RoleRepository.php create mode 100644 lib/Repository/SettingRepository.php create mode 100644 lib/Repository/TenantDepartmentRepository.php create mode 100644 lib/Repository/TenantRepository.php create mode 100644 lib/Repository/UserDepartmentRepository.php create mode 100644 lib/Repository/UserRepository.php create mode 100644 lib/Repository/UserRoleRepository.php create mode 100644 lib/Repository/UserTenantRepository.php create mode 100644 lib/Service/AuthService.php create mode 100644 lib/Service/BrandingFaviconService.php create mode 100644 lib/Service/BrandingLogoService.php create mode 100644 lib/Service/DepartmentService.php create mode 100644 lib/Service/EmailVerificationService.php create mode 100644 lib/Service/MailLogService.php create mode 100644 lib/Service/MailService.php create mode 100644 lib/Service/PageService.php create mode 100644 lib/Service/PasswordResetService.php create mode 100644 lib/Service/PermissionService.php create mode 100644 lib/Service/RememberMeService.php create mode 100644 lib/Service/RoleService.php create mode 100644 lib/Service/SettingService.php create mode 100644 lib/Service/TenantAvatarService.php create mode 100644 lib/Service/TenantFaviconService.php create mode 100644 lib/Service/TenantScopeService.php create mode 100644 lib/Service/TenantService.php create mode 100644 lib/Service/UserAvatarService.php create mode 100644 lib/Service/UserService.php create mode 100644 lib/Support/Flash.php create mode 100644 lib/Support/Guard.php create mode 100644 lib/Support/Hello.php create mode 100644 lib/Support/SearchConfig.php create mode 100644 lib/Support/Tile.php create mode 100644 lib/Support/helpers.php create mode 100644 lib/Support/helpers/app.php create mode 100644 lib/Support/helpers/auth.php create mode 100644 lib/Support/helpers/i18n.php create mode 100644 lib/Support/helpers/ui.php create mode 100644 pages/.DS_Store create mode 100644 pages/account/profile().php create mode 100644 pages/address-book/data().php create mode 100644 pages/address-book/index().php create mode 100644 pages/address-book/index(default).phtml create mode 100644 pages/address-book/view($id).php create mode 100644 pages/address-book/view(default).phtml create mode 100644 pages/admin/departments/_form.phtml create mode 100644 pages/admin/departments/create().php create mode 100644 pages/admin/departments/create(default).phtml create mode 100644 pages/admin/departments/data().php create mode 100644 pages/admin/departments/delete($id).php create mode 100644 pages/admin/departments/edit($id).php create mode 100644 pages/admin/departments/edit(default).phtml create mode 100644 pages/admin/departments/index().php create mode 100644 pages/admin/departments/index(default).phtml create mode 100644 pages/admin/index($slug).php create mode 100644 pages/admin/index().php create mode 100644 pages/admin/index(default).phtml create mode 100644 pages/admin/mail-log/data().php create mode 100644 pages/admin/mail-log/index().php create mode 100644 pages/admin/mail-log/index(default).phtml create mode 100644 pages/admin/mail-log/view($id).php create mode 100644 pages/admin/mail-log/view(default).phtml create mode 100644 pages/admin/permissions/_form.phtml create mode 100644 pages/admin/permissions/create().php create mode 100644 pages/admin/permissions/create(default).phtml create mode 100644 pages/admin/permissions/data().php create mode 100644 pages/admin/permissions/delete($id).php create mode 100644 pages/admin/permissions/edit($id).php create mode 100644 pages/admin/permissions/edit(default).phtml create mode 100644 pages/admin/permissions/index().php create mode 100644 pages/admin/permissions/index(default).phtml create mode 100644 pages/admin/roles/_form.phtml create mode 100644 pages/admin/roles/create().php create mode 100644 pages/admin/roles/create(default).phtml create mode 100644 pages/admin/roles/data().php create mode 100644 pages/admin/roles/delete($id).php create mode 100644 pages/admin/roles/edit($id).php create mode 100644 pages/admin/roles/edit(default).phtml create mode 100644 pages/admin/roles/index().php create mode 100644 pages/admin/roles/index(default).phtml create mode 100644 pages/admin/search/data().php create mode 100644 pages/admin/settings/favicon().php create mode 100644 pages/admin/settings/favicon-delete().php create mode 100644 pages/admin/settings/index().php create mode 100644 pages/admin/settings/index(default).phtml create mode 100644 pages/admin/settings/logo().php create mode 100644 pages/admin/settings/logo-delete().php create mode 100644 pages/admin/stats/index().php create mode 100644 pages/admin/stats/index(default).phtml create mode 100644 pages/admin/tenants/_form.phtml create mode 100644 pages/admin/tenants/avatar($id).php create mode 100644 pages/admin/tenants/avatar-delete($id).php create mode 100644 pages/admin/tenants/avatar-file(none).phtml create mode 100644 pages/admin/tenants/create().php create mode 100644 pages/admin/tenants/create(default).phtml create mode 100644 pages/admin/tenants/data().php create mode 100644 pages/admin/tenants/delete($id).php create mode 100644 pages/admin/tenants/edit($id).php create mode 100644 pages/admin/tenants/edit(default).phtml create mode 100644 pages/admin/tenants/favicon($id).php create mode 100644 pages/admin/tenants/favicon-delete($id).php create mode 100644 pages/admin/tenants/index().php create mode 100644 pages/admin/tenants/index(default).phtml create mode 100644 pages/admin/users/_form.phtml create mode 100644 pages/admin/users/activate($id).php create mode 100644 pages/admin/users/avatar($id).php create mode 100644 pages/admin/users/avatar-delete($id).php create mode 100644 pages/admin/users/avatar-file().php create mode 100644 pages/admin/users/avatar-file(none).phtml create mode 100644 pages/admin/users/bulk($action).php create mode 100644 pages/admin/users/create().php create mode 100644 pages/admin/users/create(default).phtml create mode 100644 pages/admin/users/data().php create mode 100644 pages/admin/users/deactivate($id).php create mode 100644 pages/admin/users/delete($id).php create mode 100644 pages/admin/users/edit($id).php create mode 100644 pages/admin/users/edit(default).phtml create mode 100644 pages/admin/users/export().php create mode 100644 pages/admin/users/export(none).phtml create mode 100644 pages/admin/users/forget-tokens($id).php create mode 100644 pages/admin/users/index().php create mode 100644 pages/admin/users/index(default).phtml create mode 100644 pages/admin/users/send-access($id).php create mode 100644 pages/admin/users/switch-tenant().php create mode 100644 pages/admin/users/theme().php create mode 100644 pages/auth/forgot().php create mode 100644 pages/auth/forgot(login).phtml create mode 100644 pages/auth/login().php create mode 100644 pages/auth/login(login).phtml create mode 100644 pages/auth/logout().php create mode 100644 pages/auth/register().php create mode 100644 pages/auth/register(login).phtml create mode 100644 pages/auth/reset().php create mode 100644 pages/auth/reset(login).phtml create mode 100644 pages/auth/verify().php create mode 100644 pages/auth/verify(login).phtml create mode 100644 pages/auth/verify-email().php create mode 100644 pages/auth/verify-email(login).phtml create mode 100644 pages/branding/logo(none).phtml create mode 100644 pages/error/forbidden(error).phtml create mode 100644 pages/error/method_not_allowed(error).phtml create mode 100644 pages/error/not_found(error).phtml create mode 100644 pages/flash/dismiss($id).php create mode 100644 pages/index().php create mode 100644 pages/lang().php create mode 100644 pages/page/copy-language().php create mode 100644 pages/page/index($slug).php create mode 100644 pages/page/index(default).phtml create mode 100644 pages/search/data().php create mode 100644 pages/search/index().php create mode 100644 pages/search/index(default).phtml create mode 100644 phpstan.neon create mode 100644 storage/.gitkeep create mode 100644 templates/.DS_Store create mode 100644 templates/default.phtml create mode 100644 templates/emails/de/access_info.html create mode 100644 templates/emails/de/access_info.txt create mode 100644 templates/emails/de/email_verification.html create mode 100644 templates/emails/de/email_verification.txt create mode 100644 templates/emails/de/partials/footer.html create mode 100644 templates/emails/de/partials/footer.txt create mode 100644 templates/emails/de/partials/header.html create mode 100644 templates/emails/de/partials/header.txt create mode 100644 templates/emails/de/reset_code.html create mode 100644 templates/emails/de/reset_code.txt create mode 100644 templates/emails/en/access_info.html create mode 100644 templates/emails/en/access_info.txt create mode 100644 templates/emails/en/email_verification.html create mode 100644 templates/emails/en/email_verification.txt create mode 100644 templates/emails/en/partials/footer.html create mode 100644 templates/emails/en/partials/footer.txt create mode 100644 templates/emails/en/partials/header.html create mode 100644 templates/emails/en/partials/header.txt create mode 100644 templates/emails/en/reset_code.html create mode 100644 templates/emails/en/reset_code.txt create mode 100644 templates/error.phtml create mode 100644 templates/login.phtml create mode 100644 templates/partials/.DS_Store create mode 100644 templates/partials/app-aside-icon-bar.phtml create mode 100644 templates/partials/app-aside.phtml create mode 100644 templates/partials/app-flash.phtml create mode 100644 templates/partials/app-footer.phtml create mode 100644 templates/partials/app-language-switcher.phtml create mode 100644 templates/partials/app-tile.phtml create mode 100644 templates/partials/app-topbar.phtml create mode 100644 tests/.DS_Store create mode 100644 tests/Http/RequestTest.php create mode 100644 tests/Service/UserServicePasswordTest.php create mode 100644 web/.DS_Store create mode 100644 web/.htaccess create mode 100644 web/brand/logo.svg create mode 100644 web/css/base/variables.css create mode 100644 web/css/components/app-badges.css create mode 100644 web/css/components/app-blockquote.css create mode 100644 web/css/components/app-brand.css create mode 100644 web/css/components/app-breadcrumb.css create mode 100644 web/css/components/app-buttons.css create mode 100644 web/css/components/app-dashboard-titlebar.css create mode 100644 web/css/components/app-details-titlebar.css create mode 100644 web/css/components/app-details.css create mode 100644 web/css/components/app-flash.css create mode 100644 web/css/components/app-forms.css create mode 100644 web/css/components/app-list-table.css create mode 100644 web/css/components/app-list-tabs.css create mode 100644 web/css/components/app-list-titlebar.css create mode 100644 web/css/components/app-list-toolbar.css create mode 100644 web/css/components/app-page-copy.css create mode 100644 web/css/components/app-page-editor.css create mode 100644 web/css/components/app-profile.css create mode 100644 web/css/components/app-search.css create mode 100644 web/css/components/app-tabs.css create mode 100644 web/css/components/app-tile.css create mode 100644 web/css/components/app-tooltips.css create mode 100644 web/css/components/vendor-editorjs.css create mode 100644 web/css/components/vendor-gridjs.css create mode 100644 web/css/components/vendor-multi-select.css create mode 100644 web/css/layout/app-aside-icon-bar.css create mode 100644 web/css/layout/app-shell.css create mode 100644 web/css/layout/app-sidebar.css create mode 100644 web/css/layout/app-topbar.css create mode 100644 web/css/pages/app-login.css create mode 100644 web/favicon/apple-touch-icon.png create mode 100644 web/favicon/favicon-16x16.png create mode 100644 web/favicon/favicon-32x32.png create mode 100644 web/favicon/favicon-96x96.png create mode 100644 web/favicon/favicon.ico create mode 100644 web/favicon/favicon.svg create mode 100644 web/favicon/site.webmanifest create mode 100644 web/favicon/tenants/21a17705-d67e-4e20-8cc3-cf994bcfc7bb/apple-touch-icon.png create mode 100644 web/favicon/tenants/21a17705-d67e-4e20-8cc3-cf994bcfc7bb/favicon-16x16.png create mode 100644 web/favicon/tenants/21a17705-d67e-4e20-8cc3-cf994bcfc7bb/favicon-32x32.png create mode 100644 web/favicon/tenants/21a17705-d67e-4e20-8cc3-cf994bcfc7bb/favicon-96x96.png create mode 100644 web/favicon/tenants/21a17705-d67e-4e20-8cc3-cf994bcfc7bb/web-app-manifest-192x192.png create mode 100644 web/favicon/tenants/21a17705-d67e-4e20-8cc3-cf994bcfc7bb/web-app-manifest-512x512.png create mode 100644 web/favicon/web-app-manifest-192x192.png create mode 100644 web/favicon/web-app-manifest-512x512.png create mode 100644 web/img/favicon.ico create mode 100644 web/img/forkme_right_red_aa0000.png create mode 100644 web/img/minty_square.png create mode 100644 web/img/mintyphp_logo.png create mode 100644 web/index.php create mode 100644 web/js/app-init.js create mode 100644 web/js/app-login-init.js create mode 100644 web/js/components/app-async-flash.js create mode 100644 web/js/components/app-bulk-selection.js create mode 100644 web/js/components/app-color-default-toggle.js create mode 100644 web/js/components/app-copy-badge.js create mode 100644 web/js/components/app-flash-auto-dismiss.js create mode 100644 web/js/components/app-fslightbox-refresh.js create mode 100644 web/js/components/app-global-search.js create mode 100644 web/js/components/app-multiselect-init.js create mode 100644 web/js/components/app-nav-history.js create mode 100644 web/js/components/app-page-editor.js create mode 100644 web/js/components/app-password-hints.js create mode 100644 web/js/components/app-tabs.js create mode 100644 web/js/components/app-tenant-switcher.js create mode 100644 web/js/components/app-theme-toggle.js create mode 100644 web/js/components/app-toggle-aside-panels.js create mode 100644 web/js/components/app-toggle-details-aside.js create mode 100644 web/js/components/app-toggle-sidebar.js create mode 100644 web/js/components/app-toggle-toolbar.js create mode 100644 web/js/core/app-grid-factory.js create mode 100644 web/js/pages/app-list-utils.js create mode 100644 web/js/pages/app-users-list.js create mode 100644 web/vendor/bootstrap-icons/0-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/0-circle.svg create mode 100644 web/vendor/bootstrap-icons/0-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/0-square.svg create mode 100644 web/vendor/bootstrap-icons/1-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/1-circle.svg create mode 100644 web/vendor/bootstrap-icons/1-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/1-square.svg create mode 100644 web/vendor/bootstrap-icons/123.svg create mode 100644 web/vendor/bootstrap-icons/2-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/2-circle.svg create mode 100644 web/vendor/bootstrap-icons/2-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/2-square.svg create mode 100644 web/vendor/bootstrap-icons/3-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/3-circle.svg create mode 100644 web/vendor/bootstrap-icons/3-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/3-square.svg create mode 100644 web/vendor/bootstrap-icons/4-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/4-circle.svg create mode 100644 web/vendor/bootstrap-icons/4-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/4-square.svg create mode 100644 web/vendor/bootstrap-icons/5-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/5-circle.svg create mode 100644 web/vendor/bootstrap-icons/5-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/5-square.svg create mode 100644 web/vendor/bootstrap-icons/6-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/6-circle.svg create mode 100644 web/vendor/bootstrap-icons/6-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/6-square.svg create mode 100644 web/vendor/bootstrap-icons/7-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/7-circle.svg create mode 100644 web/vendor/bootstrap-icons/7-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/7-square.svg create mode 100644 web/vendor/bootstrap-icons/8-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/8-circle.svg create mode 100644 web/vendor/bootstrap-icons/8-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/8-square.svg create mode 100644 web/vendor/bootstrap-icons/9-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/9-circle.svg create mode 100644 web/vendor/bootstrap-icons/9-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/9-square.svg create mode 100644 web/vendor/bootstrap-icons/activity.svg create mode 100644 web/vendor/bootstrap-icons/airplane-engines-fill.svg create mode 100644 web/vendor/bootstrap-icons/airplane-engines.svg create mode 100644 web/vendor/bootstrap-icons/airplane-fill.svg create mode 100644 web/vendor/bootstrap-icons/airplane.svg create mode 100644 web/vendor/bootstrap-icons/alarm-fill.svg create mode 100644 web/vendor/bootstrap-icons/alarm.svg create mode 100644 web/vendor/bootstrap-icons/alexa.svg create mode 100644 web/vendor/bootstrap-icons/align-bottom.svg create mode 100644 web/vendor/bootstrap-icons/align-center.svg create mode 100644 web/vendor/bootstrap-icons/align-end.svg create mode 100644 web/vendor/bootstrap-icons/align-middle.svg create mode 100644 web/vendor/bootstrap-icons/align-start.svg create mode 100644 web/vendor/bootstrap-icons/align-top.svg create mode 100644 web/vendor/bootstrap-icons/alipay.svg create mode 100644 web/vendor/bootstrap-icons/alphabet-uppercase.svg create mode 100644 web/vendor/bootstrap-icons/alphabet.svg create mode 100644 web/vendor/bootstrap-icons/alt.svg create mode 100644 web/vendor/bootstrap-icons/amazon.svg create mode 100644 web/vendor/bootstrap-icons/amd.svg create mode 100644 web/vendor/bootstrap-icons/android.svg create mode 100644 web/vendor/bootstrap-icons/android2.svg create mode 100644 web/vendor/bootstrap-icons/anthropic.svg create mode 100644 web/vendor/bootstrap-icons/app-indicator.svg create mode 100644 web/vendor/bootstrap-icons/app.svg create mode 100644 web/vendor/bootstrap-icons/apple-music.svg create mode 100644 web/vendor/bootstrap-icons/apple.svg create mode 100644 web/vendor/bootstrap-icons/archive-fill.svg create mode 100644 web/vendor/bootstrap-icons/archive.svg create mode 100644 web/vendor/bootstrap-icons/arrow-90deg-down.svg create mode 100644 web/vendor/bootstrap-icons/arrow-90deg-left.svg create mode 100644 web/vendor/bootstrap-icons/arrow-90deg-right.svg create mode 100644 web/vendor/bootstrap-icons/arrow-90deg-up.svg create mode 100644 web/vendor/bootstrap-icons/arrow-bar-down.svg create mode 100644 web/vendor/bootstrap-icons/arrow-bar-left.svg create mode 100644 web/vendor/bootstrap-icons/arrow-bar-right.svg create mode 100644 web/vendor/bootstrap-icons/arrow-bar-up.svg create mode 100644 web/vendor/bootstrap-icons/arrow-clockwise.svg create mode 100644 web/vendor/bootstrap-icons/arrow-counterclockwise.svg create mode 100644 web/vendor/bootstrap-icons/arrow-down-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/arrow-down-circle.svg create mode 100644 web/vendor/bootstrap-icons/arrow-down-left-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/arrow-down-left-circle.svg create mode 100644 web/vendor/bootstrap-icons/arrow-down-left-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/arrow-down-left-square.svg create mode 100644 web/vendor/bootstrap-icons/arrow-down-left.svg create mode 100644 web/vendor/bootstrap-icons/arrow-down-right-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/arrow-down-right-circle.svg create mode 100644 web/vendor/bootstrap-icons/arrow-down-right-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/arrow-down-right-square.svg create mode 100644 web/vendor/bootstrap-icons/arrow-down-right.svg create mode 100644 web/vendor/bootstrap-icons/arrow-down-short.svg create mode 100644 web/vendor/bootstrap-icons/arrow-down-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/arrow-down-square.svg create mode 100644 web/vendor/bootstrap-icons/arrow-down-up.svg create mode 100644 web/vendor/bootstrap-icons/arrow-down.svg create mode 100644 web/vendor/bootstrap-icons/arrow-left-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/arrow-left-circle.svg create mode 100644 web/vendor/bootstrap-icons/arrow-left-right.svg create mode 100644 web/vendor/bootstrap-icons/arrow-left-short.svg create mode 100644 web/vendor/bootstrap-icons/arrow-left-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/arrow-left-square.svg create mode 100644 web/vendor/bootstrap-icons/arrow-left.svg create mode 100644 web/vendor/bootstrap-icons/arrow-repeat.svg create mode 100644 web/vendor/bootstrap-icons/arrow-return-left.svg create mode 100644 web/vendor/bootstrap-icons/arrow-return-right.svg create mode 100644 web/vendor/bootstrap-icons/arrow-right-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/arrow-right-circle.svg create mode 100644 web/vendor/bootstrap-icons/arrow-right-short.svg create mode 100644 web/vendor/bootstrap-icons/arrow-right-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/arrow-right-square.svg create mode 100644 web/vendor/bootstrap-icons/arrow-right.svg create mode 100644 web/vendor/bootstrap-icons/arrow-through-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/arrow-through-heart.svg create mode 100644 web/vendor/bootstrap-icons/arrow-up-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/arrow-up-circle.svg create mode 100644 web/vendor/bootstrap-icons/arrow-up-left-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/arrow-up-left-circle.svg create mode 100644 web/vendor/bootstrap-icons/arrow-up-left-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/arrow-up-left-square.svg create mode 100644 web/vendor/bootstrap-icons/arrow-up-left.svg create mode 100644 web/vendor/bootstrap-icons/arrow-up-right-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/arrow-up-right-circle.svg create mode 100644 web/vendor/bootstrap-icons/arrow-up-right-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/arrow-up-right-square.svg create mode 100644 web/vendor/bootstrap-icons/arrow-up-right.svg create mode 100644 web/vendor/bootstrap-icons/arrow-up-short.svg create mode 100644 web/vendor/bootstrap-icons/arrow-up-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/arrow-up-square.svg create mode 100644 web/vendor/bootstrap-icons/arrow-up.svg create mode 100644 web/vendor/bootstrap-icons/arrows-angle-contract.svg create mode 100644 web/vendor/bootstrap-icons/arrows-angle-expand.svg create mode 100644 web/vendor/bootstrap-icons/arrows-collapse-vertical.svg create mode 100644 web/vendor/bootstrap-icons/arrows-collapse.svg create mode 100644 web/vendor/bootstrap-icons/arrows-expand-vertical.svg create mode 100644 web/vendor/bootstrap-icons/arrows-expand.svg create mode 100644 web/vendor/bootstrap-icons/arrows-fullscreen.svg create mode 100644 web/vendor/bootstrap-icons/arrows-move.svg create mode 100644 web/vendor/bootstrap-icons/arrows-vertical.svg create mode 100644 web/vendor/bootstrap-icons/arrows.svg create mode 100644 web/vendor/bootstrap-icons/aspect-ratio-fill.svg create mode 100644 web/vendor/bootstrap-icons/aspect-ratio.svg create mode 100644 web/vendor/bootstrap-icons/asterisk.svg create mode 100644 web/vendor/bootstrap-icons/at.svg create mode 100644 web/vendor/bootstrap-icons/award-fill.svg create mode 100644 web/vendor/bootstrap-icons/award.svg create mode 100644 web/vendor/bootstrap-icons/back.svg create mode 100644 web/vendor/bootstrap-icons/backpack-fill.svg create mode 100644 web/vendor/bootstrap-icons/backpack.svg create mode 100644 web/vendor/bootstrap-icons/backpack2-fill.svg create mode 100644 web/vendor/bootstrap-icons/backpack2.svg create mode 100644 web/vendor/bootstrap-icons/backpack3-fill.svg create mode 100644 web/vendor/bootstrap-icons/backpack3.svg create mode 100644 web/vendor/bootstrap-icons/backpack4-fill.svg create mode 100644 web/vendor/bootstrap-icons/backpack4.svg create mode 100644 web/vendor/bootstrap-icons/backspace-fill.svg create mode 100644 web/vendor/bootstrap-icons/backspace-reverse-fill.svg create mode 100644 web/vendor/bootstrap-icons/backspace-reverse.svg create mode 100644 web/vendor/bootstrap-icons/backspace.svg create mode 100644 web/vendor/bootstrap-icons/badge-3d-fill.svg create mode 100644 web/vendor/bootstrap-icons/badge-3d.svg create mode 100644 web/vendor/bootstrap-icons/badge-4k-fill.svg create mode 100644 web/vendor/bootstrap-icons/badge-4k.svg create mode 100644 web/vendor/bootstrap-icons/badge-8k-fill.svg create mode 100644 web/vendor/bootstrap-icons/badge-8k.svg create mode 100644 web/vendor/bootstrap-icons/badge-ad-fill.svg create mode 100644 web/vendor/bootstrap-icons/badge-ad.svg create mode 100644 web/vendor/bootstrap-icons/badge-ar-fill.svg create mode 100644 web/vendor/bootstrap-icons/badge-ar.svg create mode 100644 web/vendor/bootstrap-icons/badge-cc-fill.svg create mode 100644 web/vendor/bootstrap-icons/badge-cc.svg create mode 100644 web/vendor/bootstrap-icons/badge-hd-fill.svg create mode 100644 web/vendor/bootstrap-icons/badge-hd.svg create mode 100644 web/vendor/bootstrap-icons/badge-sd-fill.svg create mode 100644 web/vendor/bootstrap-icons/badge-sd.svg create mode 100644 web/vendor/bootstrap-icons/badge-tm-fill.svg create mode 100644 web/vendor/bootstrap-icons/badge-tm.svg create mode 100644 web/vendor/bootstrap-icons/badge-vo-fill.svg create mode 100644 web/vendor/bootstrap-icons/badge-vo.svg create mode 100644 web/vendor/bootstrap-icons/badge-vr-fill.svg create mode 100644 web/vendor/bootstrap-icons/badge-vr.svg create mode 100644 web/vendor/bootstrap-icons/badge-wc-fill.svg create mode 100644 web/vendor/bootstrap-icons/badge-wc.svg create mode 100644 web/vendor/bootstrap-icons/bag-check-fill.svg create mode 100644 web/vendor/bootstrap-icons/bag-check.svg create mode 100644 web/vendor/bootstrap-icons/bag-dash-fill.svg create mode 100644 web/vendor/bootstrap-icons/bag-dash.svg create mode 100644 web/vendor/bootstrap-icons/bag-fill.svg create mode 100644 web/vendor/bootstrap-icons/bag-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/bag-heart.svg create mode 100644 web/vendor/bootstrap-icons/bag-plus-fill.svg create mode 100644 web/vendor/bootstrap-icons/bag-plus.svg create mode 100644 web/vendor/bootstrap-icons/bag-x-fill.svg create mode 100644 web/vendor/bootstrap-icons/bag-x.svg create mode 100644 web/vendor/bootstrap-icons/bag.svg create mode 100644 web/vendor/bootstrap-icons/balloon-fill.svg create mode 100644 web/vendor/bootstrap-icons/balloon-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/balloon-heart.svg create mode 100644 web/vendor/bootstrap-icons/balloon.svg create mode 100644 web/vendor/bootstrap-icons/ban-fill.svg create mode 100644 web/vendor/bootstrap-icons/ban.svg create mode 100644 web/vendor/bootstrap-icons/bandaid-fill.svg create mode 100644 web/vendor/bootstrap-icons/bandaid.svg create mode 100644 web/vendor/bootstrap-icons/bank.svg create mode 100644 web/vendor/bootstrap-icons/bank2.svg create mode 100644 web/vendor/bootstrap-icons/bar-chart-fill.svg create mode 100644 web/vendor/bootstrap-icons/bar-chart-line-fill.svg create mode 100644 web/vendor/bootstrap-icons/bar-chart-line.svg create mode 100644 web/vendor/bootstrap-icons/bar-chart-steps.svg create mode 100644 web/vendor/bootstrap-icons/bar-chart.svg create mode 100644 web/vendor/bootstrap-icons/basket-fill.svg create mode 100644 web/vendor/bootstrap-icons/basket.svg create mode 100644 web/vendor/bootstrap-icons/basket2-fill.svg create mode 100644 web/vendor/bootstrap-icons/basket2.svg create mode 100644 web/vendor/bootstrap-icons/basket3-fill.svg create mode 100644 web/vendor/bootstrap-icons/basket3.svg create mode 100644 web/vendor/bootstrap-icons/battery-charging.svg create mode 100644 web/vendor/bootstrap-icons/battery-full.svg create mode 100644 web/vendor/bootstrap-icons/battery-half.svg create mode 100644 web/vendor/bootstrap-icons/battery-low.svg create mode 100644 web/vendor/bootstrap-icons/battery.svg create mode 100644 web/vendor/bootstrap-icons/beaker-fill.svg create mode 100644 web/vendor/bootstrap-icons/beaker.svg create mode 100644 web/vendor/bootstrap-icons/behance.svg create mode 100644 web/vendor/bootstrap-icons/bell-fill.svg create mode 100644 web/vendor/bootstrap-icons/bell-slash-fill.svg create mode 100644 web/vendor/bootstrap-icons/bell-slash.svg create mode 100644 web/vendor/bootstrap-icons/bell.svg create mode 100644 web/vendor/bootstrap-icons/bezier.svg create mode 100644 web/vendor/bootstrap-icons/bezier2.svg create mode 100644 web/vendor/bootstrap-icons/bicycle.svg create mode 100644 web/vendor/bootstrap-icons/bing.svg create mode 100644 web/vendor/bootstrap-icons/binoculars-fill.svg create mode 100644 web/vendor/bootstrap-icons/binoculars.svg create mode 100644 web/vendor/bootstrap-icons/blockquote-left.svg create mode 100644 web/vendor/bootstrap-icons/blockquote-right.svg create mode 100644 web/vendor/bootstrap-icons/bluesky.svg create mode 100644 web/vendor/bootstrap-icons/bluetooth.svg create mode 100644 web/vendor/bootstrap-icons/body-text.svg create mode 100644 web/vendor/bootstrap-icons/book-fill.svg create mode 100644 web/vendor/bootstrap-icons/book-half.svg create mode 100644 web/vendor/bootstrap-icons/book.svg create mode 100644 web/vendor/bootstrap-icons/bookmark-check-fill.svg create mode 100644 web/vendor/bootstrap-icons/bookmark-check.svg create mode 100644 web/vendor/bootstrap-icons/bookmark-dash-fill.svg create mode 100644 web/vendor/bootstrap-icons/bookmark-dash.svg create mode 100644 web/vendor/bootstrap-icons/bookmark-fill.svg create mode 100644 web/vendor/bootstrap-icons/bookmark-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/bookmark-heart.svg create mode 100644 web/vendor/bootstrap-icons/bookmark-plus-fill.svg create mode 100644 web/vendor/bootstrap-icons/bookmark-plus.svg create mode 100644 web/vendor/bootstrap-icons/bookmark-star-fill.svg create mode 100644 web/vendor/bootstrap-icons/bookmark-star.svg create mode 100644 web/vendor/bootstrap-icons/bookmark-x-fill.svg create mode 100644 web/vendor/bootstrap-icons/bookmark-x.svg create mode 100644 web/vendor/bootstrap-icons/bookmark.svg create mode 100644 web/vendor/bootstrap-icons/bookmarks-fill.svg create mode 100644 web/vendor/bootstrap-icons/bookmarks.svg create mode 100644 web/vendor/bootstrap-icons/bookshelf.svg create mode 100644 web/vendor/bootstrap-icons/boombox-fill.svg create mode 100644 web/vendor/bootstrap-icons/boombox.svg create mode 100644 web/vendor/bootstrap-icons/bootstrap-fill.svg create mode 100644 web/vendor/bootstrap-icons/bootstrap-icons.css create mode 100644 web/vendor/bootstrap-icons/bootstrap-icons.json create mode 100644 web/vendor/bootstrap-icons/bootstrap-icons.min.css create mode 100644 web/vendor/bootstrap-icons/bootstrap-icons.scss create mode 100644 web/vendor/bootstrap-icons/bootstrap-icons.svg create mode 100644 web/vendor/bootstrap-icons/bootstrap-reboot.svg create mode 100644 web/vendor/bootstrap-icons/bootstrap.svg create mode 100644 web/vendor/bootstrap-icons/border-all.svg create mode 100644 web/vendor/bootstrap-icons/border-bottom.svg create mode 100644 web/vendor/bootstrap-icons/border-center.svg create mode 100644 web/vendor/bootstrap-icons/border-inner.svg create mode 100644 web/vendor/bootstrap-icons/border-left.svg create mode 100644 web/vendor/bootstrap-icons/border-middle.svg create mode 100644 web/vendor/bootstrap-icons/border-outer.svg create mode 100644 web/vendor/bootstrap-icons/border-right.svg create mode 100644 web/vendor/bootstrap-icons/border-style.svg create mode 100644 web/vendor/bootstrap-icons/border-top.svg create mode 100644 web/vendor/bootstrap-icons/border-width.svg create mode 100644 web/vendor/bootstrap-icons/border.svg create mode 100644 web/vendor/bootstrap-icons/bounding-box-circles.svg create mode 100644 web/vendor/bootstrap-icons/bounding-box.svg create mode 100644 web/vendor/bootstrap-icons/box-arrow-down-left.svg create mode 100644 web/vendor/bootstrap-icons/box-arrow-down-right.svg create mode 100644 web/vendor/bootstrap-icons/box-arrow-down.svg create mode 100644 web/vendor/bootstrap-icons/box-arrow-in-down-left.svg create mode 100644 web/vendor/bootstrap-icons/box-arrow-in-down-right.svg create mode 100644 web/vendor/bootstrap-icons/box-arrow-in-down.svg create mode 100644 web/vendor/bootstrap-icons/box-arrow-in-left.svg create mode 100644 web/vendor/bootstrap-icons/box-arrow-in-right.svg create mode 100644 web/vendor/bootstrap-icons/box-arrow-in-up-left.svg create mode 100644 web/vendor/bootstrap-icons/box-arrow-in-up-right.svg create mode 100644 web/vendor/bootstrap-icons/box-arrow-in-up.svg create mode 100644 web/vendor/bootstrap-icons/box-arrow-left.svg create mode 100644 web/vendor/bootstrap-icons/box-arrow-right.svg create mode 100644 web/vendor/bootstrap-icons/box-arrow-up-left.svg create mode 100644 web/vendor/bootstrap-icons/box-arrow-up-right.svg create mode 100644 web/vendor/bootstrap-icons/box-arrow-up.svg create mode 100644 web/vendor/bootstrap-icons/box-fill.svg create mode 100644 web/vendor/bootstrap-icons/box-seam-fill.svg create mode 100644 web/vendor/bootstrap-icons/box-seam.svg create mode 100644 web/vendor/bootstrap-icons/box.svg create mode 100644 web/vendor/bootstrap-icons/box2-fill.svg create mode 100644 web/vendor/bootstrap-icons/box2-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/box2-heart.svg create mode 100644 web/vendor/bootstrap-icons/box2.svg create mode 100644 web/vendor/bootstrap-icons/boxes.svg create mode 100644 web/vendor/bootstrap-icons/braces-asterisk.svg create mode 100644 web/vendor/bootstrap-icons/braces.svg create mode 100644 web/vendor/bootstrap-icons/bricks.svg create mode 100644 web/vendor/bootstrap-icons/briefcase-fill.svg create mode 100644 web/vendor/bootstrap-icons/briefcase.svg create mode 100644 web/vendor/bootstrap-icons/brightness-alt-high-fill.svg create mode 100644 web/vendor/bootstrap-icons/brightness-alt-high.svg create mode 100644 web/vendor/bootstrap-icons/brightness-alt-low-fill.svg create mode 100644 web/vendor/bootstrap-icons/brightness-alt-low.svg create mode 100644 web/vendor/bootstrap-icons/brightness-high-fill.svg create mode 100644 web/vendor/bootstrap-icons/brightness-high.svg create mode 100644 web/vendor/bootstrap-icons/brightness-low-fill.svg create mode 100644 web/vendor/bootstrap-icons/brightness-low.svg create mode 100644 web/vendor/bootstrap-icons/brilliance.svg create mode 100644 web/vendor/bootstrap-icons/broadcast-pin.svg create mode 100644 web/vendor/bootstrap-icons/broadcast.svg create mode 100644 web/vendor/bootstrap-icons/browser-chrome.svg create mode 100644 web/vendor/bootstrap-icons/browser-edge.svg create mode 100644 web/vendor/bootstrap-icons/browser-firefox.svg create mode 100644 web/vendor/bootstrap-icons/browser-safari.svg create mode 100644 web/vendor/bootstrap-icons/brush-fill.svg create mode 100644 web/vendor/bootstrap-icons/brush.svg create mode 100644 web/vendor/bootstrap-icons/bucket-fill.svg create mode 100644 web/vendor/bootstrap-icons/bucket.svg create mode 100644 web/vendor/bootstrap-icons/bug-fill.svg create mode 100644 web/vendor/bootstrap-icons/bug.svg create mode 100644 web/vendor/bootstrap-icons/building-add.svg create mode 100644 web/vendor/bootstrap-icons/building-check.svg create mode 100644 web/vendor/bootstrap-icons/building-dash.svg create mode 100644 web/vendor/bootstrap-icons/building-down.svg create mode 100644 web/vendor/bootstrap-icons/building-exclamation.svg create mode 100644 web/vendor/bootstrap-icons/building-fill-add.svg create mode 100644 web/vendor/bootstrap-icons/building-fill-check.svg create mode 100644 web/vendor/bootstrap-icons/building-fill-dash.svg create mode 100644 web/vendor/bootstrap-icons/building-fill-down.svg create mode 100644 web/vendor/bootstrap-icons/building-fill-exclamation.svg create mode 100644 web/vendor/bootstrap-icons/building-fill-gear.svg create mode 100644 web/vendor/bootstrap-icons/building-fill-lock.svg create mode 100644 web/vendor/bootstrap-icons/building-fill-slash.svg create mode 100644 web/vendor/bootstrap-icons/building-fill-up.svg create mode 100644 web/vendor/bootstrap-icons/building-fill-x.svg create mode 100644 web/vendor/bootstrap-icons/building-fill.svg create mode 100644 web/vendor/bootstrap-icons/building-gear.svg create mode 100644 web/vendor/bootstrap-icons/building-lock.svg create mode 100644 web/vendor/bootstrap-icons/building-slash.svg create mode 100644 web/vendor/bootstrap-icons/building-up.svg create mode 100644 web/vendor/bootstrap-icons/building-x.svg create mode 100644 web/vendor/bootstrap-icons/building.svg create mode 100644 web/vendor/bootstrap-icons/buildings-fill.svg create mode 100644 web/vendor/bootstrap-icons/buildings.svg create mode 100644 web/vendor/bootstrap-icons/bullseye.svg create mode 100644 web/vendor/bootstrap-icons/bus-front-fill.svg create mode 100644 web/vendor/bootstrap-icons/bus-front.svg create mode 100644 web/vendor/bootstrap-icons/c-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/c-circle.svg create mode 100644 web/vendor/bootstrap-icons/c-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/c-square.svg create mode 100644 web/vendor/bootstrap-icons/cake-fill.svg create mode 100644 web/vendor/bootstrap-icons/cake.svg create mode 100644 web/vendor/bootstrap-icons/cake2-fill.svg create mode 100644 web/vendor/bootstrap-icons/cake2.svg create mode 100644 web/vendor/bootstrap-icons/calculator-fill.svg create mode 100644 web/vendor/bootstrap-icons/calculator.svg create mode 100644 web/vendor/bootstrap-icons/calendar-check-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar-check.svg create mode 100644 web/vendor/bootstrap-icons/calendar-date-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar-date.svg create mode 100644 web/vendor/bootstrap-icons/calendar-day-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar-day.svg create mode 100644 web/vendor/bootstrap-icons/calendar-event-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar-event.svg create mode 100644 web/vendor/bootstrap-icons/calendar-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar-heart.svg create mode 100644 web/vendor/bootstrap-icons/calendar-minus-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar-minus.svg create mode 100644 web/vendor/bootstrap-icons/calendar-month-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar-month.svg create mode 100644 web/vendor/bootstrap-icons/calendar-plus-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar-plus.svg create mode 100644 web/vendor/bootstrap-icons/calendar-range-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar-range.svg create mode 100644 web/vendor/bootstrap-icons/calendar-week-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar-week.svg create mode 100644 web/vendor/bootstrap-icons/calendar-x-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar-x.svg create mode 100644 web/vendor/bootstrap-icons/calendar.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-check-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-check.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-date-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-date.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-day-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-day.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-event-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-event.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-heart.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-minus-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-minus.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-month-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-month.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-plus-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-plus.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-range-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-range.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-week-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-week.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-x-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar2-x.svg create mode 100644 web/vendor/bootstrap-icons/calendar2.svg create mode 100644 web/vendor/bootstrap-icons/calendar3-event-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar3-event.svg create mode 100644 web/vendor/bootstrap-icons/calendar3-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar3-range-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar3-range.svg create mode 100644 web/vendor/bootstrap-icons/calendar3-week-fill.svg create mode 100644 web/vendor/bootstrap-icons/calendar3-week.svg create mode 100644 web/vendor/bootstrap-icons/calendar3.svg create mode 100644 web/vendor/bootstrap-icons/calendar4-event.svg create mode 100644 web/vendor/bootstrap-icons/calendar4-range.svg create mode 100644 web/vendor/bootstrap-icons/calendar4-week.svg create mode 100644 web/vendor/bootstrap-icons/calendar4.svg create mode 100644 web/vendor/bootstrap-icons/camera-fill.svg create mode 100644 web/vendor/bootstrap-icons/camera-reels-fill.svg create mode 100644 web/vendor/bootstrap-icons/camera-reels.svg create mode 100644 web/vendor/bootstrap-icons/camera-video-fill.svg create mode 100644 web/vendor/bootstrap-icons/camera-video-off-fill.svg create mode 100644 web/vendor/bootstrap-icons/camera-video-off.svg create mode 100644 web/vendor/bootstrap-icons/camera-video.svg create mode 100644 web/vendor/bootstrap-icons/camera.svg create mode 100644 web/vendor/bootstrap-icons/camera2.svg create mode 100644 web/vendor/bootstrap-icons/capslock-fill.svg create mode 100644 web/vendor/bootstrap-icons/capslock.svg create mode 100644 web/vendor/bootstrap-icons/capsule-pill.svg create mode 100644 web/vendor/bootstrap-icons/capsule.svg create mode 100644 web/vendor/bootstrap-icons/car-front-fill.svg create mode 100644 web/vendor/bootstrap-icons/car-front.svg create mode 100644 web/vendor/bootstrap-icons/card-checklist.svg create mode 100644 web/vendor/bootstrap-icons/card-heading.svg create mode 100644 web/vendor/bootstrap-icons/card-image.svg create mode 100644 web/vendor/bootstrap-icons/card-list.svg create mode 100644 web/vendor/bootstrap-icons/card-text.svg create mode 100644 web/vendor/bootstrap-icons/caret-down-fill.svg create mode 100644 web/vendor/bootstrap-icons/caret-down-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/caret-down-square.svg create mode 100644 web/vendor/bootstrap-icons/caret-down.svg create mode 100644 web/vendor/bootstrap-icons/caret-left-fill.svg create mode 100644 web/vendor/bootstrap-icons/caret-left-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/caret-left-square.svg create mode 100644 web/vendor/bootstrap-icons/caret-left.svg create mode 100644 web/vendor/bootstrap-icons/caret-right-fill.svg create mode 100644 web/vendor/bootstrap-icons/caret-right-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/caret-right-square.svg create mode 100644 web/vendor/bootstrap-icons/caret-right.svg create mode 100644 web/vendor/bootstrap-icons/caret-up-fill.svg create mode 100644 web/vendor/bootstrap-icons/caret-up-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/caret-up-square.svg create mode 100644 web/vendor/bootstrap-icons/caret-up.svg create mode 100644 web/vendor/bootstrap-icons/cart-check-fill.svg create mode 100644 web/vendor/bootstrap-icons/cart-check.svg create mode 100644 web/vendor/bootstrap-icons/cart-dash-fill.svg create mode 100644 web/vendor/bootstrap-icons/cart-dash.svg create mode 100644 web/vendor/bootstrap-icons/cart-fill.svg create mode 100644 web/vendor/bootstrap-icons/cart-plus-fill.svg create mode 100644 web/vendor/bootstrap-icons/cart-plus.svg create mode 100644 web/vendor/bootstrap-icons/cart-x-fill.svg create mode 100644 web/vendor/bootstrap-icons/cart-x.svg create mode 100644 web/vendor/bootstrap-icons/cart.svg create mode 100644 web/vendor/bootstrap-icons/cart2.svg create mode 100644 web/vendor/bootstrap-icons/cart3.svg create mode 100644 web/vendor/bootstrap-icons/cart4.svg create mode 100644 web/vendor/bootstrap-icons/cash-coin.svg create mode 100644 web/vendor/bootstrap-icons/cash-stack.svg create mode 100644 web/vendor/bootstrap-icons/cash.svg create mode 100644 web/vendor/bootstrap-icons/cassette-fill.svg create mode 100644 web/vendor/bootstrap-icons/cassette.svg create mode 100644 web/vendor/bootstrap-icons/cast.svg create mode 100644 web/vendor/bootstrap-icons/cc-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/cc-circle.svg create mode 100644 web/vendor/bootstrap-icons/cc-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/cc-square.svg create mode 100644 web/vendor/bootstrap-icons/chat-dots-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-dots.svg create mode 100644 web/vendor/bootstrap-icons/chat-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-heart.svg create mode 100644 web/vendor/bootstrap-icons/chat-left-dots-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-left-dots.svg create mode 100644 web/vendor/bootstrap-icons/chat-left-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-left-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-left-heart.svg create mode 100644 web/vendor/bootstrap-icons/chat-left-quote-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-left-quote.svg create mode 100644 web/vendor/bootstrap-icons/chat-left-text-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-left-text.svg create mode 100644 web/vendor/bootstrap-icons/chat-left.svg create mode 100644 web/vendor/bootstrap-icons/chat-quote-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-quote.svg create mode 100644 web/vendor/bootstrap-icons/chat-right-dots-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-right-dots.svg create mode 100644 web/vendor/bootstrap-icons/chat-right-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-right-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-right-heart.svg create mode 100644 web/vendor/bootstrap-icons/chat-right-quote-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-right-quote.svg create mode 100644 web/vendor/bootstrap-icons/chat-right-text-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-right-text.svg create mode 100644 web/vendor/bootstrap-icons/chat-right.svg create mode 100644 web/vendor/bootstrap-icons/chat-square-dots-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-square-dots.svg create mode 100644 web/vendor/bootstrap-icons/chat-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-square-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-square-heart.svg create mode 100644 web/vendor/bootstrap-icons/chat-square-quote-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-square-quote.svg create mode 100644 web/vendor/bootstrap-icons/chat-square-text-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-square-text.svg create mode 100644 web/vendor/bootstrap-icons/chat-square.svg create mode 100644 web/vendor/bootstrap-icons/chat-text-fill.svg create mode 100644 web/vendor/bootstrap-icons/chat-text.svg create mode 100644 web/vendor/bootstrap-icons/chat.svg create mode 100644 web/vendor/bootstrap-icons/check-all.svg create mode 100644 web/vendor/bootstrap-icons/check-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/check-circle.svg create mode 100644 web/vendor/bootstrap-icons/check-lg.svg create mode 100644 web/vendor/bootstrap-icons/check-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/check-square.svg create mode 100644 web/vendor/bootstrap-icons/check.svg create mode 100644 web/vendor/bootstrap-icons/check2-all.svg create mode 100644 web/vendor/bootstrap-icons/check2-circle.svg create mode 100644 web/vendor/bootstrap-icons/check2-square.svg create mode 100644 web/vendor/bootstrap-icons/check2.svg create mode 100644 web/vendor/bootstrap-icons/chevron-bar-contract.svg create mode 100644 web/vendor/bootstrap-icons/chevron-bar-down.svg create mode 100644 web/vendor/bootstrap-icons/chevron-bar-expand.svg create mode 100644 web/vendor/bootstrap-icons/chevron-bar-left.svg create mode 100644 web/vendor/bootstrap-icons/chevron-bar-right.svg create mode 100644 web/vendor/bootstrap-icons/chevron-bar-up.svg create mode 100644 web/vendor/bootstrap-icons/chevron-compact-down.svg create mode 100644 web/vendor/bootstrap-icons/chevron-compact-left.svg create mode 100644 web/vendor/bootstrap-icons/chevron-compact-right.svg create mode 100644 web/vendor/bootstrap-icons/chevron-compact-up.svg create mode 100644 web/vendor/bootstrap-icons/chevron-contract.svg create mode 100644 web/vendor/bootstrap-icons/chevron-double-down.svg create mode 100644 web/vendor/bootstrap-icons/chevron-double-left.svg create mode 100644 web/vendor/bootstrap-icons/chevron-double-right.svg create mode 100644 web/vendor/bootstrap-icons/chevron-double-up.svg create mode 100644 web/vendor/bootstrap-icons/chevron-down.svg create mode 100644 web/vendor/bootstrap-icons/chevron-expand.svg create mode 100644 web/vendor/bootstrap-icons/chevron-left.svg create mode 100644 web/vendor/bootstrap-icons/chevron-right.svg create mode 100644 web/vendor/bootstrap-icons/chevron-up.svg create mode 100644 web/vendor/bootstrap-icons/circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/circle-half.svg create mode 100644 web/vendor/bootstrap-icons/circle-square.svg create mode 100644 web/vendor/bootstrap-icons/circle.svg create mode 100644 web/vendor/bootstrap-icons/claude.svg create mode 100644 web/vendor/bootstrap-icons/clipboard-check-fill.svg create mode 100644 web/vendor/bootstrap-icons/clipboard-check.svg create mode 100644 web/vendor/bootstrap-icons/clipboard-data-fill.svg create mode 100644 web/vendor/bootstrap-icons/clipboard-data.svg create mode 100644 web/vendor/bootstrap-icons/clipboard-fill.svg create mode 100644 web/vendor/bootstrap-icons/clipboard-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/clipboard-heart.svg create mode 100644 web/vendor/bootstrap-icons/clipboard-minus-fill.svg create mode 100644 web/vendor/bootstrap-icons/clipboard-minus.svg create mode 100644 web/vendor/bootstrap-icons/clipboard-plus-fill.svg create mode 100644 web/vendor/bootstrap-icons/clipboard-plus.svg create mode 100644 web/vendor/bootstrap-icons/clipboard-pulse.svg create mode 100644 web/vendor/bootstrap-icons/clipboard-x-fill.svg create mode 100644 web/vendor/bootstrap-icons/clipboard-x.svg create mode 100644 web/vendor/bootstrap-icons/clipboard.svg create mode 100644 web/vendor/bootstrap-icons/clipboard2-check-fill.svg create mode 100644 web/vendor/bootstrap-icons/clipboard2-check.svg create mode 100644 web/vendor/bootstrap-icons/clipboard2-data-fill.svg create mode 100644 web/vendor/bootstrap-icons/clipboard2-data.svg create mode 100644 web/vendor/bootstrap-icons/clipboard2-fill.svg create mode 100644 web/vendor/bootstrap-icons/clipboard2-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/clipboard2-heart.svg create mode 100644 web/vendor/bootstrap-icons/clipboard2-minus-fill.svg create mode 100644 web/vendor/bootstrap-icons/clipboard2-minus.svg create mode 100644 web/vendor/bootstrap-icons/clipboard2-plus-fill.svg create mode 100644 web/vendor/bootstrap-icons/clipboard2-plus.svg create mode 100644 web/vendor/bootstrap-icons/clipboard2-pulse-fill.svg create mode 100644 web/vendor/bootstrap-icons/clipboard2-pulse.svg create mode 100644 web/vendor/bootstrap-icons/clipboard2-x-fill.svg create mode 100644 web/vendor/bootstrap-icons/clipboard2-x.svg create mode 100644 web/vendor/bootstrap-icons/clipboard2.svg create mode 100644 web/vendor/bootstrap-icons/clock-fill.svg create mode 100644 web/vendor/bootstrap-icons/clock-history.svg create mode 100644 web/vendor/bootstrap-icons/clock.svg create mode 100644 web/vendor/bootstrap-icons/cloud-arrow-down-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-arrow-down.svg create mode 100644 web/vendor/bootstrap-icons/cloud-arrow-up-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-arrow-up.svg create mode 100644 web/vendor/bootstrap-icons/cloud-check-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-check.svg create mode 100644 web/vendor/bootstrap-icons/cloud-download-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-download.svg create mode 100644 web/vendor/bootstrap-icons/cloud-drizzle-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-drizzle.svg create mode 100644 web/vendor/bootstrap-icons/cloud-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-fog-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-fog.svg create mode 100644 web/vendor/bootstrap-icons/cloud-fog2-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-fog2.svg create mode 100644 web/vendor/bootstrap-icons/cloud-hail-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-hail.svg create mode 100644 web/vendor/bootstrap-icons/cloud-haze-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-haze.svg create mode 100644 web/vendor/bootstrap-icons/cloud-haze2-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-haze2.svg create mode 100644 web/vendor/bootstrap-icons/cloud-lightning-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-lightning-rain-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-lightning-rain.svg create mode 100644 web/vendor/bootstrap-icons/cloud-lightning.svg create mode 100644 web/vendor/bootstrap-icons/cloud-minus-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-minus.svg create mode 100644 web/vendor/bootstrap-icons/cloud-moon-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-moon.svg create mode 100644 web/vendor/bootstrap-icons/cloud-plus-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-plus.svg create mode 100644 web/vendor/bootstrap-icons/cloud-rain-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-rain-heavy-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-rain-heavy.svg create mode 100644 web/vendor/bootstrap-icons/cloud-rain.svg create mode 100644 web/vendor/bootstrap-icons/cloud-slash-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-slash.svg create mode 100644 web/vendor/bootstrap-icons/cloud-sleet-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-sleet.svg create mode 100644 web/vendor/bootstrap-icons/cloud-snow-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-snow.svg create mode 100644 web/vendor/bootstrap-icons/cloud-sun-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-sun.svg create mode 100644 web/vendor/bootstrap-icons/cloud-upload-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloud-upload.svg create mode 100644 web/vendor/bootstrap-icons/cloud.svg create mode 100644 web/vendor/bootstrap-icons/clouds-fill.svg create mode 100644 web/vendor/bootstrap-icons/clouds.svg create mode 100644 web/vendor/bootstrap-icons/cloudy-fill.svg create mode 100644 web/vendor/bootstrap-icons/cloudy.svg create mode 100644 web/vendor/bootstrap-icons/code-slash.svg create mode 100644 web/vendor/bootstrap-icons/code-square.svg create mode 100644 web/vendor/bootstrap-icons/code.svg create mode 100644 web/vendor/bootstrap-icons/coin.svg create mode 100644 web/vendor/bootstrap-icons/collection-fill.svg create mode 100644 web/vendor/bootstrap-icons/collection-play-fill.svg create mode 100644 web/vendor/bootstrap-icons/collection-play.svg create mode 100644 web/vendor/bootstrap-icons/collection.svg create mode 100644 web/vendor/bootstrap-icons/columns-gap.svg create mode 100644 web/vendor/bootstrap-icons/columns.svg create mode 100644 web/vendor/bootstrap-icons/command.svg create mode 100644 web/vendor/bootstrap-icons/compass-fill.svg create mode 100644 web/vendor/bootstrap-icons/compass.svg create mode 100644 web/vendor/bootstrap-icons/cone-striped.svg create mode 100644 web/vendor/bootstrap-icons/cone.svg create mode 100644 web/vendor/bootstrap-icons/controller.svg create mode 100644 web/vendor/bootstrap-icons/cookie.svg create mode 100644 web/vendor/bootstrap-icons/copy.svg create mode 100644 web/vendor/bootstrap-icons/cpu-fill.svg create mode 100644 web/vendor/bootstrap-icons/cpu.svg create mode 100644 web/vendor/bootstrap-icons/credit-card-2-back-fill.svg create mode 100644 web/vendor/bootstrap-icons/credit-card-2-back.svg create mode 100644 web/vendor/bootstrap-icons/credit-card-2-front-fill.svg create mode 100644 web/vendor/bootstrap-icons/credit-card-2-front.svg create mode 100644 web/vendor/bootstrap-icons/credit-card-fill.svg create mode 100644 web/vendor/bootstrap-icons/credit-card.svg create mode 100644 web/vendor/bootstrap-icons/crop.svg create mode 100644 web/vendor/bootstrap-icons/crosshair.svg create mode 100644 web/vendor/bootstrap-icons/crosshair2.svg create mode 100644 web/vendor/bootstrap-icons/css.svg create mode 100644 web/vendor/bootstrap-icons/cup-fill.svg create mode 100644 web/vendor/bootstrap-icons/cup-hot-fill.svg create mode 100644 web/vendor/bootstrap-icons/cup-hot.svg create mode 100644 web/vendor/bootstrap-icons/cup-straw.svg create mode 100644 web/vendor/bootstrap-icons/cup.svg create mode 100644 web/vendor/bootstrap-icons/currency-bitcoin.svg create mode 100644 web/vendor/bootstrap-icons/currency-dollar.svg create mode 100644 web/vendor/bootstrap-icons/currency-euro.svg create mode 100644 web/vendor/bootstrap-icons/currency-exchange.svg create mode 100644 web/vendor/bootstrap-icons/currency-pound.svg create mode 100644 web/vendor/bootstrap-icons/currency-rupee.svg create mode 100644 web/vendor/bootstrap-icons/currency-yen.svg create mode 100644 web/vendor/bootstrap-icons/cursor-fill.svg create mode 100644 web/vendor/bootstrap-icons/cursor-text.svg create mode 100644 web/vendor/bootstrap-icons/cursor.svg create mode 100644 web/vendor/bootstrap-icons/dash-circle-dotted.svg create mode 100644 web/vendor/bootstrap-icons/dash-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/dash-circle.svg create mode 100644 web/vendor/bootstrap-icons/dash-lg.svg create mode 100644 web/vendor/bootstrap-icons/dash-square-dotted.svg create mode 100644 web/vendor/bootstrap-icons/dash-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/dash-square.svg create mode 100644 web/vendor/bootstrap-icons/dash.svg create mode 100644 web/vendor/bootstrap-icons/database-add.svg create mode 100644 web/vendor/bootstrap-icons/database-check.svg create mode 100644 web/vendor/bootstrap-icons/database-dash.svg create mode 100644 web/vendor/bootstrap-icons/database-down.svg create mode 100644 web/vendor/bootstrap-icons/database-exclamation.svg create mode 100644 web/vendor/bootstrap-icons/database-fill-add.svg create mode 100644 web/vendor/bootstrap-icons/database-fill-check.svg create mode 100644 web/vendor/bootstrap-icons/database-fill-dash.svg create mode 100644 web/vendor/bootstrap-icons/database-fill-down.svg create mode 100644 web/vendor/bootstrap-icons/database-fill-exclamation.svg create mode 100644 web/vendor/bootstrap-icons/database-fill-gear.svg create mode 100644 web/vendor/bootstrap-icons/database-fill-lock.svg create mode 100644 web/vendor/bootstrap-icons/database-fill-slash.svg create mode 100644 web/vendor/bootstrap-icons/database-fill-up.svg create mode 100644 web/vendor/bootstrap-icons/database-fill-x.svg create mode 100644 web/vendor/bootstrap-icons/database-fill.svg create mode 100644 web/vendor/bootstrap-icons/database-gear.svg create mode 100644 web/vendor/bootstrap-icons/database-lock.svg create mode 100644 web/vendor/bootstrap-icons/database-slash.svg create mode 100644 web/vendor/bootstrap-icons/database-up.svg create mode 100644 web/vendor/bootstrap-icons/database-x.svg create mode 100644 web/vendor/bootstrap-icons/database.svg create mode 100644 web/vendor/bootstrap-icons/device-hdd-fill.svg create mode 100644 web/vendor/bootstrap-icons/device-hdd.svg create mode 100644 web/vendor/bootstrap-icons/device-ssd-fill.svg create mode 100644 web/vendor/bootstrap-icons/device-ssd.svg create mode 100644 web/vendor/bootstrap-icons/diagram-2-fill.svg create mode 100644 web/vendor/bootstrap-icons/diagram-2.svg create mode 100644 web/vendor/bootstrap-icons/diagram-3-fill.svg create mode 100644 web/vendor/bootstrap-icons/diagram-3.svg create mode 100644 web/vendor/bootstrap-icons/diamond-fill.svg create mode 100644 web/vendor/bootstrap-icons/diamond-half.svg create mode 100644 web/vendor/bootstrap-icons/diamond.svg create mode 100644 web/vendor/bootstrap-icons/dice-1-fill.svg create mode 100644 web/vendor/bootstrap-icons/dice-1.svg create mode 100644 web/vendor/bootstrap-icons/dice-2-fill.svg create mode 100644 web/vendor/bootstrap-icons/dice-2.svg create mode 100644 web/vendor/bootstrap-icons/dice-3-fill.svg create mode 100644 web/vendor/bootstrap-icons/dice-3.svg create mode 100644 web/vendor/bootstrap-icons/dice-4-fill.svg create mode 100644 web/vendor/bootstrap-icons/dice-4.svg create mode 100644 web/vendor/bootstrap-icons/dice-5-fill.svg create mode 100644 web/vendor/bootstrap-icons/dice-5.svg create mode 100644 web/vendor/bootstrap-icons/dice-6-fill.svg create mode 100644 web/vendor/bootstrap-icons/dice-6.svg create mode 100644 web/vendor/bootstrap-icons/disc-fill.svg create mode 100644 web/vendor/bootstrap-icons/disc.svg create mode 100644 web/vendor/bootstrap-icons/discord.svg create mode 100644 web/vendor/bootstrap-icons/display-fill.svg create mode 100644 web/vendor/bootstrap-icons/display.svg create mode 100644 web/vendor/bootstrap-icons/displayport-fill.svg create mode 100644 web/vendor/bootstrap-icons/displayport.svg create mode 100644 web/vendor/bootstrap-icons/distribute-horizontal.svg create mode 100644 web/vendor/bootstrap-icons/distribute-vertical.svg create mode 100644 web/vendor/bootstrap-icons/door-closed-fill.svg create mode 100644 web/vendor/bootstrap-icons/door-closed.svg create mode 100644 web/vendor/bootstrap-icons/door-open-fill.svg create mode 100644 web/vendor/bootstrap-icons/door-open.svg create mode 100644 web/vendor/bootstrap-icons/dot.svg create mode 100644 web/vendor/bootstrap-icons/download.svg create mode 100644 web/vendor/bootstrap-icons/dpad-fill.svg create mode 100644 web/vendor/bootstrap-icons/dpad.svg create mode 100644 web/vendor/bootstrap-icons/dribbble.svg create mode 100644 web/vendor/bootstrap-icons/dropbox.svg create mode 100644 web/vendor/bootstrap-icons/droplet-fill.svg create mode 100644 web/vendor/bootstrap-icons/droplet-half.svg create mode 100644 web/vendor/bootstrap-icons/droplet.svg create mode 100644 web/vendor/bootstrap-icons/duffle-fill.svg create mode 100644 web/vendor/bootstrap-icons/duffle.svg create mode 100644 web/vendor/bootstrap-icons/ear-fill.svg create mode 100644 web/vendor/bootstrap-icons/ear.svg create mode 100644 web/vendor/bootstrap-icons/earbuds.svg create mode 100644 web/vendor/bootstrap-icons/easel-fill.svg create mode 100644 web/vendor/bootstrap-icons/easel.svg create mode 100644 web/vendor/bootstrap-icons/easel2-fill.svg create mode 100644 web/vendor/bootstrap-icons/easel2.svg create mode 100644 web/vendor/bootstrap-icons/easel3-fill.svg create mode 100644 web/vendor/bootstrap-icons/easel3.svg create mode 100644 web/vendor/bootstrap-icons/egg-fill.svg create mode 100644 web/vendor/bootstrap-icons/egg-fried.svg create mode 100644 web/vendor/bootstrap-icons/egg.svg create mode 100644 web/vendor/bootstrap-icons/eject-fill.svg create mode 100644 web/vendor/bootstrap-icons/eject.svg create mode 100644 web/vendor/bootstrap-icons/emoji-angry-fill.svg create mode 100644 web/vendor/bootstrap-icons/emoji-angry.svg create mode 100644 web/vendor/bootstrap-icons/emoji-astonished-fill.svg create mode 100644 web/vendor/bootstrap-icons/emoji-astonished.svg create mode 100644 web/vendor/bootstrap-icons/emoji-dizzy-fill.svg create mode 100644 web/vendor/bootstrap-icons/emoji-dizzy.svg create mode 100644 web/vendor/bootstrap-icons/emoji-expressionless-fill.svg create mode 100644 web/vendor/bootstrap-icons/emoji-expressionless.svg create mode 100644 web/vendor/bootstrap-icons/emoji-frown-fill.svg create mode 100644 web/vendor/bootstrap-icons/emoji-frown.svg create mode 100644 web/vendor/bootstrap-icons/emoji-grimace-fill.svg create mode 100644 web/vendor/bootstrap-icons/emoji-grimace.svg create mode 100644 web/vendor/bootstrap-icons/emoji-grin-fill.svg create mode 100644 web/vendor/bootstrap-icons/emoji-grin.svg create mode 100644 web/vendor/bootstrap-icons/emoji-heart-eyes-fill.svg create mode 100644 web/vendor/bootstrap-icons/emoji-heart-eyes.svg create mode 100644 web/vendor/bootstrap-icons/emoji-kiss-fill.svg create mode 100644 web/vendor/bootstrap-icons/emoji-kiss.svg create mode 100644 web/vendor/bootstrap-icons/emoji-laughing-fill.svg create mode 100644 web/vendor/bootstrap-icons/emoji-laughing.svg create mode 100644 web/vendor/bootstrap-icons/emoji-neutral-fill.svg create mode 100644 web/vendor/bootstrap-icons/emoji-neutral.svg create mode 100644 web/vendor/bootstrap-icons/emoji-smile-fill.svg create mode 100644 web/vendor/bootstrap-icons/emoji-smile-upside-down-fill.svg create mode 100644 web/vendor/bootstrap-icons/emoji-smile-upside-down.svg create mode 100644 web/vendor/bootstrap-icons/emoji-smile.svg create mode 100644 web/vendor/bootstrap-icons/emoji-sunglasses-fill.svg create mode 100644 web/vendor/bootstrap-icons/emoji-sunglasses.svg create mode 100644 web/vendor/bootstrap-icons/emoji-surprise-fill.svg create mode 100644 web/vendor/bootstrap-icons/emoji-surprise.svg create mode 100644 web/vendor/bootstrap-icons/emoji-tear-fill.svg create mode 100644 web/vendor/bootstrap-icons/emoji-tear.svg create mode 100644 web/vendor/bootstrap-icons/emoji-wink-fill.svg create mode 100644 web/vendor/bootstrap-icons/emoji-wink.svg create mode 100644 web/vendor/bootstrap-icons/envelope-arrow-down-fill.svg create mode 100644 web/vendor/bootstrap-icons/envelope-arrow-down.svg create mode 100644 web/vendor/bootstrap-icons/envelope-arrow-up-fill.svg create mode 100644 web/vendor/bootstrap-icons/envelope-arrow-up.svg create mode 100644 web/vendor/bootstrap-icons/envelope-at-fill.svg create mode 100644 web/vendor/bootstrap-icons/envelope-at.svg create mode 100644 web/vendor/bootstrap-icons/envelope-check-fill.svg create mode 100644 web/vendor/bootstrap-icons/envelope-check.svg create mode 100644 web/vendor/bootstrap-icons/envelope-dash-fill.svg create mode 100644 web/vendor/bootstrap-icons/envelope-dash.svg create mode 100644 web/vendor/bootstrap-icons/envelope-exclamation-fill.svg create mode 100644 web/vendor/bootstrap-icons/envelope-exclamation.svg create mode 100644 web/vendor/bootstrap-icons/envelope-fill.svg create mode 100644 web/vendor/bootstrap-icons/envelope-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/envelope-heart.svg create mode 100644 web/vendor/bootstrap-icons/envelope-open-fill.svg create mode 100644 web/vendor/bootstrap-icons/envelope-open-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/envelope-open-heart.svg create mode 100644 web/vendor/bootstrap-icons/envelope-open.svg create mode 100644 web/vendor/bootstrap-icons/envelope-paper-fill.svg create mode 100644 web/vendor/bootstrap-icons/envelope-paper-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/envelope-paper-heart.svg create mode 100644 web/vendor/bootstrap-icons/envelope-paper.svg create mode 100644 web/vendor/bootstrap-icons/envelope-plus-fill.svg create mode 100644 web/vendor/bootstrap-icons/envelope-plus.svg create mode 100644 web/vendor/bootstrap-icons/envelope-slash-fill.svg create mode 100644 web/vendor/bootstrap-icons/envelope-slash.svg create mode 100644 web/vendor/bootstrap-icons/envelope-x-fill.svg create mode 100644 web/vendor/bootstrap-icons/envelope-x.svg create mode 100644 web/vendor/bootstrap-icons/envelope.svg create mode 100644 web/vendor/bootstrap-icons/eraser-fill.svg create mode 100644 web/vendor/bootstrap-icons/eraser.svg create mode 100644 web/vendor/bootstrap-icons/escape.svg create mode 100644 web/vendor/bootstrap-icons/ethernet.svg create mode 100644 web/vendor/bootstrap-icons/ev-front-fill.svg create mode 100644 web/vendor/bootstrap-icons/ev-front.svg create mode 100644 web/vendor/bootstrap-icons/ev-station-fill.svg create mode 100644 web/vendor/bootstrap-icons/ev-station.svg create mode 100644 web/vendor/bootstrap-icons/exclamation-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/exclamation-circle.svg create mode 100644 web/vendor/bootstrap-icons/exclamation-diamond-fill.svg create mode 100644 web/vendor/bootstrap-icons/exclamation-diamond.svg create mode 100644 web/vendor/bootstrap-icons/exclamation-lg.svg create mode 100644 web/vendor/bootstrap-icons/exclamation-octagon-fill.svg create mode 100644 web/vendor/bootstrap-icons/exclamation-octagon.svg create mode 100644 web/vendor/bootstrap-icons/exclamation-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/exclamation-square.svg create mode 100644 web/vendor/bootstrap-icons/exclamation-triangle-fill.svg create mode 100644 web/vendor/bootstrap-icons/exclamation-triangle.svg create mode 100644 web/vendor/bootstrap-icons/exclamation.svg create mode 100644 web/vendor/bootstrap-icons/exclude.svg create mode 100644 web/vendor/bootstrap-icons/explicit-fill.svg create mode 100644 web/vendor/bootstrap-icons/explicit.svg create mode 100644 web/vendor/bootstrap-icons/exposure.svg create mode 100644 web/vendor/bootstrap-icons/eye-fill.svg create mode 100644 web/vendor/bootstrap-icons/eye-slash-fill.svg create mode 100644 web/vendor/bootstrap-icons/eye-slash.svg create mode 100644 web/vendor/bootstrap-icons/eye.svg create mode 100644 web/vendor/bootstrap-icons/eyedropper.svg create mode 100644 web/vendor/bootstrap-icons/eyeglasses.svg create mode 100644 web/vendor/bootstrap-icons/facebook.svg create mode 100644 web/vendor/bootstrap-icons/fan.svg create mode 100644 web/vendor/bootstrap-icons/fast-forward-btn-fill.svg create mode 100644 web/vendor/bootstrap-icons/fast-forward-btn.svg create mode 100644 web/vendor/bootstrap-icons/fast-forward-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/fast-forward-circle.svg create mode 100644 web/vendor/bootstrap-icons/fast-forward-fill.svg create mode 100644 web/vendor/bootstrap-icons/fast-forward.svg create mode 100644 web/vendor/bootstrap-icons/feather.svg create mode 100644 web/vendor/bootstrap-icons/feather2.svg create mode 100644 web/vendor/bootstrap-icons/file-arrow-down-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-arrow-down.svg create mode 100644 web/vendor/bootstrap-icons/file-arrow-up-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-arrow-up.svg create mode 100644 web/vendor/bootstrap-icons/file-bar-graph-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-bar-graph.svg create mode 100644 web/vendor/bootstrap-icons/file-binary-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-binary.svg create mode 100644 web/vendor/bootstrap-icons/file-break-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-break.svg create mode 100644 web/vendor/bootstrap-icons/file-check-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-check.svg create mode 100644 web/vendor/bootstrap-icons/file-code-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-code.svg create mode 100644 web/vendor/bootstrap-icons/file-diff-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-diff.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-arrow-down-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-arrow-down.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-arrow-up-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-arrow-up.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-bar-graph-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-bar-graph.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-binary-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-binary.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-break-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-break.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-check-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-check.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-code-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-code.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-diff-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-diff.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-easel-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-easel.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-excel-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-excel.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-font-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-font.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-image-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-image.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-lock-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-lock.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-lock2-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-lock2.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-medical-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-medical.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-minus-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-minus.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-music-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-music.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-pdf-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-pdf.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-person-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-person.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-play-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-play.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-plus-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-plus.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-post-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-post.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-ppt-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-ppt.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-richtext-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-richtext.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-ruled-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-ruled.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-slides-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-slides.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-spreadsheet-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-spreadsheet.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-text-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-text.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-word-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-word.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-x-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-x.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-zip-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark-zip.svg create mode 100644 web/vendor/bootstrap-icons/file-earmark.svg create mode 100644 web/vendor/bootstrap-icons/file-easel-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-easel.svg create mode 100644 web/vendor/bootstrap-icons/file-excel-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-excel.svg create mode 100644 web/vendor/bootstrap-icons/file-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-font-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-font.svg create mode 100644 web/vendor/bootstrap-icons/file-image-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-image.svg create mode 100644 web/vendor/bootstrap-icons/file-lock-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-lock.svg create mode 100644 web/vendor/bootstrap-icons/file-lock2-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-lock2.svg create mode 100644 web/vendor/bootstrap-icons/file-medical-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-medical.svg create mode 100644 web/vendor/bootstrap-icons/file-minus-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-minus.svg create mode 100644 web/vendor/bootstrap-icons/file-music-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-music.svg create mode 100644 web/vendor/bootstrap-icons/file-pdf-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-pdf.svg create mode 100644 web/vendor/bootstrap-icons/file-person-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-person.svg create mode 100644 web/vendor/bootstrap-icons/file-play-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-play.svg create mode 100644 web/vendor/bootstrap-icons/file-plus-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-plus.svg create mode 100644 web/vendor/bootstrap-icons/file-post-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-post.svg create mode 100644 web/vendor/bootstrap-icons/file-ppt-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-ppt.svg create mode 100644 web/vendor/bootstrap-icons/file-richtext-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-richtext.svg create mode 100644 web/vendor/bootstrap-icons/file-ruled-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-ruled.svg create mode 100644 web/vendor/bootstrap-icons/file-slides-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-slides.svg create mode 100644 web/vendor/bootstrap-icons/file-spreadsheet-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-spreadsheet.svg create mode 100644 web/vendor/bootstrap-icons/file-text-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-text.svg create mode 100644 web/vendor/bootstrap-icons/file-word-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-word.svg create mode 100644 web/vendor/bootstrap-icons/file-x-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-x.svg create mode 100644 web/vendor/bootstrap-icons/file-zip-fill.svg create mode 100644 web/vendor/bootstrap-icons/file-zip.svg create mode 100644 web/vendor/bootstrap-icons/file.svg create mode 100644 web/vendor/bootstrap-icons/files-alt.svg create mode 100644 web/vendor/bootstrap-icons/files.svg create mode 100644 web/vendor/bootstrap-icons/filetype-aac.svg create mode 100644 web/vendor/bootstrap-icons/filetype-ai.svg create mode 100644 web/vendor/bootstrap-icons/filetype-bmp.svg create mode 100644 web/vendor/bootstrap-icons/filetype-cs.svg create mode 100644 web/vendor/bootstrap-icons/filetype-css.svg create mode 100644 web/vendor/bootstrap-icons/filetype-csv.svg create mode 100644 web/vendor/bootstrap-icons/filetype-doc.svg create mode 100644 web/vendor/bootstrap-icons/filetype-docx.svg create mode 100644 web/vendor/bootstrap-icons/filetype-exe.svg create mode 100644 web/vendor/bootstrap-icons/filetype-gif.svg create mode 100644 web/vendor/bootstrap-icons/filetype-heic.svg create mode 100644 web/vendor/bootstrap-icons/filetype-html.svg create mode 100644 web/vendor/bootstrap-icons/filetype-java.svg create mode 100644 web/vendor/bootstrap-icons/filetype-jpg.svg create mode 100644 web/vendor/bootstrap-icons/filetype-js.svg create mode 100644 web/vendor/bootstrap-icons/filetype-json.svg create mode 100644 web/vendor/bootstrap-icons/filetype-jsx.svg create mode 100644 web/vendor/bootstrap-icons/filetype-key.svg create mode 100644 web/vendor/bootstrap-icons/filetype-m4p.svg create mode 100644 web/vendor/bootstrap-icons/filetype-md.svg create mode 100644 web/vendor/bootstrap-icons/filetype-mdx.svg create mode 100644 web/vendor/bootstrap-icons/filetype-mov.svg create mode 100644 web/vendor/bootstrap-icons/filetype-mp3.svg create mode 100644 web/vendor/bootstrap-icons/filetype-mp4.svg create mode 100644 web/vendor/bootstrap-icons/filetype-otf.svg create mode 100644 web/vendor/bootstrap-icons/filetype-pdf.svg create mode 100644 web/vendor/bootstrap-icons/filetype-php.svg create mode 100644 web/vendor/bootstrap-icons/filetype-png.svg create mode 100644 web/vendor/bootstrap-icons/filetype-ppt.svg create mode 100644 web/vendor/bootstrap-icons/filetype-pptx.svg create mode 100644 web/vendor/bootstrap-icons/filetype-psd.svg create mode 100644 web/vendor/bootstrap-icons/filetype-py.svg create mode 100644 web/vendor/bootstrap-icons/filetype-raw.svg create mode 100644 web/vendor/bootstrap-icons/filetype-rb.svg create mode 100644 web/vendor/bootstrap-icons/filetype-sass.svg create mode 100644 web/vendor/bootstrap-icons/filetype-scss.svg create mode 100644 web/vendor/bootstrap-icons/filetype-sh.svg create mode 100644 web/vendor/bootstrap-icons/filetype-sql.svg create mode 100644 web/vendor/bootstrap-icons/filetype-svg.svg create mode 100644 web/vendor/bootstrap-icons/filetype-tiff.svg create mode 100644 web/vendor/bootstrap-icons/filetype-tsx.svg create mode 100644 web/vendor/bootstrap-icons/filetype-ttf.svg create mode 100644 web/vendor/bootstrap-icons/filetype-txt.svg create mode 100644 web/vendor/bootstrap-icons/filetype-wav.svg create mode 100644 web/vendor/bootstrap-icons/filetype-woff.svg create mode 100644 web/vendor/bootstrap-icons/filetype-xls.svg create mode 100644 web/vendor/bootstrap-icons/filetype-xlsx.svg create mode 100644 web/vendor/bootstrap-icons/filetype-xml.svg create mode 100644 web/vendor/bootstrap-icons/filetype-yml.svg create mode 100644 web/vendor/bootstrap-icons/film.svg create mode 100644 web/vendor/bootstrap-icons/filter-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/filter-circle.svg create mode 100644 web/vendor/bootstrap-icons/filter-left.svg create mode 100644 web/vendor/bootstrap-icons/filter-right.svg create mode 100644 web/vendor/bootstrap-icons/filter-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/filter-square.svg create mode 100644 web/vendor/bootstrap-icons/filter.svg create mode 100644 web/vendor/bootstrap-icons/fingerprint.svg create mode 100644 web/vendor/bootstrap-icons/fire.svg create mode 100644 web/vendor/bootstrap-icons/flag-fill.svg create mode 100644 web/vendor/bootstrap-icons/flag.svg create mode 100644 web/vendor/bootstrap-icons/flask-fill.svg create mode 100644 web/vendor/bootstrap-icons/flask-florence-fill.svg create mode 100644 web/vendor/bootstrap-icons/flask-florence.svg create mode 100644 web/vendor/bootstrap-icons/flask.svg create mode 100644 web/vendor/bootstrap-icons/floppy-fill.svg create mode 100644 web/vendor/bootstrap-icons/floppy.svg create mode 100644 web/vendor/bootstrap-icons/floppy2-fill.svg create mode 100644 web/vendor/bootstrap-icons/floppy2.svg create mode 100644 web/vendor/bootstrap-icons/flower1.svg create mode 100644 web/vendor/bootstrap-icons/flower2.svg create mode 100644 web/vendor/bootstrap-icons/flower3.svg create mode 100644 web/vendor/bootstrap-icons/folder-check.svg create mode 100644 web/vendor/bootstrap-icons/folder-fill.svg create mode 100644 web/vendor/bootstrap-icons/folder-minus.svg create mode 100644 web/vendor/bootstrap-icons/folder-plus.svg create mode 100644 web/vendor/bootstrap-icons/folder-symlink-fill.svg create mode 100644 web/vendor/bootstrap-icons/folder-symlink.svg create mode 100644 web/vendor/bootstrap-icons/folder-x.svg create mode 100644 web/vendor/bootstrap-icons/folder.svg create mode 100644 web/vendor/bootstrap-icons/folder2-open.svg create mode 100644 web/vendor/bootstrap-icons/folder2.svg create mode 100644 web/vendor/bootstrap-icons/fonts.svg create mode 100644 web/vendor/bootstrap-icons/fonts/bootstrap-icons.woff create mode 100644 web/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2 create mode 100644 web/vendor/bootstrap-icons/fork-knife.svg create mode 100644 web/vendor/bootstrap-icons/forward-fill.svg create mode 100644 web/vendor/bootstrap-icons/forward.svg create mode 100644 web/vendor/bootstrap-icons/front.svg create mode 100644 web/vendor/bootstrap-icons/fuel-pump-diesel-fill.svg create mode 100644 web/vendor/bootstrap-icons/fuel-pump-diesel.svg create mode 100644 web/vendor/bootstrap-icons/fuel-pump-fill.svg create mode 100644 web/vendor/bootstrap-icons/fuel-pump.svg create mode 100644 web/vendor/bootstrap-icons/fullscreen-exit.svg create mode 100644 web/vendor/bootstrap-icons/fullscreen.svg create mode 100644 web/vendor/bootstrap-icons/funnel-fill.svg create mode 100644 web/vendor/bootstrap-icons/funnel.svg create mode 100644 web/vendor/bootstrap-icons/gear-fill.svg create mode 100644 web/vendor/bootstrap-icons/gear-wide-connected.svg create mode 100644 web/vendor/bootstrap-icons/gear-wide.svg create mode 100644 web/vendor/bootstrap-icons/gear.svg create mode 100644 web/vendor/bootstrap-icons/gem.svg create mode 100644 web/vendor/bootstrap-icons/gender-ambiguous.svg create mode 100644 web/vendor/bootstrap-icons/gender-female.svg create mode 100644 web/vendor/bootstrap-icons/gender-male.svg create mode 100644 web/vendor/bootstrap-icons/gender-neuter.svg create mode 100644 web/vendor/bootstrap-icons/gender-trans.svg create mode 100644 web/vendor/bootstrap-icons/geo-alt-fill.svg create mode 100644 web/vendor/bootstrap-icons/geo-alt.svg create mode 100644 web/vendor/bootstrap-icons/geo-fill.svg create mode 100644 web/vendor/bootstrap-icons/geo.svg create mode 100644 web/vendor/bootstrap-icons/gift-fill.svg create mode 100644 web/vendor/bootstrap-icons/gift.svg create mode 100644 web/vendor/bootstrap-icons/git.svg create mode 100644 web/vendor/bootstrap-icons/github.svg create mode 100644 web/vendor/bootstrap-icons/gitlab.svg create mode 100644 web/vendor/bootstrap-icons/globe-americas-fill.svg create mode 100644 web/vendor/bootstrap-icons/globe-americas.svg create mode 100644 web/vendor/bootstrap-icons/globe-asia-australia-fill.svg create mode 100644 web/vendor/bootstrap-icons/globe-asia-australia.svg create mode 100644 web/vendor/bootstrap-icons/globe-central-south-asia-fill.svg create mode 100644 web/vendor/bootstrap-icons/globe-central-south-asia.svg create mode 100644 web/vendor/bootstrap-icons/globe-europe-africa-fill.svg create mode 100644 web/vendor/bootstrap-icons/globe-europe-africa.svg create mode 100644 web/vendor/bootstrap-icons/globe.svg create mode 100644 web/vendor/bootstrap-icons/globe2.svg create mode 100644 web/vendor/bootstrap-icons/google-play.svg create mode 100644 web/vendor/bootstrap-icons/google.svg create mode 100644 web/vendor/bootstrap-icons/gpu-card.svg create mode 100644 web/vendor/bootstrap-icons/graph-down-arrow.svg create mode 100644 web/vendor/bootstrap-icons/graph-down.svg create mode 100644 web/vendor/bootstrap-icons/graph-up-arrow.svg create mode 100644 web/vendor/bootstrap-icons/graph-up.svg create mode 100644 web/vendor/bootstrap-icons/grid-1x2-fill.svg create mode 100644 web/vendor/bootstrap-icons/grid-1x2.svg create mode 100644 web/vendor/bootstrap-icons/grid-3x2-gap-fill.svg create mode 100644 web/vendor/bootstrap-icons/grid-3x2-gap.svg create mode 100644 web/vendor/bootstrap-icons/grid-3x2.svg create mode 100644 web/vendor/bootstrap-icons/grid-3x3-gap-fill.svg create mode 100644 web/vendor/bootstrap-icons/grid-3x3-gap.svg create mode 100644 web/vendor/bootstrap-icons/grid-3x3.svg create mode 100644 web/vendor/bootstrap-icons/grid-fill.svg create mode 100644 web/vendor/bootstrap-icons/grid.svg create mode 100644 web/vendor/bootstrap-icons/grip-horizontal.svg create mode 100644 web/vendor/bootstrap-icons/grip-vertical.svg create mode 100644 web/vendor/bootstrap-icons/h-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/h-circle.svg create mode 100644 web/vendor/bootstrap-icons/h-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/h-square.svg create mode 100644 web/vendor/bootstrap-icons/hammer.svg create mode 100644 web/vendor/bootstrap-icons/hand-index-fill.svg create mode 100644 web/vendor/bootstrap-icons/hand-index-thumb-fill.svg create mode 100644 web/vendor/bootstrap-icons/hand-index-thumb.svg create mode 100644 web/vendor/bootstrap-icons/hand-index.svg create mode 100644 web/vendor/bootstrap-icons/hand-thumbs-down-fill.svg create mode 100644 web/vendor/bootstrap-icons/hand-thumbs-down.svg create mode 100644 web/vendor/bootstrap-icons/hand-thumbs-up-fill.svg create mode 100644 web/vendor/bootstrap-icons/hand-thumbs-up.svg create mode 100644 web/vendor/bootstrap-icons/handbag-fill.svg create mode 100644 web/vendor/bootstrap-icons/handbag.svg create mode 100644 web/vendor/bootstrap-icons/hash.svg create mode 100644 web/vendor/bootstrap-icons/hdd-fill.svg create mode 100644 web/vendor/bootstrap-icons/hdd-network-fill.svg create mode 100644 web/vendor/bootstrap-icons/hdd-network.svg create mode 100644 web/vendor/bootstrap-icons/hdd-rack-fill.svg create mode 100644 web/vendor/bootstrap-icons/hdd-rack.svg create mode 100644 web/vendor/bootstrap-icons/hdd-stack-fill.svg create mode 100644 web/vendor/bootstrap-icons/hdd-stack.svg create mode 100644 web/vendor/bootstrap-icons/hdd.svg create mode 100644 web/vendor/bootstrap-icons/hdmi-fill.svg create mode 100644 web/vendor/bootstrap-icons/hdmi.svg create mode 100644 web/vendor/bootstrap-icons/headphones.svg create mode 100644 web/vendor/bootstrap-icons/headset-vr.svg create mode 100644 web/vendor/bootstrap-icons/headset.svg create mode 100644 web/vendor/bootstrap-icons/heart-arrow.svg create mode 100644 web/vendor/bootstrap-icons/heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/heart-half.svg create mode 100644 web/vendor/bootstrap-icons/heart-pulse-fill.svg create mode 100644 web/vendor/bootstrap-icons/heart-pulse.svg create mode 100644 web/vendor/bootstrap-icons/heart.svg create mode 100644 web/vendor/bootstrap-icons/heartbreak-fill.svg create mode 100644 web/vendor/bootstrap-icons/heartbreak.svg create mode 100644 web/vendor/bootstrap-icons/hearts.svg create mode 100644 web/vendor/bootstrap-icons/heptagon-fill.svg create mode 100644 web/vendor/bootstrap-icons/heptagon-half.svg create mode 100644 web/vendor/bootstrap-icons/heptagon.svg create mode 100644 web/vendor/bootstrap-icons/hexagon-fill.svg create mode 100644 web/vendor/bootstrap-icons/hexagon-half.svg create mode 100644 web/vendor/bootstrap-icons/hexagon.svg create mode 100644 web/vendor/bootstrap-icons/highlighter.svg create mode 100644 web/vendor/bootstrap-icons/highlights.svg create mode 100644 web/vendor/bootstrap-icons/hospital-fill.svg create mode 100644 web/vendor/bootstrap-icons/hospital.svg create mode 100644 web/vendor/bootstrap-icons/hourglass-bottom.svg create mode 100644 web/vendor/bootstrap-icons/hourglass-split.svg create mode 100644 web/vendor/bootstrap-icons/hourglass-top.svg create mode 100644 web/vendor/bootstrap-icons/hourglass.svg create mode 100644 web/vendor/bootstrap-icons/house-add-fill.svg create mode 100644 web/vendor/bootstrap-icons/house-add.svg create mode 100644 web/vendor/bootstrap-icons/house-check-fill.svg create mode 100644 web/vendor/bootstrap-icons/house-check.svg create mode 100644 web/vendor/bootstrap-icons/house-dash-fill.svg create mode 100644 web/vendor/bootstrap-icons/house-dash.svg create mode 100644 web/vendor/bootstrap-icons/house-door-fill.svg create mode 100644 web/vendor/bootstrap-icons/house-door.svg create mode 100644 web/vendor/bootstrap-icons/house-down-fill.svg create mode 100644 web/vendor/bootstrap-icons/house-down.svg create mode 100644 web/vendor/bootstrap-icons/house-exclamation-fill.svg create mode 100644 web/vendor/bootstrap-icons/house-exclamation.svg create mode 100644 web/vendor/bootstrap-icons/house-fill.svg create mode 100644 web/vendor/bootstrap-icons/house-gear-fill.svg create mode 100644 web/vendor/bootstrap-icons/house-gear.svg create mode 100644 web/vendor/bootstrap-icons/house-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/house-heart.svg create mode 100644 web/vendor/bootstrap-icons/house-lock-fill.svg create mode 100644 web/vendor/bootstrap-icons/house-lock.svg create mode 100644 web/vendor/bootstrap-icons/house-slash-fill.svg create mode 100644 web/vendor/bootstrap-icons/house-slash.svg create mode 100644 web/vendor/bootstrap-icons/house-up-fill.svg create mode 100644 web/vendor/bootstrap-icons/house-up.svg create mode 100644 web/vendor/bootstrap-icons/house-x-fill.svg create mode 100644 web/vendor/bootstrap-icons/house-x.svg create mode 100644 web/vendor/bootstrap-icons/house.svg create mode 100644 web/vendor/bootstrap-icons/houses-fill.svg create mode 100644 web/vendor/bootstrap-icons/houses.svg create mode 100644 web/vendor/bootstrap-icons/hr.svg create mode 100644 web/vendor/bootstrap-icons/hurricane.svg create mode 100644 web/vendor/bootstrap-icons/hypnotize.svg create mode 100644 web/vendor/bootstrap-icons/image-alt.svg create mode 100644 web/vendor/bootstrap-icons/image-fill.svg create mode 100644 web/vendor/bootstrap-icons/image.svg create mode 100644 web/vendor/bootstrap-icons/images.svg create mode 100644 web/vendor/bootstrap-icons/inbox-fill.svg create mode 100644 web/vendor/bootstrap-icons/inbox.svg create mode 100644 web/vendor/bootstrap-icons/inboxes-fill.svg create mode 100644 web/vendor/bootstrap-icons/inboxes.svg create mode 100644 web/vendor/bootstrap-icons/incognito.svg create mode 100644 web/vendor/bootstrap-icons/indent.svg create mode 100644 web/vendor/bootstrap-icons/infinity.svg create mode 100644 web/vendor/bootstrap-icons/info-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/info-circle.svg create mode 100644 web/vendor/bootstrap-icons/info-lg.svg create mode 100644 web/vendor/bootstrap-icons/info-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/info-square.svg create mode 100644 web/vendor/bootstrap-icons/info.svg create mode 100644 web/vendor/bootstrap-icons/input-cursor-text.svg create mode 100644 web/vendor/bootstrap-icons/input-cursor.svg create mode 100644 web/vendor/bootstrap-icons/instagram.svg create mode 100644 web/vendor/bootstrap-icons/intersect.svg create mode 100644 web/vendor/bootstrap-icons/javascript.svg create mode 100644 web/vendor/bootstrap-icons/journal-album.svg create mode 100644 web/vendor/bootstrap-icons/journal-arrow-down.svg create mode 100644 web/vendor/bootstrap-icons/journal-arrow-up.svg create mode 100644 web/vendor/bootstrap-icons/journal-bookmark-fill.svg create mode 100644 web/vendor/bootstrap-icons/journal-bookmark.svg create mode 100644 web/vendor/bootstrap-icons/journal-check.svg create mode 100644 web/vendor/bootstrap-icons/journal-code.svg create mode 100644 web/vendor/bootstrap-icons/journal-medical.svg create mode 100644 web/vendor/bootstrap-icons/journal-minus.svg create mode 100644 web/vendor/bootstrap-icons/journal-plus.svg create mode 100644 web/vendor/bootstrap-icons/journal-richtext.svg create mode 100644 web/vendor/bootstrap-icons/journal-text.svg create mode 100644 web/vendor/bootstrap-icons/journal-x.svg create mode 100644 web/vendor/bootstrap-icons/journal.svg create mode 100644 web/vendor/bootstrap-icons/journals.svg create mode 100644 web/vendor/bootstrap-icons/joystick.svg create mode 100644 web/vendor/bootstrap-icons/justify-left.svg create mode 100644 web/vendor/bootstrap-icons/justify-right.svg create mode 100644 web/vendor/bootstrap-icons/justify.svg create mode 100644 web/vendor/bootstrap-icons/kanban-fill.svg create mode 100644 web/vendor/bootstrap-icons/kanban.svg create mode 100644 web/vendor/bootstrap-icons/key-fill.svg create mode 100644 web/vendor/bootstrap-icons/key.svg create mode 100644 web/vendor/bootstrap-icons/keyboard-fill.svg create mode 100644 web/vendor/bootstrap-icons/keyboard.svg create mode 100644 web/vendor/bootstrap-icons/ladder.svg create mode 100644 web/vendor/bootstrap-icons/lamp-fill.svg create mode 100644 web/vendor/bootstrap-icons/lamp.svg create mode 100644 web/vendor/bootstrap-icons/laptop-fill.svg create mode 100644 web/vendor/bootstrap-icons/laptop.svg create mode 100644 web/vendor/bootstrap-icons/layer-backward.svg create mode 100644 web/vendor/bootstrap-icons/layer-forward.svg create mode 100644 web/vendor/bootstrap-icons/layers-fill.svg create mode 100644 web/vendor/bootstrap-icons/layers-half.svg create mode 100644 web/vendor/bootstrap-icons/layers.svg create mode 100644 web/vendor/bootstrap-icons/layout-sidebar-inset-reverse.svg create mode 100644 web/vendor/bootstrap-icons/layout-sidebar-inset.svg create mode 100644 web/vendor/bootstrap-icons/layout-sidebar-reverse.svg create mode 100644 web/vendor/bootstrap-icons/layout-sidebar.svg create mode 100644 web/vendor/bootstrap-icons/layout-split.svg create mode 100644 web/vendor/bootstrap-icons/layout-text-sidebar-reverse.svg create mode 100644 web/vendor/bootstrap-icons/layout-text-sidebar.svg create mode 100644 web/vendor/bootstrap-icons/layout-text-window-reverse.svg create mode 100644 web/vendor/bootstrap-icons/layout-text-window.svg create mode 100644 web/vendor/bootstrap-icons/layout-three-columns.svg create mode 100644 web/vendor/bootstrap-icons/layout-wtf.svg create mode 100644 web/vendor/bootstrap-icons/leaf-fill.svg create mode 100644 web/vendor/bootstrap-icons/leaf.svg create mode 100644 web/vendor/bootstrap-icons/life-preserver.svg create mode 100644 web/vendor/bootstrap-icons/lightbulb-fill.svg create mode 100644 web/vendor/bootstrap-icons/lightbulb-off-fill.svg create mode 100644 web/vendor/bootstrap-icons/lightbulb-off.svg create mode 100644 web/vendor/bootstrap-icons/lightbulb.svg create mode 100644 web/vendor/bootstrap-icons/lightning-charge-fill.svg create mode 100644 web/vendor/bootstrap-icons/lightning-charge.svg create mode 100644 web/vendor/bootstrap-icons/lightning-fill.svg create mode 100644 web/vendor/bootstrap-icons/lightning.svg create mode 100644 web/vendor/bootstrap-icons/line.svg create mode 100644 web/vendor/bootstrap-icons/link-45deg.svg create mode 100644 web/vendor/bootstrap-icons/link.svg create mode 100644 web/vendor/bootstrap-icons/linkedin.svg create mode 100644 web/vendor/bootstrap-icons/list-check.svg create mode 100644 web/vendor/bootstrap-icons/list-columns-reverse.svg create mode 100644 web/vendor/bootstrap-icons/list-columns.svg create mode 100644 web/vendor/bootstrap-icons/list-nested.svg create mode 100644 web/vendor/bootstrap-icons/list-ol.svg create mode 100644 web/vendor/bootstrap-icons/list-stars.svg create mode 100644 web/vendor/bootstrap-icons/list-task.svg create mode 100644 web/vendor/bootstrap-icons/list-ul.svg create mode 100644 web/vendor/bootstrap-icons/list.svg create mode 100644 web/vendor/bootstrap-icons/lock-fill.svg create mode 100644 web/vendor/bootstrap-icons/lock.svg create mode 100644 web/vendor/bootstrap-icons/luggage-fill.svg create mode 100644 web/vendor/bootstrap-icons/luggage.svg create mode 100644 web/vendor/bootstrap-icons/lungs-fill.svg create mode 100644 web/vendor/bootstrap-icons/lungs.svg create mode 100644 web/vendor/bootstrap-icons/magic.svg create mode 100644 web/vendor/bootstrap-icons/magnet-fill.svg create mode 100644 web/vendor/bootstrap-icons/magnet.svg create mode 100644 web/vendor/bootstrap-icons/mailbox-flag.svg create mode 100644 web/vendor/bootstrap-icons/mailbox.svg create mode 100644 web/vendor/bootstrap-icons/mailbox2-flag.svg create mode 100644 web/vendor/bootstrap-icons/mailbox2.svg create mode 100644 web/vendor/bootstrap-icons/map-fill.svg create mode 100644 web/vendor/bootstrap-icons/map.svg create mode 100644 web/vendor/bootstrap-icons/markdown-fill.svg create mode 100644 web/vendor/bootstrap-icons/markdown.svg create mode 100644 web/vendor/bootstrap-icons/marker-tip.svg create mode 100644 web/vendor/bootstrap-icons/mask.svg create mode 100644 web/vendor/bootstrap-icons/mastodon.svg create mode 100644 web/vendor/bootstrap-icons/measuring-cup-fill.svg create mode 100644 web/vendor/bootstrap-icons/measuring-cup.svg create mode 100644 web/vendor/bootstrap-icons/medium.svg create mode 100644 web/vendor/bootstrap-icons/megaphone-fill.svg create mode 100644 web/vendor/bootstrap-icons/megaphone.svg create mode 100644 web/vendor/bootstrap-icons/memory.svg create mode 100644 web/vendor/bootstrap-icons/menu-app-fill.svg create mode 100644 web/vendor/bootstrap-icons/menu-app.svg create mode 100644 web/vendor/bootstrap-icons/menu-button-fill.svg create mode 100644 web/vendor/bootstrap-icons/menu-button-wide-fill.svg create mode 100644 web/vendor/bootstrap-icons/menu-button-wide.svg create mode 100644 web/vendor/bootstrap-icons/menu-button.svg create mode 100644 web/vendor/bootstrap-icons/menu-down.svg create mode 100644 web/vendor/bootstrap-icons/menu-up.svg create mode 100644 web/vendor/bootstrap-icons/messenger.svg create mode 100644 web/vendor/bootstrap-icons/meta.svg create mode 100644 web/vendor/bootstrap-icons/mic-fill.svg create mode 100644 web/vendor/bootstrap-icons/mic-mute-fill.svg create mode 100644 web/vendor/bootstrap-icons/mic-mute.svg create mode 100644 web/vendor/bootstrap-icons/mic.svg create mode 100644 web/vendor/bootstrap-icons/microsoft-teams.svg create mode 100644 web/vendor/bootstrap-icons/microsoft.svg create mode 100644 web/vendor/bootstrap-icons/minecart-loaded.svg create mode 100644 web/vendor/bootstrap-icons/minecart.svg create mode 100644 web/vendor/bootstrap-icons/modem-fill.svg create mode 100644 web/vendor/bootstrap-icons/modem.svg create mode 100644 web/vendor/bootstrap-icons/moisture.svg create mode 100644 web/vendor/bootstrap-icons/moon-fill.svg create mode 100644 web/vendor/bootstrap-icons/moon-stars-fill.svg create mode 100644 web/vendor/bootstrap-icons/moon-stars.svg create mode 100644 web/vendor/bootstrap-icons/moon.svg create mode 100644 web/vendor/bootstrap-icons/mortarboard-fill.svg create mode 100644 web/vendor/bootstrap-icons/mortarboard.svg create mode 100644 web/vendor/bootstrap-icons/motherboard-fill.svg create mode 100644 web/vendor/bootstrap-icons/motherboard.svg create mode 100644 web/vendor/bootstrap-icons/mouse-fill.svg create mode 100644 web/vendor/bootstrap-icons/mouse.svg create mode 100644 web/vendor/bootstrap-icons/mouse2-fill.svg create mode 100644 web/vendor/bootstrap-icons/mouse2.svg create mode 100644 web/vendor/bootstrap-icons/mouse3-fill.svg create mode 100644 web/vendor/bootstrap-icons/mouse3.svg create mode 100644 web/vendor/bootstrap-icons/music-note-beamed.svg create mode 100644 web/vendor/bootstrap-icons/music-note-list.svg create mode 100644 web/vendor/bootstrap-icons/music-note.svg create mode 100644 web/vendor/bootstrap-icons/music-player-fill.svg create mode 100644 web/vendor/bootstrap-icons/music-player.svg create mode 100644 web/vendor/bootstrap-icons/newspaper.svg create mode 100644 web/vendor/bootstrap-icons/nintendo-switch.svg create mode 100644 web/vendor/bootstrap-icons/node-minus-fill.svg create mode 100644 web/vendor/bootstrap-icons/node-minus.svg create mode 100644 web/vendor/bootstrap-icons/node-plus-fill.svg create mode 100644 web/vendor/bootstrap-icons/node-plus.svg create mode 100644 web/vendor/bootstrap-icons/noise-reduction.svg create mode 100644 web/vendor/bootstrap-icons/nut-fill.svg create mode 100644 web/vendor/bootstrap-icons/nut.svg create mode 100644 web/vendor/bootstrap-icons/nvidia.svg create mode 100644 web/vendor/bootstrap-icons/nvme-fill.svg create mode 100644 web/vendor/bootstrap-icons/nvme.svg create mode 100644 web/vendor/bootstrap-icons/octagon-fill.svg create mode 100644 web/vendor/bootstrap-icons/octagon-half.svg create mode 100644 web/vendor/bootstrap-icons/octagon.svg create mode 100644 web/vendor/bootstrap-icons/openai.svg create mode 100644 web/vendor/bootstrap-icons/opencollective.svg create mode 100644 web/vendor/bootstrap-icons/optical-audio-fill.svg create mode 100644 web/vendor/bootstrap-icons/optical-audio.svg create mode 100644 web/vendor/bootstrap-icons/option.svg create mode 100644 web/vendor/bootstrap-icons/outlet.svg create mode 100644 web/vendor/bootstrap-icons/p-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/p-circle.svg create mode 100644 web/vendor/bootstrap-icons/p-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/p-square.svg create mode 100644 web/vendor/bootstrap-icons/paint-bucket.svg create mode 100644 web/vendor/bootstrap-icons/palette-fill.svg create mode 100644 web/vendor/bootstrap-icons/palette.svg create mode 100644 web/vendor/bootstrap-icons/palette2.svg create mode 100644 web/vendor/bootstrap-icons/paperclip.svg create mode 100644 web/vendor/bootstrap-icons/paragraph.svg create mode 100644 web/vendor/bootstrap-icons/pass-fill.svg create mode 100644 web/vendor/bootstrap-icons/pass.svg create mode 100644 web/vendor/bootstrap-icons/passport-fill.svg create mode 100644 web/vendor/bootstrap-icons/passport.svg create mode 100644 web/vendor/bootstrap-icons/patch-check-fill.svg create mode 100644 web/vendor/bootstrap-icons/patch-check.svg create mode 100644 web/vendor/bootstrap-icons/patch-exclamation-fill.svg create mode 100644 web/vendor/bootstrap-icons/patch-exclamation.svg create mode 100644 web/vendor/bootstrap-icons/patch-minus-fill.svg create mode 100644 web/vendor/bootstrap-icons/patch-minus.svg create mode 100644 web/vendor/bootstrap-icons/patch-plus-fill.svg create mode 100644 web/vendor/bootstrap-icons/patch-plus.svg create mode 100644 web/vendor/bootstrap-icons/patch-question-fill.svg create mode 100644 web/vendor/bootstrap-icons/patch-question.svg create mode 100644 web/vendor/bootstrap-icons/pause-btn-fill.svg create mode 100644 web/vendor/bootstrap-icons/pause-btn.svg create mode 100644 web/vendor/bootstrap-icons/pause-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/pause-circle.svg create mode 100644 web/vendor/bootstrap-icons/pause-fill.svg create mode 100644 web/vendor/bootstrap-icons/pause.svg create mode 100644 web/vendor/bootstrap-icons/paypal.svg create mode 100644 web/vendor/bootstrap-icons/pc-display-horizontal.svg create mode 100644 web/vendor/bootstrap-icons/pc-display.svg create mode 100644 web/vendor/bootstrap-icons/pc-horizontal.svg create mode 100644 web/vendor/bootstrap-icons/pc.svg create mode 100644 web/vendor/bootstrap-icons/pci-card-network.svg create mode 100644 web/vendor/bootstrap-icons/pci-card-sound.svg create mode 100644 web/vendor/bootstrap-icons/pci-card.svg create mode 100644 web/vendor/bootstrap-icons/peace-fill.svg create mode 100644 web/vendor/bootstrap-icons/peace.svg create mode 100644 web/vendor/bootstrap-icons/pen-fill.svg create mode 100644 web/vendor/bootstrap-icons/pen.svg create mode 100644 web/vendor/bootstrap-icons/pencil-fill.svg create mode 100644 web/vendor/bootstrap-icons/pencil-square.svg create mode 100644 web/vendor/bootstrap-icons/pencil.svg create mode 100644 web/vendor/bootstrap-icons/pentagon-fill.svg create mode 100644 web/vendor/bootstrap-icons/pentagon-half.svg create mode 100644 web/vendor/bootstrap-icons/pentagon.svg create mode 100644 web/vendor/bootstrap-icons/people-fill.svg create mode 100644 web/vendor/bootstrap-icons/people.svg create mode 100644 web/vendor/bootstrap-icons/percent.svg create mode 100644 web/vendor/bootstrap-icons/perplexity.svg create mode 100644 web/vendor/bootstrap-icons/person-add.svg create mode 100644 web/vendor/bootstrap-icons/person-arms-up.svg create mode 100644 web/vendor/bootstrap-icons/person-badge-fill.svg create mode 100644 web/vendor/bootstrap-icons/person-badge.svg create mode 100644 web/vendor/bootstrap-icons/person-bounding-box.svg create mode 100644 web/vendor/bootstrap-icons/person-check-fill.svg create mode 100644 web/vendor/bootstrap-icons/person-check.svg create mode 100644 web/vendor/bootstrap-icons/person-circle.svg create mode 100644 web/vendor/bootstrap-icons/person-dash-fill.svg create mode 100644 web/vendor/bootstrap-icons/person-dash.svg create mode 100644 web/vendor/bootstrap-icons/person-down.svg create mode 100644 web/vendor/bootstrap-icons/person-exclamation.svg create mode 100644 web/vendor/bootstrap-icons/person-fill-add.svg create mode 100644 web/vendor/bootstrap-icons/person-fill-check.svg create mode 100644 web/vendor/bootstrap-icons/person-fill-dash.svg create mode 100644 web/vendor/bootstrap-icons/person-fill-down.svg create mode 100644 web/vendor/bootstrap-icons/person-fill-exclamation.svg create mode 100644 web/vendor/bootstrap-icons/person-fill-gear.svg create mode 100644 web/vendor/bootstrap-icons/person-fill-lock.svg create mode 100644 web/vendor/bootstrap-icons/person-fill-slash.svg create mode 100644 web/vendor/bootstrap-icons/person-fill-up.svg create mode 100644 web/vendor/bootstrap-icons/person-fill-x.svg create mode 100644 web/vendor/bootstrap-icons/person-fill.svg create mode 100644 web/vendor/bootstrap-icons/person-gear.svg create mode 100644 web/vendor/bootstrap-icons/person-heart.svg create mode 100644 web/vendor/bootstrap-icons/person-hearts.svg create mode 100644 web/vendor/bootstrap-icons/person-lines-fill.svg create mode 100644 web/vendor/bootstrap-icons/person-lock.svg create mode 100644 web/vendor/bootstrap-icons/person-plus-fill.svg create mode 100644 web/vendor/bootstrap-icons/person-plus.svg create mode 100644 web/vendor/bootstrap-icons/person-raised-hand.svg create mode 100644 web/vendor/bootstrap-icons/person-rolodex.svg create mode 100644 web/vendor/bootstrap-icons/person-slash.svg create mode 100644 web/vendor/bootstrap-icons/person-square.svg create mode 100644 web/vendor/bootstrap-icons/person-standing-dress.svg create mode 100644 web/vendor/bootstrap-icons/person-standing.svg create mode 100644 web/vendor/bootstrap-icons/person-up.svg create mode 100644 web/vendor/bootstrap-icons/person-vcard-fill.svg create mode 100644 web/vendor/bootstrap-icons/person-vcard.svg create mode 100644 web/vendor/bootstrap-icons/person-video.svg create mode 100644 web/vendor/bootstrap-icons/person-video2.svg create mode 100644 web/vendor/bootstrap-icons/person-video3.svg create mode 100644 web/vendor/bootstrap-icons/person-walking.svg create mode 100644 web/vendor/bootstrap-icons/person-wheelchair.svg create mode 100644 web/vendor/bootstrap-icons/person-workspace.svg create mode 100644 web/vendor/bootstrap-icons/person-x-fill.svg create mode 100644 web/vendor/bootstrap-icons/person-x.svg create mode 100644 web/vendor/bootstrap-icons/person.svg create mode 100644 web/vendor/bootstrap-icons/phone-fill.svg create mode 100644 web/vendor/bootstrap-icons/phone-flip.svg create mode 100644 web/vendor/bootstrap-icons/phone-landscape-fill.svg create mode 100644 web/vendor/bootstrap-icons/phone-landscape.svg create mode 100644 web/vendor/bootstrap-icons/phone-vibrate-fill.svg create mode 100644 web/vendor/bootstrap-icons/phone-vibrate.svg create mode 100644 web/vendor/bootstrap-icons/phone.svg create mode 100644 web/vendor/bootstrap-icons/pie-chart-fill.svg create mode 100644 web/vendor/bootstrap-icons/pie-chart.svg create mode 100644 web/vendor/bootstrap-icons/piggy-bank-fill.svg create mode 100644 web/vendor/bootstrap-icons/piggy-bank.svg create mode 100644 web/vendor/bootstrap-icons/pin-angle-fill.svg create mode 100644 web/vendor/bootstrap-icons/pin-angle.svg create mode 100644 web/vendor/bootstrap-icons/pin-fill.svg create mode 100644 web/vendor/bootstrap-icons/pin-map-fill.svg create mode 100644 web/vendor/bootstrap-icons/pin-map.svg create mode 100644 web/vendor/bootstrap-icons/pin.svg create mode 100644 web/vendor/bootstrap-icons/pinterest.svg create mode 100644 web/vendor/bootstrap-icons/pip-fill.svg create mode 100644 web/vendor/bootstrap-icons/pip.svg create mode 100644 web/vendor/bootstrap-icons/play-btn-fill.svg create mode 100644 web/vendor/bootstrap-icons/play-btn.svg create mode 100644 web/vendor/bootstrap-icons/play-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/play-circle.svg create mode 100644 web/vendor/bootstrap-icons/play-fill.svg create mode 100644 web/vendor/bootstrap-icons/play.svg create mode 100644 web/vendor/bootstrap-icons/playstation.svg create mode 100644 web/vendor/bootstrap-icons/plug-fill.svg create mode 100644 web/vendor/bootstrap-icons/plug.svg create mode 100644 web/vendor/bootstrap-icons/plugin.svg create mode 100644 web/vendor/bootstrap-icons/plus-circle-dotted.svg create mode 100644 web/vendor/bootstrap-icons/plus-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/plus-circle.svg create mode 100644 web/vendor/bootstrap-icons/plus-lg.svg create mode 100644 web/vendor/bootstrap-icons/plus-slash-minus.svg create mode 100644 web/vendor/bootstrap-icons/plus-square-dotted.svg create mode 100644 web/vendor/bootstrap-icons/plus-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/plus-square.svg create mode 100644 web/vendor/bootstrap-icons/plus.svg create mode 100644 web/vendor/bootstrap-icons/postage-fill.svg create mode 100644 web/vendor/bootstrap-icons/postage-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/postage-heart.svg create mode 100644 web/vendor/bootstrap-icons/postage.svg create mode 100644 web/vendor/bootstrap-icons/postcard-fill.svg create mode 100644 web/vendor/bootstrap-icons/postcard-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/postcard-heart.svg create mode 100644 web/vendor/bootstrap-icons/postcard.svg create mode 100644 web/vendor/bootstrap-icons/power.svg create mode 100644 web/vendor/bootstrap-icons/prescription.svg create mode 100644 web/vendor/bootstrap-icons/prescription2.svg create mode 100644 web/vendor/bootstrap-icons/printer-fill.svg create mode 100644 web/vendor/bootstrap-icons/printer.svg create mode 100644 web/vendor/bootstrap-icons/projector-fill.svg create mode 100644 web/vendor/bootstrap-icons/projector.svg create mode 100644 web/vendor/bootstrap-icons/puzzle-fill.svg create mode 100644 web/vendor/bootstrap-icons/puzzle.svg create mode 100644 web/vendor/bootstrap-icons/qr-code-scan.svg create mode 100644 web/vendor/bootstrap-icons/qr-code.svg create mode 100644 web/vendor/bootstrap-icons/question-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/question-circle.svg create mode 100644 web/vendor/bootstrap-icons/question-diamond-fill.svg create mode 100644 web/vendor/bootstrap-icons/question-diamond.svg create mode 100644 web/vendor/bootstrap-icons/question-lg.svg create mode 100644 web/vendor/bootstrap-icons/question-octagon-fill.svg create mode 100644 web/vendor/bootstrap-icons/question-octagon.svg create mode 100644 web/vendor/bootstrap-icons/question-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/question-square.svg create mode 100644 web/vendor/bootstrap-icons/question.svg create mode 100644 web/vendor/bootstrap-icons/quora.svg create mode 100644 web/vendor/bootstrap-icons/quote.svg create mode 100644 web/vendor/bootstrap-icons/r-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/r-circle.svg create mode 100644 web/vendor/bootstrap-icons/r-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/r-square.svg create mode 100644 web/vendor/bootstrap-icons/radar.svg create mode 100644 web/vendor/bootstrap-icons/radioactive.svg create mode 100644 web/vendor/bootstrap-icons/rainbow.svg create mode 100644 web/vendor/bootstrap-icons/receipt-cutoff.svg create mode 100644 web/vendor/bootstrap-icons/receipt.svg create mode 100644 web/vendor/bootstrap-icons/reception-0.svg create mode 100644 web/vendor/bootstrap-icons/reception-1.svg create mode 100644 web/vendor/bootstrap-icons/reception-2.svg create mode 100644 web/vendor/bootstrap-icons/reception-3.svg create mode 100644 web/vendor/bootstrap-icons/reception-4.svg create mode 100644 web/vendor/bootstrap-icons/record-btn-fill.svg create mode 100644 web/vendor/bootstrap-icons/record-btn.svg create mode 100644 web/vendor/bootstrap-icons/record-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/record-circle.svg create mode 100644 web/vendor/bootstrap-icons/record-fill.svg create mode 100644 web/vendor/bootstrap-icons/record.svg create mode 100644 web/vendor/bootstrap-icons/record2-fill.svg create mode 100644 web/vendor/bootstrap-icons/record2.svg create mode 100644 web/vendor/bootstrap-icons/recycle.svg create mode 100644 web/vendor/bootstrap-icons/reddit.svg create mode 100644 web/vendor/bootstrap-icons/regex.svg create mode 100644 web/vendor/bootstrap-icons/repeat-1.svg create mode 100644 web/vendor/bootstrap-icons/repeat.svg create mode 100644 web/vendor/bootstrap-icons/reply-all-fill.svg create mode 100644 web/vendor/bootstrap-icons/reply-all.svg create mode 100644 web/vendor/bootstrap-icons/reply-fill.svg create mode 100644 web/vendor/bootstrap-icons/reply.svg create mode 100644 web/vendor/bootstrap-icons/rewind-btn-fill.svg create mode 100644 web/vendor/bootstrap-icons/rewind-btn.svg create mode 100644 web/vendor/bootstrap-icons/rewind-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/rewind-circle.svg create mode 100644 web/vendor/bootstrap-icons/rewind-fill.svg create mode 100644 web/vendor/bootstrap-icons/rewind.svg create mode 100644 web/vendor/bootstrap-icons/robot.svg create mode 100644 web/vendor/bootstrap-icons/rocket-fill.svg create mode 100644 web/vendor/bootstrap-icons/rocket-takeoff-fill.svg create mode 100644 web/vendor/bootstrap-icons/rocket-takeoff.svg create mode 100644 web/vendor/bootstrap-icons/rocket.svg create mode 100644 web/vendor/bootstrap-icons/router-fill.svg create mode 100644 web/vendor/bootstrap-icons/router.svg create mode 100644 web/vendor/bootstrap-icons/rss-fill.svg create mode 100644 web/vendor/bootstrap-icons/rss.svg create mode 100644 web/vendor/bootstrap-icons/rulers.svg create mode 100644 web/vendor/bootstrap-icons/safe-fill.svg create mode 100644 web/vendor/bootstrap-icons/safe.svg create mode 100644 web/vendor/bootstrap-icons/safe2-fill.svg create mode 100644 web/vendor/bootstrap-icons/safe2.svg create mode 100644 web/vendor/bootstrap-icons/save-fill.svg create mode 100644 web/vendor/bootstrap-icons/save.svg create mode 100644 web/vendor/bootstrap-icons/save2-fill.svg create mode 100644 web/vendor/bootstrap-icons/save2.svg create mode 100644 web/vendor/bootstrap-icons/scissors.svg create mode 100644 web/vendor/bootstrap-icons/scooter.svg create mode 100644 web/vendor/bootstrap-icons/screwdriver.svg create mode 100644 web/vendor/bootstrap-icons/sd-card-fill.svg create mode 100644 web/vendor/bootstrap-icons/sd-card.svg create mode 100644 web/vendor/bootstrap-icons/search-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/search-heart.svg create mode 100644 web/vendor/bootstrap-icons/search.svg create mode 100644 web/vendor/bootstrap-icons/segmented-nav.svg create mode 100644 web/vendor/bootstrap-icons/send-arrow-down-fill.svg create mode 100644 web/vendor/bootstrap-icons/send-arrow-down.svg create mode 100644 web/vendor/bootstrap-icons/send-arrow-up-fill.svg create mode 100644 web/vendor/bootstrap-icons/send-arrow-up.svg create mode 100644 web/vendor/bootstrap-icons/send-check-fill.svg create mode 100644 web/vendor/bootstrap-icons/send-check.svg create mode 100644 web/vendor/bootstrap-icons/send-dash-fill.svg create mode 100644 web/vendor/bootstrap-icons/send-dash.svg create mode 100644 web/vendor/bootstrap-icons/send-exclamation-fill.svg create mode 100644 web/vendor/bootstrap-icons/send-exclamation.svg create mode 100644 web/vendor/bootstrap-icons/send-fill.svg create mode 100644 web/vendor/bootstrap-icons/send-plus-fill.svg create mode 100644 web/vendor/bootstrap-icons/send-plus.svg create mode 100644 web/vendor/bootstrap-icons/send-slash-fill.svg create mode 100644 web/vendor/bootstrap-icons/send-slash.svg create mode 100644 web/vendor/bootstrap-icons/send-x-fill.svg create mode 100644 web/vendor/bootstrap-icons/send-x.svg create mode 100644 web/vendor/bootstrap-icons/send.svg create mode 100644 web/vendor/bootstrap-icons/server.svg create mode 100644 web/vendor/bootstrap-icons/shadows.svg create mode 100644 web/vendor/bootstrap-icons/share-fill.svg create mode 100644 web/vendor/bootstrap-icons/share.svg create mode 100644 web/vendor/bootstrap-icons/shield-check.svg create mode 100644 web/vendor/bootstrap-icons/shield-exclamation.svg create mode 100644 web/vendor/bootstrap-icons/shield-fill-check.svg create mode 100644 web/vendor/bootstrap-icons/shield-fill-exclamation.svg create mode 100644 web/vendor/bootstrap-icons/shield-fill-minus.svg create mode 100644 web/vendor/bootstrap-icons/shield-fill-plus.svg create mode 100644 web/vendor/bootstrap-icons/shield-fill-x.svg create mode 100644 web/vendor/bootstrap-icons/shield-fill.svg create mode 100644 web/vendor/bootstrap-icons/shield-lock-fill.svg create mode 100644 web/vendor/bootstrap-icons/shield-lock.svg create mode 100644 web/vendor/bootstrap-icons/shield-minus.svg create mode 100644 web/vendor/bootstrap-icons/shield-plus.svg create mode 100644 web/vendor/bootstrap-icons/shield-shaded.svg create mode 100644 web/vendor/bootstrap-icons/shield-slash-fill.svg create mode 100644 web/vendor/bootstrap-icons/shield-slash.svg create mode 100644 web/vendor/bootstrap-icons/shield-x.svg create mode 100644 web/vendor/bootstrap-icons/shield.svg create mode 100644 web/vendor/bootstrap-icons/shift-fill.svg create mode 100644 web/vendor/bootstrap-icons/shift.svg create mode 100644 web/vendor/bootstrap-icons/shop-window.svg create mode 100644 web/vendor/bootstrap-icons/shop.svg create mode 100644 web/vendor/bootstrap-icons/shuffle.svg create mode 100644 web/vendor/bootstrap-icons/sign-dead-end-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-dead-end.svg create mode 100644 web/vendor/bootstrap-icons/sign-do-not-enter-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-do-not-enter.svg create mode 100644 web/vendor/bootstrap-icons/sign-intersection-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-intersection-side-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-intersection-side.svg create mode 100644 web/vendor/bootstrap-icons/sign-intersection-t-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-intersection-t.svg create mode 100644 web/vendor/bootstrap-icons/sign-intersection-y-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-intersection-y.svg create mode 100644 web/vendor/bootstrap-icons/sign-intersection.svg create mode 100644 web/vendor/bootstrap-icons/sign-merge-left-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-merge-left.svg create mode 100644 web/vendor/bootstrap-icons/sign-merge-right-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-merge-right.svg create mode 100644 web/vendor/bootstrap-icons/sign-no-left-turn-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-no-left-turn.svg create mode 100644 web/vendor/bootstrap-icons/sign-no-parking-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-no-parking.svg create mode 100644 web/vendor/bootstrap-icons/sign-no-right-turn-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-no-right-turn.svg create mode 100644 web/vendor/bootstrap-icons/sign-railroad-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-railroad.svg create mode 100644 web/vendor/bootstrap-icons/sign-stop-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-stop-lights-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-stop-lights.svg create mode 100644 web/vendor/bootstrap-icons/sign-stop.svg create mode 100644 web/vendor/bootstrap-icons/sign-turn-left-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-turn-left.svg create mode 100644 web/vendor/bootstrap-icons/sign-turn-right-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-turn-right.svg create mode 100644 web/vendor/bootstrap-icons/sign-turn-slight-left-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-turn-slight-left.svg create mode 100644 web/vendor/bootstrap-icons/sign-turn-slight-right-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-turn-slight-right.svg create mode 100644 web/vendor/bootstrap-icons/sign-yield-fill.svg create mode 100644 web/vendor/bootstrap-icons/sign-yield.svg create mode 100644 web/vendor/bootstrap-icons/signal.svg create mode 100644 web/vendor/bootstrap-icons/signpost-2-fill.svg create mode 100644 web/vendor/bootstrap-icons/signpost-2.svg create mode 100644 web/vendor/bootstrap-icons/signpost-fill.svg create mode 100644 web/vendor/bootstrap-icons/signpost-split-fill.svg create mode 100644 web/vendor/bootstrap-icons/signpost-split.svg create mode 100644 web/vendor/bootstrap-icons/signpost.svg create mode 100644 web/vendor/bootstrap-icons/sim-fill.svg create mode 100644 web/vendor/bootstrap-icons/sim-slash-fill.svg create mode 100644 web/vendor/bootstrap-icons/sim-slash.svg create mode 100644 web/vendor/bootstrap-icons/sim.svg create mode 100644 web/vendor/bootstrap-icons/sina-weibo.svg create mode 100644 web/vendor/bootstrap-icons/skip-backward-btn-fill.svg create mode 100644 web/vendor/bootstrap-icons/skip-backward-btn.svg create mode 100644 web/vendor/bootstrap-icons/skip-backward-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/skip-backward-circle.svg create mode 100644 web/vendor/bootstrap-icons/skip-backward-fill.svg create mode 100644 web/vendor/bootstrap-icons/skip-backward.svg create mode 100644 web/vendor/bootstrap-icons/skip-end-btn-fill.svg create mode 100644 web/vendor/bootstrap-icons/skip-end-btn.svg create mode 100644 web/vendor/bootstrap-icons/skip-end-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/skip-end-circle.svg create mode 100644 web/vendor/bootstrap-icons/skip-end-fill.svg create mode 100644 web/vendor/bootstrap-icons/skip-end.svg create mode 100644 web/vendor/bootstrap-icons/skip-forward-btn-fill.svg create mode 100644 web/vendor/bootstrap-icons/skip-forward-btn.svg create mode 100644 web/vendor/bootstrap-icons/skip-forward-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/skip-forward-circle.svg create mode 100644 web/vendor/bootstrap-icons/skip-forward-fill.svg create mode 100644 web/vendor/bootstrap-icons/skip-forward.svg create mode 100644 web/vendor/bootstrap-icons/skip-start-btn-fill.svg create mode 100644 web/vendor/bootstrap-icons/skip-start-btn.svg create mode 100644 web/vendor/bootstrap-icons/skip-start-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/skip-start-circle.svg create mode 100644 web/vendor/bootstrap-icons/skip-start-fill.svg create mode 100644 web/vendor/bootstrap-icons/skip-start.svg create mode 100644 web/vendor/bootstrap-icons/skype.svg create mode 100644 web/vendor/bootstrap-icons/slack.svg create mode 100644 web/vendor/bootstrap-icons/slash-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/slash-circle.svg create mode 100644 web/vendor/bootstrap-icons/slash-lg.svg create mode 100644 web/vendor/bootstrap-icons/slash-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/slash-square.svg create mode 100644 web/vendor/bootstrap-icons/slash.svg create mode 100644 web/vendor/bootstrap-icons/sliders.svg create mode 100644 web/vendor/bootstrap-icons/sliders2-vertical.svg create mode 100644 web/vendor/bootstrap-icons/sliders2.svg create mode 100644 web/vendor/bootstrap-icons/smartwatch.svg create mode 100644 web/vendor/bootstrap-icons/snapchat.svg create mode 100644 web/vendor/bootstrap-icons/snow.svg create mode 100644 web/vendor/bootstrap-icons/snow2.svg create mode 100644 web/vendor/bootstrap-icons/snow3.svg create mode 100644 web/vendor/bootstrap-icons/sort-alpha-down-alt.svg create mode 100644 web/vendor/bootstrap-icons/sort-alpha-down.svg create mode 100644 web/vendor/bootstrap-icons/sort-alpha-up-alt.svg create mode 100644 web/vendor/bootstrap-icons/sort-alpha-up.svg create mode 100644 web/vendor/bootstrap-icons/sort-down-alt.svg create mode 100644 web/vendor/bootstrap-icons/sort-down.svg create mode 100644 web/vendor/bootstrap-icons/sort-numeric-down-alt.svg create mode 100644 web/vendor/bootstrap-icons/sort-numeric-down.svg create mode 100644 web/vendor/bootstrap-icons/sort-numeric-up-alt.svg create mode 100644 web/vendor/bootstrap-icons/sort-numeric-up.svg create mode 100644 web/vendor/bootstrap-icons/sort-up-alt.svg create mode 100644 web/vendor/bootstrap-icons/sort-up.svg create mode 100644 web/vendor/bootstrap-icons/soundwave.svg create mode 100644 web/vendor/bootstrap-icons/sourceforge.svg create mode 100644 web/vendor/bootstrap-icons/speaker-fill.svg create mode 100644 web/vendor/bootstrap-icons/speaker.svg create mode 100644 web/vendor/bootstrap-icons/speedometer.svg create mode 100644 web/vendor/bootstrap-icons/speedometer2.svg create mode 100644 web/vendor/bootstrap-icons/spellcheck.svg create mode 100644 web/vendor/bootstrap-icons/spotify.svg create mode 100644 web/vendor/bootstrap-icons/square-fill.svg create mode 100644 web/vendor/bootstrap-icons/square-half.svg create mode 100644 web/vendor/bootstrap-icons/square.svg create mode 100644 web/vendor/bootstrap-icons/stack-overflow.svg create mode 100644 web/vendor/bootstrap-icons/stack.svg create mode 100644 web/vendor/bootstrap-icons/star-fill.svg create mode 100644 web/vendor/bootstrap-icons/star-half.svg create mode 100644 web/vendor/bootstrap-icons/star.svg create mode 100644 web/vendor/bootstrap-icons/stars.svg create mode 100644 web/vendor/bootstrap-icons/steam.svg create mode 100644 web/vendor/bootstrap-icons/stickies-fill.svg create mode 100644 web/vendor/bootstrap-icons/stickies.svg create mode 100644 web/vendor/bootstrap-icons/sticky-fill.svg create mode 100644 web/vendor/bootstrap-icons/sticky.svg create mode 100644 web/vendor/bootstrap-icons/stop-btn-fill.svg create mode 100644 web/vendor/bootstrap-icons/stop-btn.svg create mode 100644 web/vendor/bootstrap-icons/stop-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/stop-circle.svg create mode 100644 web/vendor/bootstrap-icons/stop-fill.svg create mode 100644 web/vendor/bootstrap-icons/stop.svg create mode 100644 web/vendor/bootstrap-icons/stoplights-fill.svg create mode 100644 web/vendor/bootstrap-icons/stoplights.svg create mode 100644 web/vendor/bootstrap-icons/stopwatch-fill.svg create mode 100644 web/vendor/bootstrap-icons/stopwatch.svg create mode 100644 web/vendor/bootstrap-icons/strava.svg create mode 100644 web/vendor/bootstrap-icons/stripe.svg create mode 100644 web/vendor/bootstrap-icons/subscript.svg create mode 100644 web/vendor/bootstrap-icons/substack.svg create mode 100644 web/vendor/bootstrap-icons/subtract.svg create mode 100644 web/vendor/bootstrap-icons/suit-club-fill.svg create mode 100644 web/vendor/bootstrap-icons/suit-club.svg create mode 100644 web/vendor/bootstrap-icons/suit-diamond-fill.svg create mode 100644 web/vendor/bootstrap-icons/suit-diamond.svg create mode 100644 web/vendor/bootstrap-icons/suit-heart-fill.svg create mode 100644 web/vendor/bootstrap-icons/suit-heart.svg create mode 100644 web/vendor/bootstrap-icons/suit-spade-fill.svg create mode 100644 web/vendor/bootstrap-icons/suit-spade.svg create mode 100644 web/vendor/bootstrap-icons/suitcase-fill.svg create mode 100644 web/vendor/bootstrap-icons/suitcase-lg-fill.svg create mode 100644 web/vendor/bootstrap-icons/suitcase-lg.svg create mode 100644 web/vendor/bootstrap-icons/suitcase.svg create mode 100644 web/vendor/bootstrap-icons/suitcase2-fill.svg create mode 100644 web/vendor/bootstrap-icons/suitcase2.svg create mode 100644 web/vendor/bootstrap-icons/sun-fill.svg create mode 100644 web/vendor/bootstrap-icons/sun.svg create mode 100644 web/vendor/bootstrap-icons/sunglasses.svg create mode 100644 web/vendor/bootstrap-icons/sunrise-fill.svg create mode 100644 web/vendor/bootstrap-icons/sunrise.svg create mode 100644 web/vendor/bootstrap-icons/sunset-fill.svg create mode 100644 web/vendor/bootstrap-icons/sunset.svg create mode 100644 web/vendor/bootstrap-icons/superscript.svg create mode 100644 web/vendor/bootstrap-icons/symmetry-horizontal.svg create mode 100644 web/vendor/bootstrap-icons/symmetry-vertical.svg create mode 100644 web/vendor/bootstrap-icons/table.svg create mode 100644 web/vendor/bootstrap-icons/tablet-fill.svg create mode 100644 web/vendor/bootstrap-icons/tablet-landscape-fill.svg create mode 100644 web/vendor/bootstrap-icons/tablet-landscape.svg create mode 100644 web/vendor/bootstrap-icons/tablet.svg create mode 100644 web/vendor/bootstrap-icons/tag-fill.svg create mode 100644 web/vendor/bootstrap-icons/tag.svg create mode 100644 web/vendor/bootstrap-icons/tags-fill.svg create mode 100644 web/vendor/bootstrap-icons/tags.svg create mode 100644 web/vendor/bootstrap-icons/taxi-front-fill.svg create mode 100644 web/vendor/bootstrap-icons/taxi-front.svg create mode 100644 web/vendor/bootstrap-icons/telegram.svg create mode 100644 web/vendor/bootstrap-icons/telephone-fill.svg create mode 100644 web/vendor/bootstrap-icons/telephone-forward-fill.svg create mode 100644 web/vendor/bootstrap-icons/telephone-forward.svg create mode 100644 web/vendor/bootstrap-icons/telephone-inbound-fill.svg create mode 100644 web/vendor/bootstrap-icons/telephone-inbound.svg create mode 100644 web/vendor/bootstrap-icons/telephone-minus-fill.svg create mode 100644 web/vendor/bootstrap-icons/telephone-minus.svg create mode 100644 web/vendor/bootstrap-icons/telephone-outbound-fill.svg create mode 100644 web/vendor/bootstrap-icons/telephone-outbound.svg create mode 100644 web/vendor/bootstrap-icons/telephone-plus-fill.svg create mode 100644 web/vendor/bootstrap-icons/telephone-plus.svg create mode 100644 web/vendor/bootstrap-icons/telephone-x-fill.svg create mode 100644 web/vendor/bootstrap-icons/telephone-x.svg create mode 100644 web/vendor/bootstrap-icons/telephone.svg create mode 100644 web/vendor/bootstrap-icons/tencent-qq.svg create mode 100644 web/vendor/bootstrap-icons/terminal-dash.svg create mode 100644 web/vendor/bootstrap-icons/terminal-fill.svg create mode 100644 web/vendor/bootstrap-icons/terminal-plus.svg create mode 100644 web/vendor/bootstrap-icons/terminal-split.svg create mode 100644 web/vendor/bootstrap-icons/terminal-x.svg create mode 100644 web/vendor/bootstrap-icons/terminal.svg create mode 100644 web/vendor/bootstrap-icons/text-center.svg create mode 100644 web/vendor/bootstrap-icons/text-indent-left.svg create mode 100644 web/vendor/bootstrap-icons/text-indent-right.svg create mode 100644 web/vendor/bootstrap-icons/text-left.svg create mode 100644 web/vendor/bootstrap-icons/text-paragraph.svg create mode 100644 web/vendor/bootstrap-icons/text-right.svg create mode 100644 web/vendor/bootstrap-icons/text-wrap.svg create mode 100644 web/vendor/bootstrap-icons/textarea-resize.svg create mode 100644 web/vendor/bootstrap-icons/textarea-t.svg create mode 100644 web/vendor/bootstrap-icons/textarea.svg create mode 100644 web/vendor/bootstrap-icons/thermometer-half.svg create mode 100644 web/vendor/bootstrap-icons/thermometer-high.svg create mode 100644 web/vendor/bootstrap-icons/thermometer-low.svg create mode 100644 web/vendor/bootstrap-icons/thermometer-snow.svg create mode 100644 web/vendor/bootstrap-icons/thermometer-sun.svg create mode 100644 web/vendor/bootstrap-icons/thermometer.svg create mode 100644 web/vendor/bootstrap-icons/threads-fill.svg create mode 100644 web/vendor/bootstrap-icons/threads.svg create mode 100644 web/vendor/bootstrap-icons/three-dots-vertical.svg create mode 100644 web/vendor/bootstrap-icons/three-dots.svg create mode 100644 web/vendor/bootstrap-icons/thunderbolt-fill.svg create mode 100644 web/vendor/bootstrap-icons/thunderbolt.svg create mode 100644 web/vendor/bootstrap-icons/ticket-detailed-fill.svg create mode 100644 web/vendor/bootstrap-icons/ticket-detailed.svg create mode 100644 web/vendor/bootstrap-icons/ticket-fill.svg create mode 100644 web/vendor/bootstrap-icons/ticket-perforated-fill.svg create mode 100644 web/vendor/bootstrap-icons/ticket-perforated.svg create mode 100644 web/vendor/bootstrap-icons/ticket.svg create mode 100644 web/vendor/bootstrap-icons/tiktok.svg create mode 100644 web/vendor/bootstrap-icons/toggle-off.svg create mode 100644 web/vendor/bootstrap-icons/toggle-on.svg create mode 100644 web/vendor/bootstrap-icons/toggle2-off.svg create mode 100644 web/vendor/bootstrap-icons/toggle2-on.svg create mode 100644 web/vendor/bootstrap-icons/toggles.svg create mode 100644 web/vendor/bootstrap-icons/toggles2.svg create mode 100644 web/vendor/bootstrap-icons/tools.svg create mode 100644 web/vendor/bootstrap-icons/tornado.svg create mode 100644 web/vendor/bootstrap-icons/train-freight-front-fill.svg create mode 100644 web/vendor/bootstrap-icons/train-freight-front.svg create mode 100644 web/vendor/bootstrap-icons/train-front-fill.svg create mode 100644 web/vendor/bootstrap-icons/train-front.svg create mode 100644 web/vendor/bootstrap-icons/train-lightrail-front-fill.svg create mode 100644 web/vendor/bootstrap-icons/train-lightrail-front.svg create mode 100644 web/vendor/bootstrap-icons/translate.svg create mode 100644 web/vendor/bootstrap-icons/transparency.svg create mode 100644 web/vendor/bootstrap-icons/trash-fill.svg create mode 100644 web/vendor/bootstrap-icons/trash.svg create mode 100644 web/vendor/bootstrap-icons/trash2-fill.svg create mode 100644 web/vendor/bootstrap-icons/trash2.svg create mode 100644 web/vendor/bootstrap-icons/trash3-fill.svg create mode 100644 web/vendor/bootstrap-icons/trash3.svg create mode 100644 web/vendor/bootstrap-icons/tree-fill.svg create mode 100644 web/vendor/bootstrap-icons/tree.svg create mode 100644 web/vendor/bootstrap-icons/trello.svg create mode 100644 web/vendor/bootstrap-icons/triangle-fill.svg create mode 100644 web/vendor/bootstrap-icons/triangle-half.svg create mode 100644 web/vendor/bootstrap-icons/triangle.svg create mode 100644 web/vendor/bootstrap-icons/trophy-fill.svg create mode 100644 web/vendor/bootstrap-icons/trophy.svg create mode 100644 web/vendor/bootstrap-icons/tropical-storm.svg create mode 100644 web/vendor/bootstrap-icons/truck-flatbed.svg create mode 100644 web/vendor/bootstrap-icons/truck-front-fill.svg create mode 100644 web/vendor/bootstrap-icons/truck-front.svg create mode 100644 web/vendor/bootstrap-icons/truck.svg create mode 100644 web/vendor/bootstrap-icons/tsunami.svg create mode 100644 web/vendor/bootstrap-icons/tux.svg create mode 100644 web/vendor/bootstrap-icons/tv-fill.svg create mode 100644 web/vendor/bootstrap-icons/tv.svg create mode 100644 web/vendor/bootstrap-icons/twitch.svg create mode 100644 web/vendor/bootstrap-icons/twitter-x.svg create mode 100644 web/vendor/bootstrap-icons/twitter.svg create mode 100644 web/vendor/bootstrap-icons/type-bold.svg create mode 100644 web/vendor/bootstrap-icons/type-h1.svg create mode 100644 web/vendor/bootstrap-icons/type-h2.svg create mode 100644 web/vendor/bootstrap-icons/type-h3.svg create mode 100644 web/vendor/bootstrap-icons/type-h4.svg create mode 100644 web/vendor/bootstrap-icons/type-h5.svg create mode 100644 web/vendor/bootstrap-icons/type-h6.svg create mode 100644 web/vendor/bootstrap-icons/type-italic.svg create mode 100644 web/vendor/bootstrap-icons/type-strikethrough.svg create mode 100644 web/vendor/bootstrap-icons/type-underline.svg create mode 100644 web/vendor/bootstrap-icons/type.svg create mode 100644 web/vendor/bootstrap-icons/typescript.svg create mode 100644 web/vendor/bootstrap-icons/ubuntu.svg create mode 100644 web/vendor/bootstrap-icons/ui-checks-grid.svg create mode 100644 web/vendor/bootstrap-icons/ui-checks.svg create mode 100644 web/vendor/bootstrap-icons/ui-radios-grid.svg create mode 100644 web/vendor/bootstrap-icons/ui-radios.svg create mode 100644 web/vendor/bootstrap-icons/umbrella-fill.svg create mode 100644 web/vendor/bootstrap-icons/umbrella.svg create mode 100644 web/vendor/bootstrap-icons/unindent.svg create mode 100644 web/vendor/bootstrap-icons/union.svg create mode 100644 web/vendor/bootstrap-icons/unity.svg create mode 100644 web/vendor/bootstrap-icons/universal-access-circle.svg create mode 100644 web/vendor/bootstrap-icons/universal-access.svg create mode 100644 web/vendor/bootstrap-icons/unlock-fill.svg create mode 100644 web/vendor/bootstrap-icons/unlock.svg create mode 100644 web/vendor/bootstrap-icons/unlock2-fill.svg create mode 100644 web/vendor/bootstrap-icons/unlock2.svg create mode 100644 web/vendor/bootstrap-icons/upc-scan.svg create mode 100644 web/vendor/bootstrap-icons/upc.svg create mode 100644 web/vendor/bootstrap-icons/upload.svg create mode 100644 web/vendor/bootstrap-icons/usb-c-fill.svg create mode 100644 web/vendor/bootstrap-icons/usb-c.svg create mode 100644 web/vendor/bootstrap-icons/usb-drive-fill.svg create mode 100644 web/vendor/bootstrap-icons/usb-drive.svg create mode 100644 web/vendor/bootstrap-icons/usb-fill.svg create mode 100644 web/vendor/bootstrap-icons/usb-micro-fill.svg create mode 100644 web/vendor/bootstrap-icons/usb-micro.svg create mode 100644 web/vendor/bootstrap-icons/usb-mini-fill.svg create mode 100644 web/vendor/bootstrap-icons/usb-mini.svg create mode 100644 web/vendor/bootstrap-icons/usb-plug-fill.svg create mode 100644 web/vendor/bootstrap-icons/usb-plug.svg create mode 100644 web/vendor/bootstrap-icons/usb-symbol.svg create mode 100644 web/vendor/bootstrap-icons/usb.svg create mode 100644 web/vendor/bootstrap-icons/valentine.svg create mode 100644 web/vendor/bootstrap-icons/valentine2.svg create mode 100644 web/vendor/bootstrap-icons/vector-pen.svg create mode 100644 web/vendor/bootstrap-icons/view-list.svg create mode 100644 web/vendor/bootstrap-icons/view-stacked.svg create mode 100644 web/vendor/bootstrap-icons/vignette.svg create mode 100644 web/vendor/bootstrap-icons/vimeo.svg create mode 100644 web/vendor/bootstrap-icons/vinyl-fill.svg create mode 100644 web/vendor/bootstrap-icons/vinyl.svg create mode 100644 web/vendor/bootstrap-icons/virus.svg create mode 100644 web/vendor/bootstrap-icons/virus2.svg create mode 100644 web/vendor/bootstrap-icons/voicemail.svg create mode 100644 web/vendor/bootstrap-icons/volume-down-fill.svg create mode 100644 web/vendor/bootstrap-icons/volume-down.svg create mode 100644 web/vendor/bootstrap-icons/volume-mute-fill.svg create mode 100644 web/vendor/bootstrap-icons/volume-mute.svg create mode 100644 web/vendor/bootstrap-icons/volume-off-fill.svg create mode 100644 web/vendor/bootstrap-icons/volume-off.svg create mode 100644 web/vendor/bootstrap-icons/volume-up-fill.svg create mode 100644 web/vendor/bootstrap-icons/volume-up.svg create mode 100644 web/vendor/bootstrap-icons/vr.svg create mode 100644 web/vendor/bootstrap-icons/wallet-fill.svg create mode 100644 web/vendor/bootstrap-icons/wallet.svg create mode 100644 web/vendor/bootstrap-icons/wallet2.svg create mode 100644 web/vendor/bootstrap-icons/watch.svg create mode 100644 web/vendor/bootstrap-icons/water.svg create mode 100644 web/vendor/bootstrap-icons/webcam-fill.svg create mode 100644 web/vendor/bootstrap-icons/webcam.svg create mode 100644 web/vendor/bootstrap-icons/wechat.svg create mode 100644 web/vendor/bootstrap-icons/whatsapp.svg create mode 100644 web/vendor/bootstrap-icons/wifi-1.svg create mode 100644 web/vendor/bootstrap-icons/wifi-2.svg create mode 100644 web/vendor/bootstrap-icons/wifi-off.svg create mode 100644 web/vendor/bootstrap-icons/wifi.svg create mode 100644 web/vendor/bootstrap-icons/wikipedia.svg create mode 100644 web/vendor/bootstrap-icons/wind.svg create mode 100644 web/vendor/bootstrap-icons/window-dash.svg create mode 100644 web/vendor/bootstrap-icons/window-desktop.svg create mode 100644 web/vendor/bootstrap-icons/window-dock.svg create mode 100644 web/vendor/bootstrap-icons/window-fullscreen.svg create mode 100644 web/vendor/bootstrap-icons/window-plus.svg create mode 100644 web/vendor/bootstrap-icons/window-sidebar.svg create mode 100644 web/vendor/bootstrap-icons/window-split.svg create mode 100644 web/vendor/bootstrap-icons/window-stack.svg create mode 100644 web/vendor/bootstrap-icons/window-x.svg create mode 100644 web/vendor/bootstrap-icons/window.svg create mode 100644 web/vendor/bootstrap-icons/windows.svg create mode 100644 web/vendor/bootstrap-icons/wordpress.svg create mode 100644 web/vendor/bootstrap-icons/wrench-adjustable-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/wrench-adjustable-circle.svg create mode 100644 web/vendor/bootstrap-icons/wrench-adjustable.svg create mode 100644 web/vendor/bootstrap-icons/wrench.svg create mode 100644 web/vendor/bootstrap-icons/x-circle-fill.svg create mode 100644 web/vendor/bootstrap-icons/x-circle.svg create mode 100644 web/vendor/bootstrap-icons/x-diamond-fill.svg create mode 100644 web/vendor/bootstrap-icons/x-diamond.svg create mode 100644 web/vendor/bootstrap-icons/x-lg.svg create mode 100644 web/vendor/bootstrap-icons/x-octagon-fill.svg create mode 100644 web/vendor/bootstrap-icons/x-octagon.svg create mode 100644 web/vendor/bootstrap-icons/x-square-fill.svg create mode 100644 web/vendor/bootstrap-icons/x-square.svg create mode 100644 web/vendor/bootstrap-icons/x.svg create mode 100644 web/vendor/bootstrap-icons/xbox.svg create mode 100644 web/vendor/bootstrap-icons/yelp.svg create mode 100644 web/vendor/bootstrap-icons/yin-yang.svg create mode 100644 web/vendor/bootstrap-icons/youtube.svg create mode 100644 web/vendor/bootstrap-icons/zoom-in.svg create mode 100644 web/vendor/bootstrap-icons/zoom-out.svg create mode 100644 web/vendor/editorjs/editorjs.mjs create mode 100644 web/vendor/editorjs/editorjs.umd.js create mode 100644 web/vendor/editorjs/tools/checklist.umd.js create mode 100644 web/vendor/editorjs/tools/columns.js create mode 100644 web/vendor/editorjs/tools/header.umd.js create mode 100644 web/vendor/editorjs/tools/list.umd.js create mode 100644 web/vendor/editorjs/tools/marker.umd.js create mode 100644 web/vendor/editorjs/tools/table.umd.js create mode 100644 web/vendor/fslightbox/README.md create mode 100644 web/vendor/fslightbox/fslightbox.js create mode 100644 web/vendor/fslightbox/package.json create mode 100644 web/vendor/gridjs/gridjs.umd.js create mode 100644 web/vendor/gridjs/mermaid.min.css create mode 100644 web/vendor/gridjs/plugins/selection/selection.umd.js create mode 100644 web/vendor/multi-select/MultiSelect.css create mode 100644 web/vendor/multi-select/MultiSelect.js diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..b6ad05d6519c4c1e3efe80d0ac8da37fbc5ddbf6 GIT binary patch literal 8196 zcmeHMO=uHA6n?Y$F``02q`3%-;8hHI@Sw0QDS{wWA|86GX<}MTvazXJ5X(X@f*>Rm z^&|zsqY55+QWPqIf}kJ;FM^&5;z97>(KkP4-`k(wv_fZK=PmQSx8Jwl&hBP503gP% z*Gd3I04U%l)KDfBa=$RPks2&~IsU-l$EDo!N`y+A(qidpPVxS`;*n}>{ zs7r-eVhCN1YjcF)2wXuupS z@b&xBD~h%Ja=F^{t2kCztGu~$_TgZR;DQI)vyWc5Bd7p3mD6Bs)yr!1&CgGfSRq|$_iOl>8XBtOCgmO-O9Bsbr zD^62K8RID9%ej&-2OYSKcT^p?!3kk=gK5d`L^f_u?=Cmg4Bf5?}MO_4?dY)Yy`ouCqkCHPOzkdGY;RbrrR(B

>G-nYgzZB9yzoIy`? + RewriteEngine on + RewriteRule ^$ web/ [L] + RewriteRule (.*) web/$1 [L] + diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..a8ec1db --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Maurits van der Schee + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..19bd1bc --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +

MintyPHP MintyPHP

+ +MintyPHP aims to be a full-stack PHP 7 (or 8) framework that is: + + - Easy to learn + - Secure by design + - Light-weight + +By design, it does: + + - … have one variable scope for all layers. + - … require you to write SQL queries (no ORM). + - … use PHP as a templating language. + +Mainly to make it easy to learn for PHP developers. + +[Download](https://mintyphp.github.io/installation/) / +[Documentation](https://mintyphp.github.io/docs/) + +## External links + +- [MintyPHP v3 is released](https://tqdev.com/2022-mintyphp-v3-is-released) +- [MintyPHP now on packagist!](https://tqdev.com/2018-mindaphp-now-on-packagist) + +## Quickstart (Docker) + +1. Copy `.env.example` to `.env` (defaults are fine for local dev). +2. Build and start the stack: + + ```bash + docker compose up --build + ``` + +3. Open the app at `http://localhost:8080`. +4. Register a user, then visit `/admin` (protected route). +5. phpMyAdmin is available at `http://localhost:8081`. + +### Notes + +- MintyPHP uses Memcached for its firewall cache; the compose stack includes a `memcached` service and the PHP container has the extension enabled. +- `config/config.php` is generated and gitignored by default; adjust `.gitignore` if you want to commit it. diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..8989d23 --- /dev/null +++ b/composer.json @@ -0,0 +1,33 @@ +{ + "name": "mintyphp/mintyphp", + "description": "A refreshingly different PHP web framework that is easy to learn", + "license": "MIT", + "authors": [ + { + "name": "Maurits van der Schee", + "email": "maurits@vdschee.nl", + "homepage": "https://www.tqdev.com" + } + ], + "require": { + "php": "^8.5", + "mintyphp/core": "*", + "phpmailer/phpmailer": "^7.0" + }, + "require-dev": { + "mintyphp/tools": "*", + "mintyphp/debugger": "*", + "phpunit/phpunit": "*", + "phpstan/phpstan": "^1.9" + }, + "autoload-dev": { + "psr-4": { + "MintyPHP\\Tests\\": "tests/" + } + }, + "autoload": { + "psr-4": { + "MintyPHP\\": "lib/" + } + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..669090b --- /dev/null +++ b/composer.lock @@ -0,0 +1,1847 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "b811586ea9f2ec608a5ce87c611f8f76", + "packages": [ + { + "name": "mintyphp/core", + "version": "v3.2.0", + "source": { + "type": "git", + "url": "https://github.com/mintyphp/core.git", + "reference": "458ea5f1b3857c7d31748eb1d131c4947b9e2100" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mintyphp/core/zipball/458ea5f1b3857c7d31748eb1d131c4947b9e2100", + "reference": "458ea5f1b3857c7d31748eb1d131c4947b9e2100", + "shasum": "" + }, + "require": { + "ext-memcached": "*", + "ext-mysqli": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "type": "library", + "autoload": { + "psr-4": { + "MintyPHP\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maurits van der Schee", + "email": "maurits@vdschee.nl", + "homepage": "https://www.tqdev.com" + } + ], + "support": { + "issues": "https://github.com/mintyphp/core/issues", + "source": "https://github.com/mintyphp/core/tree/v3.2.0" + }, + "time": "2025-02-23T15:53:20+00:00" + }, + { + "name": "phpmailer/phpmailer", + "version": "v7.0.2", + "source": { + "type": "git", + "url": "https://github.com/PHPMailer/PHPMailer.git", + "reference": "ebf1655bd5b99b3f97e1a3ec0a69e5f4cd7ea088" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/ebf1655bd5b99b3f97e1a3ec0a69e5f4cd7ea088", + "reference": "ebf1655bd5b99b3f97e1a3ec0a69e5f4cd7ea088", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", + "php": ">=5.5.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "doctrine/annotations": "^1.2.6 || ^1.13.3", + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.3.2", + "phpcompatibility/php-compatibility": "^10.0.0@dev", + "squizlabs/php_codesniffer": "^3.13.5", + "yoast/phpunit-polyfills": "^1.0.4" + }, + "suggest": { + "decomplexity/SendOauth2": "Adapter for using XOAUTH2 authentication", + "directorytree/imapengine": "For uploading sent messages via IMAP, see gmail example", + "ext-imap": "Needed to support advanced email address parsing according to RFC822", + "ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses", + "ext-openssl": "Needed for secure SMTP sending and DKIM signing", + "greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication", + "hayageek/oauth2-yahoo": "Needed for Yahoo XOAUTH2 authentication", + "league/oauth2-google": "Needed for Google XOAUTH2 authentication", + "psr/log": "For optional PSR-3 debug logging", + "symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)", + "thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPMailer\\PHPMailer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-only" + ], + "authors": [ + { + "name": "Marcus Bointon", + "email": "phpmailer@synchromedia.co.uk" + }, + { + "name": "Jim Jagielski", + "email": "jimjag@gmail.com" + }, + { + "name": "Andy Prevost", + "email": "codeworxtech@users.sourceforge.net" + }, + { + "name": "Brent R. Matzelle" + } + ], + "description": "PHPMailer is a full-featured email creation and transfer class for PHP", + "support": { + "issues": "https://github.com/PHPMailer/PHPMailer/issues", + "source": "https://github.com/PHPMailer/PHPMailer/tree/v7.0.2" + }, + "funding": [ + { + "url": "https://github.com/Synchro", + "type": "github" + } + ], + "time": "2026-01-09T18:02:33+00:00" + } + ], + "packages-dev": [ + { + "name": "mintyphp/debugger", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/mintyphp/debugger.git", + "reference": "6143b246c71d3c30c2acbcf7deea9331c6ecbe2d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mintyphp/debugger/zipball/6143b246c71d3c30c2acbcf7deea9331c6ecbe2d", + "reference": "6143b246c71d3c30c2acbcf7deea9331c6ecbe2d", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maurits van der Schee", + "email": "maurits@vdschee.nl", + "homepage": "https://www.tqdev.com" + } + ], + "support": { + "issues": "https://github.com/mintyphp/debugger/issues", + "source": "https://github.com/mintyphp/debugger/tree/v3.0.0" + }, + "time": "2022-09-23T06:36:53+00:00" + }, + { + "name": "mintyphp/tools", + "version": "v3.1.0", + "source": { + "type": "git", + "url": "https://github.com/mintyphp/tools.git", + "reference": "fb3805ff30aaf5b218ec5b154d4cbfa30d65de29" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mintyphp/tools/zipball/fb3805ff30aaf5b218ec5b154d4cbfa30d65de29", + "reference": "fb3805ff30aaf5b218ec5b154d4cbfa30d65de29", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maurits van der Schee", + "email": "maurits@vdschee.nl", + "homepage": "https://www.tqdev.com" + } + ], + "support": { + "issues": "https://github.com/mintyphp/tools/issues", + "source": "https://github.com/mintyphp/tools/tree/v3.1.0" + }, + "time": "2025-02-23T20:21:07+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.13.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "024473a478be9df5fdaca2c793f2232fe788e414" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414", + "reference": "024473a478be9df5fdaca2c793f2232fe788e414", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2025-02-12T12:17:51+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.4.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" + }, + "time": "2024-12-30T11:07:19+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "1.12.19", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "c42ba9bab7a940ed00092ecb1c77bad98896d789" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c42ba9bab7a940ed00092ecb1c77bad98896d789", + "reference": "c42ba9bab7a940ed00092ecb1c77bad98896d789", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2025-02-19T15:42:21+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "12.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "2e3038bff41d56114e5396151060f5ac9d2d6751" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2e3038bff41d56114e5396151060f5ac9d2d6751", + "reference": "2e3038bff41d56114e5396151060f5ac9d2d6751", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^5.4.0", + "php": ">=8.3", + "phpunit/php-file-iterator": "^6.0", + "phpunit/php-text-template": "^5.0", + "sebastian/complexity": "^5.0", + "sebastian/environment": "^8.0", + "sebastian/lines-of-code": "^4.0", + "sebastian/version": "^6.0", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "12.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-18T14:04:13+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "961bc913d42fe24a257bfff826a5068079ac7782" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/961bc913d42fe24a257bfff826a5068079ac7782", + "reference": "961bc913d42fe24a257bfff826a5068079ac7782", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:58:37+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/12b54e689b07a25a9b41e57736dfab6ec9ae5406", + "reference": "12b54e689b07a25a9b41e57736dfab6ec9ae5406", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^12.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:58:58+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/e1367a453f0eda562eedb4f659e13aa900d66c53", + "reference": "e1367a453f0eda562eedb4f659e13aa900d66c53", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:59:16+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "8.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc", + "reference": "f258ce36aa457f3aa3339f9ed4c81fc66dc8c2cc", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/8.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:59:38+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "12.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "e469daf4e173c4b7f2d6154d364f468f3713f632" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e469daf4e173c4b7f2d6154d364f468f3713f632", + "reference": "e469daf4e173c4b7f2d6154d364f468f3713f632", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.3", + "phpunit/php-code-coverage": "^12.0.3", + "phpunit/php-file-iterator": "^6.0.0", + "phpunit/php-invoker": "^6.0.0", + "phpunit/php-text-template": "^5.0.0", + "phpunit/php-timer": "^8.0.0", + "sebastian/cli-parser": "^4.0.0", + "sebastian/comparator": "^7.0.0", + "sebastian/diff": "^7.0.0", + "sebastian/environment": "^8.0.0", + "sebastian/exporter": "^7.0.0", + "sebastian/global-state": "^8.0.0", + "sebastian/object-enumerator": "^7.0.0", + "sebastian/type": "^6.0.0", + "sebastian/version": "^6.0.0", + "staabm/side-effects-detector": "^1.0.5" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "12.0-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.0.4" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2025-02-21T06:10:40+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "6d584c727d9114bcdc14c86711cd1cad51778e7c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/6d584c727d9114bcdc14c86711cd1cad51778e7c", + "reference": "6d584c727d9114bcdc14c86711cd1cad51778e7c", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:53:50+00:00" + }, + { + "name": "sebastian/comparator", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "18eb5a4f854dbd1d6512c459b605de2edb5a0b47" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/18eb5a4f854dbd1d6512c459b605de2edb5a0b47", + "reference": "18eb5a4f854dbd1d6512c459b605de2edb5a0b47", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.3", + "sebastian/diff": "^7.0", + "sebastian/exporter": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:54:52+00:00" + }, + { + "name": "sebastian/complexity", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/bad4316aba5303d0221f43f8cee37eb58d384bbb", + "reference": "bad4316aba5303d0221f43f8cee37eb58d384bbb", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:55:25+00:00" + }, + { + "name": "sebastian/diff", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "7ab1ea946c012266ca32390913653d844ecd085f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7ab1ea946c012266ca32390913653d844ecd085f", + "reference": "7ab1ea946c012266ca32390913653d844ecd085f", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0", + "symfony/process": "^7.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:55:46+00:00" + }, + { + "name": "sebastian/environment", + "version": "8.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "8afe311eca49171bf95405cc0078be9a3821f9f2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8afe311eca49171bf95405cc0078be9a3821f9f2", + "reference": "8afe311eca49171bf95405cc0078be9a3821f9f2", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/8.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:56:08+00:00" + }, + { + "name": "sebastian/exporter", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "76432aafc58d50691a00d86d0632f1217a47b688" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/76432aafc58d50691a00d86d0632f1217a47b688", + "reference": "76432aafc58d50691a00d86d0632f1217a47b688", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.3", + "sebastian/recursion-context": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:56:42+00:00" + }, + { + "name": "sebastian/global-state", + "version": "8.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "570a2aeb26d40f057af686d63c4e99b075fb6cbc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/570a2aeb26d40f057af686d63c4e99b075fb6cbc", + "reference": "570a2aeb26d40f057af686d63c4e99b075fb6cbc", + "shasum": "" + }, + "require": { + "php": ">=8.3", + "sebastian/object-reflector": "^5.0", + "sebastian/recursion-context": "^7.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/8.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:56:59+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "97ffee3bcfb5805568d6af7f0f893678fc076d2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/97ffee3bcfb5805568d6af7f0f893678fc076d2f", + "reference": "97ffee3bcfb5805568d6af7f0f893678fc076d2f", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:57:28+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1effe8e9b8e068e9ae228e542d5d11b5d16db894", + "reference": "1effe8e9b8e068e9ae228e542d5d11b5d16db894", + "shasum": "" + }, + "require": { + "php": ">=8.3", + "sebastian/object-reflector": "^5.0", + "sebastian/recursion-context": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:57:48+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "4bfa827c969c98be1e527abd576533293c634f6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/4bfa827c969c98be1e527abd576533293c634f6a", + "reference": "4bfa827c969c98be1e527abd576533293c634f6a", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T04:58:17+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "7.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "c405ae3a63e01b32eb71577f8ec1604e39858a7c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/c405ae3a63e01b32eb71577f8ec1604e39858a7c", + "reference": "c405ae3a63e01b32eb71577f8ec1604e39858a7c", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/7.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T05:00:01+00:00" + }, + { + "name": "sebastian/type", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "533fe082889a616f330bcba6f50965135f4f2fab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/533fe082889a616f330bcba6f50965135f4f2fab", + "reference": "533fe082889a616f330bcba6f50965135f4f2fab", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "require-dev": { + "phpunit/phpunit": "^12.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T05:00:19+00:00" + }, + { + "name": "sebastian/version", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "3e6ccf7657d4f0a59200564b08cead899313b53c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/3e6ccf7657d4f0a59200564b08cead899313b53c", + "reference": "3e6ccf7657d4f0a59200564b08cead899313b53c", + "shasum": "" + }, + "require": { + "php": ">=8.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-07T05:00:38+00:00" + }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^8.5" + }, + "platform-dev": {}, + "plugin-api-version": "2.9.0" +} diff --git a/config/config.php.example b/config/config.php.example new file mode 100644 index 0000000..34828b0 --- /dev/null +++ b/config/config.php.example @@ -0,0 +1,69 @@ + 'IVMS', + 'app_locale' => 'de', + 'app_theme' => 'dark', + 'app_theme_user' => '1', + 'app_primary_color' => '#9b3dc7', +); diff --git a/db/init/init.sql b/db/init/init.sql new file mode 100644 index 0000000..872fdb9 --- /dev/null +++ b/db/init/init.sql @@ -0,0 +1,425 @@ +-- Consolidated schema (fresh install) +-- Includes all current tables, columns, indexes, and seed data. + +CREATE TABLE IF NOT EXISTS `users` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `uuid` CHAR(36) NOT NULL, + `first_name` VARCHAR(100) NOT NULL, + `last_name` VARCHAR(100) NOT NULL, + `email` VARCHAR(255) NOT NULL, + `profile_description` TEXT NULL, + `job_title` VARCHAR(160) NULL, + `phone` VARCHAR(50) NULL, + `mobile` VARCHAR(50) NULL, + `short_dial` VARCHAR(20) NULL, + `address` VARCHAR(255) NULL, + `postal_code` VARCHAR(20) NULL, + `city` VARCHAR(100) NULL, + `country` VARCHAR(100) NULL, + `region` VARCHAR(100) NULL, + `hire_date` DATE NULL, + `email_verified_at` DATETIME NULL DEFAULT NULL, + `password` VARCHAR(255) NOT NULL, + `locale` VARCHAR(10) DEFAULT NULL, + `totp_secret` VARCHAR(255) DEFAULT NULL, + `theme` VARCHAR(10) NOT NULL DEFAULT 'light', + `primary_tenant_id` INT NULL, + `current_tenant_id` INT UNSIGNED NULL, + `created_by` INT UNSIGNED DEFAULT NULL, + `modified_by` INT UNSIGNED DEFAULT NULL, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `modified` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, + `active` TINYINT(1) NOT NULL DEFAULT 1, + `active_changed_at` DATETIME NULL DEFAULT NULL, + `active_changed_by` INT UNSIGNED DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_users_uuid` (`uuid`), + UNIQUE KEY `uniq_users_email` (`email`), + KEY `idx_users_primary_tenant_id` (`primary_tenant_id`), + KEY `idx_users_current_tenant_id` (`current_tenant_id`), + KEY `idx_users_created_by` (`created_by`), + KEY `idx_users_modified_by` (`modified_by`), + KEY `idx_users_active_changed_by` (`active_changed_by`), + CONSTRAINT `fk_users_created_by` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`) ON DELETE SET NULL, + CONSTRAINT `fk_users_modified_by` FOREIGN KEY (`modified_by`) REFERENCES `users` (`id`) ON DELETE SET NULL, + CONSTRAINT `fk_users_active_changed_by` FOREIGN KEY (`active_changed_by`) REFERENCES `users` (`id`) ON DELETE SET NULL, + CONSTRAINT `fk_users_current_tenant` FOREIGN KEY (`current_tenant_id`) REFERENCES `tenants` (`id`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `tenants` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `uuid` CHAR(36) NOT NULL, + `description` VARCHAR(255) NOT NULL, + `address` VARCHAR(255) NULL, + `postal_code` VARCHAR(20) NULL, + `city` VARCHAR(100) NULL, + `country` VARCHAR(100) NULL, + `region` VARCHAR(100) NULL, + `vat_id` VARCHAR(50) NULL, + `tax_number` VARCHAR(50) NULL, + `phone` VARCHAR(50) NULL, + `fax` VARCHAR(100) NULL, + `email` VARCHAR(190) NULL, + `support_email` VARCHAR(190) NULL, + `support_phone` VARCHAR(50) NULL, + `billing_email` VARCHAR(190) NULL, + `website` VARCHAR(255) NULL, + `privacy_url` VARCHAR(255) NULL, + `imprint_url` VARCHAR(255) NULL, + `primary_color` VARCHAR(7) NULL, + `status` VARCHAR(20) NOT NULL DEFAULT 'active', + `status_changed_at` DATETIME NULL DEFAULT NULL, + `status_changed_by` INT UNSIGNED DEFAULT NULL, + `created_by` INT UNSIGNED DEFAULT NULL, + `modified_by` INT UNSIGNED DEFAULT NULL, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `modified` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_tenants_uuid` (`uuid`), + KEY `idx_tenants_created_by` (`created_by`), + KEY `idx_tenants_modified_by` (`modified_by`), + KEY `idx_tenants_status_changed_by` (`status_changed_by`), + CONSTRAINT `fk_tenants_created_by` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`) ON DELETE SET NULL, + CONSTRAINT `fk_tenants_modified_by` FOREIGN KEY (`modified_by`) REFERENCES `users` (`id`) ON DELETE SET NULL, + CONSTRAINT `fk_tenants_status_changed_by` FOREIGN KEY (`status_changed_by`) REFERENCES `users` (`id`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `roles` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `uuid` CHAR(36) NOT NULL, + `description` VARCHAR(255) NOT NULL, + `created_by` INT UNSIGNED DEFAULT NULL, + `modified_by` INT UNSIGNED DEFAULT NULL, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `modified` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_roles_uuid` (`uuid`), + KEY `idx_roles_created_by` (`created_by`), + KEY `idx_roles_modified_by` (`modified_by`), + CONSTRAINT `fk_roles_created_by` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`) ON DELETE SET NULL, + CONSTRAINT `fk_roles_modified_by` FOREIGN KEY (`modified_by`) REFERENCES `users` (`id`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `permissions` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `key` VARCHAR(191) NOT NULL, + `description` VARCHAR(255) DEFAULT NULL, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_permissions_key` (`key`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `departments` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `uuid` CHAR(36) NOT NULL, + `description` VARCHAR(255) NOT NULL, + `created_by` INT UNSIGNED DEFAULT NULL, + `modified_by` INT UNSIGNED DEFAULT NULL, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `modified` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_departments_uuid` (`uuid`), + KEY `idx_departments_created_by` (`created_by`), + KEY `idx_departments_modified_by` (`modified_by`), + CONSTRAINT `fk_departments_created_by` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`) ON DELETE SET NULL, + CONSTRAINT `fk_departments_modified_by` FOREIGN KEY (`modified_by`) REFERENCES `users` (`id`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `pages` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `uuid` CHAR(36) NOT NULL, + `slug` VARCHAR(190) NOT NULL, + `created_by` INT UNSIGNED NULL, + `modified_by` INT UNSIGNED NULL, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `modified` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_pages_uuid` (`uuid`), + UNIQUE KEY `uniq_pages_slug` (`slug`), + KEY `idx_pages_created_by` (`created_by`), + KEY `idx_pages_modified_by` (`modified_by`), + CONSTRAINT `fk_pages_created_by` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`) ON DELETE SET NULL, + CONSTRAINT `fk_pages_modified_by` FOREIGN KEY (`modified_by`) REFERENCES `users` (`id`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `page_contents` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `page_id` INT UNSIGNED NOT NULL, + `locale` VARCHAR(10) NOT NULL, + `content` LONGTEXT NULL, + `created_by` INT UNSIGNED NULL, + `modified_by` INT UNSIGNED NULL, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `modified` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_page_locale` (`page_id`, `locale`), + KEY `idx_page_id` (`page_id`), + KEY `idx_page_contents_created_by` (`created_by`), + KEY `idx_page_contents_modified_by` (`modified_by`), + CONSTRAINT `fk_page_contents_page` FOREIGN KEY (`page_id`) REFERENCES `pages` (`id`) ON DELETE CASCADE, + CONSTRAINT `fk_page_contents_created_by` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`) ON DELETE SET NULL, + CONSTRAINT `fk_page_contents_modified_by` FOREIGN KEY (`modified_by`) REFERENCES `users` (`id`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `settings` ( + `key` VARCHAR(64) NOT NULL, + `value` TEXT NULL, + `description` VARCHAR(255) NULL, + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`key`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +CREATE TABLE IF NOT EXISTS `user_tenants` ( + `user_id` INT UNSIGNED NOT NULL, + `tenant_id` INT UNSIGNED NOT NULL, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`user_id`, `tenant_id`), + KEY `idx_user_tenants_user` (`user_id`), + KEY `idx_user_tenants_tenant` (`tenant_id`), + CONSTRAINT `fk_user_tenants_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE, + CONSTRAINT `fk_user_tenants_tenant` FOREIGN KEY (`tenant_id`) REFERENCES `tenants` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `user_roles` ( + `user_id` INT UNSIGNED NOT NULL, + `role_id` INT UNSIGNED NOT NULL, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`user_id`, `role_id`), + KEY `idx_user_roles_user` (`user_id`), + KEY `idx_user_roles_role` (`role_id`), + CONSTRAINT `fk_user_roles_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE, + CONSTRAINT `fk_user_roles_role` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `role_permissions` ( + `role_id` INT UNSIGNED NOT NULL, + `permission_id` INT UNSIGNED NOT NULL, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`role_id`, `permission_id`), + KEY `idx_role_permissions_permission` (`permission_id`), + CONSTRAINT `fk_role_permissions_role` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE, + CONSTRAINT `fk_role_permissions_permission` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `user_departments` ( + `user_id` INT UNSIGNED NOT NULL, + `department_id` INT UNSIGNED NOT NULL, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`user_id`, `department_id`), + KEY `idx_user_departments_user` (`user_id`), + KEY `idx_user_departments_department` (`department_id`), + CONSTRAINT `fk_user_departments_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE, + CONSTRAINT `fk_user_departments_department` FOREIGN KEY (`department_id`) REFERENCES `departments` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `tenant_departments` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `tenant_id` INT UNSIGNED NOT NULL, + `department_id` INT UNSIGNED NOT NULL, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_tenant_department` (`tenant_id`, `department_id`), + KEY `idx_tenant_departments_tenant` (`tenant_id`), + KEY `idx_tenant_departments_department` (`department_id`), + CONSTRAINT `fk_tenant_departments_tenant` FOREIGN KEY (`tenant_id`) REFERENCES `tenants` (`id`) ON DELETE CASCADE, + CONSTRAINT `fk_tenant_departments_department` FOREIGN KEY (`department_id`) REFERENCES `departments` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `mail_log` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `to_email` VARCHAR(255) NOT NULL, + `subject` VARCHAR(255) NOT NULL, + `template` VARCHAR(100) NULL, + `status` VARCHAR(20) NOT NULL DEFAULT 'queued', + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `sent_at` DATETIME NULL DEFAULT NULL, + `error_message` TEXT NULL, + `provider_message_id` VARCHAR(255) NULL, + PRIMARY KEY (`id`), + KEY `idx_mail_log_status` (`status`), + KEY `idx_mail_log_to_email` (`to_email`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `password_resets` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `user_id` INT UNSIGNED NOT NULL, + `code_hash` VARCHAR(255) NOT NULL, + `expires_at` DATETIME NOT NULL, + `attempts` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Failed verification attempts', + `used_at` DATETIME NULL DEFAULT NULL, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + KEY `idx_password_resets_user` (`user_id`), + KEY `idx_password_resets_expires` (`expires_at`), + CONSTRAINT `fk_password_resets_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `email_verifications` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `user_id` INT UNSIGNED NOT NULL, + `code_hash` VARCHAR(255) NOT NULL, + `expires_at` DATETIME NOT NULL, + `attempts` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Failed verification attempts', + `used_at` DATETIME NULL DEFAULT NULL, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + KEY `idx_email_verifications_user` (`user_id`), + KEY `idx_email_verifications_expires` (`expires_at`), + CONSTRAINT `fk_email_verifications_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `user_remember_tokens` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `user_id` INT UNSIGNED NOT NULL, + `selector` CHAR(24) NOT NULL, + `token_hash` CHAR(64) NOT NULL, + `expires_at` DATETIME NOT NULL, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `last_used` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_user_remember_selector` (`selector`), + KEY `idx_user_remember_user` (`user_id`), + KEY `idx_user_remember_expires` (`expires_at`), + CONSTRAINT `fk_user_remember_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +INSERT INTO `tenants` (`uuid`, `description`, `created`) +SELECT UUID(), 'Cronus', NOW() +WHERE NOT EXISTS (SELECT 1 FROM tenants WHERE description = 'Cronus'); + +INSERT INTO `departments` (`uuid`, `description`, `created`) +SELECT UUID(), 'IT', NOW() +WHERE NOT EXISTS (SELECT 1 FROM departments WHERE description = 'IT'); + +INSERT INTO `roles` (`uuid`, `description`, `created`) +SELECT UUID(), 'Admin', NOW() +WHERE NOT EXISTS (SELECT 1 FROM roles WHERE description = 'Admin'); + +INSERT INTO `users` ( + `uuid`, + `first_name`, + `last_name`, + `email`, + `password`, + `locale`, + `totp_secret`, + `theme`, + `primary_tenant_id`, + `created_by`, + `created`, + `active`, + `active_changed_at`, + `active_changed_by` +) +SELECT + UUID(), + 'Detlef', + 'Demo', + 'demo@user.com', + '$2y$12$KVCQvuy4Pl1aySBuzSpc7ehpZhAzYZkndDI9OaMi05E2P/Mhob5HO', + 'de', + NULL, + 'light', + (SELECT id FROM tenants WHERE description = 'Cronus' LIMIT 1), + NULL, + NOW(), + 1, + NOW(), + NULL +WHERE NOT EXISTS (SELECT 1 FROM users WHERE email = 'demo@user.com'); + +INSERT INTO `user_tenants` (`user_id`, `tenant_id`, `created`) +SELECT u.id, t.id, NOW() +FROM users u +JOIN tenants t ON t.description = 'Cronus' +WHERE u.email = 'demo@user.com' + AND NOT EXISTS ( + SELECT 1 FROM user_tenants ut WHERE ut.user_id = u.id AND ut.tenant_id = t.id + ); + +INSERT INTO `user_departments` (`user_id`, `department_id`, `created`) +SELECT u.id, d.id, NOW() +FROM users u +JOIN departments d ON d.description = 'IT' +WHERE u.email = 'demo@user.com' + AND NOT EXISTS ( + SELECT 1 FROM user_departments ud WHERE ud.user_id = u.id AND ud.department_id = d.id + ); + +INSERT INTO `tenant_departments` (`tenant_id`, `department_id`, `created`) +SELECT t.id, d.id, NOW() +FROM tenants t +JOIN departments d ON d.description = 'IT' +WHERE t.description = 'Cronus' + AND NOT EXISTS ( + SELECT 1 FROM tenant_departments td WHERE td.tenant_id = t.id AND td.department_id = d.id + ); + +INSERT INTO `user_roles` (`user_id`, `role_id`, `created`) +SELECT u.id, r.id, NOW() +FROM users u +JOIN roles r ON r.description = 'Admin' +WHERE u.email = 'demo@user.com' + AND NOT EXISTS ( + SELECT 1 FROM user_roles ur WHERE ur.user_id = u.id AND ur.role_id = r.id + ); + +INSERT INTO `pages` (`uuid`, `slug`, `created`) +SELECT UUID(), 'impressum', NOW() +WHERE NOT EXISTS (SELECT 1 FROM pages WHERE slug = 'impressum'); + +INSERT INTO `page_contents` (`page_id`, `locale`, `content`, `created`) +SELECT p.id, 'de', NULL, p.created +FROM pages p +WHERE NOT EXISTS ( + SELECT 1 FROM page_contents pc WHERE pc.page_id = p.id AND pc.locale = 'de' +); + +INSERT INTO `permissions` (`key`, `description`) +VALUES + ('users.view', 'Can view users'), + ('users.create', 'Can create users'), + ('users.update', 'Can update users'), + ('users.delete', 'Can delete users'), + ('users.self_update', 'Can update own user'), + ('users.update_assignments', 'Can update user assignments'), + ('address_book.view', 'Can view address book'), + ('tenants.view', 'Can view tenants'), + ('tenants.create', 'Can create tenants'), + ('tenants.update', 'Can update tenants'), + ('tenants.delete', 'Can delete tenants'), + ('departments.view', 'Can view departments'), + ('departments.create', 'Can create departments'), + ('departments.update', 'Can update departments'), + ('departments.delete', 'Can delete departments'), + ('roles.view', 'Can view roles'), + ('roles.create', 'Can create roles'), + ('roles.update', 'Can update roles'), + ('roles.delete', 'Can delete roles'), + ('permissions.view', 'Can view permissions'), + ('permissions.create', 'Can create permissions'), + ('permissions.update', 'Can update permissions'), + ('permissions.delete', 'Can delete permissions'), + ('settings.view', 'Can view settings'), + ('settings.update', 'Can update settings'), + ('mail_log.view', 'Can view mail logs'), + ('stats.view', 'Can view statistics') +ON DUPLICATE KEY UPDATE `description` = VALUES(`description`); + +INSERT INTO `role_permissions` (`role_id`, `permission_id`, `created`) +SELECT r.id, p.id, NOW() +FROM roles r +JOIN permissions p ON p.`key` IN ( + 'users.view', 'users.create', 'users.update', 'users.delete', + 'users.self_update', 'users.update_assignments', + 'address_book.view', + 'tenants.view', 'tenants.create', 'tenants.update', 'tenants.delete', + 'departments.view', 'departments.create', 'departments.update', 'departments.delete', + 'roles.view', 'roles.create', 'roles.update', 'roles.delete', + 'permissions.view', 'permissions.create', 'permissions.update', 'permissions.delete', + 'settings.view', 'settings.update', + 'mail_log.view', + 'stats.view' +) +WHERE r.description IN ('Admin', 'Administrator') OR r.id = 1 +ON DUPLICATE KEY UPDATE role_id = role_id; diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..7fe0344 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,55 @@ +services: + nginx: + image: nginx:1.25-alpine + ports: + - "8080:80" + volumes: + - ./:/var/www + - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro + depends_on: + - php + + php: + build: + context: . + dockerfile: docker/php/Dockerfile + env_file: + - .env + volumes: + - ./:/var/www + depends_on: + - db + - memcached + + db: + image: mariadb:11.4 + env_file: + - .env + environment: + MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} + MARIADB_DATABASE: ${DB_NAME} + MARIADB_USER: ${DB_USER} + MARIADB_PASSWORD: ${DB_PASS} + volumes: + - db_data:/var/lib/mysql + - ./db/init:/docker-entrypoint-initdb.d:ro + + phpmyadmin: + image: phpmyadmin:5 + ports: + - "8081:80" + env_file: + - .env + environment: + PMA_HOST: db + PMA_PORT: ${DB_PORT} + PMA_USER: ${DB_USER} + PMA_PASSWORD: ${DB_PASS} + depends_on: + - db + + memcached: + image: memcached:1.6-alpine + +volumes: + db_data: diff --git a/docker/.DS_Store b/docker/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..0473253dc78c22629cb6941695eeffca9c36094a GIT binary patch literal 6148 zcmeHKOG*Pl5Urj>7;uxN%k~JlK^w*s%mpL{5+UQvCg5_e;Kt*K;KH2iTreJeaO&A_}w3VoEe2q7s8KureTQ9&{BJ%+4Tt+^m<=`m$}hfo*=L ziJ$$5u4zeEnD?H)sB>@AR@Hpn&S5Q2U*4bJZlBKfBNpF8bgNy4n0FdcM=R=b?uv)4 zXSeSC-Q%m(wY;X?);#p)^&&QPaR!_LXTTZw=M11{vy{h*K05=>fHUyL0G|&LgE1NQ zigI*dk}Cjk46_Jy`KJX&HUN`huLuhyXev-sgIzI#ro$dBE*bWUnodC~V;`&hd3gy^ z9rh^U6q2IP&VVzJGceNSg!}(FKAFKwexBkhXTTZwV+@3GRaY~-l=aqw*W+FrF)lDz sIId>}0$o}$P+Bn-e2$!mQ~i;3_>*C;$h)vz(t-XXAcXkj4Ez8CAEO*flK=n! literal 0 HcmV?d00001 diff --git a/docker/nginx/default.conf b/docker/nginx/default.conf new file mode 100644 index 0000000..40d83a1 --- /dev/null +++ b/docker/nginx/default.conf @@ -0,0 +1,29 @@ +server { + listen 80; + server_name _; + + root /var/www/web; + index index.php; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_pass php:9000; + } + + location ~* \.mjs$ { + default_type application/javascript; + try_files $uri =404; + expires 30d; + access_log off; + } + + location ~* \.(css|js|png|jpg|jpeg|gif|svg|ico)$ { + expires 30d; + access_log off; + } +} diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile new file mode 100644 index 0000000..8a879c9 --- /dev/null +++ b/docker/php/Dockerfile @@ -0,0 +1,22 @@ +FROM php:8.5-fpm + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + git \ + unzip \ + libmemcached-dev \ + zlib1g-dev \ + libssl-dev \ + libjpeg-dev \ + libpng-dev \ + libwebp-dev \ + && pecl install memcached \ + && docker-php-ext-enable memcached \ + && docker-php-ext-configure gd --with-jpeg --with-webp \ + && docker-php-ext-install pdo_mysql mysqli gd \ + && rm -rf /var/lib/apt/lists/* + +COPY --from=composer:2 /usr/bin/composer /usr/bin/composer +COPY docker/php/php.ini /usr/local/etc/php/conf.d/zzz-minty-dev.ini + +WORKDIR /var/www diff --git a/docker/php/php.ini b/docker/php/php.ini new file mode 100644 index 0000000..7c7ed3f --- /dev/null +++ b/docker/php/php.ini @@ -0,0 +1,4 @@ +display_errors=1 +display_startup_errors=1 +error_reporting=E_ALL +memory_limit=256M diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..5726081 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,717 @@ +# IMVS - Architektur und Grundprinzipien + +## Inhaltsverzeichnis + +1. [Projektübersicht](#1-projektübersicht) +2. [Framework: MintyPHP](#2-framework-mintyphp) +3. [Verzeichnisstruktur](#3-verzeichnisstruktur) +4. [Datenbankarchitektur](#4-datenbankarchitektur) +5. [PHP-Architektur](#5-php-architektur) +6. [Frontend-Architektur](#6-frontend-architektur) +7. [Template-System](#7-template-system) +8. [Authentifizierung und Autorisierung](#8-authentifizierung-und-autorisierung) +9. [Internationalisierung](#9-internationalisierung) +10. [Best Practices](#10-best-practices) + +--- + +## 1. Projektübersicht + +**Projektname:** IMVS +**Framework:** MintyPHP v3+ +**PHP-Version:** 8.5+ +**Datenbank:** MySQL 5.7+ +**Lizenz:** MIT + +### Kernfeatures + +- Multi-Tenant-Architektur +- Rollen- und Berechtigungssystem +- Mehrsprachigkeit (DE/EN) +- Dark/Light Theme +- E-Mail-Integration mit Templates + +--- + +## 2. Framework: MintyPHP + +### Philosophie + +MintyPHP ist ein leichtgewichtiges PHP-Framework mit folgenden Prinzipien: + +- **Easy to learn** - Einfach für PHP-Entwickler zu erlernen +- **Secure by design** - Sicherheit als Grundprinzip +- **Lightweight** - Minimaler Overhead +- **Single variable scope** - Eine Variable-Scope für alle Layer +- **SQL required** - Direktes SQL statt ORM +- **PHP as templating** - PHP selbst als Template-Sprache + +### Kern-Komponenten + +| Komponente | Beschreibung | +|------------|--------------| +| `Router` | URL-Routing zu Pages | +| `DB` | Datenbankzugriff mit Prepared Statements | +| `Auth` | Basis-Authentifizierung | +| `Session` | Session-Management | +| `Buffer` | Output-Buffering für Templates | +| `I18n` | Internationalisierung | +| `Cache` | Memcached-Integration | +| `Firewall` | DDoS-Schutz | + +### Router-Konvention + +``` +URL: /admin/users/edit/abc-123 +Datei: pages/admin/users/edit($id).php +Variable: $id = 'abc-123' +``` + +--- + +## 3. Verzeichnisstruktur + +``` +ImmobilienMaklerVerkaufssoftware/ +├── config/ # Konfigurationsdateien +│ ├── config.php # Hauptkonfiguration +│ ├── router.php # Route-Definitionen +│ └── settings.php # App-Einstellungen (generiert) +├── db/ # Datenbank +│ └── init/init.sql # Schema und Seeds +├── docker/ # Docker-Konfiguration +├── docs/ # Dokumentation +├── i18n/ # Sprachdateien +│ ├── default_de.json +│ └── default_en.json +├── lib/ # Geschäftslogik +│ ├── Http/ # HTTP-Utilities +│ ├── Repository/ # Datenbankschicht +│ ├── Service/ # Business-Logic +│ └── Support/ # Helper und Guards +├── pages/ # Seiten (Controller) +│ ├── admin/ # Geschützte Admin-Seiten +│ ├── auth/ # Authentifizierung +│ ├── error/ # Fehlerseiten +│ └── page/ # CMS-Seiten +├── storage/ # Dateiablage +│ ├── branding/ # Logos, Favicons +│ ├── tenants/ # Tenant-Dateien +│ └── users/ # User-Avatare +├── templates/ # View-Templates +│ ├── partials/ # Wiederverwendbare Teile +│ └── emails/ # E-Mail-Templates +├── tests/ # PHPUnit Tests +├── vendor/ # Composer Dependencies +└── web/ # Public Root + ├── css/ # Stylesheets + ├── js/ # JavaScript-Module + ├── vendor/ # Frontend-Libraries + └── index.php # Entry Point +``` + +--- + +## 4. Datenbankarchitektur + +### Entity-Relationship-Diagramm + +``` +┌─────────────┐ ┌─────────────────┐ ┌─────────────┐ +│ USERS │────<│ USER_TENANTS │>────│ TENANTS │ +└─────────────┘ └─────────────────┘ └─────────────┘ + │ │ + │ ┌─────────────────┐ │ + └────────────<│ USER_ROLES │ │ + │ └─────────────────┘ │ + │ │ │ + │ ▼ │ + │ ┌─────────────┐ │ + │ │ ROLES │ │ + │ └─────────────┘ │ + │ │ │ + │ ┌─────────────────┐ │ + │ │ROLE_PERMISSIONS │ │ + │ └─────────────────┘ │ + │ │ │ + │ ▼ │ + │ ┌─────────────┐ │ + │ │ PERMISSIONS │ │ + │ └─────────────┘ │ + │ │ + │ ┌─────────────────┐ ┌──────┴──────┐ + └────────────<│USER_DEPARTMENTS │>────│ DEPARTMENTS │ + └─────────────────┘ └─────────────┘ + │ + ┌──────┴──────┐ + │TENANT_DEPTS │ + └─────────────┘ +``` + +### Haupttabellen + +#### users +```sql +id INT PRIMARY KEY AUTO_INCREMENT +uuid VARCHAR(36) UNIQUE +first_name VARCHAR(100) +last_name VARCHAR(100) +email VARCHAR(255) UNIQUE +password VARCHAR(255) -- bcrypt hash +locale VARCHAR(10) -- 'de', 'en' +theme VARCHAR(20) -- 'light', 'dark' +active TINYINT DEFAULT 1 +primary_tenant_id INT FK -> tenants.id +current_tenant_id INT FK -> tenants.id +created_by INT FK -> users.id +modified_by INT FK -> users.id +created DATETIME +modified DATETIME +``` + +#### tenants +```sql +id INT PRIMARY KEY AUTO_INCREMENT +uuid VARCHAR(36) UNIQUE +description VARCHAR(255) -- Name/Firma +address VARCHAR(255) +postal_code VARCHAR(20) +city VARCHAR(100) +country VARCHAR(100) +vat_id VARCHAR(50) -- MwSt-ID +tax_number VARCHAR(50) +phone VARCHAR(50) +email VARCHAR(255) +website VARCHAR(255) +created_by INT FK -> users.id +modified_by INT FK -> users.id +created DATETIME +modified DATETIME +``` + +#### roles +```sql +id INT PRIMARY KEY AUTO_INCREMENT +uuid VARCHAR(36) UNIQUE +description VARCHAR(255) -- Rollenname +created_by INT FK -> users.id +modified_by INT FK -> users.id +created DATETIME +modified DATETIME +``` + +#### permissions +```sql +id INT PRIMARY KEY AUTO_INCREMENT +key VARCHAR(100) UNIQUE -- z.B. 'users.view' +description VARCHAR(255) +created DATETIME +``` + +#### departments +```sql +id INT PRIMARY KEY AUTO_INCREMENT +uuid VARCHAR(36) UNIQUE +description VARCHAR(255) -- Abteilungsname +created_by INT FK -> users.id +modified_by INT FK -> users.id +created DATETIME +modified DATETIME +``` + +### Verknüpfungstabellen + +| Tabelle | Beschreibung | +|---------|--------------| +| `user_tenants` | User ↔ Tenant (M:N) | +| `user_roles` | User ↔ Role (M:N) | +| `user_departments` | User ↔ Department (M:N) | +| `role_permissions` | Role ↔ Permission (M:N) | +| `tenant_departments` | Tenant ↔ Department (M:N) | + +### Vordefinierte Permissions + +``` +users.view, users.create, users.update, users.delete +users.self_update, users.update_assignments +tenants.view, tenants.create, tenants.update, tenants.delete +departments.view, departments.create, departments.update, departments.delete +roles.view, roles.create, roles.update, roles.delete +permissions.view, permissions.create, permissions.update, permissions.delete +settings.view, settings.update +mail_log.view +stats.view +``` + +--- + +## 5. PHP-Architektur + +### Schichten-Architektur + +``` +┌─────────────────────────────────────────────┐ +│ Pages │ +│ (Controller/Actions) │ +├─────────────────────────────────────────────┤ +│ Services │ +│ (Business Logic, Validation) │ +├─────────────────────────────────────────────┤ +│ Repositories │ +│ (Data Access, SQL) │ +├─────────────────────────────────────────────┤ +│ DB │ +│ (MintyPHP Database) │ +└─────────────────────────────────────────────┘ +``` + +### Service-Layer (`lib/Service/`) + +Services implementieren die Geschäftslogik: + +```php +namespace MintyPHP\Service; + +class UserService +{ + // Listen + public static function list(): array + public static function listPaged(array $options): array + + // Finder + public static function findByUuid(string $uuid): ?array + public static function findById(int $id): ?array + public static function findByEmail(string $email): ?array + + // CRUD + public static function createFromAdmin(array $input, int $currentUserId): array + public static function updateFromAdmin(int $userId, array $input, int $currentUserId): array + public static function deleteByUuid(string $uuid, int $currentUserId): array + + // Bulk-Operationen + public static function deleteByUuids(array $uuids, int $currentUserId): array + public static function setActiveByUuids(array $uuids, bool $active, int $currentUserId): array +} +``` + +**Wichtige Services:** + +| Service | Verantwortung | +|---------|---------------| +| `AuthService` | Login, Logout, Session-Management | +| `UserService` | Benutzerverwaltung | +| `TenantService` | Mandantenverwaltung | +| `RoleService` | Rollenverwaltung | +| `PermissionService` | Berechtigungsprüfung und -verwaltung | +| `DepartmentService` | Abteilungsverwaltung | +| `MailService` | E-Mail-Versand | +| `SettingService` | App-Einstellungen | + +### Repository-Layer (`lib/Repository/`) + +Repositories kapseln Datenbankzugriffe: + +```php +namespace MintyPHP\Repository; + +class UserRepository +{ + public static function list(): array + { + return DB::select('SELECT * FROM users ORDER BY last_name, first_name'); + } + + public static function find(int $id): ?array + { + return DB::selectOne('SELECT * FROM users WHERE id = ?', [$id]); + } + + public static function create(array $data): int + { + return DB::insert('users', $data); + } + + public static function update(int $id, array $data): bool + { + return DB::update('users', $data, ['id' => $id]) > 0; + } +} +``` + +### Support-Layer (`lib/Support/`) + +#### Guard - Zugriffskontrolle + +```php +namespace MintyPHP\Support; + +class Guard +{ + // Nur für angemeldete Benutzer + public static function requireLogin(string $redirect = 'login'): void + + // Spezifische Berechtigung erforderlich + public static function requirePermission(string $permissionKey, string $redirect = 'admin'): void + + // Berechtigung oder 403 (für AJAX) + public static function requirePermissionOrForbidden(string $permissionKey): void +} +``` + +#### Flash - Session-Nachrichten + +```php +namespace MintyPHP\Support; + +class Flash +{ + public static function success(string $message, ?string $scope = null, ?string $key = null): string + public static function error(string $message, ?string $scope = null, ?string $key = null): string + public static function info(string $message, ?string $scope = null, ?string $key = null): string + public static function peek(?string $scope = null): array + public static function has(): bool +} +``` + +### Helper-Funktionen (`lib/Support/helpers/`) + +```php +// HTML-Escape +e($string); + +// Asset-URL +asset('css/style.css'); + +// Lokalisierte URL +lurl('admin/users'); + +// Übersetzung +t('Hello'); +t('Welcome %s', $name); + +// App-Einstellung +appSetting('app_title'); + +// Berechtigung prüfen +can('users.view'); +``` + +--- + +## 6. Frontend-Architektur + +### CSS-Struktur (`web/css/`) + +``` +web/css/ +├── base/ +│ └── variables.css # CSS-Variablen +├── layout/ +│ ├── app-shell.css # Haupt-Layout +│ ├── app-topbar.css # Header +│ ├── app-sidebar.css # Navigation +│ └── app-aside-icon-bar.css +├── components/ +│ ├── app-buttons.css +│ ├── app-forms.css +│ ├── app-list-table.css +│ ├── app-badges.css +│ ├── app-tabs.css +│ ├── app-flash.css +│ └── vendor-*.css # Third-Party +└── pages/ + └── app-login.css +``` + +### JavaScript-Module (`web/js/`) + +ES-Module-Architektur: + +``` +web/js/ +├── app-init.js # Haupt-Initialisierung +├── core/ +│ └── app-grid-factory.js # Grid/Tabellen-Generator +├── components/ +│ ├── app-tenant-switcher.js +│ ├── app-theme-toggle.js +│ ├── app-bulk-selection.js +│ ├── app-flash-auto-dismiss.js +│ └── ... +└── pages/ + ├── app-users-list.js + └── app-list-utils.js +``` + +### Modul-Pattern + +```javascript +// web/js/components/app-tenant-switcher.js +const switchTenant = async (link) => { + const tenantId = link.dataset.switchTenant; + // ... +}; + +const initTenantSwitcher = () => { + const tenantLinks = document.querySelectorAll('[data-switch-tenant]'); + tenantLinks.forEach(link => { + link.addEventListener('click', (e) => { + e.preventDefault(); + switchTenant(link); + }); + }); +}; + +// Auto-Init bei DOM Ready +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initTenantSwitcher); +} else { + initTenantSwitcher(); +} +``` + +### Import in app-init.js + +```javascript +// web/js/app-init.js +import './components/app-tenant-switcher.js'; +import './components/app-theme-toggle.js'; +import './components/app-flash-auto-dismiss.js'; +// ... +``` + +--- + +## 7. Template-System + +### Struktur + +``` +templates/ +├── default.phtml # Haupt-Layout +├── login.phtml # Login-Layout +├── error.phtml # Fehler-Layout +├── partials/ +│ ├── app-topbar.phtml +│ ├── app-sidebar.phtml +│ ├── app-aside.phtml +│ ├── app-flash.phtml +│ └── app-footer.phtml +└── emails/ + ├── de/ + │ ├── access_info.html + │ └── reset_code.html + └── en/ + └── ... +``` + +### Template-Rendering + +```php + + + + + <?php e(Buffer::get('title') ?? appTitle()); ?> + + + + + +
+ + +
+ + + + +``` + +### Page mit View + +```php +// pages/admin/users/index().php +use MintyPHP\Buffer; +use MintyPHP\Support\Guard; + +Guard::requirePermissionOrForbidden('users.view'); + +$users = UserService::list(); + +Buffer::set('title', t('Users')); + +// View wird automatisch geladen: pages/admin/users/index(default).phtml +``` + +--- + +## 8. Authentifizierung und Autorisierung + +### Login-Ablauf + +``` +1. POST /login + │ + ├─> AuthService::login(email, password) + │ ├─> Auth::login() - Passwort-Verifikation + │ ├─> $_SESSION['user'] setzen + │ ├─> PermissionService::getUserPermissions() + │ │ └─> $_SESSION['permissions'] setzen + │ └─> AuthService::loadTenantDataIntoSession() + │ ├─> $_SESSION['available_tenants'] + │ └─> $_SESSION['current_tenant'] + │ + └─> Router::redirect('admin') +``` + +### Berechtigungsprüfung + +```php +// In Page +Guard::requirePermissionOrForbidden(PermissionService::USERS_VIEW); + +// Im Template + + Neuer Benutzer + +``` + +### Session-Struktur + +```php +$_SESSION = [ + 'user' => [ + 'id' => 1, + 'uuid' => 'abc-123', + 'email' => 'user@example.com', + 'first_name' => 'Max', + 'last_name' => 'Mustermann', + 'locale' => 'de', + 'theme' => 'dark', + ], + 'permissions' => [ + 'user_id' => 1, + 'keys' => ['users.view', 'users.create', ...], + ], + 'available_tenants' => [ + ['id' => 1, 'uuid' => '...', 'description' => 'Tenant A'], + ['id' => 2, 'uuid' => '...', 'description' => 'Tenant B'], + ], + 'current_tenant' => [ + 'id' => 1, + 'uuid' => '...', + 'description' => 'Tenant A', + ], +]; +``` + +--- + +## 9. Internationalisierung + +### Sprachdateien + +```json +// i18n/default_de.json +{ + "Login": "Anmelden", + "Users": "Benutzer", + "At least %d characters": "Mindestens %d Zeichen" +} + +// i18n/default_en.json +{ + "Login": "Login", + "Users": "Users", + "At least %d characters": "At least %d characters" +} +``` + +### Verwendung + +```php +// Einfache Übersetzung +t('Login') + +// Mit Parametern +t('At least %d characters', 12) + +// Im Template + +``` + +### Sprachauflösung + +Priorität: +1. URL-Präfix (`/de/admin`, `/en/admin`) +2. Session (`$_SESSION['user']['locale']`) +3. Cookie (`locale=de`) +4. Default (`APP_LOCALE`) + +--- + +## 10. Best Practices + +### Service-Rückgabewerte + +```php +// Erfolg +return [ + 'ok' => true, + 'uuid' => $uuid, + 'id' => $id, +]; + +// Fehler +return [ + 'ok' => false, + 'error' => 'validation_error', + 'errors' => ['email' => 'Email ist erforderlich'], + 'form' => $sanitizedInput, +]; +``` + +### Datenbankzugriff + +```php +// RICHTIG - Prepared Statements +$user = DB::selectOne('SELECT * FROM users WHERE email = ?', [$email]); + +// FALSCH - SQL-Injection +$user = DB::selectOne("SELECT * FROM users WHERE email = '$email'"); +``` + +### Template-Ausgabe + +```php +// RICHTIG - Escape + + +// FALSCH - XSS-Risiko + +``` + +### Passwort-Anforderungen + +- Mindestens 12 Zeichen +- Mindestens 1 Großbuchstabe +- Mindestens 1 Kleinbuchstabe +- Mindestens 1 Ziffer +- Mindestens 1 Sonderzeichen + +### Code-Organisation + +1. **Services** - Geschäftslogik und Validierung +2. **Repositories** - Nur Datenbankzugriff, keine Logik +3. **Guards** - Zugriffskontrolle +4. **Helpers** - Wiederverwendbare Funktionen +5. **Pages** - Koordination, keine Logik + +--- + +## Weiterführende Dokumentation + +- [MintyPHP Framework](https://github.com/mevdschee/php-crud-api) +- [Docker Setup](../docker-compose.yml) +- [Database Schema](../db/init/init.sql) diff --git a/docs/README-search.md b/docs/README-search.md new file mode 100644 index 0000000..3db032e --- /dev/null +++ b/docs/README-search.md @@ -0,0 +1,25 @@ +# Search + Upload TODO (Internal) + +Goal: Unified search across DB data and file contents (PDF, DOCX), starting with MariaDB FULLTEXT and private file storage. + +## MVP Steps +1) Create `documents` table (uuid, original_name, mime, size, storage_path, content_text, created). +2) Add FULLTEXT index on `content_text` (and later title/metadata fields if needed). +3) Build `FileUploadService`: + - Validate size/type (PDF/DOCX). + - Store outside `/web` (e.g. `storage/uploads/{uuid}/file.ext`). + - Extract text: + - PDF: `pdftotext` (poppler-utils). + - DOCX: unzip + parse `word/document.xml` (fallback: LibreOffice headless). + - Save `content_text` + metadata. +4) Add upload action + form (admin area). +5) Add search endpoint: + - Search DB entities. + - Search `documents.content_text`. + - Merge results into one list. + +## Future Enhancements +- Async extraction (queue/worker) for large files. +- Dedicated search engine (Meilisearch/Typesense) when scale/relevance needs grow. +- Result ranking with field weighting (title > body). +- Optional language detection / stemming. diff --git a/docs/conventions.md b/docs/conventions.md new file mode 100644 index 0000000..b164be6 --- /dev/null +++ b/docs/conventions.md @@ -0,0 +1,17 @@ +# Conventions (Short) + +## CSS +- All project files use `app-` prefix. +- Vendor overrides use `vendor-` prefix. +- Structure: `base/`, `layout/`, `components/`, `pages/`. + +## JS +- All project files use `app-` prefix. +- Vendor scripts stay in `web/vendor`. +- Structure: `core/`, `components/`, `pages/`. + +## Partials +- All partials use `app-` prefix (e.g. `app-footer.phtml`). + +## PHP (Lib) +- Services in `lib/Service`, repositories in `lib/Repository`. diff --git a/docs/todo-editorjs-image.md b/docs/todo-editorjs-image.md new file mode 100644 index 0000000..65daf0b --- /dev/null +++ b/docs/todo-editorjs-image.md @@ -0,0 +1,63 @@ +# TODO: Editor.js Image Tool Integration + +## Goal +Integrate the Editor.js **Image Tool** with proper upload endpoints, storage, and access control. + +## Why +- Editor.js expects uploads to respond with `{ success: 1, file: { url: "..." } }`. +- We want private storage with a controlled proxy (like avatars) and optional resizing. + +## Open Decisions +- Public access? (e.g. impressum pages should be public) +- Allowed file types (recommended: PNG/JPG/WebP; avoid SVG for security) +- Resize policy (max width + WebP variants?) + +## Proposed Structure + +### Storage +- `storage/pages/{page_uuid}/assets/{asset_uuid}/original.` +- Optional variants: `w1280.webp`, `w640.webp`, etc. + +### DB +Create `page_assets` table: +- `id`, `uuid`, `page_id`, `locale` +- `file_name`, `mime`, `size`, `width`, `height` +- `created_by`, `created` + +### Endpoints +1) **Upload by file** +`pages/page/upload-image(none).phtml` + - Accepts multipart (field name `image`). + - Validates MIME/size. + - Stores file + creates DB record. + - Returns `{ success: 1, file: { url } }`. + +2) **Fetch by URL** (optional) +`pages/page/fetch-image(none).phtml` + - Accepts JSON `{ url: "..." }`. + - Downloads, validates, stores like upload. + - Returns same response. + +3) **Media proxy** +`pages/page/media(none).phtml?uuid=...` + - Checks permissions (public vs. logged‑in). + - Reads storage file, sets headers, returns file. + +### Editor.js config +Add `image` tool to `web/js/components/page-editor.js`: +```js +image: { + class: ImageTool, + config: { + endpoints: { + byFile: 'page/upload-image', + byUrl: 'page/fetch-image' + } + } +} +``` + +## Next Steps +- Decide public vs. private access rules. +- Implement service + migration + endpoints. +- Add tool config and i18n messages. diff --git a/i18n/default_de.json b/i18n/default_de.json new file mode 100644 index 0000000..5763f45 --- /dev/null +++ b/i18n/default_de.json @@ -0,0 +1,481 @@ +{ + "Login": "Login", + "Register": "Registrieren", + "Password": "Passwort", + "Forgot password": "Passwort vergessen", + "Remember me": "Angemeldet bleiben", + "Clear login tokens": "Login-Tokens löschen", + "Clear all login tokens for this user?": "Alle Login-Tokens für diesen Benutzer löschen?", + "Login tokens cleared": "Login-Tokens gelöscht", + "Send access": "Zugang versenden", + "Send access email to this user?": "Zugangsdaten an diesen Benutzer senden?", + "Access email sent": "Zugangsdaten gesendet", + "Access email failed": "Zugangsdaten konnten nicht gesendet werden", + "Your access details": "Deine Zugangsdaten", + "Reset password": "Passwort zurücksetzen", + "Verification code": "Bestätigungscode", + "Verify code": "Code prüfen", + "Verify": "Prüfen", + "Send code": "Code senden", + "Send code again": "Code erneut senden", + "Enter your email address and we will send you a verification code.": "Gib deine E-Mail-Adresse ein, wir senden dir einen Bestätigungscode.", + "Enter the verification code we sent to your email.": "Gib den Bestätigungscode ein, den wir dir per E-Mail gesendet haben.", + "Please enter a valid email address": "Bitte gib eine gültige E-Mail-Adresse ein", + "Please enter the 6-digit code": "Bitte gib den 6-stelligen Code ein", + "Invalid or expired code": "Code ist ungültig oder abgelaufen", + "Code verified": "Code bestätigt", + "Password reset code": "Code zum Zurücksetzen des Passworts", + "If the email exists, a verification code has been sent.": "Falls die E-Mail existiert, wurde ein Bestätigungscode gesendet.", + "Choose a new password for your account.": "Wähle ein neues Passwort für dein Konto.", + "Password updated": "Passwort aktualisiert", + "Password can not be updated": "Passwort kann nicht aktualisiert werden", + "Reset request not found": "Zurücksetz-Anfrage nicht gefunden", + "Reset request already used": "Zurücksetz-Anfrage wurde bereits verwendet", + "Reset request expired": "Zurücksetz-Anfrage ist abgelaufen", + "Username": "Benutzername", + "Admin": "Admin", + "Logout": "Logout", + "Account": "Konto", + "Please enter your credentials": "Bitte geben Sie Ihre Zugangsdaten ein", + "Create your account": "Erstelle dein Konto", + "First name": "Vorname", + "Last name": "Nachname", + "Email": "E-Mail", + "Password (again)": "Passwort bestätigen", + "Password requirements": "Passwort-Anforderungen", + "At least %d characters": "Mindestens %d Zeichen", + "At least one uppercase letter": "Mindestens ein Großbuchstabe", + "At least one lowercase letter": "Mindestens ein Kleinbuchstabe", + "At least one number": "Mindestens eine Zahl", + "At least one symbol": "Mindestens ein Sonderzeichen", + "Must not contain your email": "Darf deine E-Mail nicht enthalten", + "Login successful": "Login erfolgreich", + "Email/password not valid": "E-Mail oder Passwort ist ungültig", + "First name cannot be empty": "Vorname darf nicht leer sein", + "Last name cannot be empty": "Nachname darf nicht leer sein", + "Email cannot be empty": "E-Mail darf nicht leer sein", + "Email is not valid": "E-Mail ist ungültig", + "Password cannot be empty": "Passwort darf nicht leer sein", + "Passwords must match": "Passwörter müssen übereinstimmen", + "Password must be at least %d characters": "Passwort muss mindestens %d Zeichen haben", + "Password must include an uppercase letter": "Passwort muss einen Großbuchstaben enthalten", + "Password must include a lowercase letter": "Passwort muss einen Kleinbuchstaben enthalten", + "Password must include a number": "Passwort muss eine Zahl enthalten", + "Password must include a symbol": "Passwort muss ein Sonderzeichen enthalten", + "Password must not contain your email": "Passwort darf deine E-Mail nicht enthalten", + "Email is already taken": "E-Mail ist bereits vergeben", + "User can not be registered": "Benutzer kann nicht registriert werden", + "Language not supported": "Sprache wird nicht unterstützt", + "Language": "Sprache", + "Sales": "Vertrieb", + "Sales rooms": "Verkaufsräume", + "Sales processes": "Verkaufsprozesse", + "Master data": "Stammdaten", + "Properties": "Objekte", + "Units": "Einheiten", + "Organization": "Organisation", + "Users & permissions": "Benutzer & Rechte", + "Roles & permissions": "Rollen & Rechte", + "Permissions": "Berechtigungen", + "Permission key": "Berechtigungs-Schlüssel", + "Create permission": "Berechtigung erstellen", + "Edit permission": "Berechtigung bearbeiten", + "Delete this permission?": "Diese Berechtigung löschen?", + "Permission created": "Berechtigung erstellt", + "Permission updated": "Berechtigung aktualisiert", + "Permission deleted": "Berechtigung gelöscht", + "Permission not found": "Berechtigung nicht gefunden", + "Permission can not be created": "Berechtigung kann nicht erstellt werden", + "Permission can not be updated": "Berechtigung kann nicht aktualisiert werden", + "Permission key cannot be empty": "Berechtigungs-Schlüssel darf nicht leer sein", + "Permission key is invalid": "Berechtigungs-Schlüssel ist ungültig", + "Permission key already exists": "Berechtigungs-Schlüssel existiert bereits", + "Assigned permissions": "Zugewiesene Berechtigungen", + "Select permissions": "Berechtigungen auswählen", + "Permission denied": "Keine Berechtigung", + "No active tenant assigned": "Kein aktiver Mandant zugewiesen", + "Please select at least one tenant": "Bitte mindestens einen Mandanten auswählen", + "Effective permissions": "Effektive Berechtigungen", + "perm.users.view": "Benutzer anzeigen", + "perm.users.create": "Benutzer erstellen", + "perm.users.update": "Benutzer bearbeiten", + "perm.users.delete": "Benutzer löschen", + "perm.users.self_update": "Eigenen Benutzer bearbeiten", + "perm.users.update_assignments": "Benutzerzuweisungen bearbeiten", + "Permission origin": "Herkunft der Berechtigung", + "perm.tenants.view": "Mandanten anzeigen", + "perm.tenants.create": "Mandanten erstellen", + "perm.tenants.update": "Mandanten bearbeiten", + "perm.tenants.delete": "Mandanten löschen", + "perm.departments.view": "Abteilungen anzeigen", + "perm.departments.create": "Abteilungen erstellen", + "perm.departments.update": "Abteilungen bearbeiten", + "perm.departments.delete": "Abteilungen löschen", + "perm.roles.view": "Rollen anzeigen", + "perm.roles.create": "Rollen erstellen", + "perm.roles.update": "Rollen bearbeiten", + "perm.roles.delete": "Rollen löschen", + "perm.permissions.view": "Berechtigungen anzeigen", + "perm.permissions.create": "Berechtigungen erstellen", + "perm.permissions.update": "Berechtigungen bearbeiten", + "perm.permissions.delete": "Berechtigungen löschen", + "perm.settings.view": "Einstellungen anzeigen", + "perm.settings.update": "Einstellungen bearbeiten", + "perm.mail_log.view": "E-Mail-Protokolle anzeigen", + "Select row": "Zeile auswählen", + "Select all": "Alle auswählen", + "Activate": "Aktivieren", + "Deactivate": "Deaktivieren", + "Delete": "Löschen", + "Activate users?": "Benutzer aktivieren?", + "Deactivate users?": "Benutzer deaktivieren?", + "Delete users?": "Benutzer löschen?", + "Send access emails to selected users?": "Zugangsdaten an ausgewählte Benutzer senden?", + "%d users activated": "%d Benutzer aktiviert", + "%d users deactivated": "%d Benutzer deaktiviert", + "%d users deleted": "%d Benutzer gelöscht", + "Access emails sent to %d users": "Zugangsdaten an %d Benutzer gesendet", + "Access emails sent to %d users, %f failed": "Zugangsdaten an %d Benutzer gesendet, %f fehlgeschlagen", + "Failed to activate users": "Benutzer konnten nicht aktiviert werden", + "Failed to deactivate users": "Benutzer konnten nicht deaktiviert werden", + "Failed to delete users": "Benutzer konnten nicht gelöscht werden", + "Failed to send access emails": "Zugangsdaten konnten nicht gesendet werden", + "Read": "Gelesen", + "Home": "Home", + "Users": "Benutzer", + "All users": "Alle Benutzer", + "Avatar": "Avatar", + "Theme": "Theme", + "Light": "Hell", + "Dark": "Dunkel", + "Toggle theme": "Theme umschalten", + "Toggle Sidebar": "Sidebar umschalten", + "Toggle Detail Sidebar": "Detail-Seitenleiste umschalten", + "2FA Settings": "2FA Einstellungen", + "%d selected": "%d ausgewählt", + "Create user": "Benutzer anlegen", + "Add a new user account": "Neues Benutzerkonto anlegen", + "Edit user": "Benutzer bearbeiten", + "Update account details": "Kontodaten aktualisieren", + "Create": "Erstellen", + "Create & close": "Erstellen & schließen", + "Save": "Speichern", + "Save & close": "Speichern & schließen", + "Cancel": "Abbrechen", + "Active": "Aktiv", + "Actions": "Aktionen", + "ID": "ID", + "Created": "Erstellt", + "Created by": "Erstellt von", + "Modified by": "Bearbeitet von", + "Modified": "Aktualisiert", + "No users found": "Keine Benutzer gefunden", + "Yes": "Ja", + "No": "Nein", + "User created": "Benutzer erstellt", + "User updated": "Benutzer aktualisiert", + "User deleted": "Benutzer gelöscht", + "User activated": "Benutzer aktiviert", + "User deactivated": "Benutzer deaktiviert", + "User not found": "Benutzer nicht gefunden", + "User can not be updated": "Benutzer kann nicht aktualisiert werden", + "Avatar updated": "Profilbild aktualisiert", + "Avatar removed": "Profilbild entfernt", + "Upload failed": "Upload fehlgeschlagen", + "File is too large": "Datei ist zu groß", + "Invalid image file": "Ungültige Bilddatei", + "No file uploaded": "Keine Datei hochgeladen", + "You cannot delete your own account": "Du kannst deinen eigenen Account nicht löschen", + "Login required": "Login erforderlich", + "You cannot deactivate your own account": "Du kannst dein eigenes Konto nicht deaktivieren", + "Welcome back": "Willkommen zurück", + "Total users": "Benutzer gesamt", + "Open user management": "Benutzerverwaltung öffnen", + "New password (optional)": "Neues Passwort (optional)", + "TOTP secret": "TOTP-Secret", + "Account is inactive": "Konto ist deaktiviert", + "No account yet": "Noch kein Konto", + "Inactive": "Inaktiv", + "Filter": "Filter", + "UUID": "UUID", + "Profile image": "Profilbild", + "Profile": "Profil", + "Profile description": "Profilbeschreibung", + "About": "Über", + "Info": "Info", + "Search results": "Suchergebnisse", + "Result": "Ergebnis", + "Type": "Typ", + "Page": "Seite", + "Upload image": "Bild hochladen", + "Remove image": "Bild entfernen", + "App logo": "App-Logo", + "Upload logo": "Logo hochladen", + "Remove logo": "Logo entfernen", + "Logo updated": "Logo aktualisiert", + "Logo removed": "Logo entfernt", + "Allowed file types: SVG, PNG, JPG, WEBP": "Erlaubte Dateitypen: SVG, PNG, JPG, WEBP", + "Favicon": "Favicon", + "Upload favicon": "Favicon hochladen", + "Remove favicon": "Favicon entfernen", + "Favicon updated": "Favicon aktualisiert", + "Favicon removed": "Favicon entfernt", + "Allowed file types: PNG": "Erlaubte Dateitypen: PNG", + "Square images are recommended (icons are center-cropped).": "Quadratische Bilder empfohlen (Icons werden zentriert zugeschnitten).", + "Favicon preview": "Favicon Vorschau", + "Primary color": "Primärfarbe", + "Primary color is invalid": "Primärfarbe ist ungültig", + "Show filters": "Filter anzeigen", + "Hide filters": "Filter ausblenden", + "Export CSV": "CSV exportieren", + "Reset filters": "Filter zurücksetzen", + "State": "Status", + "Edit": "Bearbeiten", + "Status": "Status", + "All": "Alle", + "All people": "Alle Personen", + "Explorer": "Explorer", + "Search": "Suche", + "Search...": "Suchen...", + "Created from": "Erstellt von", + "Created to": "Erstellt bis", + "Files": "Dateien", + "Settings": "Einstellungen", + "System": "System", + "Statistics": "Statistiken", + "Organization breakdown": "Organisations-Aufschlüsselung", + "Department assignments": "Abteilungs-Zuweisungen", + "Assigned users (Active/Inactive)": "Benutzer zugewiesen (Aktiv/Inaktiv)", + "User status": "Benutzerstatus", + "Users & roles": "Benutzer & Rollen", + "Active users": "Aktive Benutzer", + "Inactive users": "Inaktive Benutzer", + "Total emails": "E-Mails gesamt", + "Sent emails": "Gesendete E-Mails", + "Failed emails": "Fehlgeschlagene E-Mails", + "Queued emails": "E-Mails in Warteschlange", + "Last 24 hours": "Letzte 24 Stunden", + "Total (24h)": "Gesamt (24h)", + "Sent (24h)": "Gesendet (24h)", + "Failed (24h)": "Fehlgeschlagen (24h)", + "Queued (24h)": "Warteschlange (24h)", + "Sidebar sections": "Sidebar-Bereiche", + "All files": "Alle Dateien", + "My files": "Meine Dateien", + "Shared with me": "Mit mir geteilt", + "Add": "Hinzufügen", + "Search options": "Suchoptionen", + "New folder": "Neuer Ordner", + "Toggle navigation": "Navigation umschalten", + "Primary navigation": "Hauptnavigation", + "Sort column ascending": "Spalte aufsteigend sortieren", + "Sort column descending": "Spalte absteigend sortieren", + "Previous": "Zurück", + "Next": "Weiter", + "Page %d of %d": "Seite %d von %d", + "Page %d": "Seite %d", + "Showing": "Zeige", + "of": "von", + "to": "bis", + "results": "Ergebnisse", + "Loading...": "Lade...", + "No records found": "Keine Einträge gefunden", + "An error happened while fetching the data": "Fehler beim Laden der Daten", + "Delete this user?": "Diesen Benutzer wirklich löschen?", + "Delete this tenant?": "Diesen Mandanten wirklich löschen?", + "Tenant": "Mandant", + "Default tenant": "Standard-Mandant", + "Default role": "Standard-Rolle", + "Default department": "Standard-Abteilung", + "Default": "Standard", + "Identity": "Stammdaten", + "Access": "Zugang", + "Access & password": "Zugang & Passwort", + "Security": "Sicherheit", + "Preferences": "Einstellungen", + "Assignments": "Zuweisungen", + "My account": "Meine Benutzereinstellungen", + "Defaults": "Standards", + "None": "Keine", + "Settings updated": "Einstellungen gespeichert", + "setting.default_tenant": "Standard-Mandant, wenn bei der Benutzeranlage keiner zugewiesen wird", + "setting.default_role": "Standard-Rolle, wenn bei der Benutzeranlage keine Rolle zugewiesen wird", + "setting.default_department": "Standard-Abteilung, wenn bei der Benutzeranlage keine Abteilung zugewiesen wird", + "setting.app_title": "App-Titel für den Browser-Tab", + "setting.app_locale": "Standard-Sprache, wenn keine Sprache gesetzt ist", + "Default language": "Standard-Sprache", + "setting.app_theme": "Standard-Theme, wenn der Benutzer keine Präferenz hat", + "setting.app_theme_user": "Benutzer dürfen ihr eigenes Theme wählen", + "setting.app_primary_color": "Überschreibt die Standard-Primärfarbe (Hex wie #2FA4A4)", + "Default theme": "Standard-Theme", + "Allow user theme": "Benutzer-Theme erlauben", + "General": "Allgemein", + "Appearance": "Darstellung", + "Use default color": "Standardfarbe verwenden", + "Tenants can override this color in their appearance settings.": "Mandanten können diese Farbe in ihren Darstellungseinstellungen überschreiben.", + "Using the default color applies the global system appearance.": "Standardfarbe verwenden heißt: Es werden die globalen Systemeinstellungen für die Darstellung genutzt.", + "Status & meta": "Status & Meta", + "Audit": "Audit", + "Overview": "Übersicht", + "Quick actions": "Schnellaktionen", + "Send email": "E-Mail senden", + "Call phone": "Telefon anrufen", + "Call mobile": "Mobil anrufen", + "Choose color": "Farbe wählen", + "Be careful - this resets the tenants color": "Achtung – das setzt die Mandantenfarbe zurück", + "Internationalization": "Internationalisierung", + "User creation rules": "Benutzeranlage-Regeln", + "Branding": "Branding", + "App title": "App-Titel", + "Tenants": "Mandanten", + "Create tenant": "Mandant anlegen", + "Edit tenant": "Mandant bearbeiten", + "Tenant created": "Mandant erstellt", + "Tenant updated": "Mandant aktualisiert", + "Tenant deleted": "Mandant gelöscht", + "Tenant not found": "Mandant nicht gefunden", + "Tenant can not be created": "Mandant kann nicht erstellt werden", + "Tenant can not be updated": "Mandant kann nicht aktualisiert werden", + "Tenant image": "Mandantenbild", + "Assigned tenants": "Zugewiesene Mandanten", + "Primary tenant": "Hauptmandant", + "Select primary tenant": "Hauptmandant auswählen", + "Please select a primary tenant": "Bitte einen Hauptmandanten auswählen", + "Primary tenant must be one of the assigned tenants": "Der Hauptmandant muss einem zugewiesenen Mandanten entsprechen", + "Structure": "Struktur", + "Departments & roles": "Abteilungen und Rollen", + "Department assignments cleaned: %d": "Abteilungszuweisungen bereinigt: %d", + "Select tenants": "Mandanten auswählen", + "Assigned roles": "Zugewiesene Rollen", + "Select roles": "Rollen auswählen", + "Department": "Abteilung", + "Departments": "Abteilungen", + "Create department": "Abteilung anlegen", + "Edit department": "Abteilung bearbeiten", + "Department created": "Abteilung erstellt", + "Department updated": "Abteilung aktualisiert", + "Department deleted": "Abteilung gelöscht", + "Department not found": "Abteilung nicht gefunden", + "Department can not be created": "Abteilung kann nicht erstellt werden", + "Department can not be updated": "Abteilung kann nicht aktualisiert werden", + "Delete this department?": "Diese Abteilung wirklich löschen?", + "Assigned departments": "Zugewiesene Abteilungen", + "Select departments": "Abteilungen auswählen", + "Role": "Rolle", + "Roles": "Rollen", + "Create role": "Rolle anlegen", + "Edit role": "Rolle bearbeiten", + "Role created": "Rolle erstellt", + "Role updated": "Rolle aktualisiert", + "Role deleted": "Rolle gelöscht", + "Role not found": "Rolle nicht gefunden", + "Role can not be created": "Rolle kann nicht erstellt werden", + "Role can not be updated": "Rolle kann nicht aktualisiert werden", + "Delete this role?": "Diese Rolle wirklich löschen?", + "Description": "Beschreibung", + "Description cannot be empty": "Beschreibung darf nicht leer sein", + "Status is invalid": "Status ist ungültig", + "Address": "Adresse", + "Postal code": "Postleitzahl", + "City": "Ort", + "Country": "Land", + "Location": "Standort", + "Mail logs": "E-Mail-Protokolle", + "Mail log": "E-Mail-Protokoll", + "View mail log": "E-Mail-Protokoll ansehen", + "Mail log not found": "E-Mail-Protokoll nicht gefunden", + "Email details": "E-Mail-Details", + "Recipient": "Empfänger", + "Subject": "Betreff", + "Template": "Vorlage", + "Sent": "Gesendet", + "Failed": "Fehlgeschlagen", + "Queued": "Warteschlange", + "Error message": "Fehlermeldung", + "Error information": "Fehlerinformationen", + "Provider message ID": "Provider-Nachrichten-ID", + "Sent at": "Gesendet am", + "Created at": "Erstellt am", + "Delivery information": "Versandinformationen", + "All statuses": "Alle Status", + "Contact": "Kontakt", + "Support": "Support", + "Support email": "Support-E-Mail", + "Support phone": "Support-Telefon", + "VAT ID": "USt-ID", + "Tax number": "Steuernummer", + "Billing email": "Rechnungs-E-Mail", + "Phone": "Telefon", + "Website": "Webseite", + "Accounting info": "Buchhaltungsinfo", + "Communication": "Kommunikation", + "Legal": "Rechtliches", + "Privacy URL": "Datenschutz-URL", + "Imprint URL": "Impressum-URL", + "Region": "Region", + "Fax": "Fax", + "Back to Login": "Zurück zum Login", + "Back": "Zurück", + "Access denied": "Zugriff verweigert", + "You do not have permission to view this content.": "Du hast keine Berechtigung, diesen Inhalt zu sehen.", + "If you believe this is an error, please contact your system administrator.": "Wenn du glaubst, dass dies ein Fehler ist, wende dich bitte an den Systemadministrator.", + "Requested URL": "Angeforderte URL", + "Audit": "Audit", + "Forward": "Vorwärts", + "Status changed": "Status geändert", + "Status changed by": "Status geändert von", + "Page": "Seite", + "Requested path": "Angeforderter Pfad", + "Page not found": "Seite nicht gefunden", + "The page you requested does not exist or has moved.": "Die angeforderte Seite existiert nicht oder wurde verschoben.", + "Page updated": "Seite aktualisiert", + "Page can not be updated": "Seite kann nicht aktualisiert werden", + "Content is invalid": "Inhalt ist ungültig", + "You are not allowed to edit this page": "Du darfst diese Seite nicht bearbeiten", + "Form expired, please try again": "Formular abgelaufen, bitte erneut versuchen", + "Start writing...": "Mit dem Schreiben beginnen...", + "View": "Ansicht", + "Heading": "Überschrift", + "Copy content to": "Inhalt kopieren nach", + "Existing content in the target language will be overwritten": "Bestehender Inhalt in der Zielsprache wird überschrieben", + "Content copied": "Inhalt kopiert", + "Target language required": "Zielsprache erforderlich", + "Source content not found": "Quellinhalt nicht gefunden", + "Employment": "Arbeitsverhältnis", + "Job title": "Position", + "Hire date": "Eintrittsdatum", + "German": "Deutsch", + "English": "Englisch", + "Switch tenant": "Mandant wechseln", + "Copy": "Kopieren", + "Registration successful! Please check your email for the verification code.": "Registrierung erfolgreich! Bitte prüfe deine E-Mails für den Bestätigungscode.", + "A new verification code has been sent.": "Ein neuer Bestätigungscode wurde gesendet.", + "Email already verified. Please login.": "E-Mail bereits bestätigt. Bitte einloggen.", + "If the email exists, a new verification code has been sent.": "Falls die E-Mail existiert, wurde ein neuer Bestätigungscode gesendet.", + "Email verified successfully! Please login.": "E-Mail erfolgreich bestätigt! Bitte einloggen.", + "Too many failed attempts. Please request a new code.": "Zu viele Fehlversuche. Bitte fordere einen neuen Code an.", + "Verify email": "E-Mail bestätigen", + "Enter the verification code we sent to your email to complete your registration.": "Gib den Bestätigungscode ein, den wir dir per E-Mail gesendet haben, um deine Registrierung abzuschließen.", + "Email verified": "E-Mail bestätigt", + "Not verified": "Nicht bestätigt", + "Verified": "Bestätigt", + "Email settings": "E-Mail Einstellungen", + "SMTP host": "SMTP Host", + "SMTP port": "SMTP Port", + "SMTP user": "SMTP Benutzer", + "SMTP password": "SMTP Passwort", + "SMTP security": "SMTP Sicherheit", + "SMTP from address": "Absender-Adresse", + "SMTP from name": "Absendername", + "Address book": "Adressbuch", + "All people": "Alle Personen", + "Mobile": "Mobil", + "Short dial": "Kurzwahl", + "setting.smtp_host": "SMTP-Serveradresse (z.B. smtp.example.com)", + "setting.smtp_port": "SMTP-Port (z.B. 587)", + "setting.smtp_user": "SMTP-Benutzername", + "setting.smtp_password": "Leer lassen, um das bestehende Passwort zu behalten", + "setting.smtp_secure": "Verschlüsselung für SMTP", + "setting.smtp_from": "Absender-E-Mail für ausgehende Nachrichten", + "setting.smtp_from_name": "Absendername für ausgehende Nachrichten" +} diff --git a/i18n/default_en.json b/i18n/default_en.json new file mode 100644 index 0000000..5b8ecdd --- /dev/null +++ b/i18n/default_en.json @@ -0,0 +1,481 @@ +{ + "Login": "Login", + "Register": "Register", + "Password": "Password", + "Forgot password": "Forgot password", + "Remember me": "Remember me", + "Clear login tokens": "Clear login tokens", + "Clear all login tokens for this user?": "Clear all login tokens for this user?", + "Login tokens cleared": "Login tokens cleared", + "Send access": "Send access", + "Send access email to this user?": "Send access email to this user?", + "Access email sent": "Access email sent", + "Access email failed": "Access email failed", + "Your access details": "Your access details", + "Reset password": "Reset password", + "Verification code": "Verification code", + "Verify code": "Verify code", + "Verify": "Verify", + "Send code": "Send code", + "Send code again": "Send code again", + "Enter your email address and we will send you a verification code.": "Enter your email address and we will send you a verification code.", + "Enter the verification code we sent to your email.": "Enter the verification code we sent to your email.", + "Please enter a valid email address": "Please enter a valid email address", + "Please enter the 6-digit code": "Please enter the 6-digit code", + "Invalid or expired code": "Invalid or expired code", + "Code verified": "Code verified", + "Password reset code": "Password reset code", + "If the email exists, a verification code has been sent.": "If the email exists, a verification code has been sent.", + "Choose a new password for your account.": "Choose a new password for your account.", + "Password updated": "Password updated", + "Password can not be updated": "Password can not be updated", + "Reset request not found": "Reset request not found", + "Reset request already used": "Reset request already used", + "Reset request expired": "Reset request expired", + "Username": "Username", + "Admin": "Admin", + "Logout": "Logout", + "Account": "Account", + "Please enter your credentials": "Please enter your credentials", + "Create your account": "Create your account", + "First name": "First name", + "Last name": "Last name", + "Email": "Email", + "Password (again)": "Password confirm", + "Password requirements": "Password requirements", + "At least %d characters": "At least %d characters", + "At least one uppercase letter": "At least one uppercase letter", + "At least one lowercase letter": "At least one lowercase letter", + "At least one number": "At least one number", + "At least one symbol": "At least one symbol", + "Must not contain your email": "Must not contain your email", + "Login successful": "Login successful", + "Email/password not valid": "Email or password is invalid", + "First name cannot be empty": "First name cannot be empty", + "Last name cannot be empty": "Last name cannot be empty", + "Email cannot be empty": "Email cannot be empty", + "Email is not valid": "Email is not valid", + "Password cannot be empty": "Password cannot be empty", + "Passwords must match": "Passwords must match", + "Password must be at least %d characters": "Password must be at least %d characters", + "Password must include an uppercase letter": "Password must include an uppercase letter", + "Password must include a lowercase letter": "Password must include a lowercase letter", + "Password must include a number": "Password must include a number", + "Password must include a symbol": "Password must include a symbol", + "Password must not contain your email": "Password must not contain your email", + "Email is already taken": "Email is already taken", + "User can not be registered": "User can not be registered", + "Language not supported": "Language not supported", + "Language": "Language", + "Sales": "Sales", + "Sales rooms": "Sales rooms", + "Sales processes": "Sales processes", + "Master data": "Master data", + "Properties": "Properties", + "Units": "Units", + "Organization": "Organization", + "Users & permissions": "Users & permissions", + "Roles & permissions": "Roles & permissions", + "Permissions": "Permissions", + "Permission key": "Permission key", + "Create permission": "Create permission", + "Edit permission": "Edit permission", + "Delete this permission?": "Delete this permission?", + "Permission created": "Permission created", + "Permission updated": "Permission updated", + "Permission deleted": "Permission deleted", + "Permission not found": "Permission not found", + "Permission can not be created": "Permission can not be created", + "Permission can not be updated": "Permission can not be updated", + "Permission key cannot be empty": "Permission key cannot be empty", + "Permission key is invalid": "Permission key is invalid", + "Permission key already exists": "Permission key already exists", + "Assigned permissions": "Assigned permissions", + "Select permissions": "Select permissions", + "Permission denied": "Permission denied", + "No active tenant assigned": "No active tenant assigned", + "Please select at least one tenant": "Please select at least one tenant", + "Effective permissions": "Effective permissions", + "perm.users.view": "View users", + "perm.users.create": "Create users", + "perm.users.update": "Update users", + "perm.users.delete": "Delete users", + "perm.users.self_update": "Update own user", + "perm.users.update_assignments": "Update user assignments", + "Permission origin": "Permission origin", + "perm.tenants.view": "View tenants", + "perm.tenants.create": "Create tenants", + "perm.tenants.update": "Update tenants", + "perm.tenants.delete": "Delete tenants", + "perm.departments.view": "View departments", + "perm.departments.create": "Create departments", + "perm.departments.update": "Update departments", + "perm.departments.delete": "Delete departments", + "perm.roles.view": "View roles", + "perm.roles.create": "Create roles", + "perm.roles.update": "Update roles", + "perm.roles.delete": "Delete roles", + "perm.permissions.view": "View permissions", + "perm.permissions.create": "Create permissions", + "perm.permissions.update": "Update permissions", + "perm.permissions.delete": "Delete permissions", + "perm.settings.view": "View settings", + "perm.settings.update": "Update settings", + "perm.mail_log.view": "View mail logs", + "Select row": "Select row", + "Select all": "Select all", + "Activate": "Activate", + "Deactivate": "Deactivate", + "Delete": "Delete", + "Activate users?": "Activate users?", + "Deactivate users?": "Deactivate users?", + "Delete users?": "Delete users?", + "Send access emails to selected users?": "Send access emails to selected users?", + "%d users activated": "%d users activated", + "%d users deactivated": "%d users deactivated", + "%d users deleted": "%d users deleted", + "Access emails sent to %d users": "Access emails sent to %d users", + "Access emails sent to %d users, %f failed": "Access emails sent to %d users, %f failed", + "Failed to activate users": "Failed to activate users", + "Failed to deactivate users": "Failed to deactivate users", + "Failed to delete users": "Failed to delete users", + "Failed to send access emails": "Failed to send access emails", + "Read": "Read", + "Home": "Home", + "Users": "Users", + "All users": "All users", + "Avatar": "Avatar", + "Theme": "Theme", + "Light": "Light", + "Dark": "Dark", + "Toggle theme": "Toggle theme", + "Toggle Sidebar": "Toggle Sidebar", + "Toggle Detail Sidebar": "Toggle Detail Sidebar", + "2FA Settings": "2FA Settings", + "%d selected": "%d selected", + "Create user": "Create user", + "Add a new user account": "Add a new user account", + "Edit user": "Edit user", + "Update account details": "Update account details", + "Create": "Create", + "Create & close": "Create & close", + "Save": "Save", + "Save & close": "Save & close", + "Cancel": "Cancel", + "Active": "Active", + "Actions": "Actions", + "ID": "ID", + "Created": "Created", + "Created by": "Created by", + "Modified by": "Modified by", + "Modified": "Modified", + "No users found": "No users found", + "Yes": "Yes", + "No": "No", + "User created": "User created", + "User updated": "User updated", + "User deleted": "User deleted", + "User activated": "User activated", + "User deactivated": "User deactivated", + "User not found": "User not found", + "User can not be updated": "User can not be updated", + "Avatar updated": "Profile image updated", + "Avatar removed": "Profile image removed", + "Upload failed": "Upload failed", + "File is too large": "File is too large", + "Invalid image file": "Invalid image file", + "No file uploaded": "No file uploaded", + "You cannot delete your own account": "You cannot delete your own account", + "Login required": "Login required", + "You cannot deactivate your own account": "You cannot deactivate your own account", + "Welcome back": "Welcome back", + "Total users": "Total users", + "Open user management": "Open user management", + "New password (optional)": "New password (optional)", + "TOTP secret": "TOTP secret", + "Account is inactive": "Account is inactive", + "No account yet": "No account yet", + "Inactive": "Inactive", + "Filter": "Filter", + "UUID": "UUID", + "Profile image": "Profile image", + "Profile": "Profile", + "Profile description": "Profile description", + "About": "About", + "Info": "Info", + "Search results": "Search results", + "Result": "Result", + "Type": "Type", + "Page": "Page", + "Upload image": "Upload image", + "Remove image": "Remove image", + "App logo": "App logo", + "Upload logo": "Upload logo", + "Remove logo": "Remove logo", + "Logo updated": "Logo updated", + "Logo removed": "Logo removed", + "Allowed file types: SVG, PNG, JPG, WEBP": "Allowed file types: SVG, PNG, JPG, WEBP", + "Favicon": "Favicon", + "Upload favicon": "Upload favicon", + "Remove favicon": "Remove favicon", + "Favicon updated": "Favicon updated", + "Favicon removed": "Favicon removed", + "Allowed file types: PNG": "Allowed file types: PNG", + "Square images are recommended (icons are center-cropped).": "Square images are recommended (icons are center-cropped).", + "Favicon preview": "Favicon preview", + "Primary color": "Primary color", + "Primary color is invalid": "Primary color is invalid", + "Show filters": "Show filters", + "Hide filters": "Hide filters", + "Export CSV": "Export CSV", + "Reset filters": "Reset filters", + "State": "State", + "Edit": "Edit", + "Status": "Status", + "All": "All", + "All people": "All people", + "Explorer": "Explorer", + "Search": "Search", + "Search...": "Search...", + "Created from": "Created from", + "Created to": "Created to", + "Files": "Files", + "Settings": "Settings", + "System": "System", + "Statistics": "Statistics", + "Organization breakdown": "Organization breakdown", + "Department assignments": "Department assignments", + "Assigned users (Active/Inactive)": "Assigned users (Active/Inactive)", + "User status": "User status", + "Users & roles": "Users & roles", + "Active users": "Active users", + "Inactive users": "Inactive users", + "Total emails": "Total emails", + "Sent emails": "Sent emails", + "Failed emails": "Failed emails", + "Queued emails": "Queued emails", + "Last 24 hours": "Last 24 hours", + "Total (24h)": "Total (24h)", + "Sent (24h)": "Sent (24h)", + "Failed (24h)": "Failed (24h)", + "Queued (24h)": "Queued (24h)", + "Sidebar sections": "Sidebar sections", + "All files": "All files", + "My files": "My files", + "Shared with me": "Shared with me", + "Add": "Add", + "Search options": "Search options", + "New folder": "New folder", + "Toggle navigation": "Toggle navigation", + "Primary navigation": "Primary navigation", + "Sort column ascending": "Sort column ascending", + "Sort column descending": "Sort column descending", + "Previous": "Previous", + "Next": "Next", + "Page %d of %d": "Page %d of %d", + "Page %d": "Page %d", + "Showing": "Showing", + "of": "of", + "to": "to", + "results": "results", + "Loading...": "Loading...", + "No records found": "No records found", + "An error happened while fetching the data": "An error happened while fetching the data", + "Delete this user?": "Delete this user?", + "Delete this tenant?": "Delete this tenant?", + "Tenant": "Tenant", + "Default tenant": "Default tenant", + "Default role": "Default role", + "Default department": "Default department", + "Default": "Default", + "Identity": "Identity", + "Access": "Access", + "Access & password": "Access & password", + "Security": "Security", + "Preferences": "Preferences", + "Assignments": "Assignments", + "My account": "My account", + "Defaults": "Defaults", + "None": "None", + "Settings updated": "Settings updated", + "setting.default_tenant": "Default tenant used when no tenant is assigned on user creation", + "setting.default_role": "Default role used when no role is assigned on user creation", + "setting.default_department": "Default department used when no department is assigned on user creation", + "setting.app_title": "App title shown in the browser title bar", + "setting.app_locale": "Default language used when no user or URL locale is set", + "Default language": "Default language", + "setting.app_theme": "Default theme used when a user has no theme preference", + "setting.app_theme_user": "Allow users to choose their own theme", + "setting.app_primary_color": "Overrides the default primary color (hex like #2FA4A4)", + "Default theme": "Default theme", + "Allow user theme": "Allow user theme", + "General": "General", + "Appearance": "Appearance", + "Use default color": "Use default color", + "Tenants can override this color in their appearance settings.": "Tenants can override this color in their appearance settings.", + "Using the default color applies the global system appearance.": "Using the default color applies the global system appearance.", + "Status & meta": "Status & meta", + "Audit": "Audit", + "Overview": "Overview", + "Quick actions": "Quick actions", + "Send email": "Send email", + "Call phone": "Call phone", + "Call mobile": "Call mobile", + "Choose color": "Choose color", + "Be careful - this resets the tenants color": "Be careful - this resets the tenant color", + "Internationalization": "Internationalization", + "User creation rules": "User creation rules", + "Branding": "Branding", + "App title": "App title", + "Tenants": "Tenants", + "Create tenant": "Create tenant", + "Edit tenant": "Edit tenant", + "Tenant created": "Tenant created", + "Tenant updated": "Tenant updated", + "Tenant deleted": "Tenant deleted", + "Tenant not found": "Tenant not found", + "Tenant can not be created": "Tenant can not be created", + "Tenant can not be updated": "Tenant can not be updated", + "Tenant image": "Tenant image", + "Assigned tenants": "Assigned tenants", + "Primary tenant": "Primary tenant", + "Select primary tenant": "Select primary tenant", + "Please select a primary tenant": "Please select a primary tenant", + "Primary tenant must be one of the assigned tenants": "Primary tenant must be one of the assigned tenants", + "Structure": "Structure", + "Departments & roles": "Departments & roles", + "Department assignments cleaned: %d": "Department assignments cleaned: %d", + "Select tenants": "Select tenants", + "Assigned roles": "Assigned roles", + "Select roles": "Select roles", + "Department": "Department", + "Departments": "Departments", + "Create department": "Create department", + "Edit department": "Edit department", + "Department created": "Department created", + "Department updated": "Department updated", + "Department deleted": "Department deleted", + "Department not found": "Department not found", + "Department can not be created": "Department can not be created", + "Department can not be updated": "Department can not be updated", + "Delete this department?": "Delete this department?", + "Assigned departments": "Assigned departments", + "Select departments": "Select departments", + "Role": "Role", + "Roles": "Roles", + "Create role": "Create role", + "Edit role": "Edit role", + "Role created": "Role created", + "Role updated": "Role updated", + "Role deleted": "Role deleted", + "Role not found": "Role not found", + "Role can not be created": "Role can not be created", + "Role can not be updated": "Role can not be updated", + "Delete this role?": "Delete this role?", + "Description": "Description", + "Description cannot be empty": "Description cannot be empty", + "Status is invalid": "Status is invalid", + "Address": "Address", + "Postal code": "Postal code", + "City": "City", + "Country": "Country", + "Location": "Location", + "Mail logs": "Mail logs", + "Mail log": "Mail log", + "View mail log": "View mail log", + "Mail log not found": "Mail log not found", + "Email details": "Email details", + "Recipient": "Recipient", + "Subject": "Subject", + "Template": "Template", + "Sent": "Sent", + "Failed": "Failed", + "Queued": "Queued", + "Error message": "Error message", + "Error information": "Error information", + "Provider message ID": "Provider message ID", + "Sent at": "Sent at", + "Created at": "Created at", + "Delivery information": "Delivery information", + "All statuses": "All statuses", + "Contact": "Contact", + "Support": "Support", + "Support email": "Support email", + "Support phone": "Support phone", + "VAT ID": "VAT ID", + "Tax number": "Tax number", + "Billing email": "Billing email", + "Phone": "Phone", + "Website": "Website", + "Accounting info": "Accounting info", + "Communication": "Communication", + "Legal": "Legal", + "Privacy URL": "Privacy URL", + "Imprint URL": "Imprint URL", + "Region": "Region", + "Fax": "Fax", + "Back to Login": "Back to Login", + "Back": "Back", + "Access denied": "Access denied", + "You do not have permission to view this content.": "You do not have permission to view this content.", + "If you believe this is an error, please contact your system administrator.": "If you believe this is an error, please contact your system administrator.", + "Requested URL": "Requested URL", + "Audit": "Audit", + "Forward": "Forward", + "Status changed": "Status changed", + "Status changed by": "Status changed by", + "Page": "Page", + "Requested path": "Requested path", + "Page not found": "Page not found", + "The page you requested does not exist or has moved.": "The page you requested does not exist or has moved.", + "Page updated": "Page updated", + "Page can not be updated": "Page can not be updated", + "Content is invalid": "Content is invalid", + "You are not allowed to edit this page": "You are not allowed to edit this page", + "Form expired, please try again": "Form expired, please try again", + "Start writing...": "Start writing...", + "View": "View", + "Heading": "Heading", + "Copy content to": "Copy content to", + "Existing content in the target language will be overwritten": "Existing content in the target language will be overwritten", + "Content copied": "Content copied", + "Target language required": "Target language required", + "Source content not found": "Source content not found", + "Employment": "Employment", + "Job title": "Job title", + "Hire date": "Hire date", + "German": "German", + "English": "English", + "Switch tenant": "Switch tenant", + "Copy": "Copy", + "Registration successful! Please check your email for the verification code.": "Registration successful! Please check your email for the verification code.", + "A new verification code has been sent.": "A new verification code has been sent.", + "Email already verified. Please login.": "Email already verified. Please login.", + "If the email exists, a new verification code has been sent.": "If the email exists, a new verification code has been sent.", + "Email verified successfully! Please login.": "Email verified successfully! Please login.", + "Too many failed attempts. Please request a new code.": "Too many failed attempts. Please request a new code.", + "Verify email": "Verify email", + "Enter the verification code we sent to your email to complete your registration.": "Enter the verification code we sent to your email to complete your registration.", + "Email verified": "Email verified", + "Not verified": "Not verified", + "Verified": "Verified", + "Email settings": "Email settings", + "SMTP host": "SMTP host", + "SMTP port": "SMTP port", + "SMTP user": "SMTP user", + "SMTP password": "SMTP password", + "SMTP security": "SMTP security", + "SMTP from address": "SMTP from address", + "SMTP from name": "SMTP from name", + "Address book": "Address book", + "All people": "All people", + "Mobile": "Mobile", + "Short dial": "Short dial", + "setting.smtp_host": "SMTP server host (e.g. smtp.example.com)", + "setting.smtp_port": "SMTP port (e.g. 587)", + "setting.smtp_user": "SMTP username", + "setting.smtp_password": "Leave empty to keep the existing password", + "setting.smtp_secure": "SMTP encryption method", + "setting.smtp_from": "From address for outgoing emails", + "setting.smtp_from_name": "From name for outgoing emails" +} diff --git a/lib/.DS_Store b/lib/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..14531885ea1c737323e571caf14b4edaf7e4930a GIT binary patch literal 6148 zcmeHKy-ve05I&bkRAuSFfW(p&35LEwsDcC=q6=fyHUgwp38Ce0%F4pTz=U`N#49i` zGW7wNcn!X@T@sT9HU#J{vOnj1XMg!5+c6QT_GHi^Y7$W$h0$xEnq%D0rDQeh;bg^Q z3=dkJemqJ_k>U^qM1kL^fL{2tO=CQXyM8x#9ecCBQ5=T7VcdhSe*SXR-oJg`bo&Qi z_9utMyX2D9*Wk7whm;_snyV zI^dboDOmO?av46cBA+6P+}7XLR#U^R6qU28j&k_ax-&i#=*G&WG{@q{HvqxWHm&(4>>nGh-Y(v$8i7rDuoV*WsiB zgHnqEqJXQwf_ZK7`M*_t|96w*O%xCX{*?mC3p-&OpJdP0(#P>x>!Wm0*f=gTs8dkc h<5)NNC|*I)hCZJgz`$Z=5FVKP2xu9k5(R!#fp?Q8l0EconfiguredPublicPaths = $publicPaths ?? (defined('APP_PUBLIC_PATHS') ? APP_PUBLIC_PATHS : []); + } + + /** + * Check if a path is publicly accessible (no authentication required). + */ + public function isPublicPath(string $path): bool + { + $normalizedPath = $this->normalizePath($path); + + // Root path check + if ($normalizedPath === '/') { + return in_array('/', $this->configuredPublicPaths, true); + } + + // Check configured public paths + if (in_array($normalizedPath, $this->configuredPublicPaths, true)) { + return true; + } + + // Check page/ prefix with slug lookup + if (str_starts_with($normalizedPath, 'page/')) { + $pageSlug = substr($normalizedPath, strlen('page/')); + if (in_array($pageSlug, $this->configuredPublicPaths, true)) { + return true; + } + } + + // Check always-public paths + if (in_array($normalizedPath, self::ALWAYS_PUBLIC_PATHS, true)) { + return true; + } + + // Check always-public prefixes + foreach (self::ALWAYS_PUBLIC_PREFIXES as $prefix) { + if (str_starts_with($normalizedPath, $prefix)) { + return true; + } + } + + return false; + } + + /** + * Redirect to login if the path requires authentication and user is not logged in. + * + * @return bool True if access is allowed, false if redirected + */ + public function requireAuthOrRedirect(string $path, bool $isLoggedIn): bool + { + if ($this->isPublicPath($path) || $isLoggedIn) { + return true; + } + + $locale = I18n::$locale ?? I18n::$defaultLocale; + Router::redirect(Request::withLocale('login', $locale)); + + return false; + } + + private function normalizePath(string $path): string + { + $normalized = trim($path, '/'); + return $normalized === '' ? '/' : $normalized; + } +} diff --git a/lib/Http/AssetDetector.php b/lib/Http/AssetDetector.php new file mode 100644 index 0000000..f6db33b --- /dev/null +++ b/lib/Http/AssetDetector.php @@ -0,0 +1,56 @@ +defaultLocale = $defaultLocale ?? I18n::$defaultLocale; + $this->availableLocales = $availableLocales ?? (defined('APP_LOCALES') ? APP_LOCALES : [$this->defaultLocale]); + $this->basePath = trim(parse_url(Router::getBaseUrl(), PHP_URL_PATH) ?: '/', '/'); + } + + /** + * Parse a request URI and extract locale information. + * + * @return array{ + * locale: string, + * pathWithoutLocale: string, + * query: string, + * hadLocaleInUrl: bool, + * hadInvalidLocale: bool + * } + */ + public function parseUri(string $uri): array + { + $path = parse_url($uri, PHP_URL_PATH) ?: ''; + $query = parse_url($uri, PHP_URL_QUERY) ?: ''; + + $relativePath = $this->stripBasePath($path); + $segments = $relativePath === '' ? [] : explode('/', $relativePath); + + $localeCandidate = $segments[0] ?? ''; + $hadLocaleInUrl = false; + $hadInvalidLocale = false; + $locale = ''; + + if ($localeCandidate !== '' && in_array($localeCandidate, $this->availableLocales, true)) { + $locale = array_shift($segments); + $hadLocaleInUrl = true; + } elseif ($localeCandidate !== '' && $this->looksLikeLocale($localeCandidate)) { + array_shift($segments); + $hadInvalidLocale = true; + } + + return [ + 'locale' => $locale, + 'pathWithoutLocale' => implode('/', $segments), + 'query' => $query, + 'hadLocaleInUrl' => $hadLocaleInUrl, + 'hadInvalidLocale' => $hadInvalidLocale, + ]; + } + + /** + * Resolve the effective locale from multiple sources (priority order): + * 1. URL segment (explicit) + * 2. User session preference + * 3. Cookie preference + * 4. Default locale + */ + public function resolveLocale(string $urlLocale, ?string $userLocale = null, ?string $cookieLocale = null): string + { + if ($urlLocale !== '' && $this->isValidLocale($urlLocale)) { + return $urlLocale; + } + + if ($userLocale !== null && $userLocale !== '' && $this->isValidLocale($userLocale)) { + return $userLocale; + } + + if ($cookieLocale !== null && $cookieLocale !== '' && $this->isValidLocale($cookieLocale)) { + return $cookieLocale; + } + + return $this->defaultLocale; + } + + /** + * Build a new REQUEST_URI without the locale segment. + */ + public function buildUriWithoutLocale(string $pathWithoutLocale, string $query): string + { + $newPath = $this->basePath !== '' ? '/' . $this->basePath : ''; + + if ($pathWithoutLocale !== '') { + $newPath .= '/' . $pathWithoutLocale; + } elseif ($newPath === '') { + $newPath = '/'; + } + + return $newPath . ($query !== '' ? '?' . $query : ''); + } + + /** + * Check if a locale string is valid (exists in available locales). + */ + public function isValidLocale(string $locale): bool + { + return in_array($locale, $this->availableLocales, true); + } + + public function getAvailableLocales(): array + { + return $this->availableLocales; + } + + public function getDefaultLocale(): string + { + return $this->defaultLocale; + } + + private function stripBasePath(string $path): string + { + $relativePath = ltrim($path, '/'); + + if ($this->basePath !== '' && strpos($relativePath, $this->basePath . '/') === 0) { + return substr($relativePath, strlen($this->basePath) + 1); + } + + if ($this->basePath !== '' && $relativePath === $this->basePath) { + return ''; + } + + return $relativePath; + } + + private function looksLikeLocale(string $candidate): bool + { + return preg_match('/^[a-z]{2}(?:-[a-z]{2})?$/i', $candidate) === 1; + } +} diff --git a/lib/Http/Request.php b/lib/Http/Request.php new file mode 100644 index 0000000..818a8f7 --- /dev/null +++ b/lib/Http/Request.php @@ -0,0 +1,102 @@ + $id > 0); + if (!$tenantIds) { + return []; + } + $placeholders = implode(',', array_fill(0, count($tenantIds), '?')); + $rows = DB::select( + 'select departments.id, departments.uuid, departments.description, departments.created_by, departments.modified_by, departments.created, departments.modified ' . + 'from departments departments join tenant_departments td on td.department_id = departments.id ' . + 'where td.tenant_id in (' . $placeholders . ') ' . + 'group by departments.id, departments.uuid, departments.description, departments.created_by, departments.modified_by, departments.created, departments.modified ' . + 'order by departments.description asc', + ...array_map('strval', $tenantIds) + ); + return self::unwrapList($rows); + } + + public static function listByIds(array $departmentIds): array + { + $departmentIds = array_values(array_unique(array_map('intval', $departmentIds))); + $departmentIds = array_filter($departmentIds, static fn ($id) => $id > 0); + if (!$departmentIds) { + return []; + } + $placeholders = implode(',', array_fill(0, count($departmentIds), '?')); + $rows = DB::select( + 'select id, uuid, description, created_by, modified_by, created, modified from departments where id in (' . $placeholders . ') order by description asc', + ...array_map('strval', $departmentIds) + ); + return self::unwrapList($rows); + } + + public static function listPaged(array $options): array + { + $limit = (int) ($options['limit'] ?? 10); + if ($limit < 1) { + $limit = 10; + } elseif ($limit > 100) { + $limit = 100; + } + + $offset = (int) ($options['offset'] ?? 0); + if ($offset < 0) { + $offset = 0; + } + + $search = trim((string) ($options['search'] ?? '')); + $tenant = trim((string) ($options['tenant'] ?? '')); + $order = (string) ($options['order'] ?? 'id'); + $dir = strtolower((string) ($options['dir'] ?? 'desc')); + $allowedOrder = ['id', 'uuid', 'description', 'created', 'modified']; + if (!in_array($order, $allowedOrder, true)) { + $order = 'id'; + } + if (!in_array($dir, ['asc', 'desc'], true)) { + $dir = 'desc'; + } + + $where = []; + $params = []; + if ($search !== '') { + $like = '%' . $search . '%'; + $where[] = '(description like ? or uuid like ?)'; + $params[] = $like; + $params[] = $like; + } + if ($tenant !== '') { + $where[] = "exists (select 1 from tenant_departments td join tenants t on t.id = td.tenant_id and t.status = 'active' where td.department_id = departments.id and t.uuid = ?)"; + $params[] = $tenant; + } + if (!empty($options['tenantUserId'])) { + $tenantUserId = (int) $options['tenantUserId']; + if ($tenantUserId > 0) { + if (defined('TENANT_SCOPE_STRICT') && TENANT_SCOPE_STRICT) { + $where[] = 'exists (select 1 from tenant_departments td ' . + "join tenants t on t.id = td.tenant_id and t.status = 'active' " . + 'join user_tenants ut on ut.tenant_id = td.tenant_id ' . + 'where ut.user_id = ? and td.department_id = departments.id)'; + $params[] = (string) $tenantUserId; + } else { + $where[] = '(not exists (select 1 from tenant_departments td where td.department_id = departments.id) ' . + 'or exists (select 1 from tenant_departments td ' . + "join tenants t on t.id = td.tenant_id and t.status = 'active' " . + 'join user_tenants ut on ut.tenant_id = td.tenant_id ' . + 'where ut.user_id = ? and td.department_id = departments.id))'; + $params[] = (string) $tenantUserId; + } + } + } elseif (array_key_exists('tenantIds', $options)) { + $tenantIds = $options['tenantIds']; + $tenantIds = is_array($tenantIds) ? array_values(array_unique(array_map('intval', $tenantIds))) : []; + if ($tenantIds) { + if (defined('TENANT_SCOPE_STRICT') && TENANT_SCOPE_STRICT) { + $where[] = 'exists (select 1 from tenant_departments td where td.department_id = departments.id and td.tenant_id in (???))'; + $params[] = $tenantIds; + } else { + $where[] = '(not exists (select 1 from tenant_departments td where td.department_id = departments.id) ' . + 'or exists (select 1 from tenant_departments td where td.department_id = departments.id and td.tenant_id in (???)))'; + $params[] = $tenantIds; + } + } else { + if (defined('TENANT_SCOPE_STRICT') && TENANT_SCOPE_STRICT) { + $where[] = '1=0'; + } else { + $where[] = 'not exists (select 1 from tenant_departments td where td.department_id = departments.id)'; + } + } + } + + $whereSql = $where ? (' where ' . implode(' and ', $where)) : ''; + $count = DB::selectValue('select count(*) from departments' . $whereSql, ...$params); + $total = $count ? (int) $count : 0; + + $query = 'select id, uuid, description, created_by, modified_by, created, modified from departments' . + $whereSql . + sprintf(' order by `%s` %s limit ? offset ?', $order, $dir); + + $queryParams = array_merge($params, [(string) $limit, (string) $offset]); + $rows = call_user_func_array(['MintyPHP\\DB', 'select'], array_merge([$query], $queryParams)); + + $list = self::unwrapList($rows); + $ids = []; + foreach ($list as $department) { + if (isset($department['id'])) { + $ids[] = (int) $department['id']; + } + } + $tenantLabelsByDepartment = []; + if ($ids) { + $placeholders = implode(',', array_fill(0, count($ids), '?')); + $labelRows = DB::select( + "select td.department_id as department_id, t.description as description from tenant_departments td join tenants t on t.id = td.tenant_id and t.status = 'active' " . + 'where td.department_id in (' . $placeholders . ') order by t.description asc', + ...array_map('strval', $ids) + ); + $collectLabels = static function (array $rows): array { + $labelsByDepartment = []; + foreach ($rows as $row) { + $departmentId = 0; + $label = ''; + if (isset($row['td']) && is_array($row['td'])) { + $departmentId = (int) ($row['td']['department_id'] ?? 0); + } + if (isset($row['t']) && is_array($row['t'])) { + $label = (string) ($row['t']['description'] ?? ''); + } + if ($departmentId === 0 || $label === '') { + foreach ($row as $value) { + if (!is_array($value)) { + continue; + } + if ($departmentId === 0 && isset($value['department_id'])) { + $departmentId = (int) $value['department_id']; + } + if ($label === '' && isset($value['description'])) { + $label = (string) $value['description']; + } + } + } + if ($departmentId === 0 && isset($row['department_id'])) { + $departmentId = (int) $row['department_id']; + } + if ($label === '' && isset($row['description'])) { + $label = (string) $row['description']; + } + if ($departmentId > 0 && $label !== '') { + $labelsByDepartment[$departmentId] ??= []; + $labelsByDepartment[$departmentId][] = $label; + } + } + return $labelsByDepartment; + }; + $tenantLabelsByDepartment = $collectLabels($labelRows); + } + foreach ($list as &$department) { + $departmentId = (int) ($department['id'] ?? 0); + $department['tenant_labels'] = $tenantLabelsByDepartment[$departmentId] ?? []; + } + unset($department); + + return [ + 'total' => $total, + 'rows' => $list, + ]; + } + + public static function find(int $id): ?array + { + $row = DB::selectOne( + 'select id, uuid, description, created_by, modified_by, created, modified from departments where id = ? limit 1', + (string) $id + ); + return self::unwrap($row); + } + + public static function findByUuid(string $uuid): ?array + { + $row = DB::selectOne( + 'select id, uuid, description, created_by, modified_by, created, modified from departments where uuid = ? limit 1', + $uuid + ); + return self::unwrap($row); + } + + private static function uuidV4(): string + { + $data = random_bytes(16); + $data[6] = chr((ord($data[6]) & 0x0f) | 0x40); + $data[8] = chr((ord($data[8]) & 0x3f) | 0x80); + return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); + } + + public static function create(array $data) + { + return DB::insert( + 'insert into departments (uuid, description, created_by, created) values (?,?,?,NOW())', + $data['uuid'] ?? self::uuidV4(), + $data['description'], + $data['created_by'] ?? null + ); + } + + public static function update(int $id, array $data): bool + { + $fields = [ + 'description' => $data['description'], + ]; + if (array_key_exists('modified_by', $data)) { + $fields['modified_by'] = $data['modified_by']; + } + + $setParts = []; + $params = []; + foreach ($fields as $field => $value) { + $setParts[] = sprintf('`%s` = ?', $field); + $params[] = $value; + } + $params[] = (string) $id; + + $query = 'update departments set ' . implode(', ', $setParts) . ' where id = ?'; + $result = DB::update($query, ...$params); + return $result !== false; + } + + public static function delete(int $id): bool + { + $result = DB::delete('delete from departments where id = ?', (string) $id); + return $result !== false; + } +} diff --git a/lib/Repository/EmailVerificationRepository.php b/lib/Repository/EmailVerificationRepository.php new file mode 100644 index 0000000..2edb68d --- /dev/null +++ b/lib/Repository/EmailVerificationRepository.php @@ -0,0 +1,71 @@ + UTC_TIMESTAMP() order by id desc limit 1', + (string) $userId + ); + if (!$row || !isset($row['email_verifications'])) { + return null; + } + return $row['email_verifications']; + } + + public static function findById(int $id): ?array + { + $row = DB::selectOne( + 'select id, user_id, code_hash, expires_at, attempts, used_at from email_verifications where id = ? limit 1', + (string) $id + ); + if (!$row || !isset($row['email_verifications'])) { + return null; + } + return $row['email_verifications']; + } + + public static function incrementAttempts(int $id): bool + { + $result = DB::update( + 'update email_verifications set attempts = attempts + 1 where id = ?', + (string) $id + ); + return $result !== false; + } + + public static function markUsed(int $id): bool + { + $result = DB::update( + 'update email_verifications set used_at = NOW() where id = ?', + (string) $id + ); + return $result !== false; + } +} diff --git a/lib/Repository/MailLogRepository.php b/lib/Repository/MailLogRepository.php new file mode 100644 index 0000000..409a235 --- /dev/null +++ b/lib/Repository/MailLogRepository.php @@ -0,0 +1,142 @@ + 100) { + $limit = 100; + } + + $offset = (int) ($options['offset'] ?? 0); + if ($offset < 0) { + $offset = 0; + } + + $search = trim((string) ($options['search'] ?? '')); + $order = (string) ($options['order'] ?? 'created_at'); + $dir = strtolower((string) ($options['dir'] ?? 'desc')); + $status = trim((string) ($options['status'] ?? '')); + $createdFrom = trim((string) ($options['created_from'] ?? '')); + $createdTo = trim((string) ($options['created_to'] ?? '')); + + $allowedOrder = ['id', 'created_at', 'sent_at', 'to_email', 'subject', 'status']; + if (!in_array($order, $allowedOrder, true)) { + $order = 'created_at'; + } + if (!in_array($dir, ['asc', 'desc'], true)) { + $dir = 'desc'; + } + + $where = []; + $params = []; + if ($search !== '') { + $like = '%' . $search . '%'; + $where[] = '(to_email like ? or subject like ? or template like ?)'; + $params[] = $like; + $params[] = $like; + $params[] = $like; + } + if ($status !== '') { + $where[] = 'status = ?'; + $params[] = $status; + } + if ($createdFrom !== '') { + $where[] = 'created_at >= ?'; + $params[] = $createdFrom . ' 00:00:00'; + } + if ($createdTo !== '') { + $where[] = 'created_at <= ?'; + $params[] = $createdTo . ' 23:59:59'; + } + + $whereSql = $where ? (' where ' . implode(' and ', $where)) : ''; + $count = DB::selectValue('select count(*) from mail_log' . $whereSql, ...$params); + $total = $count ? (int) $count : 0; + + $query = 'select id, to_email, subject, template, status, created_at, sent_at, error_message, provider_message_id from mail_log' . + $whereSql . + sprintf(' order by `%s` %s limit ? offset ?', $order, $dir); + + $queryParams = array_merge($params, [(string) $limit, (string) $offset]); + $rows = call_user_func_array(['MintyPHP\\DB', 'select'], array_merge([$query], $queryParams)); + + return [ + 'total' => $total, + 'rows' => self::unwrapList($rows), + ]; + } + + public static function find(int $id): ?array + { + $row = DB::selectOne( + 'select id, to_email, subject, template, status, created_at, sent_at, error_message, provider_message_id from mail_log where id = ? limit 1', + (string) $id + ); + return self::unwrap($row); + } +} diff --git a/lib/Repository/PageContentRepository.php b/lib/Repository/PageContentRepository.php new file mode 100644 index 0000000..a40fc41 --- /dev/null +++ b/lib/Repository/PageContentRepository.php @@ -0,0 +1,59 @@ + $data['content'] ?? null, + ]; + if (array_key_exists('modified_by', $data)) { + $fields['modified_by'] = $data['modified_by']; + } + + $setParts = []; + $params = []; + foreach ($fields as $field => $value) { + $setParts[] = sprintf('`%s` = ?', $field); + $params[] = $value; + } + $params[] = (string) $id; + + $query = 'update page_contents set ' . implode(', ', $setParts) . ', modified = NOW() where id = ?'; + $result = DB::update($query, ...$params); + return $result !== false; + } +} diff --git a/lib/Repository/PageRepository.php b/lib/Repository/PageRepository.php new file mode 100644 index 0000000..90061a5 --- /dev/null +++ b/lib/Repository/PageRepository.php @@ -0,0 +1,25 @@ + UTC_TIMESTAMP() order by id desc limit 1', + (string) $userId + ); + if (!$row || !isset($row['password_resets'])) { + return null; + } + return $row['password_resets']; + } + + public static function findById(int $id): ?array + { + $row = DB::selectOne( + 'select id, user_id, code_hash, expires_at, attempts, used_at from password_resets where id = ? limit 1', + (string) $id + ); + if (!$row || !isset($row['password_resets'])) { + return null; + } + return $row['password_resets']; + } + + public static function incrementAttempts(int $id): bool + { + $result = DB::update( + 'update password_resets set attempts = attempts + 1 where id = ?', + (string) $id + ); + return $result !== false; + } + + public static function markUsed(int $id): bool + { + $result = DB::update( + 'update password_resets set used_at = NOW() where id = ?', + (string) $id + ); + return $result !== false; + } +} diff --git a/lib/Repository/PermissionRepository.php b/lib/Repository/PermissionRepository.php new file mode 100644 index 0000000..403079d --- /dev/null +++ b/lib/Repository/PermissionRepository.php @@ -0,0 +1,104 @@ + '`key`', 'description' => 'description', 'created' => 'created']; + $orderBy = $allowedOrder[$order] ?? $allowedOrder['key']; + + $where = []; + $params = []; + if ($search !== '') { + $where[] = '(permissions.`key` like ? or permissions.description like ?)'; + $params[] = '%' . $search . '%'; + $params[] = '%' . $search . '%'; + } + $whereSql = $where ? ' where ' . implode(' and ', $where) : ''; + + $total = DB::selectValue('select count(*) from permissions' . $whereSql, ...$params); + $query = 'select id, `key`, description, created from permissions' . $whereSql . + ' order by ' . $orderBy . ' ' . $dir . ' limit ? offset ?'; + $queryParams = array_merge($params, [(string) $limit, (string) $offset]); + $rows = DB::select($query, ...$queryParams); + $list = []; + foreach ($rows as $row) { + $data = $row['permissions'] ?? $row; + if (is_array($data)) { + $list[] = $data; + } + } + return ['data' => $list, 'total' => (int) $total]; + } + + public static function find(int $id): ?array + { + $row = DB::selectOne('select id, `key`, description, created from permissions where id = ? limit 1', (string) $id); + $data = $row['permissions'] ?? $row; + return is_array($data) ? $data : null; + } + + public static function findByKey(string $key): ?array + { + $row = DB::selectOne('select id, `key`, description, created from permissions where `key` = ? limit 1', $key); + $data = $row['permissions'] ?? $row; + return is_array($data) ? $data : null; + } + + public static function create(array $data): ?int + { + $key = trim((string) ($data['key'] ?? '')); + $desc = trim((string) ($data['description'] ?? '')); + $result = DB::insert( + 'insert into permissions (`key`, description, created) values (?,?,NOW())', + $key, + $desc !== '' ? $desc : null + ); + return $result ? (int) $result : null; + } + + public static function update(int $id, array $data): bool + { + $key = trim((string) ($data['key'] ?? '')); + $desc = trim((string) ($data['description'] ?? '')); + $result = DB::update( + 'update permissions set `key` = ?, description = ? where id = ?', + $key, + $desc !== '' ? $desc : null, + (string) $id + ); + return $result !== false; + } + + public static function delete(int $id): bool + { + $result = DB::delete('delete from permissions where id = ?', (string) $id); + return (bool) $result; + } +} diff --git a/lib/Repository/RememberTokenRepository.php b/lib/Repository/RememberTokenRepository.php new file mode 100644 index 0000000..39a3240 --- /dev/null +++ b/lib/Repository/RememberTokenRepository.php @@ -0,0 +1,55 @@ + $key, + 'description' => $desc, + 'roles' => [], + ]; + } + $roleLabel = (string) (($rowRole['description'] ?? $rowRole['role'] ?? $row['role'] ?? '') ?? ''); + if ($roleLabel !== '') { + $permMap[$permId]['roles'][] = $roleLabel; + } + } + foreach ($permMap as &$item) { + $item['roles'] = array_values(array_unique($item['roles'] ?? [])); + } + unset($item); + return array_values($permMap); + } +} diff --git a/lib/Repository/RoleRepository.php b/lib/Repository/RoleRepository.php new file mode 100644 index 0000000..59153f3 --- /dev/null +++ b/lib/Repository/RoleRepository.php @@ -0,0 +1,170 @@ + 100) { + $limit = 100; + } + + $offset = (int) ($options['offset'] ?? 0); + if ($offset < 0) { + $offset = 0; + } + + $search = trim((string) ($options['search'] ?? '')); + $order = (string) ($options['order'] ?? 'id'); + $dir = strtolower((string) ($options['dir'] ?? 'desc')); + $allowedOrder = ['id', 'uuid', 'description', 'created', 'modified']; + if (!in_array($order, $allowedOrder, true)) { + $order = 'id'; + } + if (!in_array($dir, ['asc', 'desc'], true)) { + $dir = 'desc'; + } + + $where = []; + $params = []; + if ($search !== '') { + $like = '%' . $search . '%'; + $where[] = '(description like ? or uuid like ?)'; + $params[] = $like; + $params[] = $like; + } + + $whereSql = $where ? (' where ' . implode(' and ', $where)) : ''; + $count = DB::selectValue('select count(*) from roles' . $whereSql, ...$params); + $total = $count ? (int) $count : 0; + + $query = 'select id, uuid, description, created_by, modified_by, created, modified from roles' . + $whereSql . + sprintf(' order by `%s` %s limit ? offset ?', $order, $dir); + + $queryParams = array_merge($params, [(string) $limit, (string) $offset]); + $rows = call_user_func_array(['MintyPHP\\DB', 'select'], array_merge([$query], $queryParams)); + + return [ + 'total' => $total, + 'rows' => self::unwrapList($rows), + ]; + } + + public static function find(int $id): ?array + { + $row = DB::selectOne( + 'select id, uuid, description, created_by, modified_by, created, modified from roles where id = ? limit 1', + (string) $id + ); + return self::unwrap($row); + } + + public static function findByUuid(string $uuid): ?array + { + $row = DB::selectOne( + 'select id, uuid, description, created_by, modified_by, created, modified from roles where uuid = ? limit 1', + $uuid + ); + return self::unwrap($row); + } + + private static function uuidV4(): string + { + $data = random_bytes(16); + $data[6] = chr((ord($data[6]) & 0x0f) | 0x40); + $data[8] = chr((ord($data[8]) & 0x3f) | 0x80); + return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); + } + + public static function create(array $data) + { + return DB::insert( + 'insert into roles (uuid, description, created_by, created) values (?,?,?,NOW())', + $data['uuid'] ?? self::uuidV4(), + $data['description'], + $data['created_by'] ?? null + ); + } + + public static function update(int $id, array $data): bool + { + $fields = [ + 'description' => $data['description'], + ]; + if (array_key_exists('modified_by', $data)) { + $fields['modified_by'] = $data['modified_by']; + } + + $setParts = []; + $params = []; + foreach ($fields as $field => $value) { + $setParts[] = sprintf('`%s` = ?', $field); + $params[] = $value; + } + $params[] = (string) $id; + + $query = 'update roles set ' . implode(', ', $setParts) . ' where id = ?'; + $result = DB::update($query, ...$params); + return $result !== false; + } + + public static function delete(int $id): bool + { + $result = DB::delete('delete from roles where id = ?', (string) $id); + return $result !== false; + } +} diff --git a/lib/Repository/SettingRepository.php b/lib/Repository/SettingRepository.php new file mode 100644 index 0000000..613b0a7 --- /dev/null +++ b/lib/Repository/SettingRepository.php @@ -0,0 +1,35 @@ + $id > 0); + if (!$tenantIds) { + return []; + } + $placeholders = implode(',', array_fill(0, count($tenantIds), '?')); + $rows = DB::select( + 'select department_id from tenant_departments where tenant_id in (' . $placeholders . ')', + ...array_map('strval', $tenantIds) + ); + if (!is_array($rows)) { + return []; + } + $ids = []; + foreach ($rows as $row) { + $data = $row['tenant_departments'] ?? $row; + if (is_array($data) && isset($data['department_id'])) { + $ids[] = (int) $data['department_id']; + } + } + return array_values(array_unique($ids)); + } + + public static function replaceForDepartment(int $departmentId, array $tenantIds): bool + { + DB::delete('delete from tenant_departments where department_id = ?', (string) $departmentId); + $tenantIds = array_values(array_unique(array_map('intval', $tenantIds))); + $tenantIds = array_filter($tenantIds, static fn ($id) => $id > 0); + if (!$tenantIds) { + return true; + } + + foreach ($tenantIds as $tenantId) { + DB::insert( + 'insert into tenant_departments (tenant_id, department_id, created) values (?,?,NOW())', + (string) $tenantId, + (string) $departmentId + ); + } + + return true; + } +} diff --git a/lib/Repository/TenantRepository.php b/lib/Repository/TenantRepository.php new file mode 100644 index 0000000..d0b49d7 --- /dev/null +++ b/lib/Repository/TenantRepository.php @@ -0,0 +1,249 @@ + 100) { + $limit = 100; + } + + $offset = (int) ($options['offset'] ?? 0); + if ($offset < 0) { + $offset = 0; + } + + $search = trim((string) ($options['search'] ?? '')); + $order = (string) ($options['order'] ?? 'id'); + $dir = strtolower((string) ($options['dir'] ?? 'desc')); + $allowedOrder = ['id', 'uuid', 'description', 'created', 'modified']; + if (!in_array($order, $allowedOrder, true)) { + $order = 'id'; + } + if (!in_array($dir, ['asc', 'desc'], true)) { + $dir = 'desc'; + } + + $where = []; + $params = []; + if ($search !== '') { + $like = '%' . $search . '%'; + $where[] = '(description like ? or uuid like ?)'; + $params[] = $like; + $params[] = $like; + } + if (!empty($options['tenantUserId'])) { + $tenantUserId = (int) $options['tenantUserId']; + if ($tenantUserId > 0) { + $where[] = 'exists (select 1 from user_tenants ut where ut.user_id = ? and ut.tenant_id = tenants.id)'; + $params[] = (string) $tenantUserId; + } + } + + $whereSql = $where ? (' where ' . implode(' and ', $where)) : ''; + $count = DB::selectValue('select count(*) from tenants' . $whereSql, ...$params); + $total = $count ? (int) $count : 0; + + $query = 'select id, uuid, description, address, postal_code, city, country, region, vat_id, tax_number, phone, fax, email, support_email, support_phone, billing_email, website, privacy_url, imprint_url, primary_color, status, status_changed_at, status_changed_by, created_by, modified_by, created, modified from tenants' . + $whereSql . + sprintf(' order by `%s` %s limit ? offset ?', $order, $dir); + + $queryParams = array_merge($params, [(string) $limit, (string) $offset]); + $rows = call_user_func_array(['MintyPHP\\DB', 'select'], array_merge([$query], $queryParams)); + + return [ + 'total' => $total, + 'rows' => self::unwrapList($rows), + ]; + } + + public static function find(int $id): ?array + { + $row = DB::selectOne( + 'select id, uuid, description, address, postal_code, city, country, region, vat_id, tax_number, phone, fax, email, support_email, support_phone, billing_email, website, privacy_url, imprint_url, primary_color, status, status_changed_at, status_changed_by, created_by, modified_by, created, modified from tenants where id = ? limit 1', + (string) $id + ); + return self::unwrap($row); + } + + public static function findByUuid(string $uuid): ?array + { + $row = DB::selectOne( + 'select id, uuid, description, address, postal_code, city, country, region, vat_id, tax_number, phone, fax, email, support_email, support_phone, billing_email, website, privacy_url, imprint_url, primary_color, status, status_changed_at, status_changed_by, created_by, modified_by, created, modified from tenants where uuid = ? limit 1', + $uuid + ); + return self::unwrap($row); + } + + private static function uuidV4(): string + { + $data = random_bytes(16); + $data[6] = chr((ord($data[6]) & 0x0f) | 0x40); + $data[8] = chr((ord($data[8]) & 0x3f) | 0x80); + return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); + } + + public static function create(array $data) + { + return DB::insert( + 'insert into tenants (uuid, description, address, postal_code, city, country, region, vat_id, tax_number, phone, fax, email, support_email, support_phone, billing_email, website, privacy_url, imprint_url, primary_color, status, status_changed_at, status_changed_by, created_by, created) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,NOW())', + $data['uuid'] ?? self::uuidV4(), + $data['description'], + $data['address'] ?? null, + $data['postal_code'] ?? null, + $data['city'] ?? null, + $data['country'] ?? null, + $data['region'] ?? null, + $data['vat_id'] ?? null, + $data['tax_number'] ?? null, + $data['phone'] ?? null, + $data['fax'] ?? null, + $data['email'] ?? null, + $data['support_email'] ?? null, + $data['support_phone'] ?? null, + $data['billing_email'] ?? null, + $data['website'] ?? null, + $data['privacy_url'] ?? null, + $data['imprint_url'] ?? null, + $data['primary_color'] ?? null, + $data['status'] ?? 'active', + $data['status_changed_at'] ?? null, + $data['status_changed_by'] ?? null, + $data['created_by'] ?? null + ); + } + + public static function update(int $id, array $data): bool + { + $fields = [ + 'description' => $data['description'], + 'address' => $data['address'] ?? null, + 'postal_code' => $data['postal_code'] ?? null, + 'city' => $data['city'] ?? null, + 'country' => $data['country'] ?? null, + 'region' => $data['region'] ?? null, + 'vat_id' => $data['vat_id'] ?? null, + 'tax_number' => $data['tax_number'] ?? null, + 'phone' => $data['phone'] ?? null, + 'fax' => $data['fax'] ?? null, + 'email' => $data['email'] ?? null, + 'support_email' => $data['support_email'] ?? null, + 'support_phone' => $data['support_phone'] ?? null, + 'billing_email' => $data['billing_email'] ?? null, + 'website' => $data['website'] ?? null, + 'privacy_url' => $data['privacy_url'] ?? null, + 'imprint_url' => $data['imprint_url'] ?? null, + 'primary_color' => $data['primary_color'] ?? null, + 'status' => $data['status'] ?? 'active', + ]; + if (array_key_exists('modified_by', $data)) { + $fields['modified_by'] = $data['modified_by']; + } + if (array_key_exists('status_changed_at', $data)) { + $fields['status_changed_at'] = $data['status_changed_at']; + } + if (array_key_exists('status_changed_by', $data)) { + $fields['status_changed_by'] = $data['status_changed_by']; + } + + $setParts = []; + $params = []; + foreach ($fields as $field => $value) { + $setParts[] = sprintf('`%s` = ?', $field); + $params[] = $value; + } + $params[] = (string) $id; + + $query = 'update tenants set ' . implode(', ', $setParts) . ' where id = ?'; + $result = DB::update($query, ...$params); + return $result !== false; + } + + public static function delete(int $id): bool + { + $result = DB::delete('delete from tenants where id = ?', (string) $id); + return $result !== false; + } +} diff --git a/lib/Repository/UserDepartmentRepository.php b/lib/Repository/UserDepartmentRepository.php new file mode 100644 index 0000000..0087a5b --- /dev/null +++ b/lib/Repository/UserDepartmentRepository.php @@ -0,0 +1,54 @@ + $value) { + if ($key === 'users' || is_array($value)) { + continue; + } + $user[$key] = $value; + } + if (isset($row['pt']) && is_array($row['pt'])) { + $label = (string) ($row['pt']['description'] ?? ''); + if ($label !== '') { + $user['primary_tenant_label'] = $label; + } + } + $list[] = $user; + } + } + return $list; + } + + public static function list(): array + { + $rows = DB::select( + 'select id, uuid, first_name, last_name, email, profile_description, job_title, phone, mobile, short_dial, theme, primary_tenant_id, created_by, modified_by, created, modified, active from users order by id desc' + ); + return self::unwrapList($rows); + } + + public static function listPaged(array $options): array + { + $limit = (int) ($options['limit'] ?? 10); + if ($limit < 1) { + $limit = 10; + } elseif ($limit > 100) { + $limit = 100; + } + + $offset = (int) ($options['offset'] ?? 0); + if ($offset < 0) { + $offset = 0; + } + + $search = trim((string) ($options['search'] ?? '')); + $active = $options['active'] ?? null; + $createdFrom = trim((string) ($options['created_from'] ?? '')); + $createdTo = trim((string) ($options['created_to'] ?? '')); + $tenant = trim((string) ($options['tenant'] ?? '')); + $tenantUuids = array_filter(array_map('trim', explode(',', (string) ($options['tenants'] ?? '')))); + $roleIds = self::normalizeIdList($options['roles'] ?? []); + $departmentIds = self::normalizeIdList($options['departments'] ?? []); + $emailVerified = $options['email_verified'] ?? null; + $order = (string) ($options['order'] ?? 'id'); + $dir = strtolower((string) ($options['dir'] ?? 'desc')); + $allowedOrder = ['id', 'uuid', 'first_name', 'last_name', 'email', 'created', 'modified', 'active']; + if (!in_array($order, $allowedOrder, true)) { + $order = 'id'; + } + if (!in_array($dir, ['asc', 'desc'], true)) { + $dir = 'desc'; + } + + $where = []; + $params = []; + if ($search !== '') { + $like = '%' . $search . '%'; + $where[] = '(users.first_name like ? or users.last_name like ? or users.email like ?)'; + $params[] = $like; + $params[] = $like; + $params[] = $like; + } + + $activeFilter = null; + if ($active !== null && $active !== '' && $active !== 'all') { + $activeValue = strtolower((string) $active); + if (in_array($activeValue, ['1', 'true', 'active'], true)) { + $activeFilter = 1; + } elseif (in_array($activeValue, ['0', 'false', 'inactive'], true)) { + $activeFilter = 0; + } + } + if ($activeFilter !== null) { + $where[] = 'users.active = ?'; + $params[] = (string) $activeFilter; + } + + if ($createdFrom !== '') { + $where[] = 'users.created >= ?'; + $params[] = $createdFrom . ' 00:00:00'; + } + if ($createdTo !== '') { + $where[] = 'users.created <= ?'; + $params[] = $createdTo . ' 23:59:59'; + } + if ($tenantUuids) { + $where[] = 'exists (select 1 from user_tenants ut2 join tenants t2 on t2.id = ut2.tenant_id where ut2.user_id = users.id and t2.uuid in (???))'; + $params[] = array_values($tenantUuids); + } elseif ($tenant !== '') { + $where[] = 'exists (select 1 from user_tenants ut2 join tenants t2 on t2.id = ut2.tenant_id where ut2.user_id = users.id and t2.uuid = ?)'; + $params[] = $tenant; + } + if ($roleIds) { + $where[] = 'exists (select 1 from user_roles ur2 where ur2.user_id = users.id and ur2.role_id in (???))'; + $params[] = array_map('strval', $roleIds); + } + if ($departmentIds) { + $where[] = 'exists (select 1 from user_departments ud2 where ud2.user_id = users.id and ud2.department_id in (???))'; + $params[] = array_map('strval', $departmentIds); + } + if ($emailVerified !== null && $emailVerified !== '' && $emailVerified !== 'all') { + $emailVerifiedValue = strtolower((string) $emailVerified); + if (in_array($emailVerifiedValue, ['1', 'true', 'verified', 'yes'], true)) { + $where[] = 'users.email_verified_at is not null'; + } elseif (in_array($emailVerifiedValue, ['0', 'false', 'unverified', 'no'], true)) { + $where[] = 'users.email_verified_at is null'; + } + } + if (!empty($options['tenantUserId'])) { + $tenantUserId = (int) $options['tenantUserId']; + if ($tenantUserId > 0) { + if (defined('TENANT_SCOPE_STRICT') && TENANT_SCOPE_STRICT) { + $where[] = 'exists (select 1 from user_tenants ut join user_tenants ut2 on ut2.tenant_id = ut.tenant_id ' . + "join tenants t on t.id = ut.tenant_id and t.status = 'active' " . + 'where ut2.user_id = ? and ut.user_id = users.id)'; + $params[] = (string) $tenantUserId; + } else { + $where[] = '(not exists (select 1 from user_tenants ut where ut.user_id = users.id) ' . + 'or exists (select 1 from user_tenants ut join user_tenants ut2 on ut2.tenant_id = ut.tenant_id ' . + "join tenants t on t.id = ut.tenant_id and t.status = 'active' " . + 'where ut2.user_id = ? and ut.user_id = users.id))'; + $params[] = (string) $tenantUserId; + } + } + } + + $whereSql = $where ? (' where ' . implode(' and ', $where)) : ''; + $count = DB::selectValue('select count(*) from users' . $whereSql, ...$params); + $total = $count ? (int) $count : 0; + + $query = 'select users.id, users.uuid, users.first_name, users.last_name, users.email, users.profile_description, users.job_title, users.phone, users.mobile, users.short_dial, users.address, users.postal_code, users.city, users.country, users.region, users.hire_date, users.theme, users.primary_tenant_id, users.created_by, users.modified_by, users.created, users.modified, users.active, ' . + 'pt.description as primary_tenant_label ' . + "from users left join tenants pt on pt.id = users.primary_tenant_id and pt.status = 'active'" . + $whereSql . + sprintf(' order by `users`.`%s` %s limit ? offset ?', $order, $dir); + + $queryParams = array_merge($params, [(string) $limit, (string) $offset]); + $rows = call_user_func_array(['MintyPHP\\DB', 'select'], array_merge([$query], $queryParams)); + + $list = self::unwrapList($rows); + $labelRows = []; + $tenantMapByUser = []; + $roleLabelRows = []; + $departmentLabelRows = []; + + $ids = []; + foreach ($list as $user) { + if (isset($user['id'])) { + $ids[] = (int) $user['id']; + } + } + if ($ids) { + $scopeToActiveTenants = !empty($options['tenantUserId']); + $tenantLabelJoin = $scopeToActiveTenants + ? "join tenants t on t.id = ut.tenant_id and t.status = 'active' " + : 'join tenants t on t.id = ut.tenant_id '; + $placeholders = implode(',', array_fill(0, count($ids), '?')); + $labelRows = DB::select( + 'select ut.user_id as user_id, t.id as tenant_id, t.description as description from user_tenants ut ' . $tenantLabelJoin . + 'where ut.user_id in (' . $placeholders . ') order by t.description asc', + ...array_map('strval', $ids) + ); + $roleLabelRows = DB::select( + 'select ur.user_id as user_id, r.description as description from user_roles ur join roles r on r.id = ur.role_id ' . + 'where ur.user_id in (' . $placeholders . ') order by r.description asc', + ...array_map('strval', $ids) + ); + $departmentLabelRows = DB::select( + 'select ud.user_id as user_id, d.description as description from user_departments ud join departments d on d.id = ud.department_id ' . + 'where ud.user_id in (' . $placeholders . ') order by d.description asc', + ...array_map('strval', $ids) + ); + + $collectLabels = static function (array $rows, string $userKey, string $labelKey): array { + $labelsByUser = []; + foreach ($rows as $row) { + $userId = 0; + $label = ''; + if (isset($row[$userKey]) && is_array($row[$userKey])) { + $userId = (int) ($row[$userKey]['user_id'] ?? 0); + } + if (isset($row[$labelKey]) && is_array($row[$labelKey])) { + $label = (string) ($row[$labelKey]['description'] ?? ''); + } + if ($userId === 0 || $label === '') { + foreach ($row as $value) { + if (!is_array($value)) { + continue; + } + if ($userId === 0 && isset($value['user_id'])) { + $userId = (int) $value['user_id']; + } + if ($label === '' && isset($value['description'])) { + $label = (string) $value['description']; + } + } + } + if ($userId === 0 && isset($row['user_id'])) { + $userId = (int) $row['user_id']; + } + if ($label === '' && isset($row['description'])) { + $label = (string) $row['description']; + } + if ($userId > 0 && $label !== '') { + $labelsByUser[$userId] ??= []; + $labelsByUser[$userId][] = $label; + } + } + return $labelsByUser; + }; + + foreach ($labelRows as $row) { + $userId = 0; + $tenantId = 0; + $label = ''; + if (isset($row['ut']) && is_array($row['ut'])) { + $userId = (int) ($row['ut']['user_id'] ?? 0); + } + if (isset($row['t']) && is_array($row['t'])) { + $tenantId = (int) ($row['t']['tenant_id'] ?? 0); + $label = (string) ($row['t']['description'] ?? ''); + } + if ($userId === 0 || $tenantId === 0 || $label === '') { + foreach ($row as $value) { + if (!is_array($value)) { + continue; + } + if ($userId === 0 && isset($value['user_id'])) { + $userId = (int) $value['user_id']; + } + if ($tenantId === 0 && isset($value['tenant_id'])) { + $tenantId = (int) $value['tenant_id']; + } + if ($label === '' && isset($value['description'])) { + $label = (string) $value['description']; + } + } + } + if ($userId === 0 && isset($row['user_id'])) { + $userId = (int) $row['user_id']; + } + if ($tenantId === 0 && isset($row['tenant_id'])) { + $tenantId = (int) $row['tenant_id']; + } + if ($label === '' && isset($row['description'])) { + $label = (string) $row['description']; + } + if ($userId > 0 && $tenantId > 0 && $label !== '') { + $tenantMapByUser[$userId] ??= []; + $tenantMapByUser[$userId][$tenantId] = $label; + } + } + $tenantLabelsByUser = []; + foreach ($tenantMapByUser as $userId => $map) { + $tenantLabelsByUser[$userId] = array_values($map); + } + $roleLabelsByUser = $collectLabels($roleLabelRows, 'ur', 'r'); + $departmentLabelsByUser = $collectLabels($departmentLabelRows, 'ud', 'd'); + + foreach ($list as &$user) { + $userId = (int) ($user['id'] ?? 0); + $primaryId = (int) ($user['primary_tenant_id'] ?? 0); + $user['tenant_labels'] = $tenantLabelsByUser[$userId] ?? []; + if ($primaryId > 0 && isset($tenantMapByUser[$userId][$primaryId])) { + $user['primary_tenant_label'] = $tenantMapByUser[$userId][$primaryId]; + } + $user['role_labels'] = $roleLabelsByUser[$userId] ?? []; + $user['department_labels'] = $departmentLabelsByUser[$userId] ?? []; + } + unset($user); + } + + $result = [ + 'total' => $total, + 'rows' => $list, + ]; + return $result; + } + + public static function find(int $id): ?array + { + $row = DB::selectOne( + 'select id, uuid, first_name, last_name, email, profile_description, job_title, phone, mobile, short_dial, address, postal_code, city, country, region, hire_date, email_verified_at, password, locale, totp_secret, theme, primary_tenant_id, created_by, modified_by, created, modified, active from users where id = ? limit 1', + (string) $id + ); + return self::unwrap($row); + } + + public static function findByUuid(string $uuid): ?array + { + $row = DB::selectOne( + 'select id, uuid, first_name, last_name, email, profile_description, job_title, phone, mobile, short_dial, address, postal_code, city, country, region, hire_date, email_verified_at, password, locale, totp_secret, theme, primary_tenant_id, created_by, modified_by, created, modified, active, active_changed_at, active_changed_by from users where uuid = ? limit 1', + $uuid + ); + return self::unwrap($row); + } + + public static function findByEmail(string $email): ?array + { + $row = DB::selectOne( + 'select id, uuid, first_name, last_name, email, profile_description, job_title, phone, mobile, short_dial, address, postal_code, city, country, region, hire_date, email_verified_at, email_verified_at, password, locale, totp_secret, theme, primary_tenant_id, created_by, modified_by, created, modified, active, active_changed_at, active_changed_by from users where email = ? limit 1', + $email + ); + return self::unwrap($row); + } + + private static function uuidV4(): string + { + $data = random_bytes(16); + $data[6] = chr((ord($data[6]) & 0x0f) | 0x40); + $data[8] = chr((ord($data[8]) & 0x3f) | 0x80); + return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); + } + + public static function create(array $data) + { + $hash = password_hash($data['password'], PASSWORD_DEFAULT); + return DB::insert( + 'insert into users (uuid, first_name, last_name, email, profile_description, job_title, phone, mobile, short_dial, address, postal_code, city, country, region, hire_date, password, locale, totp_secret, theme, primary_tenant_id, current_tenant_id, created_by, created, active, active_changed_at, active_changed_by) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,NOW(),?,?,?)', + $data['uuid'] ?? self::uuidV4(), + $data['first_name'], + $data['last_name'], + $data['email'], + $data['profile_description'] ?? null, + $data['job_title'] ?? null, + $data['phone'] ?? null, + $data['mobile'] ?? null, + $data['short_dial'] ?? null, + $data['address'] ?? null, + $data['postal_code'] ?? null, + $data['city'] ?? null, + $data['country'] ?? null, + $data['region'] ?? null, + $data['hire_date'] ?? null, + $hash, + $data['locale'] ?? null, + $data['totp_secret'], + $data['theme'] ?? 'light', + $data['primary_tenant_id'] ?? null, + $data['current_tenant_id'] ?? $data['primary_tenant_id'] ?? null, + $data['created_by'] ?? null, + $data['active'], + $data['active_changed_at'] ?? null, + $data['active_changed_by'] ?? null + ); + } + + public static function update(int $id, array $data): bool + { + $fields = [ + 'first_name' => $data['first_name'], + 'last_name' => $data['last_name'], + 'email' => $data['email'], + 'profile_description' => $data['profile_description'] ?? null, + 'job_title' => $data['job_title'] ?? null, + 'phone' => $data['phone'] ?? null, + 'mobile' => $data['mobile'] ?? null, + 'short_dial' => $data['short_dial'] ?? null, + 'address' => $data['address'] ?? null, + 'postal_code' => $data['postal_code'] ?? null, + 'city' => $data['city'] ?? null, + 'country' => $data['country'] ?? null, + 'region' => $data['region'] ?? null, + 'hire_date' => $data['hire_date'] ?? null, + 'totp_secret' => $data['totp_secret'], + 'active' => $data['active'], + ]; + if (array_key_exists('locale', $data)) { + $fields['locale'] = $data['locale']; + } + if (array_key_exists('theme', $data)) { + $fields['theme'] = $data['theme']; + } + if (array_key_exists('primary_tenant_id', $data)) { + $fields['primary_tenant_id'] = $data['primary_tenant_id']; + } + if (array_key_exists('current_tenant_id', $data)) { + $fields['current_tenant_id'] = $data['current_tenant_id']; + } + if (array_key_exists('modified_by', $data)) { + $fields['modified_by'] = $data['modified_by']; + } + if (array_key_exists('active_changed_at', $data)) { + $fields['active_changed_at'] = $data['active_changed_at']; + } + if (array_key_exists('active_changed_by', $data)) { + $fields['active_changed_by'] = $data['active_changed_by']; + } + + if (!empty($data['password'])) { + $fields['password'] = password_hash($data['password'], PASSWORD_DEFAULT); + } + + $setParts = []; + $params = []; + foreach ($fields as $field => $value) { + $setParts[] = sprintf('`%s` = ?', $field); + $params[] = $value; + } + $params[] = (string) $id; + + $query = 'update users set ' . implode(', ', $setParts) . ' where id = ?'; + $result = DB::update($query, ...$params); + return $result !== false; + } + + public static function setActive(int $id, bool $active, ?int $changedBy = null): bool + { + $result = DB::update( + 'update users set active = ?, active_changed_at = NOW(), active_changed_by = ? where id = ?', + $active ? 1 : 0, + $changedBy, + (string) $id + ); + return $result !== false; + } + + public static function setCurrentTenant(int $id, int $tenantId): bool + { + $result = DB::update( + 'update users set current_tenant_id = ? where id = ?', + (string) $tenantId, + (string) $id + ); + return $result !== false; + } + + public static function setActiveByUuids(array $uuids, bool $active, ?int $modifiedBy = null): bool + { + $uuids = array_values(array_filter(array_map('trim', $uuids))); + if (!$uuids) { + return false; + } + $placeholders = implode(',', array_fill(0, count($uuids), '?')); + $query = "update users set active = ?, modified_by = ?, active_changed_at = NOW(), active_changed_by = ? where uuid in ($placeholders)"; + $params = array_merge([$active ? 1 : 0, $modifiedBy, $modifiedBy], $uuids); + $result = DB::update($query, ...$params); + return $result !== false; + } + + public static function setLocale(int $id, string $locale): bool + { + $result = DB::update('update users set locale = ? where id = ?', $locale, (string) $id); + return $result !== false; + } + + public static function setTheme(int $id, string $theme): bool + { + $result = DB::update('update users set theme = ? where id = ?', $theme, (string) $id); + return $result !== false; + } + + public static function setPassword(int $id, string $password): bool + { + $hash = password_hash($password, PASSWORD_DEFAULT); + $result = DB::update('update users set password = ?, modified_by = NULL where id = ?', $hash, (string) $id); + return $result !== false; + } + + public static function setEmailVerified(int $id): bool + { + $result = DB::update('update users set email_verified_at = NOW() where id = ?', (string) $id); + return $result !== false; + } + + public static function delete(int $id): bool + { + $result = DB::delete('delete from users where id = ?', (string) $id); + return $result !== false; + } + + public static function deleteByUuids(array $uuids): bool + { + $uuids = array_values(array_filter(array_map('trim', $uuids))); + if (!$uuids) { + return false; + } + $placeholders = implode(',', array_fill(0, count($uuids), '?')); + $query = "delete from users where uuid in ($placeholders)"; + $result = DB::delete($query, ...$uuids); + return $result !== false; + } + + private static function normalizeIdList($value): array + { + if (is_string($value)) { + $value = array_filter(array_map('trim', explode(',', $value))); + } elseif (!is_array($value)) { + return []; + } + $ids = []; + foreach ($value as $item) { + if ($item === '' || $item === null) { + continue; + } + $ids[] = (int) $item; + } + $ids = array_values(array_filter(array_unique($ids), static function ($id) { + return $id > 0; + })); + return $ids; + } +} diff --git a/lib/Repository/UserRoleRepository.php b/lib/Repository/UserRoleRepository.php new file mode 100644 index 0000000..fd8c9eb --- /dev/null +++ b/lib/Repository/UserRoleRepository.php @@ -0,0 +1,42 @@ + false, + 'message' => 'Please verify your email first', + 'flash_key' => 'login_not_verified', + 'needs_verification' => true, + 'email' => $email, + ]; + } + + $user = Auth::login($email, $password); + + if (!$user) { + return [ + 'ok' => false, + 'message' => 'Email/password not valid', + 'flash_key' => 'login_invalid', + ]; + } + + if (!($_SESSION['user']['active'] ?? 1)) { + Auth::logout(); + return [ + 'ok' => false, + 'message' => 'Account is inactive', + 'flash_key' => 'login_inactive', + ]; + } + + $userId = (int) ($_SESSION['user']['id'] ?? 0); + if ($userId > 0) { + PermissionService::getUserPermissions($userId, true); + self::loadTenantDataIntoSession($userId); + if (!empty($_SESSION['no_active_tenant'])) { + Auth::logout(); + return [ + 'ok' => false, + 'message' => 'No active tenant assigned', + 'flash_key' => 'login_no_active_tenant', + ]; + } + } + + return ['ok' => true]; + } + + public static function loginAndRedirect( + string $email, + string $password, + string $successTarget = 'admin', + string $failTarget = 'login', + bool $remember = false + ): void { + $result = self::login($email, $password); + + if (!($result['ok'] ?? false)) { + // Check if user needs to verify email + if (!empty($result['needs_verification'])) { + $_SESSION['email_verification_email'] = $result['email'] ?? $email; + Flash::error(t('Please verify your email first'), 'verify-email', 'login_not_verified'); + Router::redirect('verify-email'); + } + + $message = $result['message'] ?? 'Email/password not valid'; + $key = $result['flash_key'] ?? 'login_invalid'; + Flash::error($message, $failTarget, $key); + Router::redirect($failTarget); + } + + if ($remember) { + $userId = (int) ($_SESSION['user']['id'] ?? 0); + if ($userId > 0) { + RememberMeService::rememberUser($userId); + } + } + Router::redirect($successTarget); + } + + public static function register(array $data): array + { + $email = trim((string) ($data['email'] ?? '')); + $result = UserService::register($data); + if (!($result['ok'] ?? false)) { + return $result; + } + + // Get the created user to send verification email + $createdUser = UserRepository::findByEmail($email); + if ($createdUser && isset($createdUser['id'])) { + $userId = (int) $createdUser['id']; + EmailVerificationService::sendVerification($userId); + } + + // Don't login - user needs to verify email first + return ['ok' => true, 'email' => $email, 'needs_verification' => true]; + } + + public static function logout(): void + { + RememberMeService::forgetCurrentUser(); + Auth::logout(); + } + + public static function logoutAndRedirect(string $target = 'login'): void + { + RememberMeService::forgetCurrentUser(); + Auth::logout(); + Router::redirect($target); + } + + public static function loadTenantDataIntoSession(int $userId): void + { + if ($userId <= 0) { + return; + } + + // Load available tenants first + $availableTenants = UserService::getAvailableTenants($userId); + $_SESSION['available_tenants'] = $availableTenants; + $_SESSION['available_departments_by_tenant'] = UserService::getAvailableDepartmentsByTenant($userId); + + $hasTenantAdminAccess = PermissionService::userHas($userId, PermissionService::TENANTS_UPDATE) + || PermissionService::userHas($userId, PermissionService::SETTINGS_UPDATE); + + if (!$availableTenants && !$hasTenantAdminAccess) { + $_SESSION['no_active_tenant'] = true; + unset($_SESSION['current_tenant']); + return; + } + $_SESSION['no_active_tenant'] = false; + + // Load current tenant (with fallback to first available) + $currentTenant = UserService::getCurrentTenant($userId); + if (!$currentTenant && !empty($availableTenants)) { + // Fallback: use first available tenant + $currentTenant = $availableTenants[0]; + } + if ($currentTenant) { + $_SESSION['current_tenant'] = $currentTenant; + } + } +} diff --git a/lib/Service/BrandingFaviconService.php b/lib/Service/BrandingFaviconService.php new file mode 100644 index 0000000..abc5430 --- /dev/null +++ b/lib/Service/BrandingFaviconService.php @@ -0,0 +1,238 @@ + 'favicon-16x16.png', + 32 => 'favicon-32x32.png', + 96 => 'favicon-96x96.png', + 180 => 'apple-touch-icon.png', + 192 => 'web-app-manifest-192x192.png', + 512 => 'web-app-manifest-512x512.png', + ]; + + public static function storageBase(): string + { + if (defined('APP_STORAGE_PATH') && APP_STORAGE_PATH) { + return rtrim(APP_STORAGE_PATH, '/'); + } + return rtrim(dirname(__DIR__, 2) . '/storage', '/'); + } + + public static function storageDir(): string + { + return self::storageBase() . '/branding/favicon'; + } + + public static function publicDir(): string + { + return rtrim(dirname(__DIR__, 2) . '/web/favicon', '/'); + } + + public static function hasFavicon(): bool + { + $path = self::publicDir() . '/favicon-32x32.png'; + return is_file($path); + } + + public static function delete(): void + { + $dir = self::storageDir(); + if (is_dir($dir)) { + $matches = glob($dir . '/*') ?: []; + foreach ($matches as $file) { + if (is_file($file)) { + @unlink($file); + } + } + } + $public = self::publicDir(); + foreach (self::SIZES as $file) { + $target = $public . '/' . $file; + if (is_file($target)) { + @unlink($target); + } + } + } + + public static function saveUpload(array $file): array + { + if (empty($file) || !isset($file['tmp_name'])) { + return ['ok' => false, 'error' => t('No file uploaded')]; + } + if (($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + if (($file['size'] ?? 0) > self::MAX_SIZE) { + return ['ok' => false, 'error' => t('File is too large')]; + } + + $tmpPath = $file['tmp_name']; + $mime = self::detectMime($tmpPath); + if ($mime !== 'image/png') { + return ['ok' => false, 'error' => t('Invalid image file')]; + } + if (!self::canResize()) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + + $dir = self::storageDir(); + if (!is_dir($dir) && !mkdir($dir, 0755, true) && !is_dir($dir)) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + + self::delete(); + $originalPath = $dir . '/original.png'; + if (!move_uploaded_file($tmpPath, $originalPath)) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + @chmod($originalPath, 0644); + + $publicDir = self::publicDir(); + if (!is_dir($publicDir) && !mkdir($publicDir, 0755, true) && !is_dir($publicDir)) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + + foreach (self::SIZES as $size => $fileName) { + $target = $publicDir . '/' . $fileName; + if (!self::resizeSquare($originalPath, $target, $size)) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + @chmod($target, 0644); + } + + self::updateManifest(); + return ['ok' => true, 'path' => $originalPath, 'mime' => $mime]; + } + + public static function detectMime(string $path): string + { + if (function_exists('finfo_open')) { + $finfo = finfo_open(FILEINFO_MIME_TYPE); + if ($finfo) { + $mime = finfo_file($finfo, $path); + if (is_string($mime) && $mime !== '') { + return $mime; + } + } + } + return 'application/octet-stream'; + } + + private static function canResize(): bool + { + return function_exists('imagecreatetruecolor') && function_exists('imagecopyresampled'); + } + + private static function loadImage(string $path) + { + if (function_exists('imagecreatefrompng')) { + return imagecreatefrompng($path); + } + return false; + } + + private static function resizeSquare(string $sourcePath, string $targetPath, int $size): bool + { + $src = self::loadImage($sourcePath); + if (!$src) { + return false; + } + $srcWidth = imagesx($src); + $srcHeight = imagesy($src); + if ($srcWidth === 0 || $srcHeight === 0) { + imagedestroy($src); + return false; + } + + $cropSize = min($srcWidth, $srcHeight); + $srcX = (int) round(($srcWidth - $cropSize) / 2); + $srcY = (int) round(($srcHeight - $cropSize) / 2); + + $dst = imagecreatetruecolor($size, $size); + imagealphablending($dst, false); + imagesavealpha($dst, true); + $transparent = imagecolorallocatealpha($dst, 0, 0, 0, 127); + imagefilledrectangle($dst, 0, 0, $size, $size, $transparent); + + imagecopyresampled( + $dst, + $src, + 0, + 0, + $srcX, + $srcY, + $size, + $size, + $cropSize, + $cropSize + ); + + $saved = false; + if (function_exists('imagepng')) { + $saved = imagepng($dst, $targetPath, 6); + } + + imagedestroy($src); + imagedestroy($dst); + + return $saved; + } + + private static function updateManifest(): void + { + $manifestPath = self::publicDir() . '/site.webmanifest'; + $data = []; + if (is_file($manifestPath)) { + $json = file_get_contents($manifestPath); + $decoded = json_decode((string) $json, true); + if (is_array($decoded)) { + $data = $decoded; + } + } + + $title = null; + if (class_exists('MintyPHP\\Service\\SettingService')) { + $title = \MintyPHP\Service\SettingService::getAppTitle(); + } + if ($title === null || $title === '') { + $title = defined('APP_NAME') ? APP_NAME : 'IMVS'; + } + + $data['name'] = $title; + $data['short_name'] = $title; + if (!isset($data['theme_color'])) { + $data['theme_color'] = '#ffffff'; + } + if (!isset($data['background_color'])) { + $data['background_color'] = '#ffffff'; + } + if (!isset($data['display'])) { + $data['display'] = 'standalone'; + } + if (!isset($data['icons']) || !is_array($data['icons'])) { + $data['icons'] = [ + [ + 'src' => '/favicon/web-app-manifest-192x192.png', + 'sizes' => '192x192', + 'type' => 'image/png', + 'purpose' => 'maskable', + ], + [ + 'src' => '/favicon/web-app-manifest-512x512.png', + 'sizes' => '512x512', + 'type' => 'image/png', + 'purpose' => 'maskable', + ], + ]; + } + + $encoded = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); + if (is_string($encoded)) { + file_put_contents($manifestPath, $encoded . "\n"); + } + } +} diff --git a/lib/Service/BrandingLogoService.php b/lib/Service/BrandingLogoService.php new file mode 100644 index 0000000..a4b00fb --- /dev/null +++ b/lib/Service/BrandingLogoService.php @@ -0,0 +1,293 @@ + false, 'error' => t('No file uploaded')]; + } + if (($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + if (($file['size'] ?? 0) > self::MAX_SIZE) { + return ['ok' => false, 'error' => t('File is too large')]; + } + + $tmpPath = $file['tmp_name']; + $mime = self::detectMime($tmpPath); + $isSvg = self::isSvgUpload($mime, $tmpPath); + $ext = self::extensionForMime($mime, $isSvg); + if (!$ext) { + return ['ok' => false, 'error' => t('Invalid image file')]; + } + if ($isSvg && !self::isSafeSvg($tmpPath)) { + return ['ok' => false, 'error' => t('Invalid image file')]; + } + + $dir = self::brandingDir(); + if (!is_dir($dir) && !mkdir($dir, 0755, true) && !is_dir($dir)) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + + self::delete(); + $originalPath = $dir . '/original.' . $ext; + if (!move_uploaded_file($tmpPath, $originalPath)) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + @chmod($originalPath, 0644); + + $variantExt = function_exists('imagewebp') ? 'webp' : 'jpg'; + if (!$isSvg && self::canResize()) { + foreach (self::SIZES as $size) { + $target = $dir . '/logo-' . $size . '.' . $variantExt; + self::resizeAndFit($originalPath, $target, $size, $size, $variantExt); + } + } + + return ['ok' => true, 'path' => $originalPath, 'mime' => $mime]; + } + + public static function detectMime(string $path): string + { + if (function_exists('finfo_open')) { + $finfo = finfo_open(FILEINFO_MIME_TYPE); + if ($finfo) { + $mime = finfo_file($finfo, $path); + if (is_string($mime) && $mime !== '') { + if (self::isSvgUpload($mime, $path)) { + return 'image/svg+xml'; + } + return $mime; + } + } + } + if (self::isSvgUpload('application/octet-stream', $path)) { + return 'image/svg+xml'; + } + return 'application/octet-stream'; + } + + private static function extensionForMime(string $mime, bool $isSvg = false): ?string + { + if ($isSvg) { + return 'svg'; + } + $map = [ + 'image/jpeg' => 'jpg', + 'image/png' => 'png', + 'image/webp' => 'webp', + ]; + return $map[$mime] ?? null; + } + + private static function isSvgUpload(string $mime, string $path): bool + { + if ($mime === 'image/svg+xml') { + return true; + } + $head = @file_get_contents($path, false, null, 0, 1024); + if (!is_string($head) || $head === '') { + return false; + } + return stripos($head, ' filemtime($a); + }); + return $matches[0] ?? null; + } + + private static function findOriginalPath(string $dir): ?string + { + $matches = glob($dir . '/original.*'); + if (!$matches) { + return null; + } + usort($matches, static function ($a, $b) { + return filemtime($b) <=> filemtime($a); + }); + return $matches[0] ?? null; + } + + private static function canResize(): bool + { + return function_exists('imagecreatetruecolor') && function_exists('imagecopyresampled'); + } + + private static function createImageResource(string $path, string $mime) + { + if ($mime === 'image/jpeg' && function_exists('imagecreatefromjpeg')) { + return imagecreatefromjpeg($path); + } + if ($mime === 'image/png' && function_exists('imagecreatefrompng')) { + return imagecreatefrompng($path); + } + if ($mime === 'image/webp' && function_exists('imagecreatefromwebp')) { + return imagecreatefromwebp($path); + } + return false; + } + + private static function resizeAndFit(string $sourcePath, string $targetPath, int $width, int $height, string $ext): bool + { + $mime = self::detectMime($sourcePath); + $src = self::createImageResource($sourcePath, $mime); + if (!$src) { + return false; + } + + $srcWidth = imagesx($src); + $srcHeight = imagesy($src); + if ($srcWidth === 0 || $srcHeight === 0) { + imagedestroy($src); + return false; + } + + $scale = min($width / $srcWidth, $height / $srcHeight); + $dstWidth = (int) round($srcWidth * $scale); + $dstHeight = (int) round($srcHeight * $scale); + if ($dstWidth < 1) $dstWidth = 1; + if ($dstHeight < 1) $dstHeight = 1; + + $dst = imagecreatetruecolor($dstWidth, $dstHeight); + if ($ext === 'png' || $ext === 'webp') { + imagealphablending($dst, false); + imagesavealpha($dst, true); + $transparent = imagecolorallocatealpha($dst, 0, 0, 0, 127); + imagefilledrectangle($dst, 0, 0, $dstWidth, $dstHeight, $transparent); + } + + imagecopyresampled( + $dst, + $src, + 0, + 0, + 0, + 0, + $dstWidth, + $dstHeight, + $srcWidth, + $srcHeight + ); + + $saved = false; + if ($ext === 'webp' && function_exists('imagewebp')) { + $saved = imagewebp($dst, $targetPath, 82); + } elseif ($ext === 'png' && function_exists('imagepng')) { + $saved = imagepng($dst, $targetPath, 6); + } else { + $saved = imagejpeg($dst, $targetPath, 85); + } + + imagedestroy($src); + imagedestroy($dst); + + if ($saved) { + @chmod($targetPath, 0644); + } + return $saved; + } +} diff --git a/lib/Service/DepartmentService.php b/lib/Service/DepartmentService.php new file mode 100644 index 0000000..c26b997 --- /dev/null +++ b/lib/Service/DepartmentService.php @@ -0,0 +1,161 @@ + 0 && TenantScopeService::hasGlobalAccess($tenantUserId)) { + unset($options['tenantUserId'], $options['tenantIds']); + } + } + return DepartmentRepository::listPaged($options); + } + + public static function listByTenantIds(array $tenantIds): array + { + return DepartmentRepository::listByTenantIds($tenantIds); + } + + public static function listByIds(array $departmentIds): array + { + return DepartmentRepository::listByIds($departmentIds); + } + + public static function listForUserAssignments(array $tenantIds, array $selectedDepartmentIds): array + { + $departments = $tenantIds ? self::listByTenantIds($tenantIds) : self::list(); + $extraDepartments = $selectedDepartmentIds ? self::listByIds($selectedDepartmentIds) : []; + if (!$extraDepartments) { + return $departments; + } + $departmentMap = []; + foreach ($departments as $department) { + if (isset($department['id'])) { + $departmentMap[(int) $department['id']] = $department; + } + } + foreach ($extraDepartments as $department) { + if (isset($department['id'])) { + $departmentMap[(int) $department['id']] = $department; + } + } + return array_values($departmentMap); + } + + public static function findByUuid(string $uuid): ?array + { + return DepartmentRepository::findByUuid($uuid); + } + + public static function findById(int $id): ?array + { + return DepartmentRepository::find($id); + } + + public static function createFromAdmin(array $input, int $currentUserId = 0): array + { + $form = self::sanitizeBase($input); + $errors = self::validateBase($form); + + if ($errors) { + return ['ok' => false, 'errors' => $errors, 'form' => $form]; + } + + $createdId = DepartmentRepository::create([ + 'description' => $form['description'], + 'created_by' => $currentUserId > 0 ? $currentUserId : null, + ]); + + if (!$createdId) { + return ['ok' => false, 'errors' => [t('Department can not be created')], 'form' => $form]; + } + + $createdDepartment = DepartmentRepository::find((int) $createdId); + $uuid = $createdDepartment['uuid'] ?? null; + if (!empty($input['is_default']) && $createdId) { + SettingService::setDefaultDepartmentId((int) $createdId); + } + return ['ok' => true, 'form' => $form, 'uuid' => $uuid, 'id' => (int) $createdId]; + } + + public static function updateFromAdmin(int $departmentId, array $input, int $currentUserId = 0): array + { + $form = self::sanitizeBase($input); + $errors = self::validateBase($form); + + if ($errors) { + return ['ok' => false, 'errors' => $errors, 'form' => $form]; + } + + $updated = DepartmentRepository::update($departmentId, [ + 'description' => $form['description'], + 'modified_by' => $currentUserId > 0 ? $currentUserId : null, + ]); + + if (!$updated) { + return ['ok' => false, 'errors' => [t('Department can not be updated')], 'form' => $form]; + } + + return ['ok' => true, 'form' => $form]; + } + + public static function syncTenants(int $departmentId, array $tenantIds): int + { + $updated = TenantDepartmentRepository::replaceForDepartment($departmentId, $tenantIds); + if (!$updated) { + return -1; + } + return UserDepartmentRepository::removeInvalidForDepartment($departmentId); + } + + public static function deleteByUuid(string $uuid): array + { + $uuid = trim($uuid); + if ($uuid === '') { + return ['ok' => false, 'status' => 404, 'error' => 'not_found']; + } + + $department = DepartmentRepository::findByUuid($uuid); + if (!$department || !isset($department['id'])) { + return ['ok' => false, 'status' => 404, 'error' => 'not_found']; + } + + $deleted = DepartmentRepository::delete((int) $department['id']); + if (!$deleted) { + return ['ok' => false, 'status' => 500, 'error' => 'delete_failed']; + } + + return ['ok' => true, 'department' => $department]; + } + + private static function sanitizeBase(array $input): array + { + return [ + 'description' => trim((string) ($input['description'] ?? '')), + ]; + } + + private static function validateBase(array $form): array + { + $errors = []; + if ($form['description'] === '') { + $errors[] = t('Description cannot be empty'); + } + return $errors; + } +} diff --git a/lib/Service/EmailVerificationService.php b/lib/Service/EmailVerificationService.php new file mode 100644 index 0000000..1411e17 --- /dev/null +++ b/lib/Service/EmailVerificationService.php @@ -0,0 +1,146 @@ + false, 'error' => 'user_not_found']; + } + + $email = (string) ($user['email'] ?? ''); + if ($email === '') { + return ['ok' => false, 'error' => 'email_required']; + } + + EmailVerificationRepository::invalidateForUser($userId); + + $code = self::generateCode(); + $codeHash = password_hash($code, PASSWORD_DEFAULT); + $expiresAt = gmdate('Y-m-d H:i:s', time() + (self::EXPIRY_MINUTES * 60)); + + $verificationId = EmailVerificationRepository::create($userId, $codeHash, $expiresAt); + if (!$verificationId) { + return ['ok' => false, 'error' => 'create_failed']; + } + + $locale = $locale ?: ($user['locale'] ?? null) ?: (I18n::$locale ?? I18n::$defaultLocale); + $name = trim(($user['first_name'] ?? '') . ' ' . ($user['last_name'] ?? '')); + $isGerman = strpos((string) $locale, 'de') === 0; + $greeting = $isGerman ? 'Hallo' : 'Hello'; + if ($name !== '') { + $greeting .= ' ' . $name; + } + $greeting .= ','; + $verifyPath = Request::withLocale('verify-email', $locale); + $verifyUrl = appUrl($verifyPath); + $previousLocale = I18n::$locale ?? null; + I18n::$locale = $locale; + $subject = t('Email verification code'); + I18n::$locale = $previousLocale; + + $vars = [ + 'app_name' => appTitle(), + 'app_logo_url' => appLogoUrlAbsolute(128), + 'imprint_url' => appUrl(Request::withLocale('imprint', $locale)), + 'privacy_url' => appUrl(Request::withLocale('privacy', $locale)), + 'code' => $code, + 'expires_minutes' => self::EXPIRY_MINUTES, + 'verify_url' => $verifyUrl, + 'greeting' => $greeting, + ]; + MailService::sendTemplate('email_verification', $vars, $email, $subject, $locale); + + return ['ok' => true]; + } + + public static function verifyCode(string $email, string $code): array + { + $email = trim($email); + $code = trim($code); + if ($email === '' || $code === '') { + return ['ok' => false, 'error' => 'invalid']; + } + + $user = UserRepository::findByEmail($email); + if (!$user || !isset($user['id'])) { + return ['ok' => false, 'error' => 'invalid']; + } + + $userId = (int) $user['id']; + + // Check if already verified + if (!empty($user['email_verified_at'])) { + return ['ok' => false, 'error' => 'already_verified']; + } + + $verification = EmailVerificationRepository::findActiveByUserId($userId); + if (!$verification || !isset($verification['id'])) { + return ['ok' => false, 'error' => 'invalid']; + } + + $attempts = (int) ($verification['attempts'] ?? 0); + if ($attempts >= self::MAX_ATTEMPTS) { + return ['ok' => false, 'error' => 'too_many_attempts']; + } + + $hash = (string) ($verification['code_hash'] ?? ''); + if ($hash === '' || !password_verify($code, $hash)) { + EmailVerificationRepository::incrementAttempts((int) $verification['id']); + return ['ok' => false, 'error' => 'invalid']; + } + + // Mark verification as used + EmailVerificationRepository::markUsed((int) $verification['id']); + + // Mark user email as verified + UserRepository::setEmailVerified($userId); + + return ['ok' => true, 'user_id' => $userId]; + } + + public static function resendVerification(string $email, ?string $locale = null): array + { + $email = trim($email); + if ($email === '') { + return ['ok' => false, 'error' => 'email_required']; + } + + $user = UserRepository::findByEmail($email); + if (!$user || !isset($user['id'])) { + // Don't reveal if user exists + return ['ok' => true]; + } + + // Check if already verified + if (!empty($user['email_verified_at'])) { + return ['ok' => false, 'error' => 'already_verified']; + } + + return self::sendVerification((int) $user['id'], $locale); + } + + public static function getExpiryMinutes(): int + { + return self::EXPIRY_MINUTES; + } + + private static function generateCode(): string + { + $max = (10 ** self::CODE_LENGTH) - 1; + $code = (string) random_int(0, $max); + return str_pad($code, self::CODE_LENGTH, '0', STR_PAD_LEFT); + } +} diff --git a/lib/Service/MailLogService.php b/lib/Service/MailLogService.php new file mode 100644 index 0000000..b94a759 --- /dev/null +++ b/lib/Service/MailLogService.php @@ -0,0 +1,18 @@ + $template, + ]); + } + + public static function send( + string $to, + string $subject, + string $html, + string $text, + array $meta = [] + ): array { + $logId = MailLogRepository::create([ + 'to_email' => $to, + 'subject' => $subject, + 'template' => $meta['template'] ?? null, + 'status' => 'queued', + ]); + + if (!class_exists(PHPMailer::class)) { + if ($logId) { + MailLogRepository::markFailed($logId, 'PHPMailer is not installed'); + } + return ['ok' => false, 'error' => 'mailer_missing']; + } + + try { + $mailer = self::createMailer(); + $mailer->addAddress($to); + $mailer->Subject = $subject; + $mailer->Body = $html; + $mailer->AltBody = $text; + $mailer->isHTML(true); + $mailer->send(); + + if ($logId) { + MailLogRepository::markSent($logId, $mailer->getLastMessageID() ?: null); + } + return ['ok' => true]; + } catch (MailerException $e) { + if ($logId) { + MailLogRepository::markFailed($logId, $e->getMessage()); + } + return ['ok' => false, 'error' => 'send_failed']; + } + } + + private static function renderTemplate(string $template, array $vars, string $locale): array + { + $base = dirname(__DIR__, 2) . '/templates/emails'; + $htmlPath = $base . '/' . $locale . '/' . $template . '.html'; + $textPath = $base . '/' . $locale . '/' . $template . '.txt'; + $htmlHeaderPath = $base . '/' . $locale . '/partials/header.html'; + $htmlFooterPath = $base . '/' . $locale . '/partials/footer.html'; + $textHeaderPath = $base . '/' . $locale . '/partials/header.txt'; + $textFooterPath = $base . '/' . $locale . '/partials/footer.txt'; + + if (!is_file($htmlPath)) { + $htmlPath = $base . '/' . $template . '.html'; + } + if (!is_file($textPath)) { + $textPath = $base . '/' . $template . '.txt'; + } + if (!is_file($htmlHeaderPath)) { + $htmlHeaderPath = $base . '/partials/header.html'; + } + if (!is_file($htmlFooterPath)) { + $htmlFooterPath = $base . '/partials/footer.html'; + } + if (!is_file($textHeaderPath)) { + $textHeaderPath = $base . '/partials/header.txt'; + } + if (!is_file($textFooterPath)) { + $textFooterPath = $base . '/partials/footer.txt'; + } + + $html = is_file($htmlPath) ? file_get_contents($htmlPath) : ''; + $text = is_file($textPath) ? file_get_contents($textPath) : ''; + if (!isset($vars['email_header'])) { + $vars['email_header'] = is_file($htmlHeaderPath) ? file_get_contents($htmlHeaderPath) : ''; + } + if (!isset($vars['email_footer'])) { + $vars['email_footer'] = is_file($htmlFooterPath) ? file_get_contents($htmlFooterPath) : ''; + } + if (!isset($vars['email_header_text'])) { + $vars['email_header_text'] = is_file($textHeaderPath) ? file_get_contents($textHeaderPath) : ''; + } + if (!isset($vars['email_footer_text'])) { + $vars['email_footer_text'] = is_file($textFooterPath) ? file_get_contents($textFooterPath) : ''; + } + + foreach ($vars as $key => $value) { + $placeholder = '{{' . $key . '}}'; + $html = str_replace($placeholder, (string) $value, $html); + $text = str_replace($placeholder, (string) $value, $text); + } + // Second pass to resolve placeholders inside injected header/footer content. + foreach ($vars as $key => $value) { + $placeholder = '{{' . $key . '}}'; + $html = str_replace($placeholder, (string) $value, $html); + $text = str_replace($placeholder, (string) $value, $text); + } + + return [$html, $text]; + } + + private static function createMailer(): PHPMailer + { + $mailer = new PHPMailer(true); + $mailer->isSMTP(); + $host = SettingService::getSmtpHost() ?? (getenv('SMTP_HOST') ?: ''); + $port = SettingService::getSmtpPort() ?? (int) (getenv('SMTP_PORT') ?: 587); + $user = SettingService::getSmtpUser() ?? (getenv('SMTP_USER') ?: ''); + $pass = SettingService::getSmtpPassword() ?? (getenv('SMTP_PASS') ?: ''); + $secure = SettingService::getSmtpSecure() ?? strtolower((string) (getenv('SMTP_SECURE') ?: 'tls')); + $from = SettingService::getSmtpFrom() ?? (getenv('SMTP_FROM') ?: ($user ?: 'no-reply@localhost')); + $fromName = SettingService::getSmtpFromName() ?? (getenv('SMTP_FROM_NAME') ?: appTitle()); + + $mailer->Host = $host; + $mailer->Port = $port; + $mailer->SMTPAuth = $user !== '' || $pass !== ''; + $mailer->Username = $user; + $mailer->Password = $pass; + if (in_array($secure, ['tls', 'ssl'], true)) { + $mailer->SMTPSecure = $secure; + } + $mailer->setFrom($from, $fromName); + $mailer->CharSet = 'UTF-8'; + return $mailer; + } +} diff --git a/lib/Service/PageService.php b/lib/Service/PageService.php new file mode 100644 index 0000000..1261531 --- /dev/null +++ b/lib/Service/PageService.php @@ -0,0 +1,161 @@ + 0) { + $fallbackLocale = APP_LOCALES[0]; + } + + if (!$content && $fallbackLocale !== $locale) { + $content = PageContentRepository::findByPageIdAndLocale((int) $page['id'], $fallbackLocale); + if ($content) { + $usedLocale = $fallbackLocale; + } + } + + if (!$content) { + $content = [ + 'locale' => $usedLocale, + 'content' => null, + ]; + } + + return [ + 'page' => $page, + 'content' => $content, + 'locale' => $usedLocale, + ]; + } + + public static function updateContentBySlug( + string $slug, + string $content, + int $currentUserId = 0, + ?string $locale = null + ): array + { + $slug = trim($slug); + if ($slug === '') { + return ['ok' => false, 'status' => 404, 'error' => 'not_found']; + } + + $page = PageRepository::findBySlug($slug); + if (!$page || !isset($page['id'])) { + return ['ok' => false, 'status' => 404, 'error' => 'not_found']; + } + + $locale = $locale ?: (I18n::$locale ?? I18n::$defaultLocale); + + $content = trim($content); + $normalized = null; + if ($content !== '') { + $decoded = json_decode($content, true); + if (!is_array($decoded)) { + return ['ok' => false, 'errors' => [t('Content is invalid')]]; + } + if (!isset($decoded['blocks']) || !is_array($decoded['blocks'])) { + $decoded['blocks'] = []; + } + $normalized = json_encode($decoded, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + } + + $existing = PageContentRepository::findByPageIdAndLocale((int) $page['id'], $locale); + $updated = false; + if ($existing && isset($existing['id'])) { + $updated = PageContentRepository::update((int) $existing['id'], [ + 'content' => $normalized, + 'modified_by' => $currentUserId > 0 ? $currentUserId : null, + ]); + } else { + $createdId = PageContentRepository::create([ + 'page_id' => (int) $page['id'], + 'locale' => $locale, + 'content' => $normalized, + 'created_by' => $currentUserId > 0 ? $currentUserId : null, + ]); + $updated = (bool) $createdId; + } + + if (!$updated) { + return ['ok' => false, 'errors' => [t('Page can not be updated')]]; + } + + return ['ok' => true, 'page' => $page]; + } + + public static function copyContentToLocale( + string $slug, + string $fromLocale, + string $toLocale, + int $currentUserId = 0 + ): array { + $slug = trim($slug); + $fromLocale = trim($fromLocale); + $toLocale = trim($toLocale); + if ($slug === '' || $fromLocale === '' || $toLocale === '') { + return ['ok' => false, 'errors' => [t('Target language required')]]; + } + + $page = PageRepository::findBySlug($slug); + if (!$page || !isset($page['id'])) { + return ['ok' => false, 'status' => 404, 'error' => 'not_found']; + } + + $source = PageContentRepository::findByPageIdAndLocale((int) $page['id'], $fromLocale); + if (!$source) { + return ['ok' => false, 'errors' => [t('Source content not found')]]; + } + + $target = PageContentRepository::findByPageIdAndLocale((int) $page['id'], $toLocale); + + $content = $source['content'] ?? null; + $updated = false; + if ($target && isset($target['id'])) { + $updated = PageContentRepository::update((int) $target['id'], [ + 'content' => $content, + 'modified_by' => $currentUserId > 0 ? $currentUserId : null, + ]); + } else { + $createdId = PageContentRepository::create([ + 'page_id' => (int) $page['id'], + 'locale' => $toLocale, + 'content' => $content, + 'created_by' => $currentUserId > 0 ? $currentUserId : null, + ]); + $updated = (bool) $createdId; + } + + if (!$updated) { + return ['ok' => false, 'errors' => [t('Page can not be updated')]]; + } + + return ['ok' => true]; + } +} diff --git a/lib/Service/PasswordResetService.php b/lib/Service/PasswordResetService.php new file mode 100644 index 0000000..d6d61ff --- /dev/null +++ b/lib/Service/PasswordResetService.php @@ -0,0 +1,147 @@ + false, 'error' => 'email_required']; + } + + $user = UserRepository::findByEmail($email); + if (!$user || !isset($user['id'])) { + return ['ok' => true]; + } + + $userId = (int) $user['id']; + PasswordResetRepository::invalidateForUser($userId); + + $code = self::generateCode(); + $codeHash = password_hash($code, PASSWORD_DEFAULT); + $expiresAt = gmdate('Y-m-d H:i:s', time() + (self::EXPIRY_MINUTES * 60)); + + $resetId = PasswordResetRepository::create($userId, $codeHash, $expiresAt); + if (!$resetId) { + return ['ok' => false, 'error' => 'create_failed']; + } + + $locale = $locale ?: ($user['locale'] ?? null) ?: (I18n::$locale ?? I18n::$defaultLocale); + $name = trim(($user['first_name'] ?? '') . ' ' . ($user['last_name'] ?? '')); + $isGerman = strpos((string) $locale, 'de') === 0; + $greeting = $isGerman ? 'Hallo' : 'Hello'; + if ($name !== '') { + $greeting .= ' ' . $name; + } + $greeting .= ','; + $verifyPath = Request::withLocale('password/verify', $locale); + $verifyUrl = appUrl($verifyPath); + $previousLocale = I18n::$locale ?? null; + I18n::$locale = $locale; + $subject = t('Password reset code'); + I18n::$locale = $previousLocale; + + $vars = [ + 'app_name' => appTitle(), + 'app_logo_url' => appLogoUrlAbsolute(128), + 'imprint_url' => appUrl(Request::withLocale('imprint', $locale)), + 'privacy_url' => appUrl(Request::withLocale('privacy', $locale)), + 'code' => $code, + 'expires_minutes' => self::EXPIRY_MINUTES, + 'verify_url' => $verifyUrl, + 'greeting' => $greeting, + ]; + MailService::sendTemplate('reset_code', $vars, $email, $subject, $locale); + + return ['ok' => true]; + } + + public static function verifyCode(string $email, string $code): array + { + $email = trim($email); + $code = trim($code); + if ($email === '' || $code === '') { + return ['ok' => false, 'error' => 'invalid']; + } + + $user = UserRepository::findByEmail($email); + if (!$user || !isset($user['id'])) { + return ['ok' => false, 'error' => 'invalid']; + } + + $reset = PasswordResetRepository::findActiveByUserId((int) $user['id']); + if (!$reset || !isset($reset['id'])) { + return ['ok' => false, 'error' => 'invalid']; + } + + $attempts = (int) ($reset['attempts'] ?? 0); + if ($attempts >= self::MAX_ATTEMPTS) { + return ['ok' => false, 'error' => 'too_many_attempts']; + } + + $hash = (string) ($reset['code_hash'] ?? ''); + if ($hash === '' || !password_verify($code, $hash)) { + PasswordResetRepository::incrementAttempts((int) $reset['id']); + return ['ok' => false, 'error' => 'invalid']; + } + + return ['ok' => true, 'reset_id' => (int) $reset['id'], 'user_id' => (int) $user['id']]; + } + + public static function resetPassword(int $resetId, string $password, string $password2): array + { + $reset = PasswordResetRepository::findById($resetId); + if (!$reset || !isset($reset['id'])) { + return ['ok' => false, 'errors' => [t('Reset request not found')]]; + } + + if (!empty($reset['used_at'])) { + return ['ok' => false, 'errors' => [t('Reset request already used')]]; + } + + $expiresAt = (string) ($reset['expires_at'] ?? ''); + if ($expiresAt !== '') { + try { + $expiry = new \DateTimeImmutable($expiresAt, new \DateTimeZone('UTC')); + if ($expiry->getTimestamp() <= time()) { + return ['ok' => false, 'errors' => [t('Reset request expired')]]; + } + } catch (\Exception $e) { + return ['ok' => false, 'errors' => [t('Reset request expired')]]; + } + } + + $userId = (int) ($reset['user_id'] ?? 0); + if ($userId <= 0) { + return ['ok' => false, 'errors' => [t('Reset request not found')]]; + } + + $result = UserService::resetPassword($userId, $password, $password2); + if (!($result['ok'] ?? false)) { + return $result; + } + + PasswordResetRepository::markUsed($resetId); + RememberMeService::forgetAllForUser($userId); + return ['ok' => true]; + } + + private static function generateCode(): string + { + $max = (10 ** self::CODE_LENGTH) - 1; + $code = (string) random_int(0, $max); + return str_pad($code, self::CODE_LENGTH, '0', STR_PAD_LEFT); + } +} diff --git a/lib/Service/PermissionService.php b/lib/Service/PermissionService.php new file mode 100644 index 0000000..a355a89 --- /dev/null +++ b/lib/Service/PermissionService.php @@ -0,0 +1,180 @@ + $userId, + 'keys' => $keys, + ]; + return $keys; + } + + public static function getCachedPermissions(int $userId): array + { + if ($userId <= 0) { + return []; + } + $cache = $_SESSION['permissions'] ?? null; + if (is_array($cache) && (int) ($cache['user_id'] ?? 0) === $userId) { + $keys = $cache['keys'] ?? []; + return is_array($keys) ? $keys : []; + } + return []; + } + + public static function clearUserCache(int $userId): void + { + $cache = $_SESSION['permissions'] ?? null; + if (is_array($cache) && (int) ($cache['user_id'] ?? 0) === $userId) { + unset($_SESSION['permissions']); + } + } + + public static function list(): array + { + return PermissionRepository::list(); + } + + public static function listPaged(array $options): array + { + return PermissionRepository::listPaged($options); + } + + public static function find(int $id): ?array + { + return PermissionRepository::find($id); + } + + public static function findByKey(string $key): ?array + { + return PermissionRepository::findByKey($key); + } + + public static function createFromAdmin(array $input): array + { + $form = self::sanitizeBase($input); + $errors = self::validateBase($form); + if ($errors) { + return ['ok' => false, 'errors' => $errors, 'form' => $form]; + } + if (PermissionRepository::findByKey($form['key'])) { + return ['ok' => false, 'errors' => [t('Permission key already exists')], 'form' => $form]; + } + $createdId = PermissionRepository::create($form); + if (!$createdId) { + return ['ok' => false, 'errors' => [t('Permission can not be created')], 'form' => $form]; + } + return ['ok' => true, 'form' => $form, 'id' => (int) $createdId]; + } + + public static function updateFromAdmin(int $id, array $input): array + { + $form = self::sanitizeBase($input); + $errors = self::validateBase($form); + if ($errors) { + return ['ok' => false, 'errors' => $errors, 'form' => $form]; + } + $existing = PermissionRepository::findByKey($form['key']); + if ($existing && (int) ($existing['id'] ?? 0) !== $id) { + return ['ok' => false, 'errors' => [t('Permission key already exists')], 'form' => $form]; + } + $updated = PermissionRepository::update($id, $form); + if (!$updated) { + return ['ok' => false, 'errors' => [t('Permission can not be updated')], 'form' => $form]; + } + return ['ok' => true, 'form' => $form]; + } + + public static function deleteById(int $id): array + { + $permission = PermissionRepository::find($id); + if (!$permission) { + return ['ok' => false, 'status' => 404, 'error' => 'not_found']; + } + $deleted = PermissionRepository::delete($id); + if (!$deleted) { + return ['ok' => false, 'status' => 500, 'error' => 'delete_failed']; + } + return ['ok' => true, 'permission' => $permission]; + } + + private static function sanitizeBase(array $input): array + { + return [ + 'key' => trim((string) ($input['key'] ?? '')), + 'description' => trim((string) ($input['description'] ?? '')), + ]; + } + + private static function validateBase(array $form): array + { + $errors = []; + if ($form['key'] === '') { + $errors[] = t('Permission key cannot be empty'); + } elseif (!preg_match('/^[a-z0-9._-]+$/i', $form['key'])) { + $errors[] = t('Permission key is invalid'); + } + return $errors; + } +} diff --git a/lib/Service/RememberMeService.php b/lib/Service/RememberMeService.php new file mode 100644 index 0000000..d012d67 --- /dev/null +++ b/lib/Service/RememberMeService.php @@ -0,0 +1,157 @@ + 0) { + PermissionService::getUserPermissions($userId, true); + AuthService::loadTenantDataIntoSession($userId); + } + + $newToken = bin2hex(random_bytes(32)); + $newHash = hash('sha256', $newToken); + $newExpires = gmdate('Y-m-d H:i:s', time() + self::lifetimeSeconds()); + RememberTokenRepository::updateToken((int) $record['id'], $newHash, $newExpires); + self::setCookie($selector, $newToken); + + return true; + } + + public static function forgetCurrentUser(): void + { + $value = $_COOKIE[self::cookieName()] ?? ''; + if ($value !== '' && strpos($value, ':') !== false) { + [$selector] = explode(':', $value, 2); + $selector = trim($selector); + if ($selector !== '') { + $record = RememberTokenRepository::findBySelector($selector); + if ($record && isset($record['id'])) { + RememberTokenRepository::deleteById((int) $record['id']); + } + } + } + self::clearCookie(); + } + + public static function forgetAllForUser(int $userId): void + { + RememberTokenRepository::deleteByUserId($userId); + } + + private static function setCookie(string $selector, string $token): void + { + $value = $selector . ':' . $token; + $expires = time() + self::lifetimeSeconds(); + $secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') + || (($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https'); + + setcookie(self::cookieName(), $value, [ + 'expires' => $expires, + 'path' => '/', + 'secure' => $secure, + 'httponly' => true, + 'samesite' => 'Lax', + ]); + } + + private static function clearCookie(): void + { + $secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') + || (($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https'); + setcookie(self::cookieName(), '', [ + 'expires' => time() - 3600, + 'path' => '/', + 'secure' => $secure, + 'httponly' => true, + 'samesite' => 'Lax', + ]); + } + + private static function lifetimeSeconds(): int + { + return self::LIFETIME_DAYS * 24 * 60 * 60; + } + + private static function cookieName(): string + { + $name = getenv('REMEMBER_COOKIE_NAME') ?: self::COOKIE_NAME; + return trim($name) !== '' ? $name : self::COOKIE_NAME; + } +} diff --git a/lib/Service/RoleService.php b/lib/Service/RoleService.php new file mode 100644 index 0000000..910d8d5 --- /dev/null +++ b/lib/Service/RoleService.php @@ -0,0 +1,116 @@ + false, 'errors' => $errors, 'form' => $form]; + } + + $createdId = RoleRepository::create([ + 'description' => $form['description'], + 'created_by' => $currentUserId > 0 ? $currentUserId : null, + ]); + + if (!$createdId) { + return ['ok' => false, 'errors' => [t('Role can not be created')], 'form' => $form]; + } + + $createdRole = RoleRepository::find((int) $createdId); + $uuid = $createdRole['uuid'] ?? null; + if (!empty($input['is_default']) && $createdId) { + SettingService::setDefaultRoleId((int) $createdId); + } + return ['ok' => true, 'form' => $form, 'uuid' => $uuid, 'id' => (int) $createdId]; + } + + public static function updateFromAdmin(int $roleId, array $input, int $currentUserId = 0): array + { + $form = self::sanitizeBase($input); + $errors = self::validateBase($form); + + if ($errors) { + return ['ok' => false, 'errors' => $errors, 'form' => $form]; + } + + $updated = RoleRepository::update($roleId, [ + 'description' => $form['description'], + 'modified_by' => $currentUserId > 0 ? $currentUserId : null, + ]); + + if (!$updated) { + return ['ok' => false, 'errors' => [t('Role can not be updated')], 'form' => $form]; + } + + return ['ok' => true, 'form' => $form]; + } + + public static function deleteByUuid(string $uuid): array + { + $uuid = trim($uuid); + if ($uuid === '') { + return ['ok' => false, 'status' => 404, 'error' => 'not_found']; + } + + $role = RoleRepository::findByUuid($uuid); + if (!$role || !isset($role['id'])) { + return ['ok' => false, 'status' => 404, 'error' => 'not_found']; + } + + if (($role['description'] ?? '') === 'Admin') { + return ['ok' => false, 'status' => 403, 'error' => 'admin_role_protected']; + } + + $deleted = RoleRepository::delete((int) $role['id']); + if (!$deleted) { + return ['ok' => false, 'status' => 500, 'error' => 'delete_failed']; + } + + return ['ok' => true, 'role' => $role]; + } + + private static function sanitizeBase(array $input): array + { + return [ + 'description' => trim((string) ($input['description'] ?? '')), + ]; + } + + private static function validateBase(array $form): array + { + $errors = []; + if ($form['description'] === '') { + $errors[] = t('Description cannot be empty'); + } + return $errors; + } +} diff --git a/lib/Service/SettingService.php b/lib/Service/SettingService.php new file mode 100644 index 0000000..c0dea4a --- /dev/null +++ b/lib/Service/SettingService.php @@ -0,0 +1,340 @@ + 0 ? $id : null; + } + + public static function setDefaultTenantId(?int $tenantId, ?string $description = null): bool + { + $value = $tenantId && $tenantId > 0 ? (string) $tenantId : null; + if ($value !== null) { + $exists = TenantRepository::find($tenantId ?? 0); + if (!$exists) { + return false; + } + } + $desc = $description ?? 'setting.default_tenant'; + return SettingRepository::set(self::DEFAULT_TENANT_KEY, $value, $desc); + } + + public static function getDefaultRoleId(): ?int + { + $id = self::getInt(self::DEFAULT_ROLE_KEY); + return $id && $id > 0 ? $id : null; + } + + public static function setDefaultRoleId(?int $roleId, ?string $description = null): bool + { + $value = $roleId && $roleId > 0 ? (string) $roleId : null; + if ($value !== null) { + $exists = RoleRepository::find($roleId ?? 0); + if (!$exists) { + return false; + } + } + $desc = $description ?? 'setting.default_role'; + return SettingRepository::set(self::DEFAULT_ROLE_KEY, $value, $desc); + } + + public static function getDefaultDepartmentId(): ?int + { + $id = self::getInt(self::DEFAULT_DEPARTMENT_KEY); + return $id && $id > 0 ? $id : null; + } + + public static function setDefaultDepartmentId(?int $departmentId, ?string $description = null): bool + { + $value = $departmentId && $departmentId > 0 ? (string) $departmentId : null; + if ($value !== null) { + $exists = DepartmentRepository::find($departmentId ?? 0); + if (!$exists) { + return false; + } + } + $desc = $description ?? 'setting.default_department'; + return SettingRepository::set(self::DEFAULT_DEPARTMENT_KEY, $value, $desc); + } + + public static function getAppTitle(): ?string + { + $value = SettingRepository::getValue(self::APP_TITLE_KEY); + $value = $value !== null ? trim($value) : null; + return $value !== '' ? $value : null; + } + + public static function setAppTitle(?string $title, ?string $description = null): bool + { + $value = $title !== null ? trim($title) : null; + if ($value === '') { + $value = null; + } + $desc = $description ?? 'setting.app_title'; + return SettingRepository::set(self::APP_TITLE_KEY, $value, $desc); + } + + public static function getAppLocale(): ?string + { + $value = SettingRepository::getValue(self::APP_LOCALE_KEY); + $value = $value !== null ? trim((string) $value) : ''; + return $value !== '' ? $value : null; + } + + public static function setAppLocale(?string $locale, ?string $description = null): bool + { + $value = $locale !== null ? trim((string) $locale) : ''; + if ($value === '') { + $value = null; + } else { + $allowed = defined('APP_LOCALES') ? APP_LOCALES : []; + if ($allowed && !in_array($value, $allowed, true)) { + return false; + } + } + $desc = $description ?? 'setting.app_locale'; + return SettingRepository::set(self::APP_LOCALE_KEY, $value, $desc); + } + + public static function getAppTheme(): ?string + { + $value = SettingRepository::getValue(self::APP_THEME_KEY); + $value = $value !== null ? strtolower(trim((string) $value)) : ''; + if (!in_array($value, ['light', 'dark'], true)) { + return null; + } + return $value; + } + + public static function setAppTheme(?string $theme, ?string $description = null): bool + { + $value = $theme !== null ? strtolower(trim((string) $theme)) : ''; + if ($value === '' || !in_array($value, ['light', 'dark'], true)) { + $value = null; + } + $desc = $description ?? 'setting.app_theme'; + return SettingRepository::set(self::APP_THEME_KEY, $value, $desc); + } + + public static function isUserThemeAllowed(): bool + { + $value = SettingRepository::getValue(self::APP_THEME_USER_KEY); + if ($value === null || $value === '') { + return true; + } + return in_array(strtolower($value), ['1', 'true', 'yes', 'on'], true); + } + + public static function setUserThemeAllowed(bool $allowed, ?string $description = null): bool + { + $value = $allowed ? '1' : '0'; + $desc = $description ?? 'setting.app_theme_user'; + return SettingRepository::set(self::APP_THEME_USER_KEY, $value, $desc); + } + + public static function getAppPrimaryColor(): ?string + { + $value = SettingRepository::getValue(self::APP_PRIMARY_COLOR_KEY); + $value = $value !== null ? strtolower(trim((string) $value)) : ''; + if ($value === '') { + return null; + } + if (!preg_match('/^#([0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i', $value)) { + return null; + } + return $value; + } + + public static function setAppPrimaryColor(?string $color, ?string $description = null): bool + { + $value = $color !== null ? strtolower(trim((string) $color)) : ''; + if ($value !== '' && $value[0] !== '#') { + if (preg_match('/^[0-9a-f]{3}$/i', $value) + || preg_match('/^[0-9a-f]{4}$/i', $value) + || preg_match('/^[0-9a-f]{6}$/i', $value) + || preg_match('/^[0-9a-f]{8}$/i', $value)) { + $value = '#' . $value; + } + } + if ($value === '') { + $value = null; + } elseif (!preg_match('/^#([0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i', $value)) { + return false; + } + $desc = $description ?? 'setting.app_primary_color'; + return SettingRepository::set(self::APP_PRIMARY_COLOR_KEY, $value, $desc); + } + + public static function getSmtpHost(): ?string + { + $value = SettingRepository::getValue(self::SMTP_HOST_KEY); + $value = $value !== null ? trim((string) $value) : ''; + return $value !== '' ? $value : null; + } + + public static function setSmtpHost(?string $host, ?string $description = null): bool + { + $value = $host !== null ? trim((string) $host) : ''; + if ($value === '') { + $value = null; + } + $desc = $description ?? 'setting.smtp_host'; + return SettingRepository::set(self::SMTP_HOST_KEY, $value, $desc); + } + + public static function getSmtpPort(): ?int + { + $value = SettingRepository::getValue(self::SMTP_PORT_KEY); + if ($value === null || $value === '') { + return null; + } + $port = (int) $value; + return $port > 0 ? $port : null; + } + + public static function setSmtpPort(?int $port, ?string $description = null): bool + { + $value = $port && $port > 0 ? (string) $port : null; + $desc = $description ?? 'setting.smtp_port'; + return SettingRepository::set(self::SMTP_PORT_KEY, $value, $desc); + } + + public static function getSmtpUser(): ?string + { + $value = SettingRepository::getValue(self::SMTP_USER_KEY); + $value = $value !== null ? trim((string) $value) : ''; + return $value !== '' ? $value : null; + } + + public static function setSmtpUser(?string $user, ?string $description = null): bool + { + $value = $user !== null ? trim((string) $user) : ''; + if ($value === '') { + $value = null; + } + $desc = $description ?? 'setting.smtp_user'; + return SettingRepository::set(self::SMTP_USER_KEY, $value, $desc); + } + + public static function getSmtpPassword(): ?string + { + $value = SettingRepository::getValue(self::SMTP_PASSWORD_KEY); + $value = $value !== null ? (string) $value : ''; + return $value !== '' ? $value : null; + } + + public static function setSmtpPassword(?string $password, ?string $description = null): bool + { + $value = $password !== null ? (string) $password : ''; + if ($value === '') { + $value = null; + } + $desc = $description ?? 'setting.smtp_password'; + return SettingRepository::set(self::SMTP_PASSWORD_KEY, $value, $desc); + } + + public static function getSmtpSecure(): ?string + { + $value = SettingRepository::getValue(self::SMTP_SECURE_KEY); + $value = $value !== null ? strtolower(trim((string) $value)) : ''; + if (!in_array($value, ['tls', 'ssl', 'none'], true)) { + return null; + } + return $value === 'none' ? null : $value; + } + + public static function setSmtpSecure(?string $secure, ?string $description = null): bool + { + $value = $secure !== null ? strtolower(trim((string) $secure)) : ''; + if ($value === '' || $value === 'none') { + $value = null; + } elseif (!in_array($value, ['tls', 'ssl'], true)) { + return false; + } + $desc = $description ?? 'setting.smtp_secure'; + return SettingRepository::set(self::SMTP_SECURE_KEY, $value, $desc); + } + + public static function getSmtpFrom(): ?string + { + $value = SettingRepository::getValue(self::SMTP_FROM_KEY); + $value = $value !== null ? trim((string) $value) : ''; + return $value !== '' ? $value : null; + } + + public static function setSmtpFrom(?string $from, ?string $description = null): bool + { + $value = $from !== null ? trim((string) $from) : ''; + if ($value === '') { + $value = null; + } + $desc = $description ?? 'setting.smtp_from'; + return SettingRepository::set(self::SMTP_FROM_KEY, $value, $desc); + } + + public static function getSmtpFromName(): ?string + { + $value = SettingRepository::getValue(self::SMTP_FROM_NAME_KEY); + $value = $value !== null ? trim((string) $value) : ''; + return $value !== '' ? $value : null; + } + + public static function setSmtpFromName(?string $fromName, ?string $description = null): bool + { + $value = $fromName !== null ? trim((string) $fromName) : ''; + if ($value === '') { + $value = null; + } + $desc = $description ?? 'setting.smtp_from_name'; + return SettingRepository::set(self::SMTP_FROM_NAME_KEY, $value, $desc); + } +} diff --git a/lib/Service/TenantAvatarService.php b/lib/Service/TenantAvatarService.php new file mode 100644 index 0000000..4769b1c --- /dev/null +++ b/lib/Service/TenantAvatarService.php @@ -0,0 +1,328 @@ + false, 'error' => t('Tenant not found')]; + } + if (empty($file) || !isset($file['tmp_name'])) { + return ['ok' => false, 'error' => t('No file uploaded')]; + } + if (($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + if (($file['size'] ?? 0) > self::MAX_SIZE) { + return ['ok' => false, 'error' => t('File is too large')]; + } + + $tmpPath = $file['tmp_name']; + $mime = self::detectMime($tmpPath); + $isSvg = self::isSvgUpload($mime, $tmpPath); + $ext = self::extensionForMime($mime, $isSvg); + if (!$ext) { + return ['ok' => false, 'error' => t('Invalid image file')]; + } + if ($isSvg && !self::isSafeSvg($tmpPath)) { + return ['ok' => false, 'error' => t('Invalid image file')]; + } + + $dir = self::tenantDir($uuid); + if (!is_dir($dir) && !mkdir($dir, 0755, true) && !is_dir($dir)) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + + self::delete($uuid); + $originalPath = $dir . '/original.' . $ext; + if (!move_uploaded_file($tmpPath, $originalPath)) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + @chmod($originalPath, 0644); + + $variantExt = function_exists('imagewebp') ? 'webp' : 'jpg'; + if (!$isSvg && self::canResize()) { + foreach (self::SIZES as $size) { + $target = $dir . '/avatar-' . $size . '.' . $variantExt; + self::resizeAndFit($originalPath, $target, $size, $size, $variantExt); + } + } + + return ['ok' => true, 'path' => $originalPath, 'mime' => $mime]; + } + + public static function detectMime(string $path): string + { + if (function_exists('finfo_open')) { + $finfo = finfo_open(FILEINFO_MIME_TYPE); + if ($finfo) { + $mime = finfo_file($finfo, $path); + if (is_string($mime) && $mime !== '') { + if (self::isSvgUpload($mime, $path)) { + return 'image/svg+xml'; + } + return $mime; + } + } + } + if (self::isSvgUpload('application/octet-stream', $path)) { + return 'image/svg+xml'; + } + return 'application/octet-stream'; + } + + private static function extensionForMime(string $mime, bool $isSvg = false): ?string + { + if ($isSvg) { + return 'svg'; + } + $map = [ + 'image/jpeg' => 'jpg', + 'image/png' => 'png', + 'image/webp' => 'webp', + ]; + return $map[$mime] ?? null; + } + + private static function isSvgUpload(string $mime, string $path): bool + { + if ($mime === 'image/svg+xml') { + return true; + } + $head = @file_get_contents($path, false, null, 0, 1024); + if (!is_string($head) || $head === '') { + return false; + } + return stripos($head, ' filemtime($a); + }); + return $matches[0] ?? null; + } + + private static function findOriginalPath(string $dir): ?string + { + $matches = glob($dir . '/original.*'); + if (!$matches) { + return null; + } + usort($matches, static function ($a, $b) { + return filemtime($b) <=> filemtime($a); + }); + return $matches[0] ?? null; + } + + private static function canResize(): bool + { + return function_exists('imagecreatetruecolor') && function_exists('imagecopyresampled'); + } + + private static function createImageResource(string $path, string $mime) + { + if ($mime === 'image/jpeg' && function_exists('imagecreatefromjpeg')) { + return imagecreatefromjpeg($path); + } + if ($mime === 'image/png' && function_exists('imagecreatefrompng')) { + return imagecreatefrompng($path); + } + if ($mime === 'image/webp' && function_exists('imagecreatefromwebp')) { + return imagecreatefromwebp($path); + } + return false; + } + + private static function resizeAndFit(string $sourcePath, string $targetPath, int $width, int $height, string $ext): bool + { + $mime = self::detectMime($sourcePath); + $src = self::createImageResource($sourcePath, $mime); + if (!$src) { + return false; + } + + $srcWidth = imagesx($src); + $srcHeight = imagesy($src); + if ($srcWidth === 0 || $srcHeight === 0) { + imagedestroy($src); + return false; + } + + $scale = min($width / $srcWidth, $height / $srcHeight); + $dstWidth = (int) round($srcWidth * $scale); + $dstHeight = (int) round($srcHeight * $scale); + if ($dstWidth < 1) $dstWidth = 1; + if ($dstHeight < 1) $dstHeight = 1; + + $dst = imagecreatetruecolor($dstWidth, $dstHeight); + if ($ext === 'png' || $ext === 'webp') { + imagealphablending($dst, false); + imagesavealpha($dst, true); + $transparent = imagecolorallocatealpha($dst, 0, 0, 0, 127); + imagefilledrectangle($dst, 0, 0, $dstWidth, $dstHeight, $transparent); + } + + imagecopyresampled( + $dst, + $src, + 0, + 0, + 0, + 0, + $dstWidth, + $dstHeight, + $srcWidth, + $srcHeight + ); + + $saved = false; + if ($ext === 'webp' && function_exists('imagewebp')) { + $saved = imagewebp($dst, $targetPath, 82); + } elseif ($ext === 'png' && function_exists('imagepng')) { + $saved = imagepng($dst, $targetPath, 6); + } else { + $saved = imagejpeg($dst, $targetPath, 85); + } + + imagedestroy($src); + imagedestroy($dst); + + if ($saved) { + @chmod($targetPath, 0644); + } + return $saved; + } + + private static function avatarDirs(string $uuid): array + { + $dirs = [self::tenantDir($uuid)]; + $legacy = self::legacyTenantDir($uuid); + if ($legacy !== $dirs[0]) { + $dirs[] = $legacy; + } + return $dirs; + } + + private static function legacyTenantDir(string $uuid): string + { + return self::storageBase() . '/tenants/' . $uuid; + } +} diff --git a/lib/Service/TenantFaviconService.php b/lib/Service/TenantFaviconService.php new file mode 100644 index 0000000..5625324 --- /dev/null +++ b/lib/Service/TenantFaviconService.php @@ -0,0 +1,214 @@ + 'favicon-16x16.png', + 32 => 'favicon-32x32.png', + 96 => 'favicon-96x96.png', + 180 => 'apple-touch-icon.png', + 192 => 'web-app-manifest-192x192.png', + 512 => 'web-app-manifest-512x512.png', + ]; + + public static function isValidUuid(string $uuid): bool + { + return (bool) preg_match('/^[a-f0-9-]{36}$/i', $uuid); + } + + public static function storageBase(): string + { + if (defined('APP_STORAGE_PATH') && APP_STORAGE_PATH) { + return rtrim(APP_STORAGE_PATH, '/'); + } + return rtrim(dirname(__DIR__, 2) . '/storage', '/'); + } + + public static function storageDir(string $uuid): string + { + return self::storageBase() . '/tenants/' . $uuid . '/favicon'; + } + + public static function publicDir(string $uuid): string + { + return rtrim(dirname(__DIR__, 2) . '/web/favicon/tenants/' . $uuid, '/'); + } + + public static function hasFavicon(string $uuid): bool + { + if (!self::isValidUuid($uuid)) { + return false; + } + $path = self::publicDir($uuid) . '/favicon-32x32.png'; + return is_file($path); + } + + public static function delete(string $uuid): void + { + if (!self::isValidUuid($uuid)) { + return; + } + foreach (self::storageDirs($uuid) as $dir) { + if (!is_dir($dir)) { + continue; + } + $matches = glob($dir . '/*') ?: []; + foreach ($matches as $file) { + if (is_file($file)) { + @unlink($file); + } + } + } + $public = self::publicDir($uuid); + foreach (self::SIZES as $file) { + $target = $public . '/' . $file; + if (is_file($target)) { + @unlink($target); + } + } + } + + public static function saveUpload(string $uuid, array $file): array + { + if (!self::isValidUuid($uuid)) { + return ['ok' => false, 'error' => t('Tenant not found')]; + } + if (empty($file) || !isset($file['tmp_name'])) { + return ['ok' => false, 'error' => t('No file uploaded')]; + } + if (($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + if (($file['size'] ?? 0) > self::MAX_SIZE) { + return ['ok' => false, 'error' => t('File is too large')]; + } + + $tmpPath = $file['tmp_name']; + $mime = self::detectMime($tmpPath); + if ($mime !== 'image/png') { + return ['ok' => false, 'error' => t('Invalid image file')]; + } + if (!self::canResize()) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + + $dir = self::storageDir($uuid); + if (!is_dir($dir) && !mkdir($dir, 0755, true) && !is_dir($dir)) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + + self::delete($uuid); + $originalPath = $dir . '/original.png'; + if (!move_uploaded_file($tmpPath, $originalPath)) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + @chmod($originalPath, 0644); + + $publicDir = self::publicDir($uuid); + if (!is_dir($publicDir) && !mkdir($publicDir, 0755, true) && !is_dir($publicDir)) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + + foreach (self::SIZES as $size => $fileName) { + $target = $publicDir . '/' . $fileName; + if (!self::resizeSquare($originalPath, $target, $size)) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + @chmod($target, 0644); + } + + return ['ok' => true, 'path' => $originalPath, 'mime' => $mime]; + } + + public static function detectMime(string $path): string + { + if (function_exists('finfo_open')) { + $finfo = finfo_open(FILEINFO_MIME_TYPE); + if ($finfo) { + $mime = finfo_file($finfo, $path); + if (is_string($mime) && $mime !== '') { + return $mime; + } + } + } + return 'application/octet-stream'; + } + + private static function canResize(): bool + { + return function_exists('imagecreatetruecolor') && function_exists('imagecopyresampled'); + } + + private static function loadImage(string $path) + { + if (function_exists('imagecreatefrompng')) { + return imagecreatefrompng($path); + } + return false; + } + + private static function resizeSquare(string $sourcePath, string $targetPath, int $size): bool + { + $src = self::loadImage($sourcePath); + if (!$src) { + return false; + } + $srcWidth = imagesx($src); + $srcHeight = imagesy($src); + if ($srcWidth === 0 || $srcHeight === 0) { + imagedestroy($src); + return false; + } + + $cropSize = min($srcWidth, $srcHeight); + $srcX = (int) round(($srcWidth - $cropSize) / 2); + $srcY = (int) round(($srcHeight - $cropSize) / 2); + + $dst = imagecreatetruecolor($size, $size); + imagealphablending($dst, false); + imagesavealpha($dst, true); + $transparent = imagecolorallocatealpha($dst, 0, 0, 0, 127); + imagefilledrectangle($dst, 0, 0, $size, $size, $transparent); + + imagecopyresampled( + $dst, + $src, + 0, + 0, + $srcX, + $srcY, + $size, + $size, + $cropSize, + $cropSize + ); + + $saved = false; + if (function_exists('imagepng')) { + $saved = imagepng($dst, $targetPath, 6); + } + + imagedestroy($src); + imagedestroy($dst); + + return $saved; + } + + private static function storageDirs(string $uuid): array + { + $dirs = [self::storageDir($uuid)]; + $legacy = self::legacyStorageDir($uuid); + if ($legacy !== $dirs[0]) { + $dirs[] = $legacy; + } + return $dirs; + } + + private static function legacyStorageDir(string $uuid): string + { + return self::storageBase() . '/branding/tenants/' . $uuid . '/favicon'; + } +} diff --git a/lib/Service/TenantScopeService.php b/lib/Service/TenantScopeService.php new file mode 100644 index 0000000..b5f4921 --- /dev/null +++ b/lib/Service/TenantScopeService.php @@ -0,0 +1,118 @@ + 0 ? [$resourceId] : []; + } + if ($resource === 'users') { + return array_values(array_unique(array_map('intval', UserTenantRepository::listTenantIdsByUserId($resourceId)))); + } + if ($resource === 'departments') { + return array_values(array_unique(array_map('intval', TenantDepartmentRepository::listTenantIdsByDepartmentId($resourceId)))); + } + return []; + } + + private static function filterActiveTenantIds(array $tenantIds): array + { + $tenantIds = array_values(array_unique(array_map('intval', $tenantIds))); + if (!$tenantIds) { + return []; + } + return TenantRepository::listActiveIdsByIds($tenantIds); + } + + private static function canBypass(int $userId): bool + { + if ($userId <= 0) { + return false; + } + return PermissionService::userHas($userId, PermissionService::TENANTS_UPDATE) + || PermissionService::userHas($userId, PermissionService::SETTINGS_UPDATE); + } +} diff --git a/lib/Service/TenantService.php b/lib/Service/TenantService.php new file mode 100644 index 0000000..a501db0 --- /dev/null +++ b/lib/Service/TenantService.php @@ -0,0 +1,207 @@ + false, 'errors' => $errors, 'form' => $form]; + } + + $statusChangedAt = gmdate('Y-m-d H:i:s'); + $createdId = TenantRepository::create([ + 'description' => $form['description'], + 'address' => $form['address'], + 'postal_code' => $form['postal_code'], + 'city' => $form['city'], + 'country' => $form['country'], + 'region' => $form['region'], + 'vat_id' => $form['vat_id'], + 'tax_number' => $form['tax_number'], + 'phone' => $form['phone'], + 'fax' => $form['fax'], + 'email' => $form['email'], + 'support_email' => $form['support_email'], + 'support_phone' => $form['support_phone'], + 'billing_email' => $form['billing_email'], + 'website' => $form['website'], + 'privacy_url' => $form['privacy_url'], + 'imprint_url' => $form['imprint_url'], + 'primary_color' => $form['primary_color_use_default'] + ? null + : ($form['primary_color'] !== '' ? $form['primary_color'] : null), + 'status' => $form['status'], + 'status_changed_at' => $statusChangedAt, + 'status_changed_by' => $currentUserId > 0 ? $currentUserId : null, + 'created_by' => $currentUserId > 0 ? $currentUserId : null, + ]); + + if (!$createdId) { + return ['ok' => false, 'errors' => [t('Tenant can not be created')], 'form' => $form]; + } + + $createdTenant = TenantRepository::find((int) $createdId); + $uuid = $createdTenant['uuid'] ?? null; + if (!empty($input['is_default']) && $createdId) { + SettingService::setDefaultTenantId((int) $createdId); + } + return ['ok' => true, 'form' => $form, 'uuid' => $uuid, 'id' => (int) $createdId]; + } + + public static function updateFromAdmin(int $tenantId, array $input, int $currentUserId = 0): array + { + $form = self::sanitizeBase($input); + $form['status'] = self::normalizeStatus($form['status'] ?? ''); + $errors = self::validateBase($form); + + if ($errors) { + return ['ok' => false, 'errors' => $errors, 'form' => $form]; + } + + $existing = TenantRepository::find($tenantId); + $statusChanged = false; + if ($existing && isset($existing['status'])) { + $statusChanged = (string) $existing['status'] !== $form['status']; + } + + $updateData = [ + 'description' => $form['description'], + 'address' => $form['address'], + 'postal_code' => $form['postal_code'], + 'city' => $form['city'], + 'country' => $form['country'], + 'region' => $form['region'], + 'vat_id' => $form['vat_id'], + 'tax_number' => $form['tax_number'], + 'phone' => $form['phone'], + 'fax' => $form['fax'], + 'email' => $form['email'], + 'support_email' => $form['support_email'], + 'support_phone' => $form['support_phone'], + 'billing_email' => $form['billing_email'], + 'website' => $form['website'], + 'privacy_url' => $form['privacy_url'], + 'imprint_url' => $form['imprint_url'], + 'primary_color' => $form['primary_color_use_default'] + ? null + : ($form['primary_color'] !== '' ? $form['primary_color'] : null), + 'status' => $form['status'], + 'modified_by' => $currentUserId > 0 ? $currentUserId : null, + ]; + if ($statusChanged) { + $updateData['status_changed_at'] = gmdate('Y-m-d H:i:s'); + $updateData['status_changed_by'] = $currentUserId > 0 ? $currentUserId : null; + } + + $updated = TenantRepository::update($tenantId, $updateData); + + if (!$updated) { + return ['ok' => false, 'errors' => [t('Tenant can not be updated')], 'form' => $form]; + } + + return ['ok' => true, 'form' => $form]; + } + + public static function deleteByUuid(string $uuid): array + { + $uuid = trim($uuid); + if ($uuid === '') { + return ['ok' => false, 'status' => 404, 'error' => 'not_found']; + } + + $tenant = TenantRepository::findByUuid($uuid); + if (!$tenant || !isset($tenant['id'])) { + return ['ok' => false, 'status' => 404, 'error' => 'not_found']; + } + + $deleted = TenantRepository::delete((int) $tenant['id']); + if (!$deleted) { + return ['ok' => false, 'status' => 500, 'error' => 'delete_failed']; + } + + return ['ok' => true, 'tenant' => $tenant]; + } + + private static function sanitizeBase(array $input): array + { + return [ + 'description' => trim((string) ($input['description'] ?? '')), + 'address' => trim((string) ($input['address'] ?? '')), + 'postal_code' => trim((string) ($input['postal_code'] ?? '')), + 'city' => trim((string) ($input['city'] ?? '')), + 'country' => trim((string) ($input['country'] ?? '')), + 'region' => trim((string) ($input['region'] ?? '')), + 'vat_id' => trim((string) ($input['vat_id'] ?? '')), + 'tax_number' => trim((string) ($input['tax_number'] ?? '')), + 'phone' => trim((string) ($input['phone'] ?? '')), + 'fax' => trim((string) ($input['fax'] ?? '')), + 'email' => trim((string) ($input['email'] ?? '')), + 'support_email' => trim((string) ($input['support_email'] ?? '')), + 'support_phone' => trim((string) ($input['support_phone'] ?? '')), + 'billing_email' => trim((string) ($input['billing_email'] ?? '')), + 'website' => trim((string) ($input['website'] ?? '')), + 'privacy_url' => trim((string) ($input['privacy_url'] ?? '')), + 'imprint_url' => trim((string) ($input['imprint_url'] ?? '')), + 'primary_color' => trim((string) ($input['primary_color'] ?? '')), + 'primary_color_use_default' => !empty($input['primary_color_use_default']), + 'status' => trim((string) ($input['status'] ?? '')), + ]; + } + + private static function validateBase(array $form): array + { + $errors = []; + if ($form['description'] === '') { + $errors[] = t('Description cannot be empty'); + } + if (!in_array($form['status'], ['active', 'inactive'], true)) { + $errors[] = t('Status is invalid'); + } + if ( + !$form['primary_color_use_default'] + && $form['primary_color'] !== '' + && !preg_match('/^#([0-9a-f]{3}|[0-9a-f]{6})$/i', $form['primary_color']) + ) { + $errors[] = t('Primary color is invalid'); + } + return $errors; + } + + private static function normalizeStatus(string $status): string + { + $status = strtolower(trim($status)); + if (!in_array($status, ['active', 'inactive'], true)) { + return 'active'; + } + return $status; + } +} diff --git a/lib/Service/UserAvatarService.php b/lib/Service/UserAvatarService.php new file mode 100644 index 0000000..0f86d61 --- /dev/null +++ b/lib/Service/UserAvatarService.php @@ -0,0 +1,307 @@ + false, 'error' => t('User not found')]; + } + if (empty($file) || !isset($file['tmp_name'])) { + return ['ok' => false, 'error' => t('No file uploaded')]; + } + if (($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + if (($file['size'] ?? 0) > self::MAX_SIZE) { + return ['ok' => false, 'error' => t('File is too large')]; + } + + $tmpPath = $file['tmp_name']; + $mime = self::detectMime($tmpPath); + $isSvg = self::isSvgUpload($mime, $tmpPath); + $ext = self::extensionForMime($mime, $isSvg); + if (!$ext) { + return ['ok' => false, 'error' => t('Invalid image file')]; + } + if ($isSvg && !self::isSafeSvg($tmpPath)) { + return ['ok' => false, 'error' => t('Invalid image file')]; + } + + $dir = self::userDir($uuid); + if (!is_dir($dir) && !mkdir($dir, 0755, true) && !is_dir($dir)) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + + self::delete($uuid); + $originalPath = $dir . '/original.' . $ext; + if (!move_uploaded_file($tmpPath, $originalPath)) { + return ['ok' => false, 'error' => t('Upload failed')]; + } + @chmod($originalPath, 0644); + + $variantExt = function_exists('imagewebp') ? 'webp' : 'jpg'; + if (!$isSvg && self::canResize()) { + foreach (self::SIZES as $size) { + $target = $dir . '/avatar-' . $size . '.' . $variantExt; + self::resizeAndFit($originalPath, $target, $size, $size, $variantExt); + } + } + + return ['ok' => true, 'path' => $originalPath, 'mime' => $mime]; + } + + public static function detectMime(string $path): string + { + if (function_exists('finfo_open')) { + $finfo = finfo_open(FILEINFO_MIME_TYPE); + if ($finfo) { + $mime = finfo_file($finfo, $path); + if (is_string($mime) && $mime !== '') { + if (self::isSvgUpload($mime, $path)) { + return 'image/svg+xml'; + } + return $mime; + } + } + } + if (self::isSvgUpload('application/octet-stream', $path)) { + return 'image/svg+xml'; + } + return 'application/octet-stream'; + } + + private static function extensionForMime(string $mime, bool $isSvg = false): ?string + { + if ($isSvg) { + return 'svg'; + } + $map = [ + 'image/jpeg' => 'jpg', + 'image/png' => 'png', + 'image/webp' => 'webp', + ]; + return $map[$mime] ?? null; + } + + private static function isSvgUpload(string $mime, string $path): bool + { + if ($mime === 'image/svg+xml') { + return true; + } + $head = @file_get_contents($path, false, null, 0, 1024); + if (!is_string($head) || $head === '') { + return false; + } + return stripos($head, ' filemtime($a); + }); + return $matches[0] ?? null; + } + + private static function findOriginalPath(string $dir): ?string + { + $matches = glob($dir . '/original.*'); + if (!$matches) { + return null; + } + usort($matches, static function ($a, $b) { + return filemtime($b) <=> filemtime($a); + }); + return $matches[0] ?? null; + } + + private static function canResize(): bool + { + return function_exists('imagecreatetruecolor') && function_exists('imagecopyresampled'); + } + + private static function createImageResource(string $path, string $mime) + { + if ($mime === 'image/jpeg' && function_exists('imagecreatefromjpeg')) { + return imagecreatefromjpeg($path); + } + if ($mime === 'image/png' && function_exists('imagecreatefrompng')) { + return imagecreatefrompng($path); + } + if ($mime === 'image/webp' && function_exists('imagecreatefromwebp')) { + return imagecreatefromwebp($path); + } + return false; + } + + private static function resizeAndFit(string $sourcePath, string $targetPath, int $width, int $height, string $ext): bool + { + $mime = self::detectMime($sourcePath); + $src = self::createImageResource($sourcePath, $mime); + if (!$src) { + return false; + } + + $srcWidth = imagesx($src); + $srcHeight = imagesy($src); + if ($srcWidth === 0 || $srcHeight === 0) { + imagedestroy($src); + return false; + } + + $scale = min($width / $srcWidth, $height / $srcHeight); + $dstWidth = (int) round($srcWidth * $scale); + $dstHeight = (int) round($srcHeight * $scale); + if ($dstWidth < 1) $dstWidth = 1; + if ($dstHeight < 1) $dstHeight = 1; + + $dst = imagecreatetruecolor($dstWidth, $dstHeight); + if ($ext === 'png' || $ext === 'webp') { + imagealphablending($dst, false); + imagesavealpha($dst, true); + $transparent = imagecolorallocatealpha($dst, 0, 0, 0, 127); + imagefilledrectangle($dst, 0, 0, $dstWidth, $dstHeight, $transparent); + } + + imagecopyresampled( + $dst, + $src, + 0, + 0, + 0, + 0, + $dstWidth, + $dstHeight, + $srcWidth, + $srcHeight + ); + + $saved = false; + if ($ext === 'webp' && function_exists('imagewebp')) { + $saved = imagewebp($dst, $targetPath, 82); + } elseif ($ext === 'png' && function_exists('imagepng')) { + $saved = imagepng($dst, $targetPath, 6); + } else { + $saved = imagejpeg($dst, $targetPath, 85); + } + + imagedestroy($src); + imagedestroy($dst); + + if ($saved) { + @chmod($targetPath, 0644); + } + return $saved; + } +} diff --git a/lib/Service/UserService.php b/lib/Service/UserService.php new file mode 100644 index 0000000..0e7f9cf --- /dev/null +++ b/lib/Service/UserService.php @@ -0,0 +1,804 @@ + 0 && TenantScopeService::hasGlobalAccess($tenantUserId)) { + unset($options['tenantUserId']); + } + } + return UserRepository::listPaged($options); + } + + public static function findByUuid(string $uuid): ?array + { + return UserRepository::findByUuid($uuid); + } + + public static function findById(int $id): ?array + { + return UserRepository::find($id); + } + + public static function findByEmail(string $email): ?array + { + return UserRepository::findByEmail($email); + } + + public static function setLocale(int $userId, string $locale): bool + { + return UserRepository::setLocale($userId, $locale); + } + + public static function setTheme(int $userId, string $theme): bool + { + $theme = self::normalizeTheme($theme); + return UserRepository::setTheme($userId, $theme); + } + + public static function deleteByUuid(string $uuid, int $currentUserId = 0): array + { + $uuid = trim($uuid); + if ($uuid === '') { + return ['ok' => false, 'status' => 404, 'error' => 'not_found']; + } + + $user = UserRepository::findByUuid($uuid); + if (!$user || !isset($user['id'])) { + return ['ok' => false, 'status' => 404, 'error' => 'not_found']; + } + + $userId = (int) $user['id']; + if ($currentUserId && $currentUserId === $userId) { + return [ + 'ok' => false, + 'status' => 400, + 'error' => 'self_delete', + 'message' => t('You cannot delete your own account'), + ]; + } + + $deleted = UserRepository::delete($userId); + if (!$deleted) { + return ['ok' => false, 'status' => 500, 'error' => 'delete_failed']; + } + + return ['ok' => true, 'user' => $user]; + } + + public static function deleteByUuids(array $uuids, int $currentUserId = 0): array + { + $uuids = array_values(array_filter(array_map('trim', $uuids))); + if (!$uuids) { + return ['ok' => false, 'error' => 'no_selection']; + } + + if ($currentUserId > 0) { + $uuids = self::filterUuidsByTenantScope($uuids, $currentUserId); + if (!$uuids) { + return ['ok' => false, 'error' => 'permission_denied']; + } + } + + if ($currentUserId > 0) { + $currentUser = UserRepository::find($currentUserId); + $currentUuid = $currentUser['uuid'] ?? ''; + if ($currentUuid !== '') { + $uuids = array_values(array_filter($uuids, static fn ($uuid) => $uuid !== $currentUuid)); + } + if (!$uuids) { + return ['ok' => false, 'error' => 'self_delete']; + } + } + + $deleted = UserRepository::deleteByUuids($uuids); + if (!$deleted) { + return ['ok' => false, 'error' => 'delete_failed']; + } + + return ['ok' => true, 'count' => count($uuids)]; + } + + public static function createFromAdmin(array $input, int $currentUserId = 0): array + { + $form = self::sanitizeBase($input); + $form['totp_secret'] = trim((string) ($input['totp_secret'] ?? '')); + $form['theme'] = self::normalizeTheme($input['theme'] ?? null); + $form['locale'] = self::normalizeLocale($input['locale'] ?? null); + $primaryTenantId = (int) ($input['primary_tenant_id'] ?? 0); + if (array_key_exists('active', $input)) { + $form['active'] = isset($input['active']) ? 1 : 0; + } else { + $form['active'] = 1; + } + $password = (string) ($input['password'] ?? ''); + $password2 = (string) ($input['password2'] ?? ''); + + $errors = self::validateBase($form); + $errors = array_merge($errors, self::validatePassword($password, $password2, true, $form['email'])); + + $tenantIds = $input['tenant_ids'] ?? []; + if (!is_array($tenantIds)) { + $tenantIds = [$tenantIds]; + } + $tenantIds = self::normalizeTenantIds($tenantIds); + if (!$tenantIds) { + $defaultTenantId = SettingService::getDefaultTenantId(); + if ($defaultTenantId) { + $tenantIds = [$defaultTenantId]; + } + } + [$primaryTenantId, $primaryErrors] = self::normalizePrimaryTenant($primaryTenantId, $tenantIds); + $errors = array_merge($errors, $primaryErrors); + + if ($errors) { + $form['primary_tenant_id'] = $primaryTenantId; + return ['ok' => false, 'errors' => $errors, 'form' => $form]; + } + + $activeChangedAt = gmdate('Y-m-d H:i:s'); + $created = UserRepository::create([ + 'first_name' => $form['first_name'], + 'last_name' => $form['last_name'], + 'email' => $form['email'], + 'profile_description' => $form['profile_description'] !== '' ? $form['profile_description'] : null, + 'job_title' => $form['job_title'] !== '' ? $form['job_title'] : null, + 'phone' => $form['phone'] !== '' ? $form['phone'] : null, + 'mobile' => $form['mobile'] !== '' ? $form['mobile'] : null, + 'short_dial' => $form['short_dial'] !== '' ? $form['short_dial'] : null, + 'address' => $form['address'] !== '' ? $form['address'] : null, + 'postal_code' => $form['postal_code'] !== '' ? $form['postal_code'] : null, + 'city' => $form['city'] !== '' ? $form['city'] : null, + 'country' => $form['country'] !== '' ? $form['country'] : null, + 'region' => $form['region'] !== '' ? $form['region'] : null, + 'hire_date' => $form['hire_date'] !== '' ? $form['hire_date'] : null, + 'password' => $password, + 'locale' => $form['locale'], + 'totp_secret' => $form['totp_secret'], + 'theme' => $form['theme'], + 'primary_tenant_id' => $primaryTenantId > 0 ? $primaryTenantId : null, + 'active' => $form['active'], + 'created_by' => $currentUserId > 0 ? $currentUserId : null, + 'active_changed_at' => $activeChangedAt, + 'active_changed_by' => $currentUserId > 0 ? $currentUserId : null, + ]); + + if (!$created) { + return ['ok' => false, 'errors' => [t('User can not be registered')], 'form' => $form]; + } + + $createdUser = UserRepository::findByEmail($form['email']); + $uuid = $createdUser['uuid'] ?? null; + $userId = (int) ($createdUser['id'] ?? 0); + + if ($userId > 0 && $tenantIds) { + self::syncTenants($userId, $tenantIds); + } + + $roleIds = self::normalizeIdInput($input['role_ids'] ?? []); + if (!$roleIds) { + $defaultRoleId = SettingService::getDefaultRoleId(); + if ($defaultRoleId) { + $roleIds = [$defaultRoleId]; + } + } + if ($userId > 0 && $roleIds) { + self::syncRoles($userId, $roleIds); + } + + $departmentIds = self::normalizeIdInput($input['department_ids'] ?? []); + if (!$departmentIds) { + $defaultDepartmentId = SettingService::getDefaultDepartmentId(); + if ($defaultDepartmentId) { + $departmentIds = [$defaultDepartmentId]; + } + } + if ($userId > 0 && $departmentIds) { + self::syncDepartments($userId, $departmentIds); + } + + return ['ok' => true, 'form' => $form, 'uuid' => $uuid]; + } + + public static function updateFromAdmin(int $userId, array $input, int $currentUserId = 0): array + { + $form = self::sanitizeBase($input); + $form['totp_secret'] = trim((string) ($input['totp_secret'] ?? '')); + $form['theme'] = self::normalizeTheme($input['theme'] ?? null); + $form['locale'] = self::normalizeLocale($input['locale'] ?? null); + $primaryTenantId = (int) ($input['primary_tenant_id'] ?? 0); + $tenantIdsProvided = array_key_exists('tenant_ids', $input); + $primaryProvided = array_key_exists('primary_tenant_id', $input); + if ($tenantIdsProvided) { + $tenantIds = $input['tenant_ids'] ?? []; + if (!is_array($tenantIds)) { + $tenantIds = [$tenantIds]; + } + $tenantIds = self::normalizeTenantIds($tenantIds); + } else { + $tenantIds = UserTenantRepository::listTenantIdsByUserId($userId); + } + if (array_key_exists('active', $input)) { + $form['active'] = isset($input['active']) ? 1 : 0; + } else { + $existing = UserRepository::find($userId); + $form['active'] = (int) ($existing['active'] ?? 1); + } + $password = (string) ($input['password'] ?? ''); + $password2 = (string) ($input['password2'] ?? ''); + + $errors = self::validateBase($form, $userId); + if ($userId === $currentUserId && !$form['active']) { + $errors[] = t('You cannot deactivate your own account'); + } + $errors = array_merge($errors, self::validatePassword($password, $password2, false, $form['email'])); + if ($tenantIds && ($tenantIdsProvided || $primaryProvided)) { + [$primaryTenantId, $primaryErrors] = self::normalizePrimaryTenant($primaryTenantId, $tenantIds); + $errors = array_merge($errors, $primaryErrors); + } + + if ($errors) { + if ($tenantIdsProvided || $primaryProvided) { + $form['primary_tenant_id'] = $primaryTenantId; + } + return ['ok' => false, 'errors' => $errors, 'form' => $form]; + } + + if ($tenantIdsProvided || $primaryProvided) { + $form['primary_tenant_id'] = $primaryTenantId > 0 ? $primaryTenantId : null; + } + + $updateData = [ + 'first_name' => $form['first_name'], + 'last_name' => $form['last_name'], + 'email' => $form['email'], + 'profile_description' => $form['profile_description'] !== '' ? $form['profile_description'] : null, + 'job_title' => $form['job_title'] !== '' ? $form['job_title'] : null, + 'phone' => $form['phone'] !== '' ? $form['phone'] : null, + 'mobile' => $form['mobile'] !== '' ? $form['mobile'] : null, + 'short_dial' => $form['short_dial'] !== '' ? $form['short_dial'] : null, + 'address' => $form['address'] !== '' ? $form['address'] : null, + 'postal_code' => $form['postal_code'] !== '' ? $form['postal_code'] : null, + 'city' => $form['city'] !== '' ? $form['city'] : null, + 'country' => $form['country'] !== '' ? $form['country'] : null, + 'region' => $form['region'] !== '' ? $form['region'] : null, + 'hire_date' => $form['hire_date'] !== '' ? $form['hire_date'] : null, + 'totp_secret' => $form['totp_secret'], + 'theme' => $form['theme'], + 'locale' => $form['locale'], + 'active' => $form['active'], + 'password' => $password, + 'modified_by' => $currentUserId > 0 ? $currentUserId : null, + ]; + if ($tenantIdsProvided || $primaryProvided) { + $updateData['primary_tenant_id'] = $form['primary_tenant_id'] ?? null; + } + + if ((int) ($existing['active'] ?? 1) !== (int) $form['active']) { + $updateData['active_changed_at'] = gmdate('Y-m-d H:i:s'); + $updateData['active_changed_by'] = $currentUserId > 0 ? $currentUserId : null; + } + + $updated = UserRepository::update($userId, $updateData); + + if (!$updated) { + return ['ok' => false, 'errors' => [t('User can not be updated')], 'form' => $form]; + } + + return ['ok' => true, 'form' => $form]; + } + + public static function setActiveByUuid(string $uuid, bool $active, int $currentUserId = 0): array + { + $uuid = trim($uuid); + if ($uuid === '') { + return ['ok' => false, 'status' => 404, 'error' => 'not_found']; + } + + $user = UserRepository::findByUuid($uuid); + if (!$user || !isset($user['id'])) { + return ['ok' => false, 'status' => 404, 'error' => 'not_found']; + } + + $userId = (int) $user['id']; + if (!$active && $currentUserId && $currentUserId === $userId) { + return [ + 'ok' => false, + 'status' => 400, + 'error' => 'self_deactivate', + 'message' => t('You cannot deactivate your own account'), + ]; + } + + $updated = UserRepository::setActive($userId, $active, $currentUserId > 0 ? $currentUserId : null); + if (!$updated) { + return ['ok' => false, 'status' => 500, 'error' => 'update_failed']; + } + + return ['ok' => true, 'user' => $user]; + } + + public static function setActiveByUuids(array $uuids, bool $active, int $currentUserId = 0): array + { + $uuids = array_values(array_filter(array_map('trim', $uuids))); + if (!$uuids) { + return ['ok' => false, 'error' => 'no_selection']; + } + + if ($currentUserId > 0) { + $uuids = self::filterUuidsByTenantScope($uuids, $currentUserId); + if (!$uuids) { + return ['ok' => false, 'error' => 'permission_denied']; + } + } + + $updated = UserRepository::setActiveByUuids($uuids, $active, $currentUserId > 0 ? $currentUserId : null); + if (!$updated) { + return ['ok' => false, 'error' => 'update_failed']; + } + + return ['ok' => true, 'count' => count($uuids)]; + } + + private static function filterUuidsByTenantScope(array $uuids, int $currentUserId): array + { + $allowed = []; + foreach ($uuids as $uuid) { + $user = UserRepository::findByUuid((string) $uuid); + if (!$user || !isset($user['id'])) { + continue; + } + $userId = (int) $user['id']; + if ($userId === $currentUserId) { + $allowed[] = (string) $uuid; + continue; + } + if (TenantScopeService::canAccess('users', $userId, $currentUserId)) { + $allowed[] = (string) $uuid; + } + } + return array_values(array_unique($allowed)); + } + + public static function register(array $input): array + { + $form = self::sanitizeBase($input); + $password = (string) ($input['password'] ?? ''); + $password2 = (string) ($input['password2'] ?? ''); + + $errors = self::validateBase($form); + $errors = array_merge($errors, self::validatePassword($password, $password2, true, $form['email'])); + + if ($errors) { + return ['ok' => false, 'error' => $errors[0]]; + } + + $defaultTheme = SettingService::getAppTheme(); + $defaultTenantId = SettingService::getDefaultTenantId(); + $activeChangedAt = gmdate('Y-m-d H:i:s'); + $created = UserRepository::create([ + 'first_name' => $form['first_name'], + 'last_name' => $form['last_name'], + 'email' => $form['email'], + 'password' => $password, + 'locale' => I18n::$locale, + 'totp_secret' => '', + 'theme' => self::normalizeTheme($defaultTheme ?? 'light'), + 'primary_tenant_id' => $defaultTenantId ?: null, + 'active' => 1, + 'created_by' => null, + 'active_changed_at' => $activeChangedAt, + 'active_changed_by' => null, + ]); + + if (!$created) { + return ['ok' => false, 'error' => t('User can not be registered')]; + } + + $createdUser = UserRepository::findByEmail($form['email']); + $userId = (int) ($createdUser['id'] ?? 0); + if ($userId > 0) { + if ($defaultTenantId) { + self::syncTenants($userId, [$defaultTenantId]); + } + $defaultRoleId = SettingService::getDefaultRoleId(); + if ($defaultRoleId) { + self::syncRoles($userId, [$defaultRoleId]); + } + $defaultDepartmentId = SettingService::getDefaultDepartmentId(); + if ($defaultDepartmentId) { + self::syncDepartments($userId, [$defaultDepartmentId]); + } + } + + return ['ok' => true]; + } + + public static function syncTenants(int $userId, array $tenantIds): bool + { + $ids = self::normalizeTenantIds($tenantIds); + return UserTenantRepository::replaceForUser($userId, $ids); + } + + public static function syncRoles(int $userId, array $roleIds): bool + { + $ids = array_values(array_unique(array_map('intval', $roleIds))); + $ids = array_filter($ids, static fn ($id) => $id > 0); + $validIds = RoleRepository::listIds(); + if ($validIds) { + $validMap = array_fill_keys($validIds, true); + $ids = array_values(array_filter($ids, static fn ($id) => isset($validMap[$id]))); + } + $result = UserRoleRepository::replaceForUser($userId, $ids); + PermissionService::clearUserCache($userId); + return $result; + } + + public static function syncDepartments(int $userId, array $departmentIds): bool + { + $ids = array_values(array_unique(array_map('intval', $departmentIds))); + $ids = array_filter($ids, static fn ($id) => $id > 0); + $userTenantIds = TenantScopeService::getUserTenantIds($userId); + if (!$userTenantIds) { + $ids = []; + } else { + $allowedIds = TenantDepartmentRepository::listDepartmentIdsByTenantIds($userTenantIds); + if ($allowedIds) { + $allowedMap = array_fill_keys($allowedIds, true); + $ids = array_values(array_filter($ids, static fn ($id) => isset($allowedMap[$id]))); + } else { + $ids = []; + } + } + return UserDepartmentRepository::replaceForUser($userId, $ids); + } + + private static function sanitizeBase(array $input): array + { + return [ + 'first_name' => trim((string) ($input['first_name'] ?? '')), + 'last_name' => trim((string) ($input['last_name'] ?? '')), + 'email' => trim((string) ($input['email'] ?? '')), + 'profile_description' => trim((string) ($input['profile_description'] ?? '')), + 'job_title' => trim((string) ($input['job_title'] ?? '')), + 'phone' => trim((string) ($input['phone'] ?? '')), + 'mobile' => trim((string) ($input['mobile'] ?? '')), + 'short_dial' => trim((string) ($input['short_dial'] ?? '')), + 'address' => trim((string) ($input['address'] ?? '')), + 'postal_code' => trim((string) ($input['postal_code'] ?? '')), + 'city' => trim((string) ($input['city'] ?? '')), + 'country' => trim((string) ($input['country'] ?? '')), + 'region' => trim((string) ($input['region'] ?? '')), + 'hire_date' => trim((string) ($input['hire_date'] ?? '')), + ]; + } + + public static function normalizeIdInput($value): array + { + if (!is_array($value)) { + $value = [$value]; + } + $ids = array_values(array_unique(array_map('intval', $value))); + return array_values(array_filter($ids, static fn ($id) => $id > 0)); + } + + private static function normalizeTenantIds(array $tenantIds): array + { + $ids = array_values(array_unique(array_map('intval', $tenantIds))); + $ids = array_filter($ids, static fn ($id) => $id > 0); + $validIds = TenantRepository::listIds(); + if ($validIds) { + $validMap = array_fill_keys($validIds, true); + $ids = array_values(array_filter($ids, static fn ($id) => isset($validMap[$id]))); + } + return $ids; + } + + private static function normalizeTheme($value): string + { + $theme = strtolower(trim((string) $value)); + if (!in_array($theme, ['dark', 'light'], true)) { + return 'light'; + } + return $theme; + } + + private static function normalizeLocale($value): string + { + $locale = strtolower(trim((string) $value)); + $available = defined('APP_LOCALES') ? APP_LOCALES : [I18n::$defaultLocale]; + if ($locale === '' || !in_array($locale, $available, true)) { + return I18n::$locale ?? I18n::$defaultLocale; + } + return $locale; + } + + private static function validateBase(array $form, ?int $excludeId = null): array + { + $errors = []; + if ($form['first_name'] === '') { + $errors[] = t('First name cannot be empty'); + } + if ($form['last_name'] === '') { + $errors[] = t('Last name cannot be empty'); + } + if ($form['email'] === '') { + $errors[] = t('Email cannot be empty'); + } elseif (!filter_var($form['email'], FILTER_VALIDATE_EMAIL)) { + $errors[] = t('Email is not valid'); + } else { + $existing = UserRepository::findByEmail($form['email']); + if ($existing && (!isset($existing['id']) || (int) $existing['id'] !== (int) $excludeId)) { + $errors[] = t('Email is already taken'); + } + } + + return $errors; + } + + private static function normalizePrimaryTenant(int $primaryTenantId, array $tenantIds): array + { + if (!$tenantIds) { + return [0, []]; + } + if ($primaryTenantId > 0 && !in_array($primaryTenantId, $tenantIds, true)) { + return [$primaryTenantId, [t('Primary tenant must be one of the assigned tenants')]]; + } + if ($primaryTenantId === 0 && count($tenantIds) > 1) { + return [0, [t('Please select a primary tenant')]]; + } + if ($primaryTenantId === 0 && count($tenantIds) === 1) { + return [(int) $tenantIds[0], []]; + } + return [$primaryTenantId, []]; + } + + private static function validatePassword( + string $password, + string $password2, + bool $required, + ?string $email + ): array { + return self::validatePasswordStrength($password, $password2, $required, $email); + } + + public static function passwordHints(): array + { + return [ + ['rule' => 'min', 'text' => t('At least %d characters', self::PASSWORD_MIN_LENGTH)], + ['rule' => 'upper', 'text' => t('At least one uppercase letter')], + ['rule' => 'lower', 'text' => t('At least one lowercase letter')], + ['rule' => 'number', 'text' => t('At least one number')], + ['rule' => 'symbol', 'text' => t('At least one symbol')], + ['rule' => 'email', 'text' => t('Must not contain your email')], + ]; + } + + public static function passwordMinLength(): int + { + return self::PASSWORD_MIN_LENGTH; + } + + public static function resetPassword(int $userId, string $password, string $password2): array + { + $errors = self::validatePasswordStrength($password, $password2, true, ''); + if ($errors) { + return ['ok' => false, 'errors' => $errors]; + } + + $updated = UserRepository::setPassword($userId, $password); + if (!$updated) { + return ['ok' => false, 'errors' => [t('Password can not be updated')]]; + } + + return ['ok' => true]; + } + + private static function validatePasswordStrength( + string $password, + string $password2, + bool $required, + ?string $email + ): array { + $errors = []; + if ($required && $password === '') { + $errors[] = t('Password cannot be empty'); + return $errors; + } + if ($password !== '' && $password !== $password2) { + $errors[] = t('Passwords must match'); + } + if ($password === '') { + return $errors; + } + if (strlen($password) < self::PASSWORD_MIN_LENGTH) { + $errors[] = t('Password must be at least %d characters', self::PASSWORD_MIN_LENGTH); + } + if (!preg_match('/[A-Z]/', $password)) { + $errors[] = t('Password must include an uppercase letter'); + } + if (!preg_match('/[a-z]/', $password)) { + $errors[] = t('Password must include a lowercase letter'); + } + if (!preg_match('/\\d/', $password)) { + $errors[] = t('Password must include a number'); + } + if (!preg_match('/[^a-zA-Z0-9]/', $password)) { + $errors[] = t('Password must include a symbol'); + } + if ($email) { + $email = trim((string) $email); + if ($email !== '' && stripos($password, $email) !== false) { + $errors[] = t('Password must not contain your email'); + } + } + return $errors; + } + + /** + * Get the current tenant ID for a user (with fallback to primary tenant) + */ + public static function getCurrentTenantId(int $userId): ?int + { + $user = UserRepository::find($userId); + if (!$user) { + return null; + } + + $activeTenantIds = TenantScopeService::getUserTenantIds($userId); + if (!$activeTenantIds) { + return null; + } + + $currentTenantId = (int) ($user['current_tenant_id'] ?? 0); + if ($currentTenantId > 0 && in_array($currentTenantId, $activeTenantIds, true)) { + return $currentTenantId; + } + + $primaryTenantId = (int) ($user['primary_tenant_id'] ?? 0); + if ($primaryTenantId > 0 && in_array($primaryTenantId, $activeTenantIds, true)) { + return $primaryTenantId; + } + + return $activeTenantIds[0] ?? null; + } + + /** + * Get the current tenant data for a user + */ + public static function getCurrentTenant(int $userId): ?array + { + $currentTenantId = self::getCurrentTenantId($userId); + if (!$currentTenantId) { + return null; + } + + return TenantRepository::find($currentTenantId); + } + + /** + * Get all tenants the user has access to + */ + public static function getAvailableTenants(int $userId): array + { + $tenantIds = TenantScopeService::getUserTenantIds($userId); + if (!$tenantIds) { + return []; + } + + $tenants = []; + foreach ($tenantIds as $tenantId) { + $tenant = TenantRepository::find($tenantId); + if ($tenant && (($tenant['status'] ?? 'active') === 'active')) { + $tenants[] = $tenant; + } + } + + // Sort by description + usort($tenants, static function ($a, $b) { + return strcmp((string) ($a['description'] ?? ''), (string) ($b['description'] ?? '')); + }); + + return $tenants; + } + + /** + * Get available departments grouped by tenant for a user. + * Returns an array of groups: ['tenant' => [...], 'departments' => [...]] + */ + public static function getAvailableDepartmentsByTenant(int $userId): array + { + $tenants = self::getAvailableTenants($userId); + if (!$tenants) { + return []; + } + + $groups = []; + foreach ($tenants as $tenant) { + $tenantId = (int) ($tenant['id'] ?? 0); + if ($tenantId <= 0) { + continue; + } + $departmentIds = TenantDepartmentRepository::listDepartmentIdsByTenantIds([$tenantId]); + $departments = $departmentIds ? DepartmentRepository::listByIds($departmentIds) : []; + usort($departments, static function ($a, $b) { + return strcmp((string) ($a['description'] ?? ''), (string) ($b['description'] ?? '')); + }); + $departments = array_map(static function (array $department): array { + return [ + 'id' => (int) ($department['id'] ?? 0), + 'uuid' => $department['uuid'] ?? '', + 'description' => $department['description'] ?? '', + ]; + }, $departments); + + $groups[] = [ + 'tenant' => [ + 'id' => (int) ($tenant['id'] ?? 0), + 'uuid' => $tenant['uuid'] ?? '', + 'description' => $tenant['description'] ?? '', + ], + 'departments' => $departments, + ]; + } + + return $groups; + } + + /** + * Set the current tenant for a user (with validation) + */ + public static function setCurrentTenant(int $userId, int $tenantId): array + { + if ($tenantId <= 0) { + return ['ok' => false, 'error' => 'invalid_tenant']; + } + + // Verify user has access to this tenant + $userTenantIds = UserTenantRepository::listTenantIdsByUserId($userId); + if (!in_array($tenantId, $userTenantIds, true)) { + return ['ok' => false, 'error' => 'tenant_not_assigned']; + } + + // Verify tenant exists + $tenant = TenantRepository::find($tenantId); + if (!$tenant) { + return ['ok' => false, 'error' => 'tenant_not_found']; + } + if (($tenant['status'] ?? 'active') !== 'active') { + return ['ok' => false, 'error' => 'tenant_inactive']; + } + + // Update current_tenant_id + $updated = UserRepository::setCurrentTenant($userId, $tenantId); + + if (!$updated) { + return ['ok' => false, 'error' => 'update_failed']; + } + + return ['ok' => true, 'tenant' => $tenant]; + } +} diff --git a/lib/Support/Flash.php b/lib/Support/Flash.php new file mode 100644 index 0000000..c79d3a3 --- /dev/null +++ b/lib/Support/Flash.php @@ -0,0 +1,103 @@ + $id, + 'type' => $type, + 'message' => $message, + 'scope' => $scope, + 'key' => $key, + ]; + return $id; + } + + public static function success(string $message, ?string $scope = null, ?string $key = null): string + { + return self::add('success', $message, $scope, $key); + } + + public static function error(string $message, ?string $scope = null, ?string $key = null): string + { + return self::add('error', $message, $scope, $key); + } + + public static function info(string $message, ?string $scope = null, ?string $key = null): string + { + return self::add('info', $message, $scope, $key); + } + + public static function peek(?string $scope = null): array + { + self::ensureSession(); + $messages = $_SESSION[self::SESSION_KEY] ?? []; + if ($scope === null) { + return $messages; + } + + return array_values(array_filter($messages, function ($message) use ($scope) { + $messageScope = $message['scope'] ?? null; + return $messageScope === null || $messageScope === $scope; + })); + } + + public static function has(): bool + { + self::ensureSession(); + return !empty($_SESSION[self::SESSION_KEY]); + } + + public static function dismiss(string $id): void + { + self::ensureSession(); + $messages = $_SESSION[self::SESSION_KEY] ?? []; + $messages = array_values(array_filter($messages, function ($message) use ($id) { + return ($message['id'] ?? '') !== $id; + })); + + if ($messages) { + $_SESSION[self::SESSION_KEY] = $messages; + } else { + unset($_SESSION[self::SESSION_KEY]); + } + } + + public static function keep(int $times = 1) + { + self::ensureSession(); + $times = max(1, $times); + $current = (int) ($_SESSION[self::KEEP_KEY] ?? 0); + $_SESSION[self::KEEP_KEY] = max($current, $times); + } +} diff --git a/lib/Support/Guard.php b/lib/Support/Guard.php new file mode 100644 index 0000000..31eb747 --- /dev/null +++ b/lib/Support/Guard.php @@ -0,0 +1,92 @@ + 0) { + AuthService::loadTenantDataIntoSession($userId); + } else { + unset($_SESSION['current_tenant']); + } + } + + private static function refreshTenantContext(): void + { + $userId = (int) ($_SESSION['user']['id'] ?? 0); + if ($userId <= 0) { + return; + } + $last = (int) ($_SESSION['tenant_context_refreshed_at'] ?? 0); + $now = time(); + if ($last > 0 && ($now - $last) < self::TENANT_REFRESH_INTERVAL) { + return; + } + AuthService::loadTenantDataIntoSession($userId); + $_SESSION['tenant_context_refreshed_at'] = $now; + } + + public static function requirePermission(string $permissionKey, string $redirect = 'admin'): void + { + self::requireLogin(); + self::validateCurrentTenant(); + $userId = (int) ($_SESSION['user']['id'] ?? 0); + if (!$userId || !PermissionService::userHas($userId, $permissionKey)) { + Flash::error('Permission denied', $redirect, 'permission_denied'); + Router::redirect($redirect); + } + } + + public static function requirePermissionOrForbidden(string $permissionKey): void + { + self::requireLogin(); + self::validateCurrentTenant(); + $userId = (int) ($_SESSION['user']['id'] ?? 0); + if (!$userId || !PermissionService::userHas($userId, $permissionKey)) { + if (Request::wantsJson()) { + http_response_code(403); + header('Content-Type: application/json; charset=utf-8'); + echo json_encode(['error' => 'forbidden']); + exit; + } + Router::redirect('error/forbidden'); + } + } +} diff --git a/lib/Support/Hello.php b/lib/Support/Hello.php new file mode 100644 index 0000000..c8b2f79 --- /dev/null +++ b/lib/Support/Hello.php @@ -0,0 +1,13 @@ + 'and exists (select 1 from user_tenants ut where ut.user_id = users.id and ut.tenant_id in (???))', + 'address-book' => 'and exists (select 1 from user_tenants ut where ut.user_id = users.id and ut.tenant_id in (???))', + 'tenants' => 'and id in (???)', + 'departments' => 'and exists (select 1 from tenant_departments td where td.department_id = departments.id and td.tenant_id in (???))', + ]; + } + + public static function resources(string $query, string $locale): array + { + $like = '%' . $query . '%'; + + return [ + [ + 'key' => 'address-book', + 'label' => t('Address book'), + 'permission' => PermissionService::ADDRESS_BOOK_VIEW, + 'countSql' => 'select count(*) from users where active = 1 and (first_name like ? or last_name like ? or email like ?) {{tenantFilter}}', + 'countParams' => [$like, $like, $like], + 'previewSql' => 'select uuid, first_name, last_name, email from users where active = 1 and (first_name like ? or last_name like ? or email like ?) {{tenantFilter}} order by last_name, first_name limit ?', + 'previewParams' => [$like, $like, $like], + 'resultSql' => 'select uuid, first_name, last_name, email from users where active = 1 and (first_name like ? or last_name like ? or email like ?) {{tenantFilter}} order by last_name, first_name', + 'resultParams' => [$like, $like, $like], + ], + [ + 'key' => 'users', + 'label' => t('Users'), + 'permission' => PermissionService::USERS_VIEW, + 'countSql' => 'select count(*) from users where (first_name like ? or last_name like ? or email like ?) {{tenantFilter}}', + 'countParams' => [$like, $like, $like], + 'previewSql' => 'select uuid, first_name, last_name, email from users where (first_name like ? or last_name like ? or email like ?) {{tenantFilter}} order by last_name, first_name limit ?', + 'previewParams' => [$like, $like, $like], + 'resultSql' => 'select uuid, first_name, last_name, email from users where (first_name like ? or last_name like ? or email like ?) {{tenantFilter}} order by last_name, first_name', + 'resultParams' => [$like, $like, $like], + ], + [ + 'key' => 'tenants', + 'label' => t('Tenants'), + 'permission' => PermissionService::TENANTS_VIEW, + 'countSql' => 'select count(*) from tenants where description like ? {{tenantFilter}}', + 'countParams' => [$like], + 'previewSql' => 'select uuid, description from tenants where description like ? {{tenantFilter}} order by description limit ?', + 'previewParams' => [$like], + 'resultSql' => 'select uuid, description from tenants where description like ? {{tenantFilter}} order by description', + 'resultParams' => [$like], + ], + [ + 'key' => 'departments', + 'label' => t('Departments'), + 'permission' => PermissionService::DEPARTMENTS_VIEW, + 'countSql' => 'select count(*) from departments where description like ? {{tenantFilter}}', + 'countParams' => [$like], + 'previewSql' => 'select uuid, description from departments where description like ? {{tenantFilter}} order by description limit ?', + 'previewParams' => [$like], + 'resultSql' => 'select uuid, description from departments where description like ? {{tenantFilter}} order by description', + 'resultParams' => [$like], + ], + [ + 'key' => 'roles', + 'label' => t('Roles'), + 'permission' => PermissionService::ROLES_VIEW, + 'countSql' => 'select count(*) from roles where description like ?', + 'countParams' => [$like], + 'previewSql' => 'select uuid, description from roles where description like ? order by description limit ?', + 'previewParams' => [$like], + 'resultSql' => 'select uuid, description from roles where description like ? order by description', + 'resultParams' => [$like], + ], + [ + 'key' => 'permissions', + 'label' => t('Permissions'), + 'permission' => PermissionService::PERMISSIONS_VIEW, + 'countSql' => 'select count(*) from permissions where `key` like ? or description like ?', + 'countParams' => [$like, $like], + 'previewSql' => 'select id, description, `key` from permissions where `key` like ? or description like ? order by `key` limit ?', + 'previewParams' => [$like, $like], + 'resultSql' => 'select id, description, `key` from permissions where `key` like ? or description like ? order by `key`', + 'resultParams' => [$like, $like], + ], + [ + 'key' => 'pages', + 'label' => t('Pages'), + 'permission' => '', + 'countSql' => 'select count(*) from pages p join page_contents pc on pc.page_id = p.id and pc.locale = ? where p.slug like ? or pc.content like ?', + 'countParams' => [$locale, $like, $like], + 'previewSql' => 'select p.slug from pages p join page_contents pc on pc.page_id = p.id and pc.locale = ? where p.slug like ? or pc.content like ? order by p.slug limit ?', + 'previewParams' => [$locale, $like, $like], + 'resultSql' => 'select p.slug from pages p join page_contents pc on pc.page_id = p.id and pc.locale = ? where p.slug like ? or pc.content like ? order by p.slug', + 'resultParams' => [$locale, $like, $like], + ], + [ + 'key' => 'settings', + 'label' => t('Settings'), + 'permission' => PermissionService::SETTINGS_VIEW, + 'countSql' => 'select count(*) from settings where `key` like ? or value like ?', + 'countParams' => [$like, $like], + 'previewSql' => null, + 'previewParams' => [], + 'resultSql' => 'select `key`, value from settings where `key` like ? or value like ? order by `key`', + 'resultParams' => [$like, $like], + ], + ]; + } + + public static function iconForKey(string $key): string + { + return match ($key) { + 'address-book' => 'bi-people', + 'users' => 'bi-person-badge', + 'tenants' => 'bi-buildings', + 'departments' => 'bi-diagram-3', + 'roles' => 'bi-people', + 'permissions' => 'bi-shield-lock', + 'pages' => 'bi-file-text', + 'settings' => 'bi-gear', + default => 'bi-search', + }; + } + + public static function listUrl(string $key, string $query): string + { + $encoded = urlencode($query); + + return match ($key) { + 'address-book' => lurl('address-book') . '?search=' . $encoded, + 'users' => lurl('admin/users') . '?search=' . $encoded, + 'tenants' => lurl('admin/tenants') . '?search=' . $encoded, + 'departments' => lurl('admin/departments') . '?search=' . $encoded, + 'roles' => lurl('admin/roles') . '?search=' . $encoded, + 'permissions' => lurl('admin/permissions') . '?search=' . $encoded, + 'pages' => lurl(''), + 'settings' => lurl('admin/settings'), + default => lurl(''), + }; + } + + public static function mapPreviewItem(string $key, array $data, string $query): ?array + { + if ($key === 'users') { + $label = trim(($data['first_name'] ?? '') . ' ' . ($data['last_name'] ?? '')); + $email = trim((string) ($data['email'] ?? '')); + if ($email !== '') { + $label = $label === '' ? $email : ($label . ' — ' . $email); + } + $url = lurl('admin/users/edit/' . ($data['uuid'] ?? '')) . '?search=' . urlencode($query); + } elseif ($key === 'address-book') { + $label = trim(($data['first_name'] ?? '') . ' ' . ($data['last_name'] ?? '')); + $email = trim((string) ($data['email'] ?? '')); + if ($email !== '') { + $label = $label === '' ? $email : ($label . ' — ' . $email); + } + $url = lurl('address-book/view/' . ($data['uuid'] ?? '')) . '?search=' . urlencode($query); + } elseif ($key === 'permissions') { + $label = (string) ($data['description'] ?? ''); + $url = lurl('admin/permissions/edit/' . ($data['id'] ?? '')) . '?search=' . urlencode($query); + } elseif ($key === 'pages') { + $label = (string) ($data['slug'] ?? ''); + $url = lurl('page/' . $label) . '?search=' . urlencode($query); + } else { + $label = (string) ($data['description'] ?? ''); + $url = lurl('admin/' . $key . '/edit/' . ($data['uuid'] ?? '')) . '?search=' . urlencode($query); + } + + if ($label === '' || $url === '') { + return null; + } + return ['label' => $label, 'url' => $url]; + } + + public static function mapResultItem(string $key, string $label, array $data): ?array + { + $title = ''; + $description = ''; + $url = ''; + $image = ''; + if ($key === 'users') { + $title = trim(($data['first_name'] ?? '') . ' ' . ($data['last_name'] ?? '')); + $description = (string) ($data['email'] ?? ''); + $url = lurl('admin/users/edit/' . ($data['uuid'] ?? '')); + } elseif ($key === 'address-book') { + $title = trim(($data['first_name'] ?? '') . ' ' . ($data['last_name'] ?? '')); + $description = (string) ($data['email'] ?? ''); + $uuid = (string) ($data['uuid'] ?? ''); + $url = lurl('address-book/view/' . $uuid); + if ($uuid !== '' && UserAvatarService::hasAvatar($uuid)) { + $image = lurl('admin/users/avatar-file') . '?uuid=' . urlencode($uuid) . '&size=64'; + } + } elseif ($key === 'permissions') { + $title = (string) ($data['key'] ?? ''); + $description = (string) ($data['description'] ?? ''); + $url = lurl('admin/permissions/edit/' . ($data['id'] ?? '')); + } elseif ($key === 'pages') { + $title = (string) ($data['slug'] ?? ''); + $description = t('Page'); + $url = lurl('page/' . $title); + } elseif ($key === 'settings') { + $title = (string) ($data['key'] ?? ''); + $description = (string) ($data['value'] ?? ''); + $url = lurl('admin/settings'); + } else { + $title = (string) ($data['description'] ?? ''); + $description = $label; + $url = lurl('admin/' . $key . '/edit/' . ($data['uuid'] ?? '')); + } + + if ($title === '' || $url === '') { + return null; + } + + return [ + 'type' => $label, + 'title' => $title, + 'description' => $description, + 'url' => $url, + 'image' => $image, + 'icon' => self::iconForKey($key), + ]; + } +} diff --git a/lib/Support/Tile.php b/lib/Support/Tile.php new file mode 100644 index 0000000..d1e1a93 --- /dev/null +++ b/lib/Support/Tile.php @@ -0,0 +1,28 @@ + '#', + 'label' => '', + 'count' => null, + 'icon' => 'bi bi-grid-1x2', + 'iconBg' => null, + 'iconColor' => null, + 'class' => '', + ]; + + $data = array_merge($defaults, $options); + $template = dirname(__DIR__, 2) . '/templates/partials/app-tile.phtml'; + if (!is_file($template)) { + return; + } + + extract($data, EXTR_SKIP); + require $template; + } +} diff --git a/lib/Support/helpers.php b/lib/Support/helpers.php new file mode 100644 index 0000000..a889544 --- /dev/null +++ b/lib/Support/helpers.php @@ -0,0 +1,6 @@ + + strcasecmp((string) ($a['description'] ?? ''), (string) ($b['description'] ?? '')) + ); +} diff --git a/lib/Support/helpers/auth.php b/lib/Support/helpers/auth.php new file mode 100644 index 0000000..c7a1db9 --- /dev/null +++ b/lib/Support/helpers/auth.php @@ -0,0 +1,27 @@ +getTimestamp()))->setTimezone($displayTz); + } elseif (is_string($value) && $value !== '') { + try { + // Treat DB timestamps as UTC and convert for display + $date = new \DateTimeImmutable($value, new \DateTimeZone('UTC')); + $date = $date->setTimezone($displayTz); + } catch (\Exception $e) { + return $value; + } + } else { + return ''; + } + + if ($format === null) { + $locale = \MintyPHP\I18n::$locale ?? ''; + $format = (strpos((string) $locale, 'de') === 0) ? 'd.m.Y H:i' : 'Y-m-d H:i'; + } + + return $date->format($format); +} diff --git a/lib/Support/helpers/ui.php b/lib/Support/helpers/ui.php new file mode 100644 index 0000000..a19879f --- /dev/null +++ b/lib/Support/helpers/ui.php @@ -0,0 +1,178 @@ + [ + 'placeholder' => t('Search...'), + ], + 'sort' => [ + 'sortAsc' => t('Sort column ascending'), + 'sortDesc' => t('Sort column descending'), + ], + 'pagination' => [ + 'previous' => t('Previous'), + 'next' => t('Next'), + 'navigate' => t('Page %d of %d'), + 'page' => t('Page %d'), + 'showing' => t('Showing'), + 'of' => t('of'), + 'to' => t('to'), + 'results' => t('results'), + ], + 'loading' => t('Loading...'), + 'noRecordsFound' => t('No records found'), + 'error' => t('An error happened while fetching the data'), + ]; +} + +/** + * Render a multi-select filter field with hidden input sync. + * + * @param string $id Base ID for the hidden input (select gets "-ui" suffix) + * @param string $label Field label (will be translated) + * @param string $placeholder Placeholder text (will be translated) + * @param array $items Array of items with 'id' and 'description' keys + * @param array $selected Array of selected item IDs + */ +function multiSelectFilter( + string $id, + string $label, + string $placeholder, + array $items, + array $selected +): void { + ?> + + + + + $isActive ? 'active' : '', + 'aria' => $isActive ? 'aria-current="page"' : '', + 'isActive' => $isActive, + ]; +} + +function navActivePublicPages(array $extraSlugs = []): array +{ + $current = \MintyPHP\Http\Request::path(); + if ($current === '') { + return ['class' => '', 'aria' => '', 'isActive' => false]; + } + + $publicSlugs = array_merge(['imprint', 'privacy'], $extraSlugs); + $isActive = strpos($current, 'page/') === 0 || in_array($current, $publicSlugs, true); + + return [ + 'class' => $isActive ? 'active' : '', + 'aria' => $isActive ? 'aria-current="page"' : '', + 'isActive' => $isActive, + ]; +} diff --git a/pages/.DS_Store b/pages/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d45d925380a8f349db661ea6d34898dc21e25ae7 GIT binary patch literal 6148 zcmeHLJud`77=Guh%f%@q3JS$G`n!s9$*PnJLc=-kBzN|5NR*psbVP#APe4RRRF_En z1wTNe7lrV=Gh=VYE; z3>5Mn>y27@W;trMQn}9I6mSasJ_Y#Q?WHBEQj^xmet&!FSRu@4GYZ2>BdWk#IC*)# zx;eg`_?S`sCZkn1R*3vQ%E<%&7Hv}9UOmPZ%$UjjbXvNfR@_N#GwL#D#VuYsXWjx; zs15FQ%pP;6n$4f<&&n~!@i4c2w{s*lNZrdE&sTZ&xOg3g;wurYQIr3yv%7bFpuZ1BM)#>?XW0C5{vNf! zUZWLz_M?wrPhuwb#pUey>!IW};$7yfxXl~zy#JeF&t@wW6}sLj;1qBQBnt5Q;G;1H z8e@fW=|Crs06-6JX}FeaIM8PYFwht)ga;;6DNvOPeZ&x|9DZNt1sY?8s+@#m#(gxi z&?gij+2QwPI*CA`>zx8l0b79{^>Kjr|EbT<|8|l4

lU{3!*57tVx}n3CRGQ $limit, + 'offset' => $offset, + 'search' => $search, + 'order' => $order, + 'dir' => $dir, + 'tenant' => $tenant, + 'tenants' => $tenants, + 'departments' => $departments, + 'roles' => $roles, + 'tenantUserId' => $currentUserId, + 'active' => 'active', +]); + +$rows = []; +foreach ($result['rows'] as $row) { + $tenantLabels = $row['tenant_labels'] ?? []; + if (is_string($tenantLabels)) { + $tenantList = $tenantLabels !== '' + ? array_values(array_filter(array_map('trim', explode('||', $tenantLabels)))) + : []; + } elseif (is_array($tenantLabels)) { + $tenantList = array_values(array_filter(array_map('trim', $tenantLabels))); + } else { + $tenantList = []; + } + + $departmentLabels = $row['department_labels'] ?? []; + if (is_string($departmentLabels)) { + $departmentList = $departmentLabels !== '' + ? array_values(array_filter(array_map('trim', explode('||', $departmentLabels)))) + : []; + } elseif (is_array($departmentLabels)) { + $departmentList = array_values(array_filter(array_map('trim', $departmentLabels))); + } else { + $departmentList = []; + } + + $roleLabels = $row['role_labels'] ?? []; + if (is_string($roleLabels)) { + $roleList = $roleLabels !== '' + ? array_values(array_filter(array_map('trim', explode('||', $roleLabels)))) + : []; + } elseif (is_array($roleLabels)) { + $roleList = array_values(array_filter(array_map('trim', $roleLabels))); + } else { + $roleList = []; + } + + $uuid = (string) ($row['uuid'] ?? ''); + $rows[] = [ + 'uuid' => $uuid, + 'first_name' => $row['first_name'] ?? '', + 'last_name' => $row['last_name'] ?? '', + 'email' => $row['email'] ?? '', + 'phone' => $row['phone'] ?? '', + 'mobile' => $row['mobile'] ?? '', + 'short_dial' => $row['short_dial'] ?? '', + 'tenants' => $tenantList, + 'departments' => $departmentList, + 'roles' => $roleList, + 'has_avatar' => $uuid !== '' && UserAvatarService::hasAvatar($uuid), + ]; +} + +Router::json([ + 'data' => $rows, + 'total' => $result['total'] ?? 0, +]); diff --git a/pages/address-book/index().php b/pages/address-book/index().php new file mode 100644 index 0000000..22349e0 --- /dev/null +++ b/pages/address-book/index().php @@ -0,0 +1,52 @@ + 0 && in_array($id, $tenantIds, true); + })); +} elseif (TenantScopeService::isStrict()) { + $tenants = []; +} +$tenantItems = array_map( + static fn (array $tenant): array => [ + 'id' => (string) ($tenant['uuid'] ?? ''), + 'description' => $tenant['description'] ?? '', + ], + $tenants +); + +$departments = $tenantIds + ? DepartmentService::listByTenantIds($tenantIds) + : (TenantScopeService::isStrict() ? [] : DepartmentService::list()); + +$roles = RoleService::list(); + +$csrfKey = Session::$csrfSessionKey; +$csrfToken = $_SESSION[$csrfKey] ?? ''; + +Buffer::set('title', t('Address book')); +Buffer::set('grid_lang', json_encode(gridLang(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); +Buffer::set( + 'grid_csrf', + json_encode(['key' => $csrfKey, 'token' => $csrfToken], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) +); diff --git a/pages/address-book/index(default).phtml b/pages/address-book/index(default).phtml new file mode 100644 index 0000000..50189f5 --- /dev/null +++ b/pages/address-book/index(default).phtml @@ -0,0 +1,156 @@ + +

+
+

+
+ +
+
+
+ + + + +
+
+
+
+ + + + diff --git a/pages/address-book/view($id).php b/pages/address-book/view($id).php new file mode 100644 index 0000000..770d220 --- /dev/null +++ b/pages/address-book/view($id).php @@ -0,0 +1,111 @@ + 0 && $label !== '') { + $departmentMap[$tenantId][] = $label; + } +} +foreach ($departmentMap as $tenantId => $labels) { + $departmentMap[$tenantId] = array_values(array_unique($labels)); +} + +$primaryTenantId = (int) ($user['primary_tenant_id'] ?? 0); +$tenantGroups = []; +foreach (is_array($tenantRows) ? $tenantRows : [] as $row) { + $tenantId = (int) ($getRowValue($row, 'id') ?? 0); + $tenantLabel = (string) ($getRowValue($row, 'description') ?? ''); + if ($tenantId <= 0 || $tenantLabel === '') { + continue; + } + $tenantGroups[] = [ + 'label' => $tenantLabel, + 'is_primary' => $primaryTenantId > 0 && $tenantId === $primaryTenantId, + 'departments' => $departmentMap[$tenantId] ?? [], + ]; +} + +$roleLabels = $extractLabels(is_array($roleRows) ? $roleRows : []); + +$user['tenant_groups'] = $tenantGroups; +$user['role_labels'] = $roleLabels; + +$name = trim(($user['first_name'] ?? '') . ' ' . ($user['last_name'] ?? '')); +$title = $name !== '' ? $name : ($user['email'] ?? t('Address book')); +Buffer::set('title', $title); diff --git a/pages/address-book/view(default).phtml b/pages/address-book/view(default).phtml new file mode 100644 index 0000000..fdd3e4d --- /dev/null +++ b/pages/address-book/view(default).phtml @@ -0,0 +1,277 @@ +format($format); + } catch (\Exception $e) { + $hireDateLabel = $hireDate; + } +} +$avatarUuid = (string) ($values['uuid'] ?? ''); +$hasAvatar = $avatarUuid !== '' && UserAvatarService::hasAvatar($avatarUuid); + +$initials = ''; +if ($displayName !== '') { + $parts = array_filter(array_map('trim', preg_split('/\s+/', $displayName) ?: [])); + $chars = ''; + foreach ($parts as $part) { + if (function_exists('mb_substr')) { + $chars .= mb_substr($part, 0, 1); + } else { + $chars .= substr($part, 0, 1); + } + } + $initials = strtoupper($chars !== '' ? $chars : '?'); +} +$tenantGroups = $values['tenant_groups'] ?? []; +$roleLabels = $values['role_labels'] ?? []; +$hasContact = ($email !== '' || $phone !== '' || $mobile !== '' || $shortDial !== ''); +$hasAddress = ($address !== '' || $postalCode !== '' || $city !== '' || $region !== '' || $country !== ''); +$hasOrganization = (!empty($tenantGroups) || !empty($roleLabels)); +$aboutSummary = ''; +if ($profileDescription !== '') { + foreach (preg_split('/\\r\\n|\\r|\\n/', $profileDescription) as $line) { + $line = trim((string) $line); + if ($line !== '') { + $aboutSummary = $line; + break; + } + } +} + +?> + +
+
+
+ +
+ + +
+
+
+
+
+ + + + + + + +
+
+
+

+ +

+ + +

+ + + +

+ +
+
+
+
+
+
+
+
+
+ + + + + + + + + + +
+ +
+
+ +
+ +

+
+ + +
+ +

+
+ +
+
+ +
+ +

+
+ + +
+ +

+
+ +
+
+ + +
+
+ +

+ + + +

+ + +

+ + +

+ +
+
+ + +
+ + + + + + + + + + + + + + + + + +
+ + + () + + + + + + - + +
+
+ +
+ +

+
+ +

-

+ + + + + + + + + + + + + +
+ +
+ +
+ +
+ +

+
+ + + + +

+ + + +

-

+ +
+
+
+
+
+ +
diff --git a/pages/admin/departments/_form.phtml b/pages/admin/departments/_form.phtml new file mode 100644 index 0000000..d56c158 --- /dev/null +++ b/pages/admin/departments/_form.phtml @@ -0,0 +1,55 @@ + +
+
+ Stammdaten +
+ +
+ + + + + +
diff --git a/pages/admin/departments/create().php b/pages/admin/departments/create().php new file mode 100644 index 0000000..e8f5d98 --- /dev/null +++ b/pages/admin/departments/create().php @@ -0,0 +1,75 @@ + '', +]; +$tenants = TenantService::list(); +if ($allowedTenantIds) { + $tenants = array_values(array_filter($tenants, static function (array $tenant) use ($allowedTenantIds): bool { + $tenantId = (int) ($tenant['id'] ?? 0); + return $tenantId > 0 && in_array($tenantId, $allowedTenantIds, true); + })); +} elseif (TenantScopeService::isStrict()) { + $tenants = []; +} +$selectedTenantIds = []; + +if (isset($_POST['description'])) { + $result = DepartmentService::createFromAdmin($_POST, $currentUserId); + $form = $result['form'] ?? $form; + $errors = $result['errors'] ?? []; + $tenantIds = $_POST['tenant_ids'] ?? []; + if (!is_array($tenantIds)) { + $tenantIds = [$tenantIds]; + } + $selectedTenantIds = array_values(array_unique(array_map('intval', $tenantIds))); + $selectedTenantIds = TenantScopeService::filterTenantIdsForUser($selectedTenantIds, $currentUserId); + + if (TenantScopeService::isStrict() && !$selectedTenantIds) { + $errors[] = t('Please select at least one tenant'); + } + + if (($result['ok'] ?? false) && !$errors) { + $departmentId = (int) ($result['id'] ?? 0); + if ($departmentId) { + DepartmentService::syncTenants($departmentId, $selectedTenantIds); + } + $action = (string) ($_POST['action'] ?? 'create'); + if ($action === 'create_close') { + Flash::success('Department created', 'admin/departments', 'department_created'); + Router::redirect('admin/departments'); + } else { + $uuid = (string) ($result['uuid'] ?? ''); + if ($uuid !== '') { + $target = "admin/departments/edit/{$uuid}"; + Flash::success('Department created', $target, 'department_created'); + Router::redirect($target); + } else { + Flash::success('Department created', 'admin/departments', 'department_created'); + Router::redirect('admin/departments'); + } + } + } +} + +Buffer::set('title', t('Create department')); diff --git a/pages/admin/departments/create(default).phtml b/pages/admin/departments/create(default).phtml new file mode 100644 index 0000000..047c48a --- /dev/null +++ b/pages/admin/departments/create(default).phtml @@ -0,0 +1,44 @@ + $errors + * @var array $form + */ + +?> +
+
+ +
+

+ + +

+
+ + +
+
+ +
+
    + +
  • + +
+
+ + +
+
diff --git a/pages/admin/departments/data().php b/pages/admin/departments/data().php new file mode 100644 index 0000000..105d165 --- /dev/null +++ b/pages/admin/departments/data().php @@ -0,0 +1,52 @@ + $limit, + 'offset' => $offset, + 'search' => $search, + 'order' => $order, + 'dir' => $dir, + 'tenant' => $tenant, + 'tenantIds' => $tenantIds, + 'tenantUserId' => $currentUserId, +]); + +$defaultDepartmentId = SettingService::getDefaultDepartmentId(); +$rows = []; +foreach ($result['rows'] as $row) { + $departmentId = (int) ($row['id'] ?? 0); + $rows[] = [ + 'id' => $row['id'] ?? null, + 'uuid' => $row['uuid'] ?? '', + 'is_default' => $departmentId > 0 && $defaultDepartmentId === $departmentId, + 'description' => $row['description'] ?? '', + 'tenants' => $row['tenant_labels'] ?? [], + 'created' => dt($row['created'] ?? ''), + 'modified' => dt($row['modified'] ?? ''), + ]; +} + +Router::json([ + 'data' => $rows, + 'total' => $result['total'] ?? 0, +]); diff --git a/pages/admin/departments/delete($id).php b/pages/admin/departments/delete($id).php new file mode 100644 index 0000000..6f32cad --- /dev/null +++ b/pages/admin/departments/delete($id).php @@ -0,0 +1,37 @@ + 0) { + AuthService::loadTenantDataIntoSession($currentUserId); +} + +Flash::success('Department deleted', 'admin/departments', 'department_deleted'); +Router::redirect('admin/departments'); diff --git a/pages/admin/departments/edit($id).php b/pages/admin/departments/edit($id).php new file mode 100644 index 0000000..24dada4 --- /dev/null +++ b/pages/admin/departments/edit($id).php @@ -0,0 +1,111 @@ + 0) { + PermissionService::getUserPermissions($currentUserId); +} +$allowedTenantIds = TenantScopeService::getUserTenantIds($currentUserId); + +$uuid = trim((string) ($id ?? '')); +$department = $uuid !== '' ? DepartmentService::findByUuid($uuid) : null; +if (!$department) { + Flash::error('Department not found', 'admin/departments', 'department_not_found'); + Router::redirect('admin/departments'); +} + +$departmentId = (int) ($department['id'] ?? 0); +if (!TenantScopeService::canAccess('departments', $departmentId, $currentUserId)) { + Router::redirect('error/forbidden'); + return; +} +$creatorId = (int) ($department['created_by'] ?? 0); +if ($creatorId > 0) { + $creator = UserService::findById($creatorId); + if ($creator) { + $creatorName = trim(($creator['first_name'] ?? '') . ' ' . ($creator['last_name'] ?? '')); + $department['created_by_label'] = $creatorName !== '' ? $creatorName : ($creator['email'] ?? ''); + $department['created_by_uuid'] = $creator['uuid'] ?? null; + } +} +$modifierId = (int) ($department['modified_by'] ?? 0); +if ($modifierId > 0) { + $modifier = UserService::findById($modifierId); + if ($modifier) { + $modifierName = trim(($modifier['first_name'] ?? '') . ' ' . ($modifier['last_name'] ?? '')); + $department['modified_by_label'] = $modifierName !== '' ? $modifierName : ($modifier['email'] ?? ''); + $department['modified_by_uuid'] = $modifier['uuid'] ?? null; + } +} + +$errors = []; +$form = $department; +$tenants = TenantService::list(); +$selectedTenantIds = TenantDepartmentRepository::listTenantIdsByDepartmentId($departmentId); +if ($allowedTenantIds) { + $tenants = array_values(array_filter($tenants, static function (array $tenant) use ($allowedTenantIds): bool { + $tenantId = (int) ($tenant['id'] ?? 0); + return $tenantId > 0 && in_array($tenantId, $allowedTenantIds, true); + })); + $selectedTenantIds = array_values(array_intersect($selectedTenantIds, $allowedTenantIds)); +} elseif (TenantScopeService::isStrict()) { + $tenants = []; + $selectedTenantIds = []; +} + +if (isset($_POST['description'])) { + if (!PermissionService::userHas($currentUserId, PermissionService::DEPARTMENTS_UPDATE)) { + Router::redirect('error/forbidden'); + return; + } + $result = DepartmentService::updateFromAdmin($departmentId, $_POST, $currentUserId); + $form = $result['form'] ?? $form; + $errors = $result['errors'] ?? []; + $tenantIds = $_POST['tenant_ids'] ?? []; + if (!is_array($tenantIds)) { + $tenantIds = [$tenantIds]; + } + $selectedTenantIds = array_values(array_unique(array_map('intval', $tenantIds))); + $selectedTenantIds = TenantScopeService::filterTenantIdsForUser($selectedTenantIds, $currentUserId); + + if (TenantScopeService::isStrict() && !$selectedTenantIds) { + $errors[] = t('Please select at least one tenant'); + } + + if (($result['ok'] ?? false) && !$errors) { + $existingTenantIds = TenantDepartmentRepository::listTenantIdsByDepartmentId($departmentId); + $finalTenantIds = TenantScopeService::mergeTenantIdsPreservingOutOfScope( + $selectedTenantIds, + $existingTenantIds, + $allowedTenantIds + ); + $cleaned = DepartmentService::syncTenants($departmentId, $finalTenantIds); + $action = (string) ($_POST['action'] ?? 'save'); + if ($cleaned > 0) { + Flash::info(t('Department assignments cleaned: %d', $cleaned), "admin/departments/edit/{$uuid}", 'department_assignments_cleaned'); + } + if ($action === 'save_close') { + Flash::success('Department updated', 'admin/departments', 'department_updated'); + Router::redirect('admin/departments'); + } else { + Flash::success('Department updated', "admin/departments/edit/{$uuid}", 'department_updated'); + Router::redirect("admin/departments/edit/{$uuid}"); + } + } +} + +Buffer::set('title', t('Edit department')); diff --git a/pages/admin/departments/edit(default).phtml b/pages/admin/departments/edit(default).phtml new file mode 100644 index 0000000..9123041 --- /dev/null +++ b/pages/admin/departments/edit(default).phtml @@ -0,0 +1,167 @@ + $errors + * @var array $form + * @var array $department + */ + +use MintyPHP\Session; + +$values = $form ?? $department ?? []; +$isReadOnly = !can('departments.update'); + +?> + +
+
+ +
+

+ + +

+
+ + + + + + + + +
+
+ + +
+
+
    + +
  • + +
+
+
+ + + +
+ +
diff --git a/pages/admin/departments/index().php b/pages/admin/departments/index().php new file mode 100644 index 0000000..71313a9 --- /dev/null +++ b/pages/admin/departments/index().php @@ -0,0 +1,39 @@ + 0) { + PermissionService::getUserPermissions($currentUserId); +} + +$tenants = TenantService::list(); +$allowedTenantIds = TenantScopeService::getUserTenantIds($currentUserId); +if ($allowedTenantIds) { + $tenants = array_values(array_filter($tenants, static function (array $tenant) use ($allowedTenantIds): bool { + $tenantId = (int) ($tenant['id'] ?? 0); + return $tenantId > 0 && in_array($tenantId, $allowedTenantIds, true); + })); +} elseif (TenantScopeService::isStrict()) { + $tenants = []; +} +usort($tenants, static function ($a, $b) { + return strcmp((string) ($a['description'] ?? ''), (string) ($b['description'] ?? '')); +}); + +Buffer::set('title', t('Departments')); +Buffer::set('grid_lang', json_encode(gridLang(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); +$csrfKey = Session::$csrfSessionKey; +$csrfToken = $_SESSION[$csrfKey] ?? ''; +Buffer::set( + 'grid_csrf', + json_encode(['key' => $csrfKey, 'token' => $csrfToken], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) +); diff --git a/pages/admin/departments/index(default).phtml b/pages/admin/departments/index(default).phtml new file mode 100644 index 0000000..4ae14df --- /dev/null +++ b/pages/admin/departments/index(default).phtml @@ -0,0 +1,175 @@ + 1; +?> + +
+

+
+ + + + + + +
+
+ +
+ + + + + + + + + + + +
+ +
+ + +
+
+
+
+ + + + diff --git a/pages/admin/index($slug).php b/pages/admin/index($slug).php new file mode 100644 index 0000000..50332a3 --- /dev/null +++ b/pages/admin/index($slug).php @@ -0,0 +1,16 @@ + +
+ Login +
+
+

+
+ +
+
+
+ +
diff --git a/pages/admin/mail-log/data().php b/pages/admin/mail-log/data().php new file mode 100644 index 0000000..fc06a88 --- /dev/null +++ b/pages/admin/mail-log/data().php @@ -0,0 +1,57 @@ + $limit, + 'offset' => $offset, + 'search' => $search, + 'order' => $order, + 'dir' => $dir, + 'status' => $status, + 'created_from' => $createdFrom, + 'created_to' => $createdTo, +]); + +$rows = []; +foreach ($result['rows'] as $row) { + $status = (string) ($row['status'] ?? ''); + $statusBadge = 'neutral'; + if ($status === 'sent') { + $statusBadge = 'success'; + } elseif ($status === 'failed') { + $statusBadge = 'danger'; + } + + $rows[] = [ + 'id' => $row['id'] ?? null, + 'to_email' => $row['to_email'] ?? '', + 'subject' => $row['subject'] ?? '', + 'template' => $row['template'] ?? '', + 'status' => $status, + 'status_badge' => $statusBadge, + 'status_label' => t(ucfirst($status)), + 'created_at' => dt($row['created_at'] ?? ''), + 'sent_at' => dt($row['sent_at'] ?? ''), + ]; +} + +Router::json([ + 'data' => $rows, + 'total' => $result['total'] ?? 0, +]); diff --git a/pages/admin/mail-log/index().php b/pages/admin/mail-log/index().php new file mode 100644 index 0000000..2ca4213 --- /dev/null +++ b/pages/admin/mail-log/index().php @@ -0,0 +1,23 @@ + 0) { + PermissionService::getUserPermissions($currentUserId); +} + +Buffer::set('title', t('Mail logs')); +Buffer::set('grid_lang', json_encode(gridLang(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); +$csrfKey = Session::$csrfSessionKey; +$csrfToken = $_SESSION[$csrfKey] ?? ''; +Buffer::set( + 'grid_csrf', + json_encode(['key' => $csrfKey, 'token' => $csrfToken], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) +); diff --git a/pages/admin/mail-log/index(default).phtml b/pages/admin/mail-log/index(default).phtml new file mode 100644 index 0000000..fd761c2 --- /dev/null +++ b/pages/admin/mail-log/index(default).phtml @@ -0,0 +1,174 @@ + + +
+

+
+ +
+
+
+ + + + +
+
+
+
+ + + + diff --git a/pages/admin/mail-log/view($id).php b/pages/admin/mail-log/view($id).php new file mode 100644 index 0000000..e933416 --- /dev/null +++ b/pages/admin/mail-log/view($id).php @@ -0,0 +1,25 @@ + 0) { + PermissionService::getUserPermissions($currentUserId); +} + +$mailLogId = (int) ($id ?? 0); +$mailLog = $mailLogId > 0 ? MailLogService::find($mailLogId) : null; +if (!$mailLog) { + Flash::error('Mail log not found', 'admin/mail-log', 'mail_log_not_found'); + Router::redirect('admin/mail-log'); +} + +Buffer::set('title', t('View mail log')); diff --git a/pages/admin/mail-log/view(default).phtml b/pages/admin/mail-log/view(default).phtml new file mode 100644 index 0000000..6baff72 --- /dev/null +++ b/pages/admin/mail-log/view(default).phtml @@ -0,0 +1,137 @@ + + +
+
+ +
+

+ + +

+
+ +
+
+ +
+
+
+
+ + +
+
+ + +
+ +
+
+ + +
+
+
+ + +
+
+ +
+
+
+ + +
+ +
+ + +
+ +
+
+ + + +
+
+ +
+
+
+ + +
+
+
+ +
+
+ +
\ No newline at end of file diff --git a/pages/admin/permissions/_form.phtml b/pages/admin/permissions/_form.phtml new file mode 100644 index 0000000..79e163f --- /dev/null +++ b/pages/admin/permissions/_form.phtml @@ -0,0 +1,38 @@ + +
+
> + Stammdaten +
+
+ + +
+
+
+ +
diff --git a/pages/admin/permissions/create().php b/pages/admin/permissions/create().php new file mode 100644 index 0000000..c286594 --- /dev/null +++ b/pages/admin/permissions/create().php @@ -0,0 +1,42 @@ + '', + 'description' => '', +]; + +if (isset($_POST['key'])) { + $result = PermissionService::createFromAdmin($_POST); + $form = $result['form'] ?? $form; + $errors = $result['errors'] ?? []; + + if ($result['ok'] ?? false) { + $action = (string) ($_POST['action'] ?? 'create'); + if ($action === 'create_close') { + Flash::success('Permission created', 'admin/permissions', 'permission_created'); + Router::redirect('admin/permissions'); + } else { + $id = (int) ($result['id'] ?? 0); + if ($id > 0) { + $target = "admin/permissions/edit/{$id}"; + Flash::success('Permission created', $target, 'permission_created'); + Router::redirect($target); + } else { + Flash::success('Permission created', 'admin/permissions', 'permission_created'); + Router::redirect('admin/permissions'); + } + } + } +} + +Buffer::set('title', t('Create permission')); diff --git a/pages/admin/permissions/create(default).phtml b/pages/admin/permissions/create(default).phtml new file mode 100644 index 0000000..2de9bae --- /dev/null +++ b/pages/admin/permissions/create(default).phtml @@ -0,0 +1,44 @@ + $errors + * @var array $form + */ + +?> +
+
+ +
+

+ + +

+
+ + +
+
+ +
+
    + +
  • + +
+
+ + +
+
diff --git a/pages/admin/permissions/data().php b/pages/admin/permissions/data().php new file mode 100644 index 0000000..ed71004 --- /dev/null +++ b/pages/admin/permissions/data().php @@ -0,0 +1,41 @@ + [], 'total' => 0]); +} + +$limit = (int) ($_GET['limit'] ?? 10); +$offset = (int) ($_GET['offset'] ?? 0); +$search = trim((string) ($_GET['search'] ?? '')); +$order = (string) ($_GET['order'] ?? 'key'); +$dir = (string) ($_GET['dir'] ?? 'asc'); + +$result = PermissionService::listPaged([ + 'limit' => $limit, + 'offset' => $offset, + 'search' => $search, + 'order' => $order, + 'dir' => $dir, +]); + +$rows = []; +foreach ($result['data'] ?? [] as $row) { + $rows[] = [ + 'id' => $row['id'] ?? null, + 'key' => $row['key'] ?? '', + 'description' => $row['description'] ?? '', + 'created' => dt($row['created'] ?? ''), + ]; +} + +Router::json([ + 'data' => $rows, + 'total' => $result['total'] ?? 0, +]); diff --git a/pages/admin/permissions/delete($id).php b/pages/admin/permissions/delete($id).php new file mode 100644 index 0000000..ec4a00a --- /dev/null +++ b/pages/admin/permissions/delete($id).php @@ -0,0 +1,23 @@ + 0) { + PermissionService::getUserPermissions($currentUserId); +} + +$id = (int) ($id ?? 0); +$permission = $id > 0 ? PermissionService::find($id) : null; +if (!$permission) { + Flash::error('Permission not found', 'admin/permissions', 'permission_not_found'); + Router::redirect('admin/permissions'); +} + +$errors = []; +$form = $permission; +$roles = RoleRepository::list(); +$selectedRoleIds = RolePermissionRepository::listRoleIdsByPermissionId($id); + +if (isset($_POST['key'])) { + if (!PermissionService::userHas($currentUserId, PermissionService::PERMISSIONS_UPDATE)) { + Flash::error('Permission denied', "admin/permissions/edit/{$id}", 'permission_denied'); + Router::redirect("admin/permissions/edit/{$id}"); + return; + } + $result = PermissionService::updateFromAdmin($id, $_POST); + $form = $result['form'] ?? $form; + $errors = $result['errors'] ?? []; + $selectedRoleIds = $_POST['role_ids'] ?? $selectedRoleIds; + if (!is_array($selectedRoleIds)) { + $selectedRoleIds = [$selectedRoleIds]; + } + $selectedRoleIds = array_values(array_unique(array_map('intval', $selectedRoleIds))); + + if ($result['ok'] ?? false) { + $roleIds = $_POST['role_ids'] ?? []; + if (!is_array($roleIds)) { + $roleIds = [$roleIds]; + } + $roleIds = array_values(array_unique(array_map('intval', $roleIds))); + RolePermissionRepository::replaceForPermission($id, $roleIds); + $action = (string) ($_POST['action'] ?? 'save'); + if ($action === 'save_close') { + Flash::success('Permission updated', 'admin/permissions', 'permission_updated'); + Router::redirect('admin/permissions'); + } else { + Flash::success('Permission updated', "admin/permissions/edit/{$id}", 'permission_updated'); + Router::redirect("admin/permissions/edit/{$id}"); + } + } +} + +Buffer::set('title', t('Edit permission')); diff --git a/pages/admin/permissions/edit(default).phtml b/pages/admin/permissions/edit(default).phtml new file mode 100644 index 0000000..607efc8 --- /dev/null +++ b/pages/admin/permissions/edit(default).phtml @@ -0,0 +1,79 @@ + $errors + * @var array $form + * @var array $permission + */ + +?> +
+
+ +
+

+ + +

+
+ + + + + + + + +
+
+ +
+
    + +
  • + +
+
+ + +
+ +
\ No newline at end of file diff --git a/pages/admin/permissions/index().php b/pages/admin/permissions/index().php new file mode 100644 index 0000000..9dd650a --- /dev/null +++ b/pages/admin/permissions/index().php @@ -0,0 +1,23 @@ + 0) { + PermissionService::getUserPermissions($currentUserId); +} + +Buffer::set('title', t('Permissions')); +Buffer::set('grid_lang', json_encode(gridLang(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); +$csrfKey = Session::$csrfSessionKey; +$csrfToken = $_SESSION[$csrfKey] ?? ''; +Buffer::set( + 'grid_csrf', + json_encode(['key' => $csrfKey, 'token' => $csrfToken], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) +); diff --git a/pages/admin/permissions/index(default).phtml b/pages/admin/permissions/index(default).phtml new file mode 100644 index 0000000..297c8ce --- /dev/null +++ b/pages/admin/permissions/index(default).phtml @@ -0,0 +1,121 @@ + + +
+

+
+ + + + + + +
+
+
+ +
+
+
+
+ + + + diff --git a/pages/admin/roles/_form.phtml b/pages/admin/roles/_form.phtml new file mode 100644 index 0000000..842591e --- /dev/null +++ b/pages/admin/roles/_form.phtml @@ -0,0 +1,39 @@ + +
+
+ Stammdaten +
+ +
+
+ +
> + +
+ +
+
+ + +
diff --git a/pages/admin/roles/create().php b/pages/admin/roles/create().php new file mode 100644 index 0000000..aaba5f9 --- /dev/null +++ b/pages/admin/roles/create().php @@ -0,0 +1,61 @@ + '', +]; +$permissions = PermissionRepository::list(); +$selectedPermissionIds = []; + +if (isset($_POST['description'])) { + $currentUserId = (int) ($_SESSION['user']['id'] ?? 0); + $result = RoleService::createFromAdmin($_POST, $currentUserId); + $form = $result['form'] ?? $form; + $errors = $result['errors'] ?? []; + $selectedPermissionIds = $_POST['permission_ids'] ?? $selectedPermissionIds; + if (!is_array($selectedPermissionIds)) { + $selectedPermissionIds = [$selectedPermissionIds]; + } + $selectedPermissionIds = array_values(array_unique(array_map('intval', $selectedPermissionIds))); + + if ($result['ok'] ?? false) { + $permissionIds = $_POST['permission_ids'] ?? []; + if (!is_array($permissionIds)) { + $permissionIds = [$permissionIds]; + } + $permissionIds = array_values(array_unique(array_map('intval', $permissionIds))); + $createdId = (int) ($result['id'] ?? 0); + if ($createdId > 0) { + RolePermissionRepository::replaceForRole($createdId, $permissionIds); + } + $action = (string) ($_POST['action'] ?? 'create'); + if ($action === 'create_close') { + Flash::success('Role created', 'admin/roles', 'role_created'); + Router::redirect('admin/roles'); + } else { + $uuid = (string) ($result['uuid'] ?? ''); + if ($uuid !== '') { + $target = "admin/roles/edit/{$uuid}"; + Flash::success('Role created', $target, 'role_created'); + Router::redirect($target); + } else { + Flash::success('Role created', 'admin/roles', 'role_created'); + Router::redirect('admin/roles'); + } + } + } +} + +Buffer::set('title', t('Create role')); diff --git a/pages/admin/roles/create(default).phtml b/pages/admin/roles/create(default).phtml new file mode 100644 index 0000000..4be59f1 --- /dev/null +++ b/pages/admin/roles/create(default).phtml @@ -0,0 +1,44 @@ + $errors + * @var array $form + */ + +?> +
+
+ +
+

+ + +

+
+ + +
+
+ +
+
    + +
  • + +
+
+ + +
+
diff --git a/pages/admin/roles/data().php b/pages/admin/roles/data().php new file mode 100644 index 0000000..a48edfa --- /dev/null +++ b/pages/admin/roles/data().php @@ -0,0 +1,43 @@ + $limit, + 'offset' => $offset, + 'search' => $search, + 'order' => $order, + 'dir' => $dir, +]); + +$defaultRoleId = SettingService::getDefaultRoleId(); +$rows = []; +foreach ($result['rows'] as $row) { + $roleId = (int) ($row['id'] ?? 0); + $rows[] = [ + 'id' => $row['id'] ?? null, + 'uuid' => $row['uuid'] ?? '', + 'is_default' => $roleId > 0 && $defaultRoleId === $roleId, + 'description' => $row['description'] ?? '', + 'created' => dt($row['created'] ?? ''), + 'modified' => dt($row['modified'] ?? ''), + ]; +} + +Router::json([ + 'data' => $rows, + 'total' => $result['total'] ?? 0, +]); diff --git a/pages/admin/roles/delete($id).php b/pages/admin/roles/delete($id).php new file mode 100644 index 0000000..92b4f1c --- /dev/null +++ b/pages/admin/roles/delete($id).php @@ -0,0 +1,29 @@ + 0) { + PermissionService::getUserPermissions($currentUserId); +} + +$uuid = trim((string) ($id ?? '')); +$role = $uuid !== '' ? RoleService::findByUuid($uuid) : null; +if (!$role) { + Flash::error('Role not found', 'admin/roles', 'role_not_found'); + Router::redirect('admin/roles'); +} + +$roleId = (int) ($role['id'] ?? 0); +$creatorId = (int) ($role['created_by'] ?? 0); +if ($creatorId > 0) { + $creator = UserService::findById($creatorId); + if ($creator) { + $creatorName = trim(($creator['first_name'] ?? '') . ' ' . ($creator['last_name'] ?? '')); + $role['created_by_label'] = $creatorName !== '' ? $creatorName : ($creator['email'] ?? ''); + $role['created_by_uuid'] = $creator['uuid'] ?? null; + } +} +$modifierId = (int) ($role['modified_by'] ?? 0); +if ($modifierId > 0) { + $modifier = UserService::findById($modifierId); + if ($modifier) { + $modifierName = trim(($modifier['first_name'] ?? '') . ' ' . ($modifier['last_name'] ?? '')); + $role['modified_by_label'] = $modifierName !== '' ? $modifierName : ($modifier['email'] ?? ''); + $role['modified_by_uuid'] = $modifier['uuid'] ?? null; + } +} + +$errors = []; +$form = $role; +$permissions = PermissionRepository::list(); +$selectedPermissionIds = RolePermissionRepository::listPermissionIdsByRoleId($roleId); + +if (isset($_POST['description'])) { + if (!PermissionService::userHas($currentUserId, PermissionService::ROLES_UPDATE)) { + Flash::error('Permission denied', "admin/roles/edit/{$uuid}", 'permission_denied'); + Router::redirect("admin/roles/edit/{$uuid}"); + return; + } + $result = RoleService::updateFromAdmin($roleId, $_POST, $currentUserId); + $form = $result['form'] ?? $form; + $errors = $result['errors'] ?? []; + $selectedPermissionIds = $_POST['permission_ids'] ?? $selectedPermissionIds; + if (!is_array($selectedPermissionIds)) { + $selectedPermissionIds = [$selectedPermissionIds]; + } + $selectedPermissionIds = array_values(array_unique(array_map('intval', $selectedPermissionIds))); + + if ($result['ok'] ?? false) { + $permissionIds = $_POST['permission_ids'] ?? []; + if (!is_array($permissionIds)) { + $permissionIds = [$permissionIds]; + } + $permissionIds = array_values(array_unique(array_map('intval', $permissionIds))); + RolePermissionRepository::replaceForRole($roleId, $permissionIds); + $action = (string) ($_POST['action'] ?? 'save'); + if ($action === 'save_close') { + Flash::success('Role updated', 'admin/roles', 'role_updated'); + Router::redirect('admin/roles'); + } else { + Flash::success('Role updated', "admin/roles/edit/{$uuid}", 'role_updated'); + Router::redirect("admin/roles/edit/{$uuid}"); + } + } +} + +Buffer::set('title', t('Edit role')); diff --git a/pages/admin/roles/edit(default).phtml b/pages/admin/roles/edit(default).phtml new file mode 100644 index 0000000..46f3566 --- /dev/null +++ b/pages/admin/roles/edit(default).phtml @@ -0,0 +1,167 @@ + $errors + * @var array $form + * @var array $role + */ + +use MintyPHP\Session; + +$values = $form ?? $role ?? []; +$isReadOnly = !can('roles.update'); + +?> + +
+
+ +
+

+ + +

+
+ + + + + + + + +
+
+ + +
+
+
    + +
  • + +
+
+
+ + + +
+ +
diff --git a/pages/admin/roles/index().php b/pages/admin/roles/index().php new file mode 100644 index 0000000..33c7f07 --- /dev/null +++ b/pages/admin/roles/index().php @@ -0,0 +1,23 @@ + 0) { + PermissionService::getUserPermissions($currentUserId); +} + +Buffer::set('title', t('Roles')); +Buffer::set('grid_lang', json_encode(gridLang(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); +$csrfKey = Session::$csrfSessionKey; +$csrfToken = $_SESSION[$csrfKey] ?? ''; +Buffer::set( + 'grid_csrf', + json_encode(['key' => $csrfKey, 'token' => $csrfToken], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) +); diff --git a/pages/admin/roles/index(default).phtml b/pages/admin/roles/index(default).phtml new file mode 100644 index 0000000..31b4731 --- /dev/null +++ b/pages/admin/roles/index(default).phtml @@ -0,0 +1,159 @@ + + +
+

+
+ + + + + + +
+
+
+ +
+
+
+
+ + + + diff --git a/pages/admin/search/data().php b/pages/admin/search/data().php new file mode 100644 index 0000000..96d8138 --- /dev/null +++ b/pages/admin/search/data().php @@ -0,0 +1,92 @@ + 0) { + PermissionService::getUserPermissions($userId); +} + +$query = trim((string) ($_GET['q'] ?? '')); +if ($query === '') { + Router::json([]); +} + +$previewLimit = 5; +$locale = I18n::$locale ?? (I18n::$defaultLocale ?? 'de'); +$tenantIds = $userId > 0 ? UserTenantRepository::listTenantIdsByUserId($userId) : []; +$tenantScoped = !empty($tenantIds); + +$tenantScopeFilters = SearchConfig::tenantScopeFilters(); +$resources = SearchConfig::resources($query, $locale); +$results = []; + +foreach ($resources as $resource) { + $key = (string) ($resource['key'] ?? ''); + if ($key === '') { + continue; + } + + $tenantFilter = $tenantScopeFilters[$key] ?? ''; + $isTenantScoped = $tenantFilter !== ''; + if ($isTenantScoped && !$tenantScoped) { + continue; + } + + $perm = (string) ($resource['permission'] ?? ''); + if ($perm !== '' && !PermissionService::userHas($userId, $perm)) { + continue; + } + + $countSql = str_replace('{{tenantFilter}}', $isTenantScoped ? $tenantFilter : '', $resource['countSql'] ?? ''); + $countParams = $resource['countParams'] ?? []; + if ($isTenantScoped && strpos($countSql, '???') !== false) { + $countParams[] = $tenantIds; + } + $count = $countSql !== '' ? (int) DB::selectValue($countSql, ...$countParams) : 0; + + $items = []; + $previewSql = $resource['previewSql'] ?? null; + if ($previewSql) { + $previewSql = str_replace('{{tenantFilter}}', $isTenantScoped ? $tenantFilter : '', $previewSql); + $previewParams = $resource['previewParams'] ?? []; + if ($isTenantScoped && strpos($previewSql, '???') !== false) { + $previewParams[] = $tenantIds; + } + $previewParams[] = $previewLimit; + $rows = DB::select($previewSql, ...$previewParams); + foreach ($rows as $row) { + $data = $row; + if (is_array($row) && count($row) === 1) { + $data = reset($row); + } + $data = is_array($data) ? $data : []; + $mapped = SearchConfig::mapPreviewItem($key, $data, $query); + if ($mapped !== null) { + $items[] = $mapped; + } + } + } + + $result = [ + 'key' => $key, + 'label' => $resource['label'] ?? '', + 'count' => $count, + 'url' => SearchConfig::listUrl($key, $query), + 'items' => $items, + ]; + if ($key === 'pages' && !empty($items[0]['url'])) { + $result['url'] = $items[0]['url']; + } + $results[] = $result; +} + +Router::json($results); diff --git a/pages/admin/settings/favicon().php b/pages/admin/settings/favicon().php new file mode 100644 index 0000000..18c79b6 --- /dev/null +++ b/pages/admin/settings/favicon().php @@ -0,0 +1,26 @@ + SettingService::getDefaultTenantId(), + 'default_role_id' => SettingService::getDefaultRoleId(), + 'default_department_id' => SettingService::getDefaultDepartmentId(), + 'app_title' => SettingService::getAppTitle(), + 'app_locale' => SettingService::getAppLocale(), + 'app_theme' => SettingService::getAppTheme(), + 'app_theme_user' => SettingService::isUserThemeAllowed(), + 'app_primary_color' => SettingService::getAppPrimaryColor(), + 'smtp_host' => SettingService::getSmtpHost(), + 'smtp_port' => SettingService::getSmtpPort(), + 'smtp_user' => SettingService::getSmtpUser(), + 'smtp_secure' => SettingService::getSmtpSecure(), + 'smtp_from' => SettingService::getSmtpFrom(), + 'smtp_from_name' => SettingService::getSmtpFromName(), +]; +$settings = [ + 'default_tenant' => SettingService::get(SettingService::DEFAULT_TENANT_KEY), + 'default_role' => SettingService::get(SettingService::DEFAULT_ROLE_KEY), + 'default_department' => SettingService::get(SettingService::DEFAULT_DEPARTMENT_KEY), + 'app_title' => SettingService::get(SettingService::APP_TITLE_KEY), + 'app_locale' => SettingService::get(SettingService::APP_LOCALE_KEY), + 'app_theme' => SettingService::get(SettingService::APP_THEME_KEY), + 'app_theme_user' => SettingService::get(SettingService::APP_THEME_USER_KEY), + 'app_primary_color' => SettingService::get(SettingService::APP_PRIMARY_COLOR_KEY), + 'smtp_host' => SettingService::get(SettingService::SMTP_HOST_KEY), + 'smtp_port' => SettingService::get(SettingService::SMTP_PORT_KEY), + 'smtp_user' => SettingService::get(SettingService::SMTP_USER_KEY), + 'smtp_password' => SettingService::get(SettingService::SMTP_PASSWORD_KEY), + 'smtp_secure' => SettingService::get(SettingService::SMTP_SECURE_KEY), + 'smtp_from' => SettingService::get(SettingService::SMTP_FROM_KEY), + 'smtp_from_name' => SettingService::get(SettingService::SMTP_FROM_NAME_KEY), +]; + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + if (!isset($_POST['settings_submit'])) { + Router::redirect('admin/settings'); + } + Guard::requirePermission(PermissionService::SETTINGS_UPDATE); + $defaultTenantId = (int) ($_POST['default_tenant_id'] ?? 0); + $defaultRoleId = (int) ($_POST['default_role_id'] ?? 0); + $defaultDepartmentId = (int) ($_POST['default_department_id'] ?? 0); + $appTitle = trim((string) ($_POST['app_title'] ?? '')); + $appLocale = trim((string) ($_POST['app_locale'] ?? '')); + $appTheme = trim((string) ($_POST['app_theme'] ?? '')); + $appThemeUser = isset($_POST['app_theme_user']); + $rawPrimaryColor = $_POST['app_primary_color'] ?? ''; + if (is_array($rawPrimaryColor)) { + $rawPrimaryColor = ''; + } + $appPrimaryColor = trim((string) $rawPrimaryColor); + if (in_array(strtolower($appPrimaryColor), ['null', 'undefined'], true)) { + $appPrimaryColor = ''; + } + $smtpHost = trim((string) ($_POST['smtp_host'] ?? '')); + $smtpPort = (int) ($_POST['smtp_port'] ?? 0); + $smtpUser = trim((string) ($_POST['smtp_user'] ?? '')); + $smtpPassword = (string) ($_POST['smtp_password'] ?? ''); + $smtpSecure = trim((string) ($_POST['smtp_secure'] ?? '')); + $smtpFrom = trim((string) ($_POST['smtp_from'] ?? '')); + $smtpFromName = trim((string) ($_POST['smtp_from_name'] ?? '')); + + SettingService::setDefaultTenantId($defaultTenantId > 0 ? $defaultTenantId : null); + SettingService::setDefaultRoleId($defaultRoleId > 0 ? $defaultRoleId : null); + SettingService::setDefaultDepartmentId($defaultDepartmentId > 0 ? $defaultDepartmentId : null); + SettingService::setAppTitle($appTitle); + SettingService::setAppLocale($appLocale); + SettingService::setAppTheme($appTheme); + SettingService::setUserThemeAllowed($appThemeUser); + $primaryOk = SettingService::setAppPrimaryColor($appPrimaryColor); + if (!$primaryOk) { + $appPrimaryColor = ''; + Flash::error('Primary color is invalid', 'admin/settings', 'app_primary_invalid'); + } + SettingService::setSmtpHost($smtpHost); + SettingService::setSmtpPort($smtpPort > 0 ? $smtpPort : null); + SettingService::setSmtpUser($smtpUser); + if (trim($smtpPassword) !== '') { + SettingService::setSmtpPassword($smtpPassword); + } + SettingService::setSmtpSecure($smtpSecure); + SettingService::setSmtpFrom($smtpFrom); + SettingService::setSmtpFromName($smtpFromName); + + $cacheFile = __DIR__ . '/../../../config/settings.php'; + $cacheData = []; + if (is_file($cacheFile)) { + $existing = include $cacheFile; + if (is_array($existing)) { + $cacheData = $existing; + } + } + $cacheData['app_title'] = $appTitle !== '' ? $appTitle : null; + $cacheData['app_locale'] = $appLocale !== '' ? $appLocale : null; + $cacheData['app_theme'] = $appTheme !== '' ? $appTheme : null; + $cacheData['app_theme_user'] = $appThemeUser ? '1' : '0'; + $cacheData['app_primary_color'] = $appPrimaryColor !== '' ? $appPrimaryColor : null; + file_put_contents($cacheFile, " + +
+
+ +
+

+ +

+
+ + + +
+
+ +
+ +
+ +
+ +
+
+
+ +
+
+
+ + + +
+
+ + + +
+
+
+ +
+
+ + + + + + +
+
+
+
+ +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+ +
+ +
+
+
+ +
+
+ + +
+ + + +
+
+ +
+
+ +
diff --git a/pages/admin/settings/logo().php b/pages/admin/settings/logo().php new file mode 100644 index 0000000..4a9c339 --- /dev/null +++ b/pages/admin/settings/logo().php @@ -0,0 +1,26 @@ + 0 && $tenantId > 0) { + if (!isset($userTenantAssignments[$userId])) { + $userTenantAssignments[$userId] = []; + } + $userTenantAssignments[$userId][] = $tenantId; + } + } +} + +// Load tenant-department assignments +$tenantDepartmentAssignments = []; +$tenantDepartmentRows = DB::select('select tenant_id, department_id from tenant_departments'); +if (is_array($tenantDepartmentRows)) { + foreach ($tenantDepartmentRows as $row) { + $data = $row['tenant_departments'] ?? $row; + $tenantId = (int) ($data['tenant_id'] ?? 0); + $departmentId = (int) ($data['department_id'] ?? 0); + if ($tenantId > 0 && $departmentId > 0) { + if (!isset($tenantDepartmentAssignments[$tenantId])) { + $tenantDepartmentAssignments[$tenantId] = []; + } + $tenantDepartmentAssignments[$tenantId][] = $departmentId; + } + } +} + +foreach ($tenants as $tenant) { + $tenantId = (int) ($tenant['id'] ?? 0); + if ($tenantId === 0) { + continue; + } + + // Count departments for this tenant + $deptCount = 0; + $tenantDepartmentIds = $tenantDepartmentAssignments[$tenantId] ?? []; + foreach ($departments as $dept) { + $deptId = (int) ($dept['id'] ?? 0); + if ($deptId > 0 && in_array($deptId, $tenantDepartmentIds, true)) { + $deptCount++; + } + } + + // Count users for this tenant + $totalUsers = 0; + $activeUsers = 0; + $inactiveUsers = 0; + foreach ($users as $user) { + $userId = (int) ($user['id'] ?? 0); + if ($userId === 0) { + continue; + } + + // Check if user is assigned to this tenant + $userTenantIds = $userTenantAssignments[$userId] ?? []; + if (in_array($tenantId, $userTenantIds, true)) { + $totalUsers++; + $isActive = (int) ($user['active'] ?? 1); + if ($isActive === 1) { + $activeUsers++; + } else { + $inactiveUsers++; + } + } + } + + $tenantBreakdown[] = [ + 'id' => $tenantId, + 'uuid' => $tenant['uuid'] ?? '', + 'description' => $tenant['description'] ?? '', + 'departments' => $deptCount, + 'total_users' => $totalUsers, + 'active_users' => $activeUsers, + 'inactive_users' => $inactiveUsers, + ]; +} + +// Sort by description +usort($tenantBreakdown, function ($a, $b) { + return strcmp((string) ($a['description'] ?? ''), (string) ($b['description'] ?? '')); +}); + +// Mail log stats +$mailLogTotalCount = DB::selectValue('select count(*) from mail_log'); +$mailLogTotalCount = $mailLogTotalCount ? (int) $mailLogTotalCount : 0; + +$mailLogSentCount = DB::selectValue("select count(*) from mail_log where status = 'sent'"); +$mailLogSentCount = $mailLogSentCount ? (int) $mailLogSentCount : 0; + +$mailLogFailedCount = DB::selectValue("select count(*) from mail_log where status = 'failed'"); +$mailLogFailedCount = $mailLogFailedCount ? (int) $mailLogFailedCount : 0; + +$mailLogQueuedCount = DB::selectValue("select count(*) from mail_log where status = 'queued'"); +$mailLogQueuedCount = $mailLogQueuedCount ? (int) $mailLogQueuedCount : 0; + +// Mail log stats (last 24h) +$mailLogTotal24hCount = DB::selectValue("select count(*) from mail_log where created_at >= NOW() - INTERVAL 24 HOUR"); +$mailLogTotal24hCount = $mailLogTotal24hCount ? (int) $mailLogTotal24hCount : 0; + +$mailLogSent24hCount = DB::selectValue("select count(*) from mail_log where status = 'sent' and created_at >= NOW() - INTERVAL 24 HOUR"); +$mailLogSent24hCount = $mailLogSent24hCount ? (int) $mailLogSent24hCount : 0; + +$mailLogFailed24hCount = DB::selectValue("select count(*) from mail_log where status = 'failed' and created_at >= NOW() - INTERVAL 24 HOUR"); +$mailLogFailed24hCount = $mailLogFailed24hCount ? (int) $mailLogFailed24hCount : 0; + +$mailLogQueued24hCount = DB::selectValue("select count(*) from mail_log where status = 'queued' and created_at >= NOW() - INTERVAL 24 HOUR"); +$mailLogQueued24hCount = $mailLogQueued24hCount ? (int) $mailLogQueued24hCount : 0; + +// Calculate date range for last 24 hours +$date24hAgo = gmdate('Y-m-d', strtotime('-24 hours')); +$dateToday = gmdate('Y-m-d'); + +Buffer::set('title', t('Statistics')); diff --git a/pages/admin/stats/index(default).phtml b/pages/admin/stats/index(default).phtml new file mode 100644 index 0000000..fc1b2a0 --- /dev/null +++ b/pages/admin/stats/index(default).phtml @@ -0,0 +1,283 @@ + +
+ +
+
+

+
+ +
+
+
+
+
+ +
+ + + + + +
+ + +
+
+ 'admin/tenants', + 'label' => t('Tenants'), + 'count' => (string) $tenantCount, + 'icon' => 'bi bi-building', + 'iconBg' => '#e9f0ff', + 'iconColor' => '#264db3', + ]); + ?> + 'admin/departments', + 'label' => t('Departments'), + 'count' => (string) $departmentCount, + 'icon' => 'bi bi-diagram-3-fill', + 'iconBg' => '#fff2d9', + 'iconColor' => '#9a5a00', + ]); + ?> + 'admin/users', + 'label' => t('Users'), + 'count' => (string) $userCount, + 'icon' => 'bi bi-people-fill', + 'iconBg' => '#d9f2e6', + 'iconColor' => '#1f6a3a', + ]); + ?> +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + ( + / + ) + +
+
+ +
+ + +
+
+
+
+ 'admin/users', + 'label' => t('Active users'), + 'count' => (string) $activeUserCount, + 'icon' => 'bi bi-person-check-fill', + 'iconBg' => '#d9f2e6', + 'iconColor' => '#1f6a3a', + ]); + ?> + 'admin/users', + 'label' => t('Inactive users'), + 'count' => (string) $inactiveUserCount, + 'icon' => 'bi bi-person-x-fill', + 'iconBg' => '#ffe9e9', + 'iconColor' => '#a32e2e', + ]); + ?> +
+
+
+
+ 'admin/roles', + 'label' => t('Roles'), + 'count' => (string) $roleCount, + 'icon' => 'bi bi-shield-lock-fill', + 'iconBg' => '#f3e9ff', + 'iconColor' => '#5b2c83', + ]); + ?> + 'admin/permissions', + 'label' => t('Permissions'), + 'count' => (string) $permissionCount, + 'icon' => 'bi bi-key-fill', + 'iconBg' => '#fff2d9', + 'iconColor' => '#9a5a00', + ]); + ?> +
+
+
+
+ + + +
+
+
+

+
+ 'admin/mail-log', + 'label' => t('Total emails'), + 'count' => (string) $mailLogTotalCount, + 'icon' => 'bi bi-envelope-fill', + 'iconBg' => '#e9f0ff', + 'iconColor' => '#264db3', + ]); + ?> + 'admin/mail-log?status=sent', + 'label' => t('Sent emails'), + 'count' => (string) $mailLogSentCount, + 'icon' => 'bi bi-envelope-check-fill', + 'iconBg' => '#d9f2e6', + 'iconColor' => '#1f6a3a', + ]); + ?> + 'admin/mail-log?status=failed', + 'label' => t('Failed emails'), + 'count' => (string) $mailLogFailedCount, + 'icon' => 'bi bi-envelope-x-fill', + 'iconBg' => '#ffe9e9', + 'iconColor' => '#a32e2e', + ]); + ?> + 'admin/mail-log', + 'label' => t('Queued emails'), + 'count' => (string) $mailLogQueuedCount, + 'icon' => 'bi bi-envelope-paper-fill', + 'iconBg' => '#fff2d9', + 'iconColor' => '#9a5a00', + ]); + ?> +
+
+
+

+ +

+
+ 'admin/mail-log?created_from=' . urlencode($date24hAgo ?? '') . '&created_to=' . urlencode($dateToday ?? ''), + 'label' => t('Total (24h)'), + 'count' => (string) $mailLogTotal24hCount, + 'icon' => 'bi bi-envelope-fill', + 'iconBg' => '#e9f0ff', + 'iconColor' => '#264db3', + ]); + ?> + 'admin/mail-log?status=sent&created_from=' . urlencode($date24hAgo ?? '') . '&created_to=' . urlencode($dateToday ?? ''), + 'label' => t('Sent (24h)'), + 'count' => (string) $mailLogSent24hCount, + 'icon' => 'bi bi-envelope-check-fill', + 'iconBg' => '#d9f2e6', + 'iconColor' => '#1f6a3a', + ]); + ?> + 'admin/mail-log?status=failed&created_from=' . urlencode($date24hAgo ?? '') . '&created_to=' . urlencode($dateToday ?? ''), + 'label' => t('Failed (24h)'), + 'count' => (string) $mailLogFailed24hCount, + 'icon' => 'bi bi-envelope-x-fill', + 'iconBg' => '#ffe9e9', + 'iconColor' => '#a32e2e', + ]); + ?> + 'admin/mail-log?status=queued&created_from=' . urlencode($date24hAgo ?? '') . '&created_to=' . urlencode($dateToday ?? ''), + 'label' => t('Queued (24h)'), + 'count' => (string) $mailLogQueued24hCount, + 'icon' => 'bi bi-envelope-paper-fill', + 'iconBg' => '#fff2d9', + 'iconColor' => '#9a5a00', + ]); + ?> +
+
+
+
+ +
+
\ No newline at end of file diff --git a/pages/admin/tenants/_form.phtml b/pages/admin/tenants/_form.phtml new file mode 100644 index 0000000..335a7fd --- /dev/null +++ b/pages/admin/tenants/_form.phtml @@ -0,0 +1,187 @@ + +
+
+
+ + + + + + +
+ +
+ + + +
+ + +
+
+ + +
+
+ +
+
+ + +
+ +
+ +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+
+ + +
+
+ + + + + + + +
+
+
+
+ +
diff --git a/pages/admin/tenants/avatar($id).php b/pages/admin/tenants/avatar($id).php new file mode 100644 index 0000000..ec47278 --- /dev/null +++ b/pages/admin/tenants/avatar($id).php @@ -0,0 +1,33 @@ + '', + 'address' => '', + 'postal_code' => '', + 'city' => '', + 'country' => '', + 'region' => '', + 'vat_id' => '', + 'tax_number' => '', + 'phone' => '', + 'fax' => '', + 'email' => '', + 'support_email' => '', + 'support_phone' => '', + 'billing_email' => '', + 'website' => '', + 'privacy_url' => '', + 'imprint_url' => '', + 'primary_color' => '', + 'primary_color_use_default' => 0, + 'status' => 'active', +]; + +if (isset($_POST['description'])) { + $currentUserId = (int) ($_SESSION['user']['id'] ?? 0); + $result = TenantService::createFromAdmin($_POST, $currentUserId); + $form = $result['form'] ?? $form; + $errors = $result['errors'] ?? []; + + if ($result['ok'] ?? false) { + $action = (string) ($_POST['action'] ?? 'create'); + if ($action === 'create_close') { + Flash::success('Tenant created', 'admin/tenants', 'tenant_created'); + Router::redirect('admin/tenants'); + } else { + $uuid = (string) ($result['uuid'] ?? ''); + if ($uuid !== '') { + $target = "admin/tenants/edit/{$uuid}"; + Flash::success('Tenant created', $target, 'tenant_created'); + Router::redirect($target); + } else { + Flash::success('Tenant created', 'admin/tenants', 'tenant_created'); + Router::redirect('admin/tenants'); + } + } + } +} + +Buffer::set('title', t('Create tenant')); diff --git a/pages/admin/tenants/create(default).phtml b/pages/admin/tenants/create(default).phtml new file mode 100644 index 0000000..340bab4 --- /dev/null +++ b/pages/admin/tenants/create(default).phtml @@ -0,0 +1,44 @@ + $errors + * @var array $form + */ + +?> +
+
+ +
+

+ + +

+
+ + +
+
+ +
+
    + +
  • + +
+
+ + +
+
diff --git a/pages/admin/tenants/data().php b/pages/admin/tenants/data().php new file mode 100644 index 0000000..45f88e4 --- /dev/null +++ b/pages/admin/tenants/data().php @@ -0,0 +1,43 @@ + $limit, + 'offset' => $offset, + 'search' => $search, + 'order' => $order, + 'dir' => $dir, +]); + +$defaultTenantId = SettingService::getDefaultTenantId(); +$rows = []; +foreach ($result['rows'] as $row) { + $tenantId = (int) ($row['id'] ?? 0); + $rows[] = [ + 'id' => $row['id'] ?? null, + 'uuid' => $row['uuid'] ?? '', + 'is_default' => $tenantId > 0 && $defaultTenantId === $tenantId, + 'description' => $row['description'] ?? '', + 'created' => dt($row['created'] ?? ''), + 'modified' => dt($row['modified'] ?? ''), + ]; +} + +Router::json([ + 'data' => $rows, + 'total' => $result['total'] ?? 0, +]); diff --git a/pages/admin/tenants/delete($id).php b/pages/admin/tenants/delete($id).php new file mode 100644 index 0000000..b0daf1d --- /dev/null +++ b/pages/admin/tenants/delete($id).php @@ -0,0 +1,31 @@ + 0) { + AuthService::loadTenantDataIntoSession($currentUserId); +} + +Flash::success('Tenant deleted', 'admin/tenants', 'tenant_deleted'); +Router::redirect('admin/tenants'); diff --git a/pages/admin/tenants/edit($id).php b/pages/admin/tenants/edit($id).php new file mode 100644 index 0000000..97d08f5 --- /dev/null +++ b/pages/admin/tenants/edit($id).php @@ -0,0 +1,82 @@ + 0) { + PermissionService::getUserPermissions($currentUserId); +} + +$uuid = trim((string) ($id ?? '')); +$tenant = $uuid !== '' ? TenantService::findByUuid($uuid) : null; +if (!$tenant) { + Flash::error('Tenant not found', 'admin/tenants', 'tenant_not_found'); + Router::redirect('admin/tenants'); +} + +$tenantId = (int) ($tenant['id'] ?? 0); +$creatorId = (int) ($tenant['created_by'] ?? 0); +if ($creatorId > 0) { + $creator = UserService::findById($creatorId); + if ($creator) { + $creatorName = trim(($creator['first_name'] ?? '') . ' ' . ($creator['last_name'] ?? '')); + $tenant['created_by_label'] = $creatorName !== '' ? $creatorName : ($creator['email'] ?? ''); + $tenant['created_by_uuid'] = $creator['uuid'] ?? null; + } +} +$modifierId = (int) ($tenant['modified_by'] ?? 0); +if ($modifierId > 0) { + $modifier = UserService::findById($modifierId); + if ($modifier) { + $modifierName = trim(($modifier['first_name'] ?? '') . ' ' . ($modifier['last_name'] ?? '')); + $tenant['modified_by_label'] = $modifierName !== '' ? $modifierName : ($modifier['email'] ?? ''); + $tenant['modified_by_uuid'] = $modifier['uuid'] ?? null; + } +} +$statusChangedById = (int) ($tenant['status_changed_by'] ?? 0); +if ($statusChangedById > 0) { + $statusChanger = UserService::findById($statusChangedById); + if ($statusChanger) { + $statusChangerName = trim(($statusChanger['first_name'] ?? '') . ' ' . ($statusChanger['last_name'] ?? '')); + $tenant['status_changed_by_label'] = $statusChangerName !== '' ? $statusChangerName : ($statusChanger['email'] ?? ''); + $tenant['status_changed_by_uuid'] = $statusChanger['uuid'] ?? null; + } +} + +$errors = []; +$form = $tenant; + +if (isset($_POST['description'])) { + if (!PermissionService::userHas($currentUserId, PermissionService::TENANTS_UPDATE)) { + Router::redirect('error/forbidden'); + return; + } + $result = TenantService::updateFromAdmin($tenantId, $_POST, $currentUserId); + $form = $result['form'] ?? $form; + $errors = $result['errors'] ?? []; + + if ($result['ok'] ?? false) { + if ($currentUserId > 0) { + \MintyPHP\Service\AuthService::loadTenantDataIntoSession($currentUserId); + } + $action = (string) ($_POST['action'] ?? 'save'); + if ($action === 'save_close') { + Flash::success('Tenant updated', 'admin/tenants', 'tenant_updated'); + Router::redirect('admin/tenants'); + } else { + Flash::success('Tenant updated', "admin/tenants/edit/{$uuid}", 'tenant_updated'); + Router::redirect("admin/tenants/edit/{$uuid}"); + } + } +} + +Buffer::set('title', t('Edit tenant')); diff --git a/pages/admin/tenants/edit(default).phtml b/pages/admin/tenants/edit(default).phtml new file mode 100644 index 0000000..f591904 --- /dev/null +++ b/pages/admin/tenants/edit(default).phtml @@ -0,0 +1,371 @@ + $errors + * @var array $form + * @var array $tenant + */ + +use MintyPHP\Session; +use MintyPHP\Service\TenantAvatarService; +use MintyPHP\Service\TenantFaviconService; + +$values = $form ?? $tenant ?? []; +$isReadOnly = !can('tenants.update'); +$avatarUuid = (string) ($values['uuid'] ?? ''); +$hasAvatar = $avatarUuid !== '' && TenantAvatarService::hasAvatar($avatarUuid); +$hasFavicon = $avatarUuid !== '' && TenantFaviconService::hasFavicon($avatarUuid); + +?> + +
+
+ +
+

+ + +

+
+ + + + + + + + +
+
+ + +
+
+
    + +
  • + +
+
+
+ + + +
+ +
diff --git a/pages/admin/tenants/favicon($id).php b/pages/admin/tenants/favicon($id).php new file mode 100644 index 0000000..721f64c --- /dev/null +++ b/pages/admin/tenants/favicon($id).php @@ -0,0 +1,33 @@ + 0) { + PermissionService::getUserPermissions($currentUserId); +} + +Buffer::set('title', t('Tenants')); +Buffer::set('grid_lang', json_encode(gridLang(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); +$csrfKey = Session::$csrfSessionKey; +$csrfToken = $_SESSION[$csrfKey] ?? ''; +Buffer::set( + 'grid_csrf', + json_encode(['key' => $csrfKey, 'token' => $csrfToken], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) +); diff --git a/pages/admin/tenants/index(default).phtml b/pages/admin/tenants/index(default).phtml new file mode 100644 index 0000000..5d2befe --- /dev/null +++ b/pages/admin/tenants/index(default).phtml @@ -0,0 +1,159 @@ + + +
+

+
+ + + + + + +
+
+
+ +
+
+
+
+ + + + diff --git a/pages/admin/users/_form.phtml b/pages/admin/users/_form.phtml new file mode 100644 index 0000000..cf93bb2 --- /dev/null +++ b/pages/admin/users/_form.phtml @@ -0,0 +1,359 @@ + +
+
+
+ + + + + + + + + +
+ +
+
+ +
+
+ + +
+ +
+
+
+ +
+ + +
+
+
+ +
+
+ + + + +
+
+
+ +
+
+ +
+
+
+ + +
+
+ +
    + +
  • + +
  • +
+
+
+ + + +
+
+ + +
+ +
+ +
+ + 0): ?> + + + + +
+
+ + +
+ +
+
+ +
+ +
+ + +
+ +
+ +
+
+ +
+ + +
+
+ +
+
+ + + +
+
+
+
+ +
+ +
+ + +
+
+ + +
+
+
+
+ +
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+ +
+ +
diff --git a/pages/admin/users/activate($id).php b/pages/admin/users/activate($id).php new file mode 100644 index 0000000..107bb98 --- /dev/null +++ b/pages/admin/users/activate($id).php @@ -0,0 +1,41 @@ + 0 && $currentUserId !== $userId && !TenantScopeService::canAccess('users', $userId, $currentUserId)) { + if (Request::wantsJson()) { + http_response_code(403); + Router::json(['error' => 'permission_denied']); + return; + } + Router::redirect('error/forbidden'); + return; +} +$result = UserService::setActiveByUuid($uuid, true, $currentUserId); +if ($result['ok'] ?? false) { + if (Request::wantsJson()) { + http_response_code(204); + return; + } +} elseif (Request::wantsJson()) { + http_response_code((int) ($result['status'] ?? 404)); + Router::json(['error' => 'not_found']); + return; +} + +Router::redirect('admin/users'); diff --git a/pages/admin/users/avatar($id).php b/pages/admin/users/avatar($id).php new file mode 100644 index 0000000..c82145a --- /dev/null +++ b/pages/admin/users/avatar($id).php @@ -0,0 +1,41 @@ + 0 && $currentUserId !== $userId && !TenantScopeService::canAccess('users', $userId, $currentUserId)) { + Router::redirect('error/forbidden'); + return; +} + +$result = UserAvatarService::saveUpload($uuid, $_FILES['avatar'] ?? []); +if (!($result['ok'] ?? false)) { + $error = $result['error'] ?? t('Upload failed'); + Flash::error($error, "admin/users/edit/{$uuid}", 'avatar_upload_failed'); + Router::redirect("admin/users/edit/{$uuid}"); + return; +} + +Flash::success('Avatar updated', "admin/users/edit/{$uuid}", 'avatar_updated'); +Router::redirect("admin/users/edit/{$uuid}"); diff --git a/pages/admin/users/avatar-delete($id).php b/pages/admin/users/avatar-delete($id).php new file mode 100644 index 0000000..19c6db3 --- /dev/null +++ b/pages/admin/users/avatar-delete($id).php @@ -0,0 +1,34 @@ + 0 && $currentUserId !== $userId && !TenantScopeService::canAccess('users', $userId, $currentUserId)) { + Router::redirect('error/forbidden'); + return; +} + +UserAvatarService::delete($uuid); +Flash::success('Avatar removed', "admin/users/edit/{$uuid}", 'avatar_removed'); +Router::redirect("admin/users/edit/{$uuid}"); diff --git a/pages/admin/users/avatar-file().php b/pages/admin/users/avatar-file().php new file mode 100644 index 0000000..aaad6c5 --- /dev/null +++ b/pages/admin/users/avatar-file().php @@ -0,0 +1,37 @@ + 0 && $currentUserId !== $userId && !TenantScopeService::canAccess('users', $userId, $currentUserId)) { + http_response_code(403); + return; +} + +$path = UserAvatarService::findAvatarPath($uuid, $size); +if (!$path || !is_file($path)) { + http_response_code(404); + return; +} + +$mime = UserAvatarService::detectMime($path); +header('Content-Type: ' . $mime); +header('X-Content-Type-Options: nosniff'); +header('Content-Security-Policy: sandbox'); +header('Cache-Control: private, max-age=300'); +header('Content-Length: ' . filesize($path)); +readfile($path); diff --git a/pages/admin/users/avatar-file(none).phtml b/pages/admin/users/avatar-file(none).phtml new file mode 100644 index 0000000..4ba9f2b --- /dev/null +++ b/pages/admin/users/avatar-file(none).phtml @@ -0,0 +1,4 @@ + 'handleActivate', + 'deactivate' => 'handleDeactivate', + 'delete' => 'handleDelete', + 'send-access' => 'handleSendAccess', +]; +if (!isset($handlers[$action])) { + Router::json(['ok' => false, 'error' => 'invalid_action']); +} +if ($action === 'delete') { + Guard::requirePermissionOrForbidden(PermissionService::USERS_DELETE); +} +if ($action === 'send-access') { + Guard::requirePermissionOrForbidden(PermissionService::USERS_UPDATE); +} + +$raw = $_POST['uuids'] ?? ''; +$uuids = []; +if (is_array($raw)) { + $uuids = $raw; +} elseif (is_string($raw)) { + $uuids = array_filter(array_map('trim', explode(',', $raw))); +} +$uuids = array_values(array_unique(array_filter($uuids))); +if (!$uuids) { + Router::json(['ok' => false, 'error' => 'no_selection']); +} + +$currentUserId = (int) ($_SESSION['user']['id'] ?? 0); +call_user_func($handlers[$action], $uuids, $currentUserId); + +function handleActivate(array $uuids, int $currentUserId): void +{ + $result = UserService::setActiveByUuids($uuids, true, $currentUserId); + if (!($result['ok'] ?? false)) { + Router::json(['ok' => false, 'error' => 'update_failed']); + } + Router::json(['ok' => true, 'count' => (int) ($result['count'] ?? 0)]); +} + +function handleDeactivate(array $uuids, int $currentUserId): void +{ + if ($currentUserId > 0) { + $currentUser = UserService::findById($currentUserId); + $currentUuid = $currentUser['uuid'] ?? ''; + if ($currentUuid !== '') { + $uuids = array_values(array_filter($uuids, static fn ($uuid) => $uuid !== $currentUuid)); + } + if (!$uuids) { + Router::json(['ok' => false, 'error' => 'self_deactivate']); + } + } + + $result = UserService::setActiveByUuids($uuids, false, $currentUserId); + if (!($result['ok'] ?? false)) { + Router::json(['ok' => false, 'error' => 'update_failed']); + } + Router::json(['ok' => true, 'count' => (int) ($result['count'] ?? 0)]); +} + +function handleDelete(array $uuids, int $currentUserId): void +{ + $result = UserService::deleteByUuids($uuids, $currentUserId); + if (!($result['ok'] ?? false)) { + Router::json(['ok' => false, 'error' => $result['error'] ?? 'delete_failed']); + } + Router::json(['ok' => true, 'count' => (int) ($result['count'] ?? 0)]); +} + +function handleSendAccess(array $uuids, int $currentUserId): void +{ + $successCount = 0; + $failedCount = 0; + + foreach ($uuids as $uuid) { + $user = UserService::findByUuid($uuid); + if (!$user || empty($user['email'])) { + $failedCount++; + continue; + } + + $locale = $user['locale'] ?? (I18n::$locale ?? I18n::$defaultLocale); + $name = trim(($user['first_name'] ?? '') . ' ' . ($user['last_name'] ?? '')); + $isGerman = strpos((string) $locale, 'de') === 0; + $greeting = $isGerman ? 'Hallo' : 'Hello'; + if ($name !== '') { + $greeting .= ' ' . $name; + } + $greeting .= ','; + + $loginUrl = appUrl(Request::withLocale('login', $locale)); + $resetUrl = appUrl(Request::withLocale('password/forgot', $locale)); + $previousLocale = I18n::$locale ?? null; + I18n::$locale = $locale; + $subject = t('Your access details'); + I18n::$locale = $previousLocale; + + $vars = [ + 'app_name' => appTitle(), + 'app_logo_url' => appLogoUrlAbsolute(128), + 'imprint_url' => appUrl(Request::withLocale('imprint', $locale)), + 'privacy_url' => appUrl(Request::withLocale('privacy', $locale)), + 'greeting' => $greeting, + 'username' => (string) ($user['email'] ?? ''), + 'login_url' => $loginUrl, + 'reset_url' => $resetUrl, + ]; + + $result = MailService::sendTemplate('access_info', $vars, (string) $user['email'], $subject, $locale); + if ($result['ok'] ?? false) { + $successCount++; + } else { + $failedCount++; + } + } + + Router::json([ + 'ok' => $successCount > 0, + 'count' => $successCount, + 'failed' => $failedCount, + ]); +} diff --git a/pages/admin/users/create().php b/pages/admin/users/create().php new file mode 100644 index 0000000..74bccd3 --- /dev/null +++ b/pages/admin/users/create().php @@ -0,0 +1,93 @@ + 0 && in_array($tenantId, $allowedTenantIds, true); + })); +} elseif (TenantScopeService::isStrict()) { + $tenants = []; +} +$roles = RoleService::list(); +$departments = $allowedTenantIds ? DepartmentService::listByTenantIds($allowedTenantIds) : []; +if (!$allowedTenantIds && !TenantScopeService::isStrict()) { + $departments = DepartmentService::list(); +} + +$errors = []; +$form = [ + 'first_name' => '', + 'last_name' => '', + 'email' => '', + 'profile_description' => '', + 'job_title' => '', + 'phone' => '', + 'mobile' => '', + 'short_dial' => '', + 'address' => '', + 'postal_code' => '', + 'city' => '', + 'country' => '', + 'region' => '', + 'hire_date' => '', + 'totp_secret' => '', + 'locale' => I18n::$locale ?? I18n::$defaultLocale, + 'active' => 1, +]; + +if (isset($_POST['email'])) { + $input = $_POST; + $tenantIds = UserService::normalizeIdInput($input['tenant_ids'] ?? []); + if ($allowedTenantIds) { + $tenantIds = array_values(array_intersect($tenantIds, $allowedTenantIds)); + } elseif (TenantScopeService::isStrict()) { + $tenantIds = []; + } + $defaultTenantId = SettingService::getDefaultTenantId(); + if (TenantScopeService::isStrict() && !$tenantIds && !$defaultTenantId) { + $errors[] = t('Please select at least one tenant'); + } + $input['tenant_ids'] = $tenantIds; + $result = UserService::createFromAdmin($input, $currentUserId); + $form = $result['form'] ?? $form; + $errors = array_merge($errors, $result['errors'] ?? []); + + if (($result['ok'] ?? false) && !$errors) { + $action = (string) ($_POST['action'] ?? 'create'); + if ($action === 'create_close') { + Flash::success('User created', 'admin/users', 'user_created'); + Router::redirect('admin/users'); + } else { + $uuid = (string) ($result['uuid'] ?? ''); + if ($uuid !== '') { + $target = "admin/users/edit/{$uuid}"; + Flash::success('User created', $target, 'user_created'); + Router::redirect($target); + } else { + Flash::success('User created', 'admin/users', 'user_created'); + Router::redirect('admin/users'); + } + } + } +} + +Buffer::set('title', t('Create user')); diff --git a/pages/admin/users/create(default).phtml b/pages/admin/users/create(default).phtml new file mode 100644 index 0000000..523e059 --- /dev/null +++ b/pages/admin/users/create(default).phtml @@ -0,0 +1,51 @@ + $errors + * @var array $form + */ + + + +?> +
+ +
+ +
+

+ + +

+
+ + +
+
+ +
+
    + +
  • + +
+
+ + +
+
\ No newline at end of file diff --git a/pages/admin/users/data().php b/pages/admin/users/data().php new file mode 100644 index 0000000..9170775 --- /dev/null +++ b/pages/admin/users/data().php @@ -0,0 +1,106 @@ + [], 'total' => 0]); +} + +$currentUserId = (int) ($_SESSION['user']['id'] ?? 0); + +$limit = (int) ($_GET['limit'] ?? 10); +$offset = (int) ($_GET['offset'] ?? 0); +$search = trim((string) ($_GET['search'] ?? '')); +$order = (string) ($_GET['order'] ?? 'last_name'); +$dir = (string) ($_GET['dir'] ?? 'asc'); +$active = $_GET['active'] ?? 'all'; +$createdFrom = trim((string) ($_GET['created_from'] ?? '')); +$createdTo = trim((string) ($_GET['created_to'] ?? '')); +$tenant = trim((string) ($_GET['tenant'] ?? '')); +$roles = $_GET['roles'] ?? ''; +$departments = $_GET['departments'] ?? ''; +$emailVerified = $_GET['email_verified'] ?? 'all'; + +$result = UserService::listPaged([ + 'limit' => $limit, + 'offset' => $offset, + 'search' => $search, + 'order' => $order, + 'dir' => $dir, + 'active' => $active, + 'created_from' => $createdFrom, + 'created_to' => $createdTo, + 'tenant' => $tenant, + 'roles' => $roles, + 'departments' => $departments, + 'email_verified' => $emailVerified, + 'tenantUserId' => $currentUserId, +]); + +$rows = []; +foreach ($result['rows'] as $row) { + $tenantLabels = $row['tenant_labels'] ?? []; + if (is_string($tenantLabels)) { + $tenantList = $tenantLabels !== '' + ? array_values(array_filter(array_map('trim', explode('||', $tenantLabels)))) + : []; + } elseif (is_array($tenantLabels)) { + $tenantList = array_values(array_filter(array_map('trim', $tenantLabels))); + } else { + $tenantList = []; + } + $roleLabels = $row['role_labels'] ?? []; + if (is_string($roleLabels)) { + $roleList = $roleLabels !== '' + ? array_values(array_filter(array_map('trim', explode('||', $roleLabels)))) + : []; + } elseif (is_array($roleLabels)) { + $roleList = array_values(array_filter(array_map('trim', $roleLabels))); + } else { + $roleList = []; + } + $departmentLabels = $row['department_labels'] ?? []; + if (is_string($departmentLabels)) { + $departmentList = $departmentLabels !== '' + ? array_values(array_filter(array_map('trim', explode('||', $departmentLabels)))) + : []; + } elseif (is_array($departmentLabels)) { + $departmentList = array_values(array_filter(array_map('trim', $departmentLabels))); + } else { + $departmentList = []; + } + $primaryTenantLabel = (string) ($row['primary_tenant_label'] ?? ''); + if ($primaryTenantLabel === '' && count($tenantList) === 1) { + $primaryTenantLabel = (string) $tenantList[0]; + } + $uuid = (string) ($row['uuid'] ?? ''); + $rows[] = [ + 'id' => $row['id'] ?? null, + 'uuid' => $uuid, + 'first_name' => $row['first_name'] ?? '', + 'last_name' => $row['last_name'] ?? '', + 'email' => $row['email'] ?? '', + 'phone' => $row['phone'] ?? '', + 'mobile' => $row['mobile'] ?? '', + 'short_dial' => $row['short_dial'] ?? '', + 'tenants' => [ + 'items' => $tenantList, + 'primary' => $primaryTenantLabel, + ], + 'departments' => $departmentList, + 'roles' => $roleList, + 'created' => dt($row['created'] ?? ''), + 'modified' => dt($row['modified'] ?? ''), + 'active' => (int) ($row['active'] ?? 0), + 'has_avatar' => $uuid !== '' && UserAvatarService::hasAvatar($uuid), + ]; +} + +Router::json([ + 'data' => $rows, + 'total' => $result['total'] ?? 0, +]); diff --git a/pages/admin/users/deactivate($id).php b/pages/admin/users/deactivate($id).php new file mode 100644 index 0000000..5af25e8 --- /dev/null +++ b/pages/admin/users/deactivate($id).php @@ -0,0 +1,53 @@ + 0 && $currentUserId !== $userId && !TenantScopeService::canAccess('users', $userId, $currentUserId)) { + if (Request::wantsJson()) { + http_response_code(403); + Router::json(['error' => 'permission_denied']); + return; + } + Router::redirect('error/forbidden'); + return; +} +$result = UserService::setActiveByUuid($uuid, false, $currentUserId); +if (!($result['ok'] ?? false)) { + if (($result['error'] ?? '') === 'self_deactivate') { + Flash::error('You cannot deactivate your own account', 'admin/users', 'user_self_deactivate'); + if (Request::wantsJson()) { + http_response_code(400); + Router::json(['error' => 'self_deactivate']); + return; + } + } elseif (Request::wantsJson()) { + http_response_code((int) ($result['status'] ?? 404)); + Router::json(['error' => 'not_found']); + return; + } + Router::redirect('admin/users'); + return; +} + +if (Request::wantsJson()) { + http_response_code(204); + return; +} + +Router::redirect('admin/users'); diff --git a/pages/admin/users/delete($id).php b/pages/admin/users/delete($id).php new file mode 100644 index 0000000..5d34d38 --- /dev/null +++ b/pages/admin/users/delete($id).php @@ -0,0 +1,61 @@ + 0 && $currentUserId !== $userId && !TenantScopeService::canAccess('users', $userId, $currentUserId)) { + if (Request::wantsJson()) { + http_response_code(403); + Router::json(['error' => 'permission_denied']); + return; + } + Router::redirect('error/forbidden'); + return; +} +$result = UserService::deleteByUuid($uuid, $currentUserId); + +if (!($result['ok'] ?? false)) { + if (($result['error'] ?? '') === 'self_delete') { + Flash::error('You cannot delete your own account', 'admin/users', 'user_self_delete'); + if (Request::wantsJson()) { + http_response_code(400); + Router::json(['error' => 'self_delete']); + return; + } + } else { + Flash::error('User not found', 'admin/users', 'user_not_found'); + if (Request::wantsJson()) { + http_response_code(404); + Router::json(['error' => 'not_found']); + return; + } + } + Router::redirect('admin/users'); + return; +} + +if (Request::wantsJson()) { + http_response_code(204); + Router::json([]); + return; +} + +Flash::success('User deleted', 'admin/users', 'user_deleted'); +Router::redirect('admin/users'); diff --git a/pages/admin/users/edit($id).php b/pages/admin/users/edit($id).php new file mode 100644 index 0000000..669c55a --- /dev/null +++ b/pages/admin/users/edit($id).php @@ -0,0 +1,160 @@ + 0) { + PermissionService::getUserPermissions($currentUserId, true); +} + +$uuid = trim((string) ($id ?? '')); +$user = $uuid !== '' ? UserService::findByUuid($uuid) : null; +if (!$user) { + Flash::error('User not found', 'admin/users', 'user_not_found'); + Router::redirect('admin/users'); +} + +$userId = (int) ($user['id'] ?? 0); +$canViewUsers = PermissionService::userHas($currentUserId, PermissionService::USERS_VIEW); +$canUpdateUser = PermissionService::userHas($currentUserId, PermissionService::USERS_UPDATE); +$canUpdateSelf = PermissionService::userHas($currentUserId, PermissionService::USERS_SELF_UPDATE); +$canUpdateAssignments = PermissionService::userHas($currentUserId, PermissionService::USERS_UPDATE_ASSIGNMENTS); +$isOwnAccount = $currentUserId === $userId; +$canEditUser = $isOwnAccount ? ($canUpdateUser || $canUpdateSelf) : $canUpdateUser; +$canEditAssignments = $canEditUser && $canUpdateAssignments; +if (!$isOwnAccount && !TenantScopeService::canAccess('users', $userId, $currentUserId)) { + Router::redirect('error/forbidden'); + return; +} +if (!$canViewUsers && !$canEditUser) { + Router::redirect('error/forbidden'); + return; +} +$creatorId = (int) ($user['created_by'] ?? 0); +if ($creatorId > 0) { + $creator = UserService::findById($creatorId); + if ($creator) { + $creatorName = trim(($creator['first_name'] ?? '') . ' ' . ($creator['last_name'] ?? '')); + $user['created_by_label'] = $creatorName !== '' ? $creatorName : ($creator['email'] ?? ''); + $user['created_by_uuid'] = $creator['uuid'] ?? null; + } +} +$modifierId = (int) ($user['modified_by'] ?? 0); +if ($modifierId > 0) { + $modifier = UserService::findById($modifierId); + if ($modifier) { + $modifierName = trim(($modifier['first_name'] ?? '') . ' ' . ($modifier['last_name'] ?? '')); + $user['modified_by_label'] = $modifierName !== '' ? $modifierName : ($modifier['email'] ?? ''); + $user['modified_by_uuid'] = $modifier['uuid'] ?? null; + } +} +$activeChangedById = (int) ($user['active_changed_by'] ?? 0); +if ($activeChangedById > 0) { + $activeChanger = UserService::findById($activeChangedById); + if ($activeChanger) { + $activeChangerName = trim(($activeChanger['first_name'] ?? '') . ' ' . ($activeChanger['last_name'] ?? '')); + $user['active_changed_by_label'] = $activeChangerName !== '' ? $activeChangerName : ($activeChanger['email'] ?? ''); + $user['active_changed_by_uuid'] = $activeChanger['uuid'] ?? null; + } +} +$errors = []; +$form = $user; +// Users with tenants.update permission can see ALL tenants (to assign new tenants to users) +$canManageTenants = PermissionService::userHas($currentUserId, PermissionService::TENANTS_UPDATE); +$allowedTenantIds = $canManageTenants ? null : TenantScopeService::getUserTenantIds($currentUserId); + +$tenants = TenantService::list(); +if ($allowedTenantIds) { + $tenants = array_values(array_filter($tenants, static function (array $tenant) use ($allowedTenantIds): bool { + $tenantId = (int) ($tenant['id'] ?? 0); + return $tenantId > 0 && in_array($tenantId, $allowedTenantIds, true); + })); +} elseif (!$canManageTenants && TenantScopeService::isStrict()) { + $tenants = []; +} +$selectedTenantIds = UserTenantRepository::listTenantIdsByUserId($userId); +if ($allowedTenantIds) { + $selectedTenantIds = array_values(array_intersect($selectedTenantIds, $allowedTenantIds)); +} +$primaryTenantId = (int) ($user['primary_tenant_id'] ?? 0); +if (!$primaryTenantId && count($selectedTenantIds) === 1) { + $primaryTenantId = (int) $selectedTenantIds[0]; + $user['primary_tenant_id'] = $primaryTenantId; +} +$roles = RoleService::list(); +$selectedRoleIds = UserRoleRepository::listRoleIdsByUserId($userId); +$permissionRows = RolePermissionRepository::listPermissionsWithRolesByRoleIds($selectedRoleIds); +$departments = DepartmentService::listForUserAssignments($selectedTenantIds, []); +$selectedDepartmentIds = UserDepartmentRepository::listDepartmentIdsByUserId($userId); +if ($selectedDepartmentIds) { + $departments = DepartmentService::listForUserAssignments($selectedTenantIds, $selectedDepartmentIds); +} +// Keep initial $isOwnAccount/$canEditUser values for view permissions. + +if (isset($_POST['email'])) { + if (!$canEditUser) { + Router::redirect('error/forbidden'); + return; + } + $result = UserService::updateFromAdmin($userId, $_POST, $currentUserId); + $form = $result['form'] ?? $form; + $errors = $result['errors'] ?? []; + $tenantIds = UserService::normalizeIdInput($_POST['tenant_ids'] ?? []); + if ($allowedTenantIds) { + $tenantIds = array_values(array_intersect($tenantIds, $allowedTenantIds)); + } elseif (!$canManageTenants && TenantScopeService::isStrict()) { + $tenantIds = []; + } + $selectedTenantIds = $tenantIds; + $primaryTenantId = (int) ($_POST['primary_tenant_id'] ?? 0); + $selectedRoleIds = UserService::normalizeIdInput($_POST['role_ids'] ?? []); + $selectedDepartmentIds = UserService::normalizeIdInput($_POST['department_ids'] ?? []); + $departments = DepartmentService::listForUserAssignments($selectedTenantIds, $selectedDepartmentIds); + + if ($result['ok'] ?? false) { + if ($canEditAssignments) { + UserService::syncTenants($userId, $tenantIds); + UserService::syncRoles($userId, $selectedRoleIds); + UserService::syncDepartments($userId, $selectedDepartmentIds); + + // Update session if editing own account (tenant assignments changed) + if ($currentUserId === $userId) { + AuthService::loadTenantDataIntoSession($userId); + } + } + if ($currentUserId === $userId && isset($form['theme'])) { + $_SESSION['user']['theme'] = $form['theme'] ?: 'light'; + } + if ($currentUserId === $userId && isset($form['locale'])) { + $_SESSION['user']['locale'] = $form['locale']; + I18n::$locale = $form['locale']; + } + $action = (string) ($_POST['action'] ?? 'save'); + if ($action === 'save_close') { + Flash::success('User updated', 'admin/users', 'user_updated'); + Router::redirect('admin/users'); + } else { + Flash::success('User updated', "admin/users/edit/{$uuid}", 'user_updated'); + Router::redirect("admin/users/edit/{$uuid}"); + } + } +} + +Buffer::set('title', $isOwnAccount ? t('My account') : t('Edit user')); diff --git a/pages/admin/users/edit(default).phtml b/pages/admin/users/edit(default).phtml new file mode 100644 index 0000000..8f2e0e7 --- /dev/null +++ b/pages/admin/users/edit(default).phtml @@ -0,0 +1,312 @@ + $errors + * @var array $form + * @var array $user + */ + +use MintyPHP\Router; +use MintyPHP\Session; +use MintyPHP\Service\UserAvatarService; + +$values = $form ?? $user ?? []; +$avatarUuid = (string) ($values['uuid'] ?? ''); +$hasAvatar = $avatarUuid !== '' && UserAvatarService::hasAvatar($avatarUuid); +$currentUserId = (int) ($_SESSION['user']['id'] ?? 0); +$isOwnAccount = $currentUserId > 0 && $currentUserId === (int) ($values['id'] ?? 0); +$titleText = $isOwnAccount ? t('My account') : t('Edit user'); +$canViewUsers = can('users.view'); +$hideNavigation = $isOwnAccount && !$canViewUsers; + +?> + +
+
+ + + +
+

+ + + + +

+
+ + + + + + + + + + +
+
+ + +
+
+
    + +
  • + +
+
+
+ + + +
+ +
diff --git a/pages/admin/users/export().php b/pages/admin/users/export().php new file mode 100644 index 0000000..f0bbecf --- /dev/null +++ b/pages/admin/users/export().php @@ -0,0 +1,49 @@ + 5000) { + $limit = 5000; +} + +$result = UserService::listPaged([ + 'limit' => $limit, + 'offset' => 0, + 'search' => $search, + 'order' => $order, + 'dir' => $dir, + 'active' => $active, + 'created_from' => $createdFrom, + 'created_to' => $createdTo, + 'tenant' => $tenant, + 'roles' => $roles, + 'departments' => $departments, + 'tenantUserId' => $currentUserId, +]); + +$exportRows = $result['rows'] ?? []; +$exportFilename = 'users-' . date('Ymd-His') . '.csv'; diff --git a/pages/admin/users/export(none).phtml b/pages/admin/users/export(none).phtml new file mode 100644 index 0000000..d143521 --- /dev/null +++ b/pages/admin/users/export(none).phtml @@ -0,0 +1,75 @@ + 0 && $currentUserId === $userId; +$canEditUser = $isOwnAccount ? ($canUpdateUser || $canUpdateSelf) : $canUpdateUser; + +if (!$canEditUser) { + Router::redirect('error/forbidden'); + return; +} +if (!$isOwnAccount && !TenantScopeService::canAccess('users', $userId, $currentUserId)) { + Router::redirect('error/forbidden'); + return; +} + +RememberMeService::forgetAllForUser($userId); +Flash::success(t('Login tokens cleared'), "admin/users/edit/{$uuid}", 'tokens_cleared'); +Router::redirect("admin/users/edit/{$uuid}"); diff --git a/pages/admin/users/index().php b/pages/admin/users/index().php new file mode 100644 index 0000000..dcede09 --- /dev/null +++ b/pages/admin/users/index().php @@ -0,0 +1,48 @@ + 0) { + PermissionService::getUserPermissions($currentUserId); +} +$allowedTenantIds = TenantScopeService::getUserTenantIds($currentUserId); + +Buffer::set('title', t('Users')); +Buffer::set('grid_lang', json_encode(gridLang(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); +$csrfKey = Session::$csrfSessionKey; +$csrfToken = $_SESSION[$csrfKey] ?? ''; +Buffer::set( + 'grid_csrf', + json_encode(['key' => $csrfKey, 'token' => $csrfToken], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) +); + +$tenants = TenantService::list(); +if ($allowedTenantIds) { + $tenants = array_values(array_filter($tenants, static function (array $tenant) use ($allowedTenantIds): bool { + $tenantId = (int) ($tenant['id'] ?? 0); + return $tenantId > 0 && in_array($tenantId, $allowedTenantIds, true); + })); +} elseif (TenantScopeService::isStrict()) { + $tenants = []; +} +sortByDescription($tenants); + +$roles = RoleService::list(); +sortByDescription($roles); + +$departments = $allowedTenantIds ? DepartmentService::listByTenantIds($allowedTenantIds) : []; +if (!$allowedTenantIds && !TenantScopeService::isStrict()) { + $departments = DepartmentService::list(); +} +sortByDescription($departments); diff --git a/pages/admin/users/index(default).phtml b/pages/admin/users/index(default).phtml new file mode 100644 index 0000000..3b8258a --- /dev/null +++ b/pages/admin/users/index(default).phtml @@ -0,0 +1,389 @@ + 1; +?> + +
+

+
+ + + + + + + + + + + + + + + + + +
+
+ +
+ + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+
+
+ + + + + + diff --git a/pages/admin/users/send-access($id).php b/pages/admin/users/send-access($id).php new file mode 100644 index 0000000..956f60c --- /dev/null +++ b/pages/admin/users/send-access($id).php @@ -0,0 +1,73 @@ + 0 && $currentUserId === $userId; +$canEditUser = $isOwnAccount ? ($canUpdateUser || $canUpdateSelf) : $canUpdateUser; + +if (!$canEditUser) { + Router::redirect('error/forbidden'); + return; +} +if (!$isOwnAccount && !TenantScopeService::canAccess('users', $userId, $currentUserId)) { + Router::redirect('error/forbidden'); + return; +} + +$locale = $user['locale'] ?? (I18n::$locale ?? I18n::$defaultLocale); +$name = trim(($user['first_name'] ?? '') . ' ' . ($user['last_name'] ?? '')); +$isGerman = strpos((string) $locale, 'de') === 0; +$greeting = $isGerman ? 'Hallo' : 'Hello'; +if ($name !== '') { + $greeting .= ' ' . $name; +} +$greeting .= ','; + +$loginUrl = appUrl(Request::withLocale('login', $locale)); +$resetUrl = appUrl(Request::withLocale('password/forgot', $locale)); +$previousLocale = I18n::$locale ?? null; +I18n::$locale = $locale; +$subject = t('Your access details'); +I18n::$locale = $previousLocale; + +$vars = [ + 'app_name' => appTitle(), + 'app_logo_url' => appLogoUrlAbsolute(128), + 'imprint_url' => appUrl(Request::withLocale('imprint', $locale)), + 'privacy_url' => appUrl(Request::withLocale('privacy', $locale)), + 'greeting' => $greeting, + 'username' => (string) ($user['email'] ?? ''), + 'login_url' => $loginUrl, + 'reset_url' => $resetUrl, +]; + +$result = MailService::sendTemplate('access_info', $vars, (string) $user['email'], $subject, $locale); +if (!($result['ok'] ?? false)) { + Flash::error(t('Access email failed'), "admin/users/edit/{$uuid}", 'access_email_failed'); + Router::redirect("admin/users/edit/{$uuid}"); +} + +Flash::success(t('Access email sent'), "admin/users/edit/{$uuid}", 'access_email_sent'); +Router::redirect("admin/users/edit/{$uuid}"); diff --git a/pages/admin/users/switch-tenant().php b/pages/admin/users/switch-tenant().php new file mode 100644 index 0000000..837643d --- /dev/null +++ b/pages/admin/users/switch-tenant().php @@ -0,0 +1,83 @@ + false, 'error' => 'csrf']); + return; + } + Router::redirect('admin'); + return; +} + +$userId = (int) ($_SESSION['user']['id'] ?? 0); +if ($userId <= 0) { + http_response_code(401); + if (Request::wantsJson()) { + Router::json(['ok' => false, 'error' => 'unauthorized']); + return; + } + Router::redirect('login'); + return; +} + +// Get tenant_id from POST +$tenantId = (int) ($_POST['tenant_id'] ?? 0); + +if ($tenantId <= 0) { + http_response_code(400); + if (Request::wantsJson()) { + Router::json(['ok' => false, 'error' => 'invalid_tenant_id']); + return; + } + Router::redirect('admin'); + return; +} + +$result = UserService::setCurrentTenant($userId, $tenantId); +if (!($result['ok'] ?? false)) { + $error = $result['error'] ?? 'update_failed'; + http_response_code(400); + if (Request::wantsJson()) { + Router::json(['ok' => false, 'error' => $error]); + return; + } + Router::redirect('admin'); + return; +} + +// Update session with new current tenant +if (isset($_SESSION['user'])) { + $_SESSION['user']['current_tenant_id'] = $tenantId; +} + +// Update session with full tenant data +$_SESSION['current_tenant'] = $result['tenant'] ?? null; + +// Reload available tenants and departments +$_SESSION['available_tenants'] = UserService::getAvailableTenants($userId); +$_SESSION['available_departments_by_tenant'] = UserService::getAvailableDepartmentsByTenant($userId); + +if (Request::wantsJson()) { + Router::json([ + 'ok' => true, + 'tenant_id' => $tenantId, + 'tenant' => $result['tenant'] ?? null, + ]); + return; +} + +Router::redirect('admin'); diff --git a/pages/admin/users/theme().php b/pages/admin/users/theme().php new file mode 100644 index 0000000..682fc32 --- /dev/null +++ b/pages/admin/users/theme().php @@ -0,0 +1,66 @@ + false, 'error' => 'csrf']); + return; + } + Router::redirect('admin'); + return; +} + +$userId = (int) ($_SESSION['user']['id'] ?? 0); +if ($userId <= 0) { + http_response_code(401); + if (Request::wantsJson()) { + Router::json(['ok' => false, 'error' => 'unauthorized']); + return; + } + Router::redirect('login'); + return; +} + +$theme = trim((string) ($_POST['theme'] ?? '')); +if (!in_array($theme, ['light', 'dark'], true)) { + http_response_code(400); + if (Request::wantsJson()) { + Router::json(['ok' => false, 'error' => 'invalid_theme']); + return; + } + Router::redirect('admin'); + return; +} + +$updated = UserService::setTheme($userId, $theme); +if (!$updated) { + http_response_code(500); + if (Request::wantsJson()) { + Router::json(['ok' => false, 'error' => 'update_failed']); + return; + } + Router::redirect('admin'); + return; +} + +$_SESSION['user']['theme'] = $theme; + +if (Request::wantsJson()) { + Router::json(['ok' => true, 'theme' => $theme]); + return; +} + +Router::redirect('admin'); diff --git a/pages/auth/forgot().php b/pages/auth/forgot().php new file mode 100644 index 0000000..5427125 --- /dev/null +++ b/pages/auth/forgot().php @@ -0,0 +1,31 @@ + $errors + * @var string $email + */ + +use MintyPHP\Buffer; +use MintyPHP\Session; + +Buffer::set('title', t('Forgot password')); +?> + +
+
+ +
+

+

+
+
+
+ + +
+
    + +
  • + +
+
+ + + +
+
+

+ +

+
diff --git a/pages/auth/login().php b/pages/auth/login().php new file mode 100644 index 0000000..2a25fd7 --- /dev/null +++ b/pages/auth/login().php @@ -0,0 +1,19 @@ + + +
+
+ +
+

+

+
+
+
+ + +

+ +

+

+ +

+

+ ? +

+ +
+
+

?

+
diff --git a/pages/auth/logout().php b/pages/auth/logout().php new file mode 100644 index 0000000..30eb6fd --- /dev/null +++ b/pages/auth/logout().php @@ -0,0 +1,5 @@ + $firstName, + 'last_name' => $lastName, + 'email' => $email, + 'password' => $password, + 'password2' => $password2, + ]); + + if (!($result['ok'] ?? false)) { + $error = $result['error'] ?? t('User can not be registered'); + } else { + // Store email in session for verify-email page + $_SESSION['email_verification_email'] = $result['email'] ?? $email; + Flash::success(t('Registration successful! Please check your email for the verification code.'), 'verify-email', 'registration_success'); + Router::redirect('verify-email'); + } +} diff --git a/pages/auth/register(login).phtml b/pages/auth/register(login).phtml new file mode 100644 index 0000000..7888419 --- /dev/null +++ b/pages/auth/register(login).phtml @@ -0,0 +1,74 @@ + + +
+
+ +
+

+

+
+
+
+ + + +
+ + + + + + + +
+ +
    + +
  • + +
  • +
+
+
+ + +
+ + +
+
diff --git a/pages/auth/reset().php b/pages/auth/reset().php new file mode 100644 index 0000000..78dce4b --- /dev/null +++ b/pages/auth/reset().php @@ -0,0 +1,40 @@ + $errors + * @var array $passwordHints + * @var int $passwordMinLength + */ + +use MintyPHP\Buffer; +use MintyPHP\Session; + +Buffer::set('title', t('Reset password')); +?> + +
+
+ +
+

+

+
+
+
+
+ + + + + + + + +
+ +
    + +
  • + +
  • +
+
+ +
+ +
+
    + +
  • + +
+
+ + + +
+
+

+ +

+
diff --git a/pages/auth/verify().php b/pages/auth/verify().php new file mode 100644 index 0000000..85bb291 --- /dev/null +++ b/pages/auth/verify().php @@ -0,0 +1,35 @@ + $errors + * @var string $email + * @var string $code + */ + +use MintyPHP\Buffer; +use MintyPHP\Session; + +Buffer::set('title', t('Verify code')); +?> + +
+
+ +
+

+

+
+
+
+ + + +
+
    + +
  • + +
+
+ + + +
+
+

+ +  ·  + +

+
diff --git a/pages/auth/verify-email().php b/pages/auth/verify-email().php new file mode 100644 index 0000000..b5cd5fb --- /dev/null +++ b/pages/auth/verify-email().php @@ -0,0 +1,60 @@ + $errors + * @var string $email + * @var string $code + */ + +use MintyPHP\Buffer; +use MintyPHP\Session; + +Buffer::set('title', t('Verify email')); +?> + +
+
+ +
+

+

+
+
+
+ + + +
+
    + +
  • + +
+
+ + + +
+
+
+ + + + +
+

+ +

+
diff --git a/pages/branding/logo(none).phtml b/pages/branding/logo(none).phtml new file mode 100644 index 0000000..10a684c --- /dev/null +++ b/pages/branding/logo(none).phtml @@ -0,0 +1,19 @@ + +
+

+

+
+

+

+
+ +

+ + \ No newline at end of file diff --git a/pages/error/method_not_allowed(error).phtml b/pages/error/method_not_allowed(error).phtml new file mode 100644 index 0000000..a1da22d --- /dev/null +++ b/pages/error/method_not_allowed(error).phtml @@ -0,0 +1,6 @@ + +Submitting data using method GET is not allowed \ No newline at end of file diff --git a/pages/error/not_found(error).phtml b/pages/error/not_found(error).phtml new file mode 100644 index 0000000..f67ccf4 --- /dev/null +++ b/pages/error/not_found(error).phtml @@ -0,0 +1,21 @@ + +
+

+

+
+ +

:

+ + + diff --git a/pages/flash/dismiss($id).php b/pages/flash/dismiss($id).php new file mode 100644 index 0000000..cfff6fe --- /dev/null +++ b/pages/flash/dismiss($id).php @@ -0,0 +1,14 @@ + 0; +$returnPath = Request::path(); +if ($returnPath === '') { + $returnPath = 'page/' . $slug; +} +$requestedReturn = Request::safeReturnTarget((string) ($_POST['return'] ?? '')); +if ($requestedReturn !== '') { + $returnPath = $requestedReturn; +} +$formAction = '/' . ltrim($returnPath, '/'); +$wantsJson = Request::wantsJson(); + +$sessionEdit = false; +if (!empty($_SESSION['page_edit_mode']) && is_array($_SESSION['page_edit_mode'])) { + $sessionEdit = !empty($_SESSION['page_edit_mode'][$slug]); + unset($_SESSION['page_edit_mode'][$slug]); +} + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + if (!$canEdit || $notFound) { + http_response_code(403); + Flash::error(t('You are not allowed to edit this page'), $returnPath, 'page_forbidden'); + if ($wantsJson) { + Router::json(['ok' => false, 'error' => 'forbidden', 'redirect' => $returnPath]); + } + Router::redirect($returnPath); + } + + if (!Session::checkCsrfToken()) { + Flash::error(t('Form expired, please try again'), $returnPath, 'page_csrf'); + if ($wantsJson) { + Router::json(['ok' => false, 'error' => 'csrf', 'redirect' => $returnPath]); + } + Router::redirect($returnPath); + } + + $content = (string) ($_POST['content'] ?? ''); + $result = PageService::updateContentBySlug($slug, $content, $currentUserId, I18n::$locale ?? null); + + if (!($result['ok'] ?? false)) { + $errors = $result['errors'] ?? [t('Page can not be updated')]; + Flash::error((string) $errors[0], $returnPath, 'page_update_failed'); + if ($wantsJson) { + $_SESSION['page_edit_mode'][$slug] = 1; + Router::json(['ok' => false, 'error' => 'invalid', 'redirect' => $returnPath]); + } + $_SESSION['page_edit_mode'][$slug] = 1; + Router::redirect($returnPath); + } + + Flash::success(t('Page updated'), $returnPath, 'page_updated'); + if ($wantsJson) { + $_SESSION['page_edit_mode'][$slug] = 1; + Router::json(['ok' => true, 'redirect' => $returnPath]); + } + $_SESSION['page_edit_mode'][$slug] = 1; + Router::redirect($returnPath); +} + +$contentJson = ''; +if (is_array($pageContent) && isset($pageContent['content'])) { + $contentJson = (string) $pageContent['content']; +} +if ($contentJson === '') { + $contentJson = json_encode(['blocks' => []], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); +} + +$editMode = $canEdit && (($sessionEdit === true) || (($_GET['edit'] ?? '') === '1')); +$locales = defined('APP_LOCALES') ? APP_LOCALES : [I18n::$defaultLocale]; +$currentLocale = I18n::$locale ?? (I18n::$defaultLocale ?? 'de'); diff --git a/pages/page/index(default).phtml b/pages/page/index(default).phtml new file mode 100644 index 0000000..365f240 --- /dev/null +++ b/pages/page/index(default).phtml @@ -0,0 +1,113 @@ + +
+
+ +

+ +
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +
+ + + +
diff --git a/pages/search/data().php b/pages/search/data().php new file mode 100644 index 0000000..faf9aee --- /dev/null +++ b/pages/search/data().php @@ -0,0 +1,121 @@ + 0) { + PermissionService::getUserPermissions($userId); +} + +$query = trim((string) ($_GET['search'] ?? '')); +if ($query === '') { + Router::json(['data' => [], 'total' => 0]); +} + +$limit = (int) ($_GET['limit'] ?? 10); +if ($limit < 1) { + $limit = 10; +} elseif ($limit > 100) { + $limit = 100; +} +$offset = (int) ($_GET['offset'] ?? 0); +if ($offset < 0) { + $offset = 0; +} + +$locale = I18n::$locale ?? (I18n::$defaultLocale ?? 'de'); +$tenantIds = $userId > 0 ? UserTenantRepository::listTenantIdsByUserId($userId) : []; +$tenantScoped = !empty($tenantIds); + +$tenantScopeFilters = SearchConfig::tenantScopeFilters(); +$resources = SearchConfig::resources($query, $locale); +$items = []; + +foreach ($resources as $resource) { + $key = (string) ($resource['key'] ?? ''); + if ($key === '') { + continue; + } + + $perm = (string) ($resource['permission'] ?? ''); + if ($perm !== '' && !PermissionService::userHas($userId, $perm)) { + continue; + } + + $tenantFilter = $tenantScopeFilters[$key] ?? ''; + $isTenantScoped = $tenantFilter !== ''; + if ($isTenantScoped && !$tenantScoped) { + continue; + } + + $sql = $resource['resultSql'] ?? ''; + if ($sql === '') { + continue; + } + $sql = str_replace('{{tenantFilter}}', $isTenantScoped ? $tenantFilter : '', $sql); + $params = $resource['resultParams'] ?? []; + if ($isTenantScoped && strpos($sql, '???') !== false) { + $params[] = $tenantIds; + } + + $rows = DB::select($sql, ...$params); + foreach ($rows as $row) { + $data = $row; + if (is_array($row) && count($row) === 1) { + $data = reset($row); + } + $data = is_array($data) ? $data : []; + $mapped = SearchConfig::mapResultItem($key, (string) ($resource['label'] ?? ''), $data); + if ($mapped !== null) { + $items[] = $mapped; + } + } +} + +$queryLower = mb_strtolower($query); +$scoreItem = static function (array $item) use ($queryLower): int { + $title = mb_strtolower((string) ($item['title'] ?? '')); + $description = mb_strtolower((string) ($item['description'] ?? '')); + if ($title === $queryLower) { + return 400; + } + if ($title !== '' && strpos($title, $queryLower) === 0) { + return 300; + } + if ($title !== '' && strpos($title, $queryLower) !== false) { + return 200; + } + if ($description !== '' && strpos($description, $queryLower) !== false) { + return 100; + } + return 0; +}; + +usort($items, static function (array $a, array $b) use ($scoreItem): int { + $scoreA = $scoreItem($a); + $scoreB = $scoreItem($b); + if ($scoreA !== $scoreB) { + return $scoreB <=> $scoreA; + } + $title = strcmp((string) ($a['title'] ?? ''), (string) ($b['title'] ?? '')); + if ($title !== 0) { + return $title; + } + return strcmp((string) ($a['type'] ?? ''), (string) ($b['type'] ?? '')); +}); + +$total = count($items); +$items = array_slice($items, $offset, $limit); + +Router::json([ + 'data' => $items, + 'total' => $total, +]); diff --git a/pages/search/index().php b/pages/search/index().php new file mode 100644 index 0000000..b52b679 --- /dev/null +++ b/pages/search/index().php @@ -0,0 +1,17 @@ + $csrfKey, 'token' => $csrfToken], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) +); diff --git a/pages/search/index(default).phtml b/pages/search/index(default).phtml new file mode 100644 index 0000000..97747a4 --- /dev/null +++ b/pages/search/index(default).phtml @@ -0,0 +1,86 @@ + + +
+

+
+
+ +
+
+
+
+ + + + diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..ae4eb5f --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,13 @@ +parameters: + level: 5 + phpVersion: 80500 + scanFiles: + - web/index.php + paths: + - config + - lib + - pages + - templates + fileExtensions: + - php + - phtml diff --git a/storage/.gitkeep b/storage/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/storage/.gitkeep @@ -0,0 +1 @@ + diff --git a/templates/.DS_Store b/templates/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c09e888ec5dd55135eba34c7de4e4357984d5c88 GIT binary patch literal 8196 zcmeHMTWl0n7(U;$lvx<*aFZ50uxTMuq_u#gl}oa1x5~YhZSA&J%I?lc2WMxNo!KoF zG#e9MR4_h4yhWe95O`2gMCsx*7SNKQ{;PvJ{|G>| zlGuKudpZaBHqn5_0$LK(H>Ekn=>dT$f+GfmImx43ooFneB|(KbgD__ZJR>-v!1qpe zQD2=QCTQ4)5eOqt9syqatC+#EEXB<7^Ly=v>*ZM|9#30Nn)vdk%MYL2cI<3>xsLvq zI=PWa-w8xg%PdE$$TN>tk}6+IX@L7I({YQPVm%d!bj~teuchS+NEMYcs%FZOS+kW} zwEpD4pfWV9&MTV6Xm`#t9oxO%$h$;`)oORd8Qqd`?4G>A<^37QDr9YUSe=_mS($>B z@{D%NN|=ur#H)5QdB?JP9M|O23?x0{fX8KJqU50KB zCb{H>3+SOHH$+a&S+sQ7il#NK8)IEtcHDQNTAe#@zOqmmGJRw`{+5mgs{+LZNLe^JCgqHYt+P0B(oN#BjK^oVXm@Y=ObZ8vwjJ>`1cIm6~l zIwxfJkZjN$N#%|1QQOD|E80q2e@ltajk;!v@onarb&)HY(d-e11V?cUFW^PIgqQI;-oTqUjkobW&f#Nxg7dh9ukj7O#ZUMhf8eq-Ls}%& zNVQVEv`T7{nx$5$Owb&l3=7jBch%xtvHj>D1II zS9kB`EnAiC|C*G$ILA-21q*Lo6kWdZ&b!(+wO;|FK<@-#C#Qjr{cAGD$G(q^>u`I) z&qig*(uwrDnvfzv`zUFQ12WHDb!MR5uuP_;QD+3h6^%69rdEkzT~o76393r|P^nw9 zHbQBrRs_SQRvJPKlnomrl#ps=FkBL&A@c`yb@48m=A0`3U1-0^F0t>}&+IaxeGcZM z2DhVyFy4X9*y*D@fj;cUF!mq~9a-3Lu%GaL2#?}1l<+vA{VBrx(|88Y;yFA|n12PY z;x(MWNkaTPco*;C1AK@xI2&O9OG5q+_))<23YvFZi)Q>f6`Cg(w4>+eH+skYf>wt5 ztaG)f-AwPA!p6q=63XT(Ci1rB*n3Gfk$GHinp=hNSHph;blv#-|1_^EbQeY-jKFk8 z0G07Xyn{U6=v~Cm+EKdp(8U|qD+%hGQ0E`ViTcNJqF4Sfr28nTa+_E{OM()I+O&TN WnCd5YSpUQNPgs<1R@eVy_5V-n+>n?6 literal 0 HcmV?d00001 diff --git a/templates/default.phtml b/templates/default.phtml new file mode 100644 index 0000000..1c87117 --- /dev/null +++ b/templates/default.phtml @@ -0,0 +1,104 @@ + + +style=""> + + + + + <?php e($defaultTitle); ?> <?php if (Buffer::get('title')) + ; ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ + + +
+ + +
+
+ +
+
+ + + + + + + diff --git a/templates/emails/de/access_info.html b/templates/emails/de/access_info.html new file mode 100644 index 0000000..dd060ac --- /dev/null +++ b/templates/emails/de/access_info.html @@ -0,0 +1,18 @@ + + + + {{email_header}} +

{{greeting}}

+

dein Zugang wurde eingerichtet.

+

Benutzername: {{username}}

+

+ Zur Anmeldung +

+

+ Falls du dein Passwort nicht kennst, kannst du es hier zurücksetzen: + Passwort vergessen +

+

Viele Grüße
{{app_name}}

+ {{email_footer}} + + diff --git a/templates/emails/de/access_info.txt b/templates/emails/de/access_info.txt new file mode 100644 index 0000000..f900cd2 --- /dev/null +++ b/templates/emails/de/access_info.txt @@ -0,0 +1,17 @@ +{{email_header_text}} + +{{greeting}} + +dein Zugang wurde eingerichtet. + +Benutzername: {{username}} + +Zur Anmeldung: +{{login_url}} + +Falls du dein Passwort nicht kennst, kannst du es hier zurücksetzen: +{{reset_url}} + +Viele Grüße +{{app_name}} +{{email_footer_text}} diff --git a/templates/emails/de/email_verification.html b/templates/emails/de/email_verification.html new file mode 100644 index 0000000..4719398 --- /dev/null +++ b/templates/emails/de/email_verification.html @@ -0,0 +1,15 @@ + + + + {{email_header}} +

{{greeting}}

+

Vielen Dank für deine Registrierung! Bitte bestätige deine E-Mail-Adresse mit folgendem Code:

+

{{code}}

+

Dieser Code ist {{expires_minutes}} Minuten gültig.

+

Du kannst den Code hier eingeben:

+

{{verify_url}}

+

Wenn du dich nicht registriert hast, kannst du diese E-Mail ignorieren.

+

Viele Grüße
{{app_name}}

+ {{email_footer}} + + diff --git a/templates/emails/de/email_verification.txt b/templates/emails/de/email_verification.txt new file mode 100644 index 0000000..7ccdd1b --- /dev/null +++ b/templates/emails/de/email_verification.txt @@ -0,0 +1,18 @@ +{{email_header_text}} + +{{greeting}} + +Vielen Dank für deine Registrierung! Bitte bestätige deine E-Mail-Adresse mit folgendem Code: + +Dein Code: {{code}} + +Dieser Code ist {{expires_minutes}} Minuten gültig. + +Code hier eingeben: +{{verify_url}} + +Wenn du dich nicht registriert hast, kannst du diese E-Mail ignorieren. + +Viele Grüße +{{app_name}} +{{email_footer_text}} diff --git a/templates/emails/de/partials/footer.html b/templates/emails/de/partials/footer.html new file mode 100644 index 0000000..24390f4 --- /dev/null +++ b/templates/emails/de/partials/footer.html @@ -0,0 +1,16 @@ + + + + +
+ Impressum +  ·  + Datenschutz +
+ {{app_name}} · Diese E-Mail wurde automatisch erstellt. + + + + + + diff --git a/templates/emails/de/partials/footer.txt b/templates/emails/de/partials/footer.txt new file mode 100644 index 0000000..6864a0a --- /dev/null +++ b/templates/emails/de/partials/footer.txt @@ -0,0 +1,2 @@ +--- +{{app_name}} · Diese E-Mail wurde automatisch erstellt. diff --git a/templates/emails/de/partials/header.html b/templates/emails/de/partials/header.html new file mode 100644 index 0000000..e11502d --- /dev/null +++ b/templates/emails/de/partials/header.html @@ -0,0 +1,14 @@ + + + + +
+ + + + + + + + + + +
+
+ {{app_name}} + {{app_name}} +
+
diff --git a/templates/emails/de/partials/header.txt b/templates/emails/de/partials/header.txt new file mode 100644 index 0000000..8197968 --- /dev/null +++ b/templates/emails/de/partials/header.txt @@ -0,0 +1,2 @@ +{{app_name}} +================= diff --git a/templates/emails/de/reset_code.html b/templates/emails/de/reset_code.html new file mode 100644 index 0000000..9cd9409 --- /dev/null +++ b/templates/emails/de/reset_code.html @@ -0,0 +1,15 @@ + + + + {{email_header}} +

{{greeting}}

+

du hast einen Code zum Zurücksetzen deines Passworts angefordert.

+

{{code}}

+

Dieser Code ist {{expires_minutes}} Minuten gültig.

+

Du kannst den Code hier eingeben:

+

{{verify_url}}

+

Wenn du diese Anfrage nicht gestellt hast, kannst du diese E-Mail ignorieren.

+

Viele Grüße
{{app_name}}

+ {{email_footer}} + + diff --git a/templates/emails/de/reset_code.txt b/templates/emails/de/reset_code.txt new file mode 100644 index 0000000..dd1886e --- /dev/null +++ b/templates/emails/de/reset_code.txt @@ -0,0 +1,18 @@ +{{email_header_text}} + +{{greeting}} + +du hast einen Code zum Zurücksetzen deines Passworts angefordert. + +Dein Code: {{code}} + +Dieser Code ist {{expires_minutes}} Minuten gültig. + +Code hier eingeben: +{{verify_url}} + +Wenn du diese Anfrage nicht gestellt hast, kannst du diese E-Mail ignorieren. + +Viele Grüße +{{app_name}} +{{email_footer_text}} diff --git a/templates/emails/en/access_info.html b/templates/emails/en/access_info.html new file mode 100644 index 0000000..631ef40 --- /dev/null +++ b/templates/emails/en/access_info.html @@ -0,0 +1,18 @@ + + + + {{email_header}} +

{{greeting}}

+

Your access has been set up.

+

Username: {{username}}

+

+ Go to login +

+

+ If you do not know your password, you can reset it here: + Forgot password +

+

Best regards
{{app_name}}

+ {{email_footer}} + + diff --git a/templates/emails/en/access_info.txt b/templates/emails/en/access_info.txt new file mode 100644 index 0000000..c3a9b47 --- /dev/null +++ b/templates/emails/en/access_info.txt @@ -0,0 +1,17 @@ +{{email_header_text}} + +{{greeting}} + +Your access has been set up. + +Username: {{username}} + +Go to login: +{{login_url}} + +If you do not know your password, you can reset it here: +{{reset_url}} + +Best regards +{{app_name}} +{{email_footer_text}} diff --git a/templates/emails/en/email_verification.html b/templates/emails/en/email_verification.html new file mode 100644 index 0000000..4a02360 --- /dev/null +++ b/templates/emails/en/email_verification.html @@ -0,0 +1,15 @@ + + + + {{email_header}} +

{{greeting}}

+

Thank you for registering! Please confirm your email address with the following code:

+

{{code}}

+

This code is valid for {{expires_minutes}} minutes.

+

You can enter the code here:

+

{{verify_url}}

+

If you did not register, you can ignore this email.

+

Best regards
{{app_name}}

+ {{email_footer}} + + diff --git a/templates/emails/en/email_verification.txt b/templates/emails/en/email_verification.txt new file mode 100644 index 0000000..903dce2 --- /dev/null +++ b/templates/emails/en/email_verification.txt @@ -0,0 +1,18 @@ +{{email_header_text}} + +{{greeting}} + +Thank you for registering! Please confirm your email address with the following code: + +Your code: {{code}} + +This code is valid for {{expires_minutes}} minutes. + +Enter the code here: +{{verify_url}} + +If you did not register, you can ignore this email. + +Best regards +{{app_name}} +{{email_footer_text}} diff --git a/templates/emails/en/partials/footer.html b/templates/emails/en/partials/footer.html new file mode 100644 index 0000000..ea554b5 --- /dev/null +++ b/templates/emails/en/partials/footer.html @@ -0,0 +1,16 @@ +
+
+ Imprint +  ·  + Privacy +
+ {{app_name}} · This email was generated automatically. +
+
diff --git a/templates/emails/en/partials/footer.txt b/templates/emails/en/partials/footer.txt new file mode 100644 index 0000000..928429c --- /dev/null +++ b/templates/emails/en/partials/footer.txt @@ -0,0 +1,2 @@ +--- +{{app_name}} · This email was generated automatically. diff --git a/templates/emails/en/partials/header.html b/templates/emails/en/partials/header.html new file mode 100644 index 0000000..e11502d --- /dev/null +++ b/templates/emails/en/partials/header.html @@ -0,0 +1,14 @@ + + +
+ + + + + +
+
+ {{app_name}} + {{app_name}} +
+
diff --git a/templates/emails/en/partials/header.txt b/templates/emails/en/partials/header.txt new file mode 100644 index 0000000..8197968 --- /dev/null +++ b/templates/emails/en/partials/header.txt @@ -0,0 +1,2 @@ +{{app_name}} +================= diff --git a/templates/emails/en/reset_code.html b/templates/emails/en/reset_code.html new file mode 100644 index 0000000..1d68e71 --- /dev/null +++ b/templates/emails/en/reset_code.html @@ -0,0 +1,15 @@ + + + + {{email_header}} +

{{greeting}}

+

You requested a password reset code.

+

{{code}}

+

This code is valid for {{expires_minutes}} minutes.

+

You can enter the code here:

+

{{verify_url}}

+

If you did not request this, you can ignore this email.

+

Best regards
{{app_name}}

+ {{email_footer}} + + diff --git a/templates/emails/en/reset_code.txt b/templates/emails/en/reset_code.txt new file mode 100644 index 0000000..b5d7f88 --- /dev/null +++ b/templates/emails/en/reset_code.txt @@ -0,0 +1,18 @@ +{{email_header_text}} + +{{greeting}} + +You requested a password reset code. + +Your code: {{code}} + +This code is valid for {{expires_minutes}} minutes. + +Enter the code here: +{{verify_url}} + +If you did not request this, you can ignore this email. + +Best regards +{{app_name}} +{{email_footer_text}} diff --git a/templates/error.phtml b/templates/error.phtml new file mode 100644 index 0000000..5ebf3d7 --- /dev/null +++ b/templates/error.phtml @@ -0,0 +1,13 @@ + +

ERROR:

+ + +style="" > + + + + + <?php e($defaultTitle); ?> <?php if (Buffer::get('title')); ?> + + + + + + + + + + + + + + + + + + + +
+
+ + +
+
+ + + + + diff --git a/templates/partials/.DS_Store b/templates/partials/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..0676a32d725c5bfbbaabbe436ccd947ccfc99fc5 GIT binary patch literal 6148 zcmeH~O-}+b5QeA70rkSsgr}qH%3I(nub~U}Id$NN zV-t34BtQ0VRSs^eby*O9ktbObEzli#$C{DUeKS&(Bd6=AZsaObf33iPDJY} zvc^~o>Tk@yl!48u@rB%xJ+&t&2wcq-;v^IL+YeBvpHb+AW_u_C{3wm#L$qPmVg ze)Sw)*L_;o-gO`2Ciyct1I~am@XHKvW~;Q$Bf545oB?NG!+?GtGMZwZu#RY-4wPL1 zz$R`JY`sfpO_nfESVts+gjfp3(vYqgA(rFMQeK|0ju^`&*vyQRW)A6w5^Q$-nWam} zBf545oPliyPGYyM=l}KL`~P;4_nZM|;9oHin!U$fmnEgMb!TyU)@HO + diff --git a/templates/partials/app-aside.phtml b/templates/partials/app-aside.phtml new file mode 100644 index 0000000..834c42f --- /dev/null +++ b/templates/partials/app-aside.phtml @@ -0,0 +1,399 @@ + '', + 'visible' => $hasOrganization, + 'items' => [ + [ + 'label' => t('Tenants'), + 'path' => 'admin/tenants', + 'active' => navActive('admin/tenants', true), + 'visible' => $canViewTenants, + 'withTenant' => false, + ], + [ + 'label' => t('Departments'), + 'path' => 'admin/departments', + 'active' => navActive('admin/departments', true), + 'visible' => $canViewDepartments, + 'withTenant' => true, + ], + [ + 'label' => t('Users'), + 'path' => 'admin/users', + 'active' => navActive('admin/users', true), + 'visible' => $canViewUsers, + 'withTenant' => true, + ], + ], + ], + [ + 'label' => t('Roles & permissions'), + 'visible' => $hasUsersSection, + 'items' => [ + [ + 'label' => t('Roles'), + 'path' => 'admin/roles', + 'active' => navActive('admin/roles', true), + 'visible' => $canViewRoles, + 'withTenant' => false, + ], + [ + 'label' => t('Permissions'), + 'path' => 'admin/permissions', + 'active' => navActive('admin/permissions', true), + 'visible' => $canViewPermissions, + 'withTenant' => false, + ], + ], + ], + [ + 'label' => t('System'), + 'visible' => $hasSystemSection, + 'items' => [ + [ + 'label' => t('Statistics'), + 'path' => 'admin/stats', + 'active' => navActive('admin/stats', true), + 'visible' => $canViewStats, + 'withTenant' => false, + ], + [ + 'label' => t('Mail logs'), + 'path' => 'admin/mail-log', + 'active' => navActive('admin/mail-log', true), + 'visible' => $canViewMailLog, + 'withTenant' => false, + ], + [ + 'label' => t('Settings'), + 'path' => 'admin/settings', + 'active' => navActive('admin/settings', true), + 'visible' => $canViewSettings, + 'withTenant' => false, + ], + ], + ], +]; + +// Render helper for admin sections +$renderNavSection = static function (array $section, string $tenantQueryParam): void { + if (empty($section['visible'])) { + return; + } + $items = $section['items'] ?? []; + $items = array_values(array_filter($items, static fn ($item) => !empty($item['visible']))); + if (!$items) { + return; + } + ?> + + + + + '', 'aria' => '']; + ?> +
  • + > + + +
  • + + 1 && !empty($currentTenant['uuid'])) { + $tenantQueryParam = '?tenant=' . urlencode($currentTenant['uuid']); +} + +// Tenant logo display (without switcher - switcher is now in topbar) +$tenantUuid = $currentTenant['uuid'] ?? ''; +$tenantName = $currentTenant['description'] ?? ''; +$hasTenantAvatar = $tenantUuid && TenantAvatarService::hasAvatar($tenantUuid); +$addressBookUrl = lurl('address-book'); +$activeAddressTenants = array_filter(array_map('trim', explode(',', (string) ($_GET['tenants'] ?? '')))); +$activeAddressDepartments = array_filter(array_map('intval', explode(',', (string) ($_GET['departments'] ?? '')))); +$peopleGroups = $_SESSION['available_departments_by_tenant'] ?? []; +?> + diff --git a/templates/partials/app-flash.phtml b/templates/partials/app-flash.phtml new file mode 100644 index 0000000..a6eed46 --- /dev/null +++ b/templates/partials/app-flash.phtml @@ -0,0 +1,34 @@ + 5000, + 'info' => 6000, + 'warning' => 7000, + 'error' => 0, +]; + +?> +
    + + + +
    + +
    + + + +
    +
    + +
    diff --git a/templates/partials/app-footer.phtml b/templates/partials/app-footer.phtml new file mode 100644 index 0000000..5d50d45 --- /dev/null +++ b/templates/partials/app-footer.phtml @@ -0,0 +1,24 @@ + diff --git a/templates/partials/app-language-switcher.phtml b/templates/partials/app-language-switcher.phtml new file mode 100644 index 0000000..d269ffe --- /dev/null +++ b/templates/partials/app-language-switcher.phtml @@ -0,0 +1,66 @@ + + + + + + + + + + + diff --git a/templates/partials/app-tile.phtml b/templates/partials/app-tile.phtml new file mode 100644 index 0000000..467b73f --- /dev/null +++ b/templates/partials/app-tile.phtml @@ -0,0 +1,44 @@ + +style=""> + + + + + + + + + + + diff --git a/templates/partials/app-topbar.phtml b/templates/partials/app-topbar.phtml new file mode 100644 index 0000000..15aa1a8 --- /dev/null +++ b/templates/partials/app-topbar.phtml @@ -0,0 +1,106 @@ + +
    + +
    diff --git a/tests/.DS_Store b/tests/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ea19a3e1b5ea142a30180860737ea264b584566b GIT binary patch literal 6148 zcmeHKJ5Izf5FIZ;1ktQSLupac?G4N-Nc6b?+K*tRjS?Z2Iv1cpTmmFcLBTy}xCU=L zqa`N0lnB90G=9!}Z09-3#6;xAtJ#QXNJKf5aj=hOgRq~qCj+&x)A1O~%TYP4tELxe zhTqBn?_Eacbc3r&_b+?t`l`ApCd+yPTfRDezJGjpJx%?yZ~e_x_ub(4jrORdIbG8& zEoe&fboSl%enfW-Z+9n$PqKzD<5czMO14LBSP!qs#27FJjDi2a0BSZ%ejsSAF<=ZB z18WBO`{1FBL9rE#pAIzf2ms7rj)H#tw*z`M0E1#H2n)nXDo|3L9xserverBackup = $_SERVER; + Router::$baseUrl = '/'; + } + + protected function tearDown(): void + { + $_SERVER = $this->serverBackup; + parent::tearDown(); + } + + public function testPathWithQuery(): void + { + $_SERVER['REQUEST_URI'] = '/admin/users?active=1'; + + $this->assertSame('admin/users?active=1', Request::pathWithQuery()); + } + + public function testSafeReturnTargetPrefersRelativeParam(): void + { + $this->assertSame( + 'admin/users?active=1', + Request::safeReturnTarget('admin/users?active=1') + ); + } + + public function testWantsJsonFromAcceptHeader(): void + { + $_SERVER['HTTP_ACCEPT'] = 'application/json'; + + $this->assertTrue(Request::wantsJson()); + } + + public function testWantsJsonFalseForHtml(): void + { + $_SERVER['HTTP_ACCEPT'] = 'text/html'; + + $this->assertFalse(Request::wantsJson()); + } +} diff --git a/tests/Service/UserServicePasswordTest.php b/tests/Service/UserServicePasswordTest.php new file mode 100644 index 0000000..3257939 --- /dev/null +++ b/tests/Service/UserServicePasswordTest.php @@ -0,0 +1,49 @@ +invoke(null, $password, $password2, $required, $email); + } + + public function testRequiresPasswordWhenRequired(): void + { + $errors = $this->validate('', '', true, 'test@example.com'); + $this->assertNotEmpty($errors); + } + + public function testRejectsMismatch(): void + { + $errors = $this->validate('Abcd1234$efg', 'Abcd1234$xxx', true, 'test@example.com'); + $this->assertNotEmpty($errors); + } + + public function testAcceptsStrongPassword(): void + { + $errors = $this->validate('StrongPass1!', 'StrongPass1!', true, 'test@example.com'); + $this->assertSame([], $errors); + } + + public function testRejectsPasswordContainingEmail(): void + { + $errors = $this->validate('test@example.comA1!', 'test@example.comA1!', true, 'test@example.com'); + $this->assertNotEmpty($errors); + } +} diff --git a/web/.DS_Store b/web/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..3c9725fc7f55466b9133bdaf6e49c9e890f40584 GIT binary patch literal 6148 zcmeHLyGjE=6upyVHE7|Z(n8oDu&}mSCH8`)jmBuA7+2z>u~`tY5JW*l1n~pX*w_ey zl_KH?*r@;D2k5yoqnX(?*onx!FmpEdF=ytGoymlV)c8hags7K@ifD|5E_B}*$GK%J zXFUTzrN^i&S4XDi;`(YPR~({%DDd|b;CDBmGBs$HRw(uU7PkCoJua2X%W)ar;`31d z)7#&-6442p*+pe8m)PIM{e}26>)i+Th|+>N1E5x)#DatHtO-^Cz-F4 z7O>h)S_E%QD;_Uh1=$Rj|9*FWd*@j5r^a#T(LT$Yj|xGC^)FJLs@^<;^I9w7@)IS~ zFPFEhyRCD1vr&&PxIr1^Xep&Oy$^r-U9O9sm%jBAy;fc0GNof4kGf!<4rn~j-zuow z@K!ha_?nKpyg}n(aL;J$jp6dQ%kk#XJm7hVeXjt{Y_?*zLFq*SQ9u;ASs2ReNP02biZhG%`I14DKIBa4Yacwowu0!^v1R}5v!;SX(IWHB*l%1LQvjANOV zy`d=04u7cANks;w7X?HCUxB>&*vsetMEm={UnHMI0a4&zDWD3asnR%>WY5;j;`po$ t(Pq%tI4?1%OVHWlSU>Pl%>OHBLoDP6U}P~d2oFqt2xu9k69s-%fe%;Oy=nje literal 0 HcmV?d00001 diff --git a/web/.htaccess b/web/.htaccess new file mode 100644 index 0000000..6f3a18a --- /dev/null +++ b/web/.htaccess @@ -0,0 +1,9 @@ +php_flag display_startup_errors on +php_flag display_errors on + + + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^(.*)$ index.php [QSA,L] + diff --git a/web/brand/logo.svg b/web/brand/logo.svg new file mode 100644 index 0000000..973159c --- /dev/null +++ b/web/brand/logo.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/css/base/variables.css b/web/css/base/variables.css new file mode 100644 index 0000000..9406177 --- /dev/null +++ b/web/css/base/variables.css @@ -0,0 +1,713 @@ +@charset "UTF-8"; + +:host, +:root { + --app-font-family-emoji: + "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --app-font-family-sans-serif: + system-ui, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, Helvetica, Arial, + "Helvetica Neue", sans-serif, var(--app-font-family-emoji); + --app-font-family-monospace: + ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", + monospace, var(--app-font-family-emoji); + --app-font-family: var(--app-font-family-sans-serif); + --app-line-height: 1.5; + --app-font-weight: 400; + --app-font-size: 100%; + --app-text-underline-offset: 0.1rem; + --app-border-radius: 0.5rem; + --app-border-width: 0.0625rem; + --app-outline-width: 0.125rem; + --app-transition: 0.2s ease-in-out; + --app-spacing: 1rem; + --app-typography-spacing-vertical: 1rem; + --app-block-spacing-vertical: 1.5rem; + --app-block-spacing-horizontal: 1.5rem; + --app-grid-column-gap: var(--app-spacing); + --app-grid-row-gap: var(--app-spacing); + --app-flex-gap: var(--app-spacing); + --app-form-element-spacing-vertical: .5rem; + --app-form-element-spacing-horizontal: .7rem; + --app-button-padding-vertical: var(--app-form-element-spacing-vertical); + --app-button-padding-horizontal: var(--app-form-element-spacing-horizontal); + --app-button-padding-vertical-small: calc( + var(--app-form-element-spacing-vertical) * 0.3 + ); + --app-button-padding-horizontal-small: calc( + var(--app-form-element-spacing-horizontal) * 0.5 + ); + --app-group-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --app-group-box-shadow-focus-with-button: 0 0 0 var(--app-outline-width) + var(--app-primary-focus); + --app-group-box-shadow-focus-with-input: 0 0 0 0.0625rem + var(--app-form-element-border-color); + --app-modal-overlay-backdrop-filter: blur(0.375rem); + --app-nav-element-spacing-vertical: 1rem; + --app-nav-element-spacing-horizontal: 0.5rem; + --app-nav-link-spacing-vertical: 0.5rem; + --app-nav-link-spacing-horizontal: 0.5rem; + --app-nav-breadcrumb-divider: ">"; + --app-primary-h-base: 180.75; + --app-primary-s-base: 37.38%; + --app-primary-l-base: 58.04%; + --app-secondary-h-base: 223; + --app-secondary-s-base: 19%; + --app-secondary-l-base: 45%; + --app-badge-background-color: coral; +} + +/* Icons */ +:host, +:root { + --app-icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E"); + --app-icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E"); + --app-icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); + --app-icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E"); + --app-icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E"); + --app-icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E"); + --app-icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E"); + --app-icon-loading: url("data:image/svg+xml,%3Csvg fill='none' height='24' width='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg' %3E%3Cstyle%3E g %7B animation: rotate 2s linear infinite; transform-origin: center center; %7D circle %7B stroke-dasharray: 75,100; stroke-dashoffset: -5; animation: dash 1.5s ease-in-out infinite; stroke-linecap: round; %7D @keyframes rotate %7B 0%25 %7B transform: rotate(0deg); %7D 100%25 %7B transform: rotate(360deg); %7D %7D @keyframes dash %7B 0%25 %7B stroke-dasharray: 1,100; stroke-dashoffset: 0; %7D 50%25 %7B stroke-dasharray: 44.5,100; stroke-dashoffset: -17.5; %7D 100%25 %7B stroke-dasharray: 44.5,100; stroke-dashoffset: -62; %7D %7D %3C/style%3E%3Cg%3E%3Ccircle cx='12' cy='12' r='10' fill='none' stroke='rgb(136, 145, 164)' stroke-width='4' /%3E%3C/g%3E%3C/svg%3E"); +} + +@media (min-width: 576px) { + :host, + :root { + --app-font-size: 100%; + } +} + +@media (min-width: 768px) { + :host, + :root { + --app-font-size: 100%; + } +} + +@media (min-width: 1024px) { + :host, + :root { + --app-font-size: 100%; + } +} + +@media (min-width: 1280px) { + :host, + :root { + --app-font-size: 100%; + } +} + +@media (min-width: 1536px) { + :host, + :root { + --app-font-size: 100%; + } +} + +:host(:not([data-theme="dark"])), +:root:not([data-theme="dark"]), +[data-theme="light"] { + color-scheme: light; + --app-background-color: #fff; + --app-sidebar-background-color: rgb(247 250 252); + --app-color: #373c44; + --app-text-selection-color: rgba(2, 154, 232, 0.25); + --app-muted-color: #646b79; + --app-muted-border-color: rgb(231, 234, 239.5); + --app-primary-h-light: 180.75; + --app-primary-s-light: 37.38%; + --app-primary-l-light: 58.04%; + --app-primary-h: var(--app-primary-h-light, var(--app-primary-h-base)); + --app-primary-s: var(--app-primary-s-light, var(--app-primary-s-base)); + --app-primary-l: var(--app-primary-l-light, var(--app-primary-l-base)); + --app-primary-l-hover: -7%; + --app-primary-l-hover-bg: -4%; + --app-primary-l-focus: 16%; + --app-primary: hsl( + var(--app-primary-h) var(--app-primary-s) var(--app-primary-l) + ); + --app-primary-background: var(--app-primary); + --app-primary-border: var(--app-primary-background); + --app-primary-underline: hsl( + var(--app-primary-h) var(--app-primary-s) var(--app-primary-l) / 0.5 + ); + --app-primary-hover: hsl( + var(--app-primary-h) var(--app-primary-s) + calc(var(--app-primary-l) + var(--app-primary-l-hover)) + ); + --app-primary-hover-background: hsl( + var(--app-primary-h) var(--app-primary-s) + calc(var(--app-primary-l) + var(--app-primary-l-hover-bg)) + ); + --app-primary-hover-border: var(--app-primary-hover-background); + --app-primary-hover-underline: var(--app-primary-hover); + --app-primary-focus: hsl( + var(--app-primary-h) var(--app-primary-s) + calc(var(--app-primary-l) + var(--app-primary-l-focus)) / 0.5 + ); + --app-primary-inverse: #fff; + --app-secondary-h-light: 223; + --app-secondary-s-light: 19%; + --app-secondary-l-light: 45%; + --app-secondary-h: var(--app-secondary-h-light, var(--app-secondary-h-base)); + --app-secondary-s: var(--app-secondary-s-light, var(--app-secondary-s-base)); + --app-secondary-l: var(--app-secondary-l-light, var(--app-secondary-l-base)); + --app-secondary-l-hover: -6%; + --app-secondary-l-hover-bg: -6%; + --app-secondary-l-focus: 0%; + --app-secondary: hsl( + var(--app-secondary-h) var(--app-secondary-s) var(--app-secondary-l) + ); + --app-secondary-background: hsl( + var(--app-secondary-h) var(--app-secondary-s) + calc(var(--app-secondary-l) - 4%) + ); + --app-secondary-border: var(--app-secondary-background); + --app-secondary-underline: hsl( + var(--app-secondary-h) var(--app-secondary-s) var(--app-secondary-l) / 0.5 + ); + --app-secondary-hover: hsl( + var(--app-secondary-h) var(--app-secondary-s) + calc(var(--app-secondary-l) + var(--app-secondary-l-hover)) + ); + --app-secondary-hover-background: hsl( + var(--app-secondary-h) var(--app-secondary-s) + calc(var(--app-secondary-l) + var(--app-secondary-l-hover-bg)) + ); + --app-secondary-hover-border: var(--app-secondary-hover-background); + --app-secondary-hover-underline: var(--app-secondary-hover); + --app-secondary-focus: hsl( + var(--app-secondary-h) var(--app-secondary-s) var(--app-secondary-l) / 0.25 + ); + --app-secondary-inverse: #fff; + --app-contrast: #181c25; + --app-contrast-background: #181c25; + --app-contrast-border: var(--app-contrast-background); + --app-contrast-underline: rgba(24, 28, 37, 0.5); + --app-contrast-hover: #000; + --app-contrast-hover-background: #000; + --app-contrast-hover-border: var(--app-contrast-hover-background); + --app-contrast-hover-underline: var(--app-secondary-hover); + --app-contrast-focus: rgba(93, 107, 137, 0.25); + --app-contrast-inverse: #fff; + --app-box-shadow: + 0.0145rem 0.029rem 0.174rem rgba(129, 145, 181, 0.01698), + 0.0335rem 0.067rem 0.402rem rgba(129, 145, 181, 0.024), + 0.0625rem 0.125rem 0.75rem rgba(129, 145, 181, 0.03), + 0.1125rem 0.225rem 1.35rem rgba(129, 145, 181, 0.036), + 0.2085rem 0.417rem 2.502rem rgba(129, 145, 181, 0.04302), + 0.5rem 1rem 6rem rgba(129, 145, 181, 0.06), + 0 0 0 0.0625rem rgba(129, 145, 181, 0.015); + --app-h1-color: #2d3138; + --app-h2-color: #373c44; + --app-h3-color: #424751; + --app-h4-color: #4d535e; + --app-h5-color: #5c6370; + --app-h6-color: #646b79; + --app-mark-background-color: rgb(252.5, 230.5, 191.5); + --app-mark-color: #0f1114; + --app-ins-color: rgb(28.5, 105.5, 84); + --app-del-color: rgb(136, 56.5, 53); + --app-blockquote-border-color: var(--app-muted-border-color); + --app-blockquote-footer-color: var(--app-muted-color); + --app-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --app-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --app-table-border-color: var(--app-muted-border-color); + --app-table-row-stripped-background-color: rgba(111, 120, 135, 0.0375); + --app-code-background-color: rgb(243, 244.5, 246.75); + --app-code-color: #646b79; + --app-code-kbd-background-color: var(--app-color); + --app-code-kbd-color: var(--app-background-color); + --app-form-element-background-color: rgb(251, 251.5, 252.25); + --app-form-element-selected-background-color: #dfe3eb; + --app-form-element-border-color: #cfd5e2; + --app-border: var(--app-form-element-border-color); + --app-form-element-color: #23262c; + --app-form-element-placeholder-color: var(--app-muted-color); + --app-form-element-active-background-color: #fff; + --app-form-element-active-border-color: var(--app-primary-border); + --app-form-element-focus-color: var(--app-primary-border); + --app-form-element-disabled-opacity: 0.5; + --app-form-element-invalid-border-color: rgb(183.5, 105.5, 106.5); + --app-form-element-invalid-active-border-color: rgb(200.25, 79.25, 72.25); + --app-form-element-invalid-focus-color: var( + --app-form-element-invalid-active-border-color + ); + --app-form-element-valid-border-color: rgb(76, 154.5, 137.5); + --app-form-element-valid-active-border-color: rgb(39, 152.75, 118.75); + --app-form-element-valid-focus-color: var( + --app-form-element-valid-active-border-color + ); + --app-notice-success-color: var(--app-form-element-valid-border-color); + --app-notice-success-border-color: var(--app-form-element-valid-border-color); + --app-notice-success-background-color: rgba(76, 154.5, 137.5, 0.12); + --app-notice-warning-color: rgb(173, 113, 34); + --app-notice-warning-border-color: rgb(214, 145, 55); + --app-notice-warning-background-color: rgba(214, 145, 55, 0.12); + --app-notice-info-color: var(--app-secondary); + --app-notice-info-border-color: var(--app-secondary); + --app-notice-info-background-color: rgba(96.9, 110.5, 137.7, 0.12); + --app-notice-error-color: var(--app-form-element-invalid-border-color); + --app-notice-error-border-color: var(--app-form-element-invalid-border-color); + --app-notice-error-background-color: rgb(255 0 0 / 13%); + --app-switch-background-color: #bfc7d9; + --app-switch-checked-background-color: var(--app-primary-background); + --app-switch-color: #fff; + --app-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --app-range-border-color: #dfe3eb; + --app-range-active-border-color: #bfc7d9; + --app-range-thumb-border-color: var(--app-background-color); + --app-range-thumb-color: var(--app-secondary-background); + --app-range-thumb-active-color: var(--app-primary-background); + --app-accordion-border-color: var(--app-muted-border-color); + --app-accordion-active-summary-color: var(--app-primary-hover); + --app-accordion-close-summary-color: var(--app-color); + --app-accordion-open-summary-color: var(--app-muted-color); + --app-card-background-color: var(--app-background-color); + --app-card-border-color: var(--app-muted-border-color); + --app-card-box-shadow: var(--app-box-shadow); + --app-card-sectioning-background-color: rgb(251, 251.5, 252.25); + --app-dropdown-background-color: #fff; + --app-dropdown-border-color: #eff1f4; + --app-dropdown-box-shadow: var(--app-box-shadow); + --app-dropdown-color: var(--app-color); + --app-dropdown-hover-background-color: #eff1f4; + --app-loading-spinner-opacity: 0.5; + --app-modal-overlay-background-color: rgba(232, 234, 237, 0.75); + --app-progress-background-color: #dfe3eb; + --app-progress-color: var(--app-primary-background); + --app-tooltip-background-color: var(--app-contrast-background); + --app-tooltip-color: var(--app-contrast-inverse); + --app-icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(76, 154.5, 137.5)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E"); + --app-icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(200.25, 79.25, 72.25)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E"); +} + +:host(:not([data-theme="dark"])) + input:is( + [type="submit"], + [type="button"], + [type="reset"], + [type="checkbox"], + [type="radio"], + [type="file"] + ), +:root:not([data-theme="dark"]) + input:is( + [type="submit"], + [type="button"], + [type="reset"], + [type="checkbox"], + [type="radio"], + [type="file"] + ), +[data-theme="light"] + input:is( + [type="submit"], + [type="button"], + [type="reset"], + [type="checkbox"], + [type="radio"], + [type="file"] + ) { + --app-form-element-focus-color: var(--app-primary-focus); +} + +@media only screen and (prefers-color-scheme: dark) { + :host(:not([data-theme])), + :root:not([data-theme]) { + color-scheme: dark; + --app-background-color: rgb(19, 22.5, 30.5); + --app-sidebar-background-color: rgb(18 20 27); + --app-color: #c2c7d0; + --app-text-selection-color: rgba(1, 170, 255, 0.1875); + --app-muted-color: #7b8495; + --app-muted-border-color: #202632; + --app-primary-h-dark: var(--app-primary-h-light, var(--app-primary-h-base)); + --app-primary-s-dark: var(--app-primary-s-light, var(--app-primary-s-base)); + --app-primary-l-dark: var(--app-primary-l-light, var(--app-primary-l-base)); + --app-primary-h: var(--app-primary-h-dark, var(--app-primary-h-base)); + --app-primary-s: var(--app-primary-s-dark, var(--app-primary-s-base)); + --app-primary-l: var(--app-primary-l-dark, var(--app-primary-l-base)); + --app-primary-l-hover: -7%; + --app-primary-l-hover-bg: -4%; + --app-primary-l-focus: 16%; + --app-primary: hsl( + var(--app-primary-h) var(--app-primary-s) var(--app-primary-l) + ); + --app-primary-background: var(--app-primary); + --app-primary-border: var(--app-primary-background); + --app-primary-underline: hsl( + var(--app-primary-h) var(--app-primary-s) var(--app-primary-l) / 0.5 + ); + --app-primary-hover: hsl( + var(--app-primary-h) var(--app-primary-s) + calc(var(--app-primary-l) + var(--app-primary-l-hover)) + ); + --app-primary-hover-background: hsl( + var(--app-primary-h) var(--app-primary-s) + calc(var(--app-primary-l) + var(--app-primary-l-hover-bg)) + ); + --app-primary-hover-border: var(--app-primary-hover-background); + --app-primary-hover-underline: var(--app-primary-hover); + --app-primary-focus: hsl( + var(--app-primary-h) var(--app-primary-s) + calc(var(--app-primary-l) + var(--app-primary-l-focus)) / 0.5 + ); + --app-primary-inverse: #fff; + --app-secondary-h-dark: var( + --app-secondary-h-light, + var(--app-secondary-h-base) + ); + --app-secondary-s-dark: var( + --app-secondary-s-light, + var(--app-secondary-s-base) + ); + --app-secondary-l-dark: var( + --app-secondary-l-light, + var(--app-secondary-l-base) + ); + --app-secondary-h: var(--app-secondary-h-dark, var(--app-secondary-h-base)); + --app-secondary-s: var(--app-secondary-s-dark, var(--app-secondary-s-base)); + --app-secondary-l: var(--app-secondary-l-dark, var(--app-secondary-l-base)); + --app-secondary-l-hover: -6%; + --app-secondary-l-hover-bg: -6%; + --app-secondary-l-focus: 0%; + --app-secondary: hsl( + var(--app-secondary-h) var(--app-secondary-s) var(--app-secondary-l) + ); + --app-secondary-background: hsl( + var(--app-secondary-h) var(--app-secondary-s) + calc(var(--app-secondary-l) - 4%) + ); + --app-secondary-border: var(--app-secondary-background); + --app-secondary-underline: hsl( + var(--app-secondary-h) var(--app-secondary-s) var(--app-secondary-l) / 0.5 + ); + --app-secondary-hover: hsl( + var(--app-secondary-h) var(--app-secondary-s) + calc(var(--app-secondary-l) + var(--app-secondary-l-hover)) + ); + --app-secondary-hover-background: hsl( + var(--app-secondary-h) var(--app-secondary-s) + calc(var(--app-secondary-l) + var(--app-secondary-l-hover-bg)) + ); + --app-secondary-hover-border: var(--app-secondary-hover-background); + --app-secondary-hover-underline: var(--app-secondary-hover); + --app-secondary-focus: hsl( + var(--app-secondary-h) var(--app-secondary-s) var(--app-secondary-l) / + 0.25 + ); + --app-secondary-inverse: #fff; + --app-contrast: #dfe3eb; + --app-contrast-background: #eff1f4; + --app-contrast-border: var(--app-contrast-background); + --app-contrast-underline: rgba(223, 227, 235, 0.5); + --app-contrast-hover: #fff; + --app-contrast-hover-background: #fff; + --app-contrast-hover-border: var(--app-contrast-hover-background); + --app-contrast-hover-underline: var(--app-contrast-hover); + --app-contrast-focus: rgba(207, 213, 226, 0.25); + --app-contrast-inverse: #000; + --app-box-shadow: + 0.0145rem 0.029rem 0.174rem rgba(7, 8.5, 12, 0.01698), + 0.0335rem 0.067rem 0.402rem rgba(7, 8.5, 12, 0.024), + 0.0625rem 0.125rem 0.75rem rgba(7, 8.5, 12, 0.03), + 0.1125rem 0.225rem 1.35rem rgba(7, 8.5, 12, 0.036), + 0.2085rem 0.417rem 2.502rem rgba(7, 8.5, 12, 0.04302), + 0.5rem 1rem 6rem rgba(7, 8.5, 12, 0.06), + 0 0 0 0.0625rem rgba(7, 8.5, 12, 0.015); + --app-h1-color: #f0f1f3; + --app-h2-color: #e0e3e7; + --app-h3-color: #c2c7d0; + --app-h4-color: #b3b9c5; + --app-h5-color: #a4acba; + --app-h6-color: #8891a4; + --app-mark-background-color: #014063; + --app-mark-color: #fff; + --app-ins-color: #62af9a; + --app-del-color: rgb(205.5, 126, 123); + --app-blockquote-border-color: var(--app-muted-border-color); + --app-blockquote-footer-color: var(--app-muted-color); + --app-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --app-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --app-table-border-color: var(--app-muted-border-color); + --app-table-row-stripped-background-color: rgba(111, 120, 135, 0.0375); + --app-code-background-color: rgb(26, 30.5, 40.25); + --app-code-color: #8891a4; + --app-code-kbd-background-color: var(--app-color); + --app-code-kbd-color: var(--app-background-color); + --app-form-element-background-color: rgb(28, 33, 43.5); + --app-form-element-selected-background-color: #2a3140; + --app-form-element-border-color: #2a3140; + --app-border: var(--app-form-element-border-color); + --app-form-element-color: #e0e3e7; + --app-form-element-placeholder-color: #8891a4; + --app-form-element-active-background-color: rgb(26, 30.5, 40.25); + --app-form-element-active-border-color: var(--app-primary-border); + --app-form-element-focus-color: var(--app-primary-border); + --app-form-element-disabled-opacity: 0.5; + --app-form-element-invalid-border-color: rgb(149.5, 74, 80); + --app-form-element-invalid-active-border-color: rgb(183.25, 63.5, 59); + --app-form-element-invalid-focus-color: var( + --app-form-element-invalid-active-border-color + ); + --app-form-element-valid-border-color: #2a7b6f; + --app-form-element-valid-active-border-color: rgb(22, 137, 105.5); + --app-form-element-valid-focus-color: var( + --app-form-element-valid-active-border-color + ); + --app-switch-background-color: #333c4e; + --app-switch-checked-background-color: var(--app-primary-background); + --app-switch-color: #fff; + --app-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --app-range-border-color: #202632; + --app-range-active-border-color: #2a3140; + --app-range-thumb-border-color: var(--app-background-color); + --app-range-thumb-color: var(--app-secondary-background); + --app-range-thumb-active-color: var(--app-primary-background); + --app-accordion-border-color: var(--app-muted-border-color); + --app-accordion-active-summary-color: var(--app-primary-hover); + --app-accordion-close-summary-color: var(--app-color); + --app-accordion-open-summary-color: var(--app-muted-color); + --app-card-background-color: #181c25; + --app-card-border-color: var(--app-card-background-color); + --app-card-box-shadow: var(--app-box-shadow); + --app-card-sectioning-background-color: rgb(26, 30.5, 40.25); + --app-dropdown-background-color: #181c25; + --app-dropdown-border-color: #202632; + --app-dropdown-box-shadow: var(--app-box-shadow); + --app-dropdown-color: var(--app-color); + --app-dropdown-hover-background-color: #202632; + --app-loading-spinner-opacity: 0.5; + --app-modal-overlay-background-color: rgba(7.5, 8.5, 10, 0.75); + --app-progress-background-color: #202632; + --app-progress-color: var(--app-primary-background); + --app-tooltip-background-color: var(--app-contrast-background); + --app-tooltip-color: var(--app-contrast-inverse); + --app-icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(42, 123, 111)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E"); + --app-icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(149.5, 74, 80)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E"); + } + + :host(:not([data-theme])) + input:is( + [type="submit"], + [type="button"], + [type="reset"], + [type="checkbox"], + [type="radio"], + [type="file"] + ), + :root:not([data-theme]) + input:is( + [type="submit"], + [type="button"], + [type="reset"], + [type="checkbox"], + [type="radio"], + [type="file"] + ) { + --app-form-element-focus-color: var(--app-primary-focus); + } +} + +[data-theme="dark"] { + color-scheme: dark; + --app-background-color: rgb(19, 22.5, 30.5); + --app-sidebar-background-color: rgb(18 20 27); + --app-color: #c2c7d0; + --app-text-selection-color: rgba(1, 170, 255, 0.1875); + --app-muted-color: #7b8495; + --app-muted-border-color: #202632; + --app-primary-h-dark: var(--app-primary-h-light, var(--app-primary-h-base)); + --app-primary-s-dark: var(--app-primary-s-light, var(--app-primary-s-base)); + --app-primary-l-dark: var(--app-primary-l-light, var(--app-primary-l-base)); + --app-primary-h: var(--app-primary-h-dark, var(--app-primary-h-base)); + --app-primary-s: var(--app-primary-s-dark, var(--app-primary-s-base)); + --app-primary-l: var(--app-primary-l-dark, var(--app-primary-l-base)); + --app-primary-l-hover: -7%; + --app-primary-l-hover-bg: -4%; + --app-primary-l-focus: 16%; + --app-primary: hsl( + var(--app-primary-h) var(--app-primary-s) var(--app-primary-l) + ); + --app-primary-background: var(--app-primary); + --app-primary-border: var(--app-primary-background); + --app-primary-underline: hsl( + var(--app-primary-h) var(--app-primary-s) var(--app-primary-l) / 0.5 + ); + --app-primary-hover: hsl( + var(--app-primary-h) var(--app-primary-s) + calc(var(--app-primary-l) + var(--app-primary-l-hover)) + ); + --app-primary-hover-background: hsl( + var(--app-primary-h) var(--app-primary-s) + calc(var(--app-primary-l) + var(--app-primary-l-hover-bg)) + ); + --app-primary-hover-border: var(--app-primary-hover-background); + --app-primary-hover-underline: var(--app-primary-hover); + --app-primary-focus: hsl( + var(--app-primary-h) var(--app-primary-s) + calc(var(--app-primary-l) + var(--app-primary-l-focus)) / 0.5 + ); + --app-primary-inverse: #fff; + --app-secondary-h-dark: var( + --app-secondary-h-light, + var(--app-secondary-h-base) + ); + --app-secondary-s-dark: var( + --app-secondary-s-light, + var(--app-secondary-s-base) + ); + --app-secondary-l-dark: var( + --app-secondary-l-light, + var(--app-secondary-l-base) + ); + --app-secondary-h: var(--app-secondary-h-dark, var(--app-secondary-h-base)); + --app-secondary-s: var(--app-secondary-s-dark, var(--app-secondary-s-base)); + --app-secondary-l: var(--app-secondary-l-dark, var(--app-secondary-l-base)); + --app-secondary-l-hover: -6%; + --app-secondary-l-hover-bg: -6%; + --app-secondary-l-focus: 0%; + --app-secondary: hsl( + var(--app-secondary-h) var(--app-secondary-s) var(--app-secondary-l) + ); + --app-secondary-background: hsl( + var(--app-secondary-h) var(--app-secondary-s) + calc(var(--app-secondary-l) - 4%) + ); + --app-secondary-border: var(--app-secondary-background); + --app-secondary-underline: hsl( + var(--app-secondary-h) var(--app-secondary-s) var(--app-secondary-l) / 0.5 + ); + --app-secondary-hover: hsl( + var(--app-secondary-h) var(--app-secondary-s) + calc(var(--app-secondary-l) + var(--app-secondary-l-hover)) + ); + --app-secondary-hover-background: hsl( + var(--app-secondary-h) var(--app-secondary-s) + calc(var(--app-secondary-l) + var(--app-secondary-l-hover-bg)) + ); + --app-secondary-hover-border: var(--app-secondary-hover-background); + --app-secondary-hover-underline: var(--app-secondary-hover); + --app-secondary-focus: hsl( + var(--app-secondary-h) var(--app-secondary-s) var(--app-secondary-l) / 0.25 + ); + --app-secondary-inverse: #fff; + --app-contrast: #dfe3eb; + --app-contrast-background: #eff1f4; + --app-contrast-border: var(--app-contrast-background); + --app-contrast-underline: rgba(223, 227, 235, 0.5); + --app-contrast-hover: #fff; + --app-contrast-hover-background: #fff; + --app-contrast-hover-border: var(--app-contrast-hover-background); + --app-contrast-hover-underline: var(--app-contrast-hover); + --app-contrast-focus: rgba(207, 213, 226, 0.25); + --app-contrast-inverse: #000; + --app-box-shadow: + 0.0145rem 0.029rem 0.174rem rgba(7, 8.5, 12, 0.01698), + 0.0335rem 0.067rem 0.402rem rgba(7, 8.5, 12, 0.024), + 0.0625rem 0.125rem 0.75rem rgba(7, 8.5, 12, 0.03), + 0.1125rem 0.225rem 1.35rem rgba(7, 8.5, 12, 0.036), + 0.2085rem 0.417rem 2.502rem rgba(7, 8.5, 12, 0.04302), + 0.5rem 1rem 6rem rgba(7, 8.5, 12, 0.06), + 0 0 0 0.0625rem rgba(7, 8.5, 12, 0.015); + --app-h1-color: #f0f1f3; + --app-h2-color: #e0e3e7; + --app-h3-color: #c2c7d0; + --app-h4-color: #b3b9c5; + --app-h5-color: #a4acba; + --app-h6-color: #8891a4; + --app-mark-background-color: #014063; + --app-mark-color: #fff; + --app-ins-color: #62af9a; + --app-del-color: rgb(205.5, 126, 123); + --app-blockquote-border-color: var(--app-muted-border-color); + --app-blockquote-footer-color: var(--app-muted-color); + --app-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --app-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --app-table-border-color: var(--app-muted-border-color); + --app-table-row-stripped-background-color: rgba(111, 120, 135, 0.0375); + --app-code-background-color: rgb(26, 30.5, 40.25); + --app-code-color: #8891a4; + --app-code-kbd-background-color: var(--app-color); + --app-code-kbd-color: var(--app-background-color); + --app-form-element-background-color: rgb(28, 33, 43.5); + --app-form-element-selected-background-color: #2a3140; + --app-form-element-border-color: #2a3140; + --app-border: var(--app-form-element-border-color); + --app-form-element-color: #e0e3e7; + --app-form-element-placeholder-color: #8891a4; + --app-form-element-active-background-color: rgb(26, 30.5, 40.25); + --app-form-element-active-border-color: var(--app-primary-border); + --app-form-element-focus-color: var(--app-primary-border); + --app-form-element-disabled-opacity: 0.5; + --app-form-element-invalid-border-color: rgb(149.5, 74, 80); + --app-form-element-invalid-active-border-color: rgb(183.25, 63.5, 59); + --app-form-element-invalid-focus-color: var( + --app-form-element-invalid-active-border-color + ); + --app-form-element-valid-border-color: #2a7b6f; + --app-form-element-valid-active-border-color: rgb(22, 137, 105.5); + --app-form-element-valid-focus-color: var( + --app-form-element-valid-active-border-color + ); + --app-notice-success-color: var(--app-form-element-valid-border-color); + --app-notice-success-border-color: var(--app-form-element-valid-border-color); + --app-notice-success-background-color: rgba(42, 123, 111, 0.2); + --app-notice-warning-color: rgb(199, 140, 61); + --app-notice-warning-border-color: rgb(199, 140, 61); + --app-notice-warning-background-color: rgba(199, 140, 61, 0.2); + --app-notice-info-color: var(--app-secondary); + --app-notice-info-border-color: var(--app-secondary); + --app-notice-info-background-color: rgba(114.4, 130.1, 165.1, 0.2); + --app-notice-error-color: var(--app-form-element-invalid-border-color); + --app-notice-error-border-color: var(--app-form-element-invalid-border-color); + --app-notice-error-background-color: rgba(149.5, 74, 80, 0.2); + --app-switch-background-color: #333c4e; + --app-switch-checked-background-color: var(--app-primary-background); + --app-switch-color: #fff; + --app-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0); + --app-range-border-color: #202632; + --app-range-active-border-color: #2a3140; + --app-range-thumb-border-color: var(--app-background-color); + --app-range-thumb-color: var(--app-secondary-background); + --app-range-thumb-active-color: var(--app-primary-background); + --app-accordion-border-color: var(--app-muted-border-color); + --app-accordion-active-summary-color: var(--app-primary-hover); + --app-accordion-close-summary-color: var(--app-color); + --app-accordion-open-summary-color: var(--app-muted-color); + --app-card-background-color: #181c25; + --app-card-border-color: var(--app-card-background-color); + --app-card-box-shadow: var(--app-box-shadow); + --app-card-sectioning-background-color: rgb(26, 30.5, 40.25); + --app-dropdown-background-color: #181c25; + --app-dropdown-border-color: #202632; + --app-dropdown-box-shadow: var(--app-box-shadow); + --app-dropdown-color: var(--app-color); + --app-dropdown-hover-background-color: #202632; + --app-loading-spinner-opacity: 0.5; + --app-modal-overlay-background-color: rgba(7.5, 8.5, 10, 0.75); + --app-progress-background-color: #202632; + --app-progress-color: var(--app-primary-background); + --app-tooltip-background-color: var(--app-contrast-background); + --app-tooltip-color: var(--app-contrast-inverse); + --app-icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(42, 123, 111)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E"); + --app-icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(149.5, 74, 80)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E"); +} + +[data-theme="dark"] + input:is( + [type="submit"], + [type="button"], + [type="reset"], + [type="checkbox"], + [type="radio"], + [type="file"] + ) { + --app-form-element-focus-color: var(--app-primary-focus); +} + +:host, +:root { + --app-scrollbar-width: 0px; +} diff --git a/web/css/components/app-badges.css b/web/css/components/app-badges.css new file mode 100644 index 0000000..82ef859 --- /dev/null +++ b/web/css/components/app-badges.css @@ -0,0 +1,127 @@ +:root { + --badge-success-bg: #e6f6eb; + --badge-success-color: #1f6a3a; + --badge-success-border: #c9ead3; + --badge-danger-bg: #fdecec; + --badge-danger-color: #8f2c2c; + --badge-danger-border: #f6caca; + --badge-info-bg: #e9f0ff; + --badge-info-color: #264db3; + --badge-info-border: #cbd7ff; + --badge-warn-bg: #fff5e6; + --badge-warn-color: #9a5a00; + --badge-warn-border: #ffd9a6; + --badge-neutral-bg: #f2f4f7; + --badge-neutral-color: #4a5568; + --badge-neutral-border: #e1e6ee; +} + +[data-theme="dark"] { + --badge-success-bg: #163a2a; + --badge-success-color: #8fe0b0; + --badge-success-border: #25523c; + --badge-danger-bg: #3a1b1b; + --badge-danger-color: #f2a3a3; + --badge-danger-border: #5b2c2c; + --badge-info-bg: #1a253f; + --badge-info-color: #9fb6ff; + --badge-info-border: #2a3a66; + --badge-warn-bg: #3a2a14; + --badge-warn-color: #ffd596; + --badge-warn-border: #5b401d; + --badge-neutral-bg: #222831; + --badge-neutral-color: #cbd5e1; + --badge-neutral-border: #2f3945; +} + +.badge[role="button"], +.badge { + display: inline-flex; + align-items: center; + gap: 0.35em; + padding: 0.15em 0.6em; + border-radius: 999px; + font-size: 0.85em; + font-weight: 400; + line-height: 1.2; + border: 1px solid transparent; + white-space: nowrap; +} + +.badge[data-copy="true"] { + gap: 0.45em; + padding-right: 0.4em; + cursor: pointer; + user-select: none; +} + +.badge .badge-copy-icon { + display: inline-flex; + align-items: center; + justify-content: center; + color: inherit; + line-height: 1; + font-size: 10px; +} + +.badge .badge-copy-icon .bi { + font-size: 0.95em; +} + +.badge .badge-copy-icon .bi-check2 { + display: none; +} + +.badge.is-copied .badge-copy-icon .bi-copy { + display: none; +} + +.badge.is-copied .badge-copy-icon .bi-check2 { + display: inline; +} + +.badge[data-copy="true"]:focus-visible { + outline: 2px solid currentColor; + outline-offset: 2px; + border-radius: 6px; +} + +.badge[data-variant="success"] { + background: var(--badge-success-bg); + color: var(--badge-success-color); + border-color: var(--badge-success-border); +} + +.badge[data-variant="danger"] { + background: var(--badge-danger-bg); + color: var(--badge-danger-color); + border-color: var(--badge-danger-border); +} + +.badge[data-variant="info"] { + background: var(--badge-info-bg); + color: var(--badge-info-color); + border-color: var(--badge-info-border); +} + +.badge[data-variant="warn"] { + background: var(--badge-warn-bg); + color: var(--badge-warn-color); + border-color: var(--badge-warn-border); +} +.badge[data-variant="warning"] { + background: var(--badge-warn-bg); + color: var(--badge-warn-color); + border-color: var(--badge-warn-border); +} + +.badge[data-variant="neutral"] { + background: var(--badge-neutral-bg); + color: var(--badge-neutral-color); + border-color: var(--badge-neutral-border); +} + +.badge-list { + display: flex; + gap: 0.35rem; +} diff --git a/web/css/components/app-blockquote.css b/web/css/components/app-blockquote.css new file mode 100644 index 0000000..6a5b744 --- /dev/null +++ b/web/css/components/app-blockquote.css @@ -0,0 +1,66 @@ +:root { + --app-blockquote-background-color: var( + --app-form-element-active-background-color + ); +} + +blockquote { + --blockquote-bg: var(--app-blockquote-background-color); + --blockquote-color: inherit; + --blockquote-border: var(--app-blockquote-border-color); + --blockquote-footer-color: var(--app-blockquote-footer-color); + + display: block; + margin: var(--app-typography-spacing-vertical) 0; + padding: var(--app-spacing); + border-right: none; + border-left: 0.25rem solid var(--app-blockquote-border-color); + border-inline-start: 0.25rem solid var(--app-blockquote-border-color); + border-inline-end: none; + background-color: var(--blockquote-bg); + color: var(--blockquote-color); + border-left-color: var(--blockquote-border); + border-inline-start-color: var(--blockquote-border); + border-radius: var(--app-border-radius); +} + +blockquote footer { + margin-top: calc(var(--app-typography-spacing-vertical) * 0.5); + color: var(--blockquote-footer-color); +} + +blockquote[data-variant="success"] { + --blockquote-bg: var(--badge-success-bg); + --blockquote-color: var(--badge-success-color); + --blockquote-border: var(--badge-success-border); + --blockquote-footer-color: var(--badge-success-color); +} + +blockquote[data-variant="danger"] { + --blockquote-bg: var(--badge-danger-bg); + --blockquote-color: var(--badge-danger-color); + --blockquote-border: var(--badge-danger-border); + --blockquote-footer-color: var(--badge-danger-color); +} + +blockquote[data-variant="info"] { + --blockquote-bg: var(--badge-info-bg); + --blockquote-color: var(--badge-info-color); + --blockquote-border: var(--badge-info-border); + --blockquote-footer-color: var(--badge-info-color); +} + +blockquote[data-variant="warn"], +blockquote[data-variant="warning"] { + --blockquote-bg: var(--badge-warn-bg); + --blockquote-color: var(--badge-warn-color); + --blockquote-border: var(--badge-warn-border); + --blockquote-footer-color: var(--badge-warn-color); +} + +blockquote[data-variant="neutral"] { + --blockquote-bg: var(--badge-neutral-bg); + --blockquote-color: var(--badge-neutral-color); + --blockquote-border: var(--badge-neutral-border); + --blockquote-footer-color: var(--badge-neutral-color); +} diff --git a/web/css/components/app-brand.css b/web/css/components/app-brand.css new file mode 100644 index 0000000..0d54441 --- /dev/null +++ b/web/css/components/app-brand.css @@ -0,0 +1,31 @@ +.brand { + display: flex; + align-items: center; + gap: 10px; +} + +img.brand-logo { + width: 30px; + height: 30px; + object-fit: contain; + flex-shrink: 0; +} + +.brand-name { + line-height: 1; + font-weight: bold; + color: var(--app-contrast); +} + +.brand-info { + line-height: 1; +} + +.brand-slogan { + font-size: 0.85em; + color: var(--app-muted-color); +} + +.badge:empty { + padding: 0; +} \ No newline at end of file diff --git a/web/css/components/app-breadcrumb.css b/web/css/components/app-breadcrumb.css new file mode 100644 index 0000000..913296c --- /dev/null +++ b/web/css/components/app-breadcrumb.css @@ -0,0 +1,12 @@ +.app-breadcrumb { + margin-bottom: 5px; + display: flex; + align-items: center; + gap: 3px; + font-size: 11px; +} + +.app-breadcrumb a { + color: inherit; + text-decoration: none; +} \ No newline at end of file diff --git a/web/css/components/app-buttons.css b/web/css/components/app-buttons.css new file mode 100644 index 0000000..d8f3d3d --- /dev/null +++ b/web/css/components/app-buttons.css @@ -0,0 +1,44 @@ +.danger:is(button, [type="submit"], [type="button"], [role="button"]) { + --app-background-color: var(--app-notice-error-border-color); + --app-border-color: var(--app-notice-error-border-color); + --app-color: var(--app-secondary-inverse); +} + +.danger:is(button, [type="submit"], [type="button"], [role="button"]):is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + --app-background-color: var(--app-form-element-invalid-active-border-color); + --app-border-color: var(--app-form-element-invalid-active-border-color); + --app-color: var(--app-secondary-inverse); +} + +.danger:is(button, [type="submit"], [type="button"], [role="button"]).outline { + --app-background-color: transparent; + --app-border-color: var(--app-notice-error-border-color); + --app-color: var(--app-notice-error-border-color); +} + +.danger:is( + button, + [type="submit"], + [type="button"], + [role="button"] + ).outline:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + --app-background-color: var(--app-notice-error-background-color); + --app-border-color: var(--app-notice-error-border-color); + --app-color: var(--app-notice-error-border-color); +} + +.danger:is(button, [type="submit"], [type="button"], [role="button"]):focus { + --app-box-shadow: + var(--app-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), + 0 0 0 var(--app-outline-width) var(--app-form-element-invalid-focus-color); +} diff --git a/web/css/components/app-dashboard-titlebar.css b/web/css/components/app-dashboard-titlebar.css new file mode 100644 index 0000000..b33ada9 --- /dev/null +++ b/web/css/components/app-dashboard-titlebar.css @@ -0,0 +1,55 @@ +.app-dashboard-titlebar { + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + gap: 10px; + margin-block-end: var(--app-spacing); +} + +.app-dashboard-titlebar h1, +.app-dashboard-titlebar h2, +.app-dashboard-titlebar h3, +.app-dashboard-titlebar h4, +.app-dashboard-titlebar h5, +.app-dashboard-titlebar h6 { + margin: 0; +} + +.app-dashboard-titlebar button, +.app-dashboard-titlebar [role="button"] { + --app-button-padding-horizontal: 10px; + --app-button-padding-vertical: 6px; + font-size: 13px; + margin: 0; +} + +.app-dashboard-titlebar-actions { + display: flex; + align-items: center; + gap: 10px; + white-space: nowrap; +} + +.app-dashboard-titlebar h1 i { + background: var(--app-muted-border-color); + width: 35px; + height: 29px; + font-size: 15px; + border-radius: var(--app-border-radius); + display: inline-flex; + align-items: center; + justify-content: center; + color: var(--app-contrast); +} + +.app-dashboard-titlebar h1:has(i) { + display: flex; + align-items: center; + gap: 7px; + line-height: 1; +} + +.app-dashboard-titlebar h1 a:hover i { + background: var(--app-border); +} \ No newline at end of file diff --git a/web/css/components/app-details-titlebar.css b/web/css/components/app-details-titlebar.css new file mode 100644 index 0000000..203d643 --- /dev/null +++ b/web/css/components/app-details-titlebar.css @@ -0,0 +1,87 @@ +.app-details-titlebar { + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + gap: 10px; + border-bottom: 1px solid var(--app-border); + padding-block-end: var(--app-spacing); + margin-bottom: calc(var(--app-spacing) * 2); +} + +.app-details-titlebar h1, +.app-details-titlebar h2, +.app-details-titlebar h3, +.app-details-titlebar h4, +.app-details-titlebar h5, +.app-details-titlebar h6 { + margin: 0; +} + +.app-details-titlebar button, +.app-details-titlebar [role="button"] { + --app-button-padding-horizontal: 10px; + --app-button-padding-vertical: 6px; + font-size: 13px; + margin: 0; +} + +.app-details-titlebar-actions { + display: flex; + align-items: center; + gap: 10px; + white-space: nowrap; +} + +.app-details-titlebar h1 i { + background: var(--app-background-color); + width: 35px; + height: 29px; + font-size: 15px; + border-radius: var(--app-border-radius); + display: inline-flex; + align-items: center; + justify-content: center; + color: var(--app-contrast); + border: 1px solid var(--app-border); + color: var(--app-muted-color); + box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 2px; +} + +.app-details-titlebar h1:has(i) { + display: flex; + align-items: center; + gap: 7px; + line-height: 1; +} +.app-details-titlebar details.dropdown { + margin-bottom: 0; +} + +.app-details-titlebar details.dropdown summary:after { + display: none; +} + +.app-details-titlebar details.dropdown li { + padding: 0!important; + margin: 0!important; + border-bottom: 1px solid var(--app-border); +} + +.app-details-titlebar details.dropdown li:last-child { + border-bottom: none; +} + +.app-details-titlebar details.dropdown ul { + padding: 0!important; + margin: 0!important; +} + +.app-details-titlebar details.dropdown li button, +.app-details-titlebar details.dropdown li [role=button] { + margin: 0!important; + border: none; + border-radius: 0; + width: 100%; + text-align: left; +} \ No newline at end of file diff --git a/web/css/components/app-details.css b/web/css/components/app-details.css new file mode 100644 index 0000000..9ee32d8 --- /dev/null +++ b/web/css/components/app-details.css @@ -0,0 +1,137 @@ +.app-details-container aside { + padding-top: var(--app-spacing); +} + +.user-avatar-block, +.entity-avatar-block { + --avatar-size: 96px; + --avatar-ratio: 1 / 1; + display: grid; + gap: calc(var(--app-spacing) * 0.75); + margin-bottom: calc(var(--app-spacing) * 1.25); + width: var(--avatar-size); + aspect-ratio: var(--avatar-ratio); +} + +.user-avatar-image, +.user-avatar-placeholder, +.entity-avatar-image, +.entity-avatar-placeholder { + width: 100%; + height: 100%; + border: 1px solid var(--app-muted-border-color); + background: var(--app-card-background-color); + display: inline-flex; + align-items: center; + justify-content: center; + font-weight: 600; + color: var(--app-muted-color); +} + +.user-avatar-placeholder, +.entity-avatar-placeholder { + font-size: 1.5rem; +} + +.user-avatar-image { + object-fit: cover; +} + +.entity-avatar-image { + object-fit: contain; + padding: 3px; +} + +.avatar-round .user-avatar-image, +.avatar-round .user-avatar-placeholder, +.avatar-round .entity-avatar-image, +.avatar-round .entity-avatar-placeholder { + border-radius: 999px; + aspect-ratio: 1; +} + +.avatar-square .user-avatar-image, +.avatar-square .user-avatar-placeholder, +.avatar-square .entity-avatar-image, +.avatar-square .entity-avatar-placeholder { + border-radius: var(--app-radius); +} + +.avatar-ratio-1-1 { + --avatar-ratio: 1 / 1; +} + +.avatar-ratio-3-2 { + --avatar-ratio: 3 / 2; +} + +.avatar-ratio-4-3 { + --avatar-ratio: 4 / 3; +} + +.avatar-ratio-16-9 { + --avatar-ratio: 16 / 9; +} + +.avatar-borderless .user-avatar-image, +.avatar-borderless .user-avatar-placeholder, +.avatar-borderless .entity-avatar-image, +.avatar-borderless .entity-avatar-placeholder { + border: none; +} + +.avatar-size-auto { + width: auto; + aspect-ratio: auto; +} + +.avatar-size-auto .user-avatar-image, +.avatar-size-auto .user-avatar-placeholder, +.avatar-size-auto .entity-avatar-image, +.avatar-size-auto .entity-avatar-placeholder { + width: auto; + height: auto; + max-width: 100%; + max-height: 100%; +} + +.app-details-container > section > * { + padding-inline: calc(var(--app-spacing) * 2); +} + +.app-details-container .app-breadcrumb { + padding-top: calc(var(--app-spacing) * 2); + position: sticky; + top: 20px; + background: var(--app-background-color); +} + +.app-details-container .app-details-titlebar { + position: sticky; + top: 69px; + background: var(--app-background-color); +} + +@media (min-width: 968px) { + /* .app-details-container > section { + padding: calc(var(--app-spacing) * 2) calc(var(--app-spacing) * 2) + calc(var(--app-spacing) * 2) calc(var(--app-spacing) * 0); + } */ + .app-details-container:has(aside) { + display: grid; + grid-template-columns: minmax(0, 2fr) minmax(0, 300px); + min-height: 82vh; + } + .app-details-container.is-aside-collapsed { + grid-template-columns: minmax(0, 1fr); + } + .app-details-container.is-aside-collapsed aside { + display: none; + } + .app-details-container aside { + border-left: 1px solid var(--app-border); + padding: calc(var(--app-spacing) * 2); + border-top: none; + min-height: 100vh; + } +} diff --git a/web/css/components/app-flash.css b/web/css/components/app-flash.css new file mode 100644 index 0000000..1a518d9 --- /dev/null +++ b/web/css/components/app-flash.css @@ -0,0 +1,119 @@ +.notice { + --app-notice-border-color: var(--app-muted-border-color); + --app-notice-background-color: var(--app-card-background-color); + --app-notice-accent-color: var(--app-color); + border: var(--app-border-width) solid var(--app-notice-border-color); + border-radius: var(--app-border-radius); + background: var(--app-notice-background-color); + padding: calc(var(--app-spacing) * .5) calc(var(--app-spacing) * 1); + padding-right: calc(var(--app-spacing) * .5); + margin-bottom: var(--app-spacing); + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--app-spacing); + position: relative; + overflow: hidden; + color: var(--app-notice-border-color); +} + +#async-messages .notice { + border: none; + border-radius: 0; + padding: 0; + padding-right: 5px; + padding-left: 15px; + margin-bottom: 0; + display: flex; + align-items: center; + justify-content: space-between; + gap: 5px; + position: relative; + overflow: hidden; + color: var(--app-notice-border-color); +} + + +.notice strong { + color: var(--app-notice-accent-color); +} + +.notice[data-variant=success] { + --app-notice-border-color: var(--app-notice-success-border-color); + --app-notice-background-color: var(--app-notice-success-background-color); + --app-notice-accent-color: var(--app-notice-success-color); +} + +.notice[data-variant=warning] { + --app-notice-border-color: var(--app-notice-warning-border-color); + --app-notice-background-color: var(--app-notice-warning-background-color); + --app-notice-accent-color: var(--app-notice-warning-color); +} + +.notice[data-variant=info] { + --app-notice-border-color: var(--app-notice-info-border-color); + --app-notice-background-color: var(--app-notice-info-background-color); + --app-notice-accent-color: var(--app-notice-info-color); +} + +.notice[data-variant=error] { + --app-notice-border-color: var(--app-notice-error-border-color); + --app-notice-background-color: var(--app-notice-error-background-color); + --app-notice-accent-color: var(--app-notice-error-color); +} + +.notice.flash-timed::after { + content: ""; + position: absolute; + left: 0; + bottom: 0; + height: 3px; + width: 100%; + background: var(--app-notice-border-color); + transform-origin: left; + transform: scaleX(0); + animation: flash-progress var(--flash-timeout, 4000ms) linear forwards; + opacity: 0.9; +} + +.notice.flash-timed:hover::after { + animation-play-state: paused; +} + +@keyframes flash-progress { + from { + transform: scaleX(0); + } + to { + transform: scaleX(1); + } +} + +@media (prefers-reduced-motion: reduce) { + .notice.flash-timed::after { + animation: none; + } +} + +.notice button[type=submit] { + border: 1px solid var(--app-notice-border-color) !important; + background: var(--app-notice-background-color); + color: var(--app-notice-border-color); +} + +.notice ul { + margin: 0; + padding-left: 20px; +} + +.notice li:last-child { + margin: 0; +} + +.app-details-errors { + padding-block-start: 1rem; +} + +.flash-stack:has(.notice) { + margin-top: var(--app-spacing); +} \ No newline at end of file diff --git a/web/css/components/app-forms.css b/web/css/components/app-forms.css new file mode 100644 index 0000000..4d7a5a2 --- /dev/null +++ b/web/css/components/app-forms.css @@ -0,0 +1,62 @@ +.form-hint { + font-size: small; +} + +ul.form-hint-list { + margin: 0; + padding-left: var(--app-spacing); +} + +ul.form-hint-list li { + margin: 0; +} + +ul.form-hint-list li.is-valid { + color: var(--app-form-element-valid-border-color); +} + +ul.form-hint-list li.is-invalid { + color: var(--app-form-element-invalid-border-color); +} + +ul.form-hint-list li.is-valid:after { + content: "\F26B"; + font-family: "Bootstrap-icons"; + margin-left: 4px; + font-size: 10px; +} + +ul.form-hint-list li.is-invalid:after { + content: "\F33A"; + font-family: "Bootstrap-icons"; + margin-left: 4px; + font-size: 10px; +} + +label:has([type="checkbox"], [type="radio"]) { + display: flex; + line-height: 1; + align-items: center; +} + +input[type="color"] { + padding: 0; + width: 42px; + border: 0; + margin: 0; + height: 42px; + flex-shrink: 0; +} + +label:has(input[type="color"]) { + display: flex; + align-items: center; + gap: 10px; +} + +small.muted { + display: block; + width: 100%; + color: var(--app-muted-color); +} + diff --git a/web/css/components/app-list-table.css b/web/css/components/app-list-table.css new file mode 100644 index 0000000..3ff8ae8 --- /dev/null +++ b/web/css/components/app-list-table.css @@ -0,0 +1,7 @@ +.app-list-table table { + margin: 0; +} + +.app-list-table { + white-space: nowrap; +} \ No newline at end of file diff --git a/web/css/components/app-list-tabs.css b/web/css/components/app-list-tabs.css new file mode 100644 index 0000000..5e5bcde --- /dev/null +++ b/web/css/components/app-list-tabs.css @@ -0,0 +1,37 @@ +:root { + --list-tabs-border: var(--app-border); + --list-tabs-active: var(--app-primary); + --list-tabs-muted: var(--app-muted-color); +} + +.app-list-tabs { + display: flex; + flex-wrap: wrap; + margin-bottom: var(--app-spacing); + border-bottom: 1px solid var(--list-tabs-border); +} + +.app-list-tabs button, +.app-list-tabs a { + background: transparent; + border: 0; + padding: 5px 10px 5px 10px; + color: var(--list-tabs-muted); + cursor: pointer; + font-weight: 500; + border-bottom: 2px solid transparent; + text-decoration: none; +} + +.app-list-tabs button:hover, +.app-list-tabs button:focus-visible, +.app-list-tabs a:hover, +.app-list-tabs a:focus-visible { + color: var(--app-color); +} + +.app-list-tabs button.is-active, +.app-list-tabs a.is-active { + color: var(--app-color); + border-color: var(--list-tabs-active); +} diff --git a/web/css/components/app-list-titlebar.css b/web/css/components/app-list-titlebar.css new file mode 100644 index 0000000..0c86fad --- /dev/null +++ b/web/css/components/app-list-titlebar.css @@ -0,0 +1,79 @@ +.app-list-titlebar { + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + gap: 10px; + margin-bottom: calc(var(--app-spacing) * 1); +} + +.app-list-titlebar h1, +.app-list-titlebar h2, +.app-list-titlebar h3, +.app-list-titlebar h4, +.app-list-titlebar h5, +.app-list-titlebar h6 { + margin: 0; +} + +.app-list-titlebar button, +.app-list-titlebar [role="button"] { + --app-button-padding-horizontal: 10px; + --app-button-padding-vertical: 6px; + font-size: 13px; + margin: 0; +} + +.app-list-titlebar-actions { + display: flex; + align-items: center; + gap: 10px; +} + +.app-list-titlebar h1 i { + background: var(--app-muted-border-color); + width: 35px; + height: 35px; + font-size: 16px; + border-radius: var(--app-border-radius); + display: inline-flex; + align-items: center; + justify-content: center; +} + +.app-list-titlebar h1:has(i) { + display: flex; + align-items: center; + gap: 7px; +} + +.app-list-titlebar details.dropdown { + margin-bottom: 0; +} + +.app-list-titlebar details.dropdown summary:after { + display: none; +} + +.app-list-titlebar details.dropdown li { + padding: 0!important; + margin: 0!important; + border-bottom: 1px solid var(--app-border); +} + +.app-list-titlebar details.dropdown li:last-child { + border-bottom: none; +} + +.app-list-titlebar details.dropdown ul { + padding: 0!important; + margin: 0!important; +} + +.app-list-titlebar details.dropdown li button, .app-list-titlebar details.dropdown li [role=button] { + margin: 0 !important; + border: none; + border-radius: 0; + width: 100%; + text-align: left; +} \ No newline at end of file diff --git a/web/css/components/app-list-toolbar.css b/web/css/components/app-list-toolbar.css new file mode 100644 index 0000000..fb7198b --- /dev/null +++ b/web/css/components/app-list-toolbar.css @@ -0,0 +1,69 @@ +.app-list-toolbar { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 10px; + margin-bottom: calc(var(--app-spacing) * 1); +} + +.app-list-toolbar > * { + margin: 0 !important; + width: auto !important; + --app-form-element-spacing-horizontal: 10px; + --app-form-element-spacing-vertical: 6px; + font-size: 13px !important; + height: auto !important; +} +.app-list-toolbar > * > * { + margin: 0 !important; + width: auto !important; + --app-form-element-spacing-horizontal: 10px; + --app-form-element-spacing-vertical: 6px; + font-size: 13px !important; + height: auto !important; +} + +.app-list-toolbar + input:not( + [type="checkbox"], + .app-list-toolbar [type="radio"], + .app-list-toolbar [type="range"], + .app-list-toolbar [type="file"] + ):is( + [type="date"], + [type="datetime-local"], + [type="month"], + [type="time"], + [type="week"] + ) { + width: auto; +} + +.app-list-toolbar > label > span { + display: block; + font-size: 11px !important; +} + +.app-list-toolbar + .multi-select + .multi-select-header + .multi-select-header-placeholder { + font-size: 13px; +} + +.app-list-toolbar .multi-select .multi-select-header, .app-list-toolbar .multi-select .multi-select-option, .app-list-toolbar .multi-select .multi-select-all { + min-height: unset; + padding-left: 5px; +} + +.app-list-toolbar .multi-select { + width: 200px !important; +} + +.app-list-toolbar span.multi-select-header-option { + background: transparent !important; + border: 0 !important; + padding: 0 !important; + padding-left: 3px !important; + font-size: 11px !important; +} \ No newline at end of file diff --git a/web/css/components/app-page-copy.css b/web/css/components/app-page-copy.css new file mode 100644 index 0000000..c06755e --- /dev/null +++ b/web/css/components/app-page-copy.css @@ -0,0 +1,10 @@ + + +.app-page-copy .app-field { + min-width: 200px; +} + + +.app-page-copy .app-field [role="group"] { + margin-bottom: 0; +} \ No newline at end of file diff --git a/web/css/components/app-page-editor.css b/web/css/components/app-page-editor.css new file mode 100644 index 0000000..b3c4798 --- /dev/null +++ b/web/css/components/app-page-editor.css @@ -0,0 +1,74 @@ +.app-page-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--app-spacing); + margin-bottom: var(--app-spacing); +} + +.app-page-header > div { + display: flex; + align-items: center; + gap: var(--app-spacing); +} + +.app-page-header > div > * { + margin-bottom: 0; + width: auto; +} + +.app-page-header button, +.app-page-header input { + margin-bottom: 0; + width: auto; +} + +.app-page-header h1 { + margin: 0; +} + + + +label.app-field > span { + display: block; +} + +label.app-field > small { + display: block; +} + + +.page-editor-actions { + margin-top: var(--app-spacing); + display: flex; + gap: var(--app-spacing); + justify-content: flex-end; +} + +.page-editor[data-edit-mode="view"] .page-editor-actions { + display: none; +} + +.page-editor[data-edit-mode="view"] .ce-toolbar, +.page-editor[data-edit-mode="view"] .ce-inline-toolbar, +.page-editor[data-edit-mode="view"] .ce-popover { + display: none !important; +} + +.ce-block__content, .ce-toolbar__content { + max-width: 90%!important; +} + +.ce-editorjsColumns_wrapper .ce-toolbar__content, +.ce-editorjsColumns_wrapper .ce-block__content { + max-width: 100% ! Important; +} + +.ce-popover-item[data-item-name="columns"] svg { + width: 14px; + height: 14px; +} + +.app-details-aside-section button { + margin-bottom: 0; +} \ No newline at end of file diff --git a/web/css/components/app-profile.css b/web/css/components/app-profile.css new file mode 100644 index 0000000..41a466e --- /dev/null +++ b/web/css/components/app-profile.css @@ -0,0 +1,570 @@ +.app-profile-card { + border: 1px solid var(--app-border); + background: var(--app-card-background-color); + overflow: hidden; + border-radius: var(--app-border-radius); + margin-bottom: var(--app-spacing); +} + +.app-profile-header { + display: flex; + align-items: flex-start; + padding: 0 calc(var(--app-spacing) * 1) 0 calc(var(--app-spacing) * 1); + flex-direction: column; + justify-content: center; + margin-top: -42px; + z-index: 1; + position: relative; +} + +.app-profile-meta h2 { + margin: 0; +} + +.app-profile-meta p { + margin: 0.25rem 0 0; + color: var(--app-muted-color); +} + +.app-profile-body { + border: 1px solid var(--app-border); + background: var(--app-card-background-color); + overflow: hidden; + border-radius: var(--app-border-radius); + margin-bottom: var(--app-spacing); +} + +.app-profile-body [data-tab-panel] { + padding-inline: var(--app-spacing); +} + +.app-profile-body [data-tab-panel]:not(:has(p)) { + padding-block-end: var(--app-spacing); +} + +.app-profile-table { + width: 100%; + border: 1px solid var(--app-border); + border-radius: var(--app-border-radius); + border-collapse: separate; + border-spacing: 0; + background: transparent; + overflow: hidden; +} + +.app-profile-table th, +.app-profile-table td { + padding: 0.55rem 0.75rem; + background: transparent; + border-bottom: 1px solid var(--app-border); + text-align: left; + vertical-align: top; +} + +.app-profile-table thead th { + font-weight: 600; +} + +.app-profile-table tr:last-child td { + border-bottom: 0; +} + +@keyframes ani-app-profile-banner { + 0% { + --c-0: hsla(212, 0%, 0%, 1); + --s-start-0: 14.489998991212337%; + --s-end-0: 72%; + --y-0: 93%; + --x-0: 93%; + --c-1: hsla(212, 0%, 0%, 1); + --s-start-1: 0%; + --s-end-1: 45%; + --y-1: 9%; + --x-1: 26%; + --x-2: 15%; + --s-start-2: 2.9253667596993065%; + --s-end-2: 22.388851682060018%; + --c-2: hsla(257, 91%, 27%, 0.35); + --y-2: 79%; + --x-3: 40%; + --s-start-3: 3.985353824694249%; + --s-end-3: 47.580278608924694%; + --y-3: 104%; + --c-3: hsla(212, 100%, 50%, 0.5); + --y-4: 60%; + --x-4: 0%; + --c-4: hsla(224, 72%, 36%, 1); + --s-start-4: 2.391200382592061%; + --s-end-4: 29.307684556768592%; + --s-start-5: 2.9253667596993065%; + --s-end-5: 22.388851682060018%; + --y-5: 37%; + --c-5: hsla(248, 52%, 24%, 1); + --x-5: 92%; + --x-6: 101%; + --y-6: 16%; + --s-start-6: 13.173642363290591%; + --s-end-6: 31.747336520355095%; + --c-6: hsla(212, 100%, 50%, 0.19); + --y-7: 13%; + --s-start-7: 1%; + --s-end-7: 31%; + --x-7: 90%; + --c-7: hsla(227, 98%, 53%, 1); + --y-8: 56%; + --s-start-8: 3.985353824694249%; + --s-end-8: 13.103042116379756%; + --c-8: hsla(166, 71%, 60%, 0.32); + --x-8: 104%; + --c-9: hsla(219, 83%, 23%, 0.18); + --s-start-9: 18.597054544690312%; + --s-end-9: 31%; + --x-9: 97%; + --y-9: 19%; + } + + 100% { + --c-0: hsla(306, 0%, 0%, 1); + --s-start-0: 2.391200382592061%; + --s-end-0: 43.902064173373226%; + --y-0: 9%; + --x-0: 7%; + --c-1: hsla(306, 0%, 0%, 1); + --s-start-1: 9%; + --s-end-1: 54.805582404585024%; + --y-1: 93%; + --x-1: 96%; + --x-2: -2%; + --s-start-2: 3%; + --s-end-2: 26.722813338714598%; + --c-2: hsla(166, 72%, 60%, 1); + --y-2: 103%; + --x-3: 33%; + --s-start-3: 2.391200382592061%; + --s-end-3: 32.0689540200964%; + --y-3: 82%; + --c-3: hsla(180, 100%, 50%, 0.26); + --y-4: 81%; + --x-4: 37%; + --c-4: hsla(212, 88%, 26%, 0.58); + --s-start-4: 4.40642490323111%; + --s-end-4: 37.23528104246256%; + --s-start-5: 3%; + --s-end-5: 32.537089799783296%; + --y-5: 99%; + --c-5: hsla(271, 98%, 53%, 0.31); + --x-5: 54%; + --x-6: 104%; + --y-6: 43%; + --s-start-6: 6%; + --s-end-6: 42.501105312974815%; + --c-6: hsla(262, 100%, 50%, 0.15); + --y-7: -16%; + --s-start-7: 5%; + --s-end-7: 13.10107024898374%; + --x-7: 104%; + --c-7: hsla(298, 36%, 23%, 1); + --y-8: 30%; + --s-start-8: 2.391200382592061%; + --s-end-8: 27.141813016850573%; + --c-8: hsla(180, 100%, 50%, 0.11); + --x-8: 97%; + --c-9: hsla(219, 83%, 23%, 0.59); + --s-start-9: 5%; + --s-end-9: 21.32164536610654%; + --x-9: 78%; + --y-9: 4%; + } +} + +@property --c-0 { + syntax: ""; + inherits: false; + initial-value: hsla(212, 0%, 0%, 1); +} + +@property --s-start-0 { + syntax: ""; + inherits: false; + initial-value: 14.489998991212337%; +} + +@property --s-end-0 { + syntax: ""; + inherits: false; + initial-value: 72%; +} + +@property --y-0 { + syntax: ""; + inherits: false; + initial-value: 93%; +} + +@property --x-0 { + syntax: ""; + inherits: false; + initial-value: 93%; +} + +@property --c-1 { + syntax: ""; + inherits: false; + initial-value: hsla(212, 0%, 0%, 1); +} + +@property --s-start-1 { + syntax: ""; + inherits: false; + initial-value: 0%; +} + +@property --s-end-1 { + syntax: ""; + inherits: false; + initial-value: 45%; +} + +@property --y-1 { + syntax: ""; + inherits: false; + initial-value: 9%; +} + +@property --x-1 { + syntax: ""; + inherits: false; + initial-value: 26%; +} + +@property --x-2 { + syntax: ""; + inherits: false; + initial-value: 15%; +} + +@property --s-start-2 { + syntax: ""; + inherits: false; + initial-value: 2.9253667596993065%; +} + +@property --s-end-2 { + syntax: ""; + inherits: false; + initial-value: 22.388851682060018%; +} + +@property --c-2 { + syntax: ""; + inherits: false; + initial-value: hsla(257, 91%, 27%, 0.35); +} + +@property --y-2 { + syntax: ""; + inherits: false; + initial-value: 79%; +} + +@property --x-3 { + syntax: ""; + inherits: false; + initial-value: 40%; +} + +@property --s-start-3 { + syntax: ""; + inherits: false; + initial-value: 3.985353824694249%; +} + +@property --s-end-3 { + syntax: ""; + inherits: false; + initial-value: 47.580278608924694%; +} + +@property --y-3 { + syntax: ""; + inherits: false; + initial-value: 104%; +} + +@property --c-3 { + syntax: ""; + inherits: false; + initial-value: hsla(212, 100%, 50%, 0.5); +} + +@property --y-4 { + syntax: ""; + inherits: false; + initial-value: 60%; +} + +@property --x-4 { + syntax: ""; + inherits: false; + initial-value: 0%; +} + +@property --c-4 { + syntax: ""; + inherits: false; + initial-value: hsla(224, 72%, 36%, 1); +} + +@property --s-start-4 { + syntax: ""; + inherits: false; + initial-value: 2.391200382592061%; +} + +@property --s-end-4 { + syntax: ""; + inherits: false; + initial-value: 29.307684556768592%; +} + +@property --s-start-5 { + syntax: ""; + inherits: false; + initial-value: 2.9253667596993065%; +} + +@property --s-end-5 { + syntax: ""; + inherits: false; + initial-value: 22.388851682060018%; +} + +@property --y-5 { + syntax: ""; + inherits: false; + initial-value: 37%; +} + +@property --c-5 { + syntax: ""; + inherits: false; + initial-value: hsla(248, 52%, 24%, 1); +} + +@property --x-5 { + syntax: ""; + inherits: false; + initial-value: 92%; +} + +@property --x-6 { + syntax: ""; + inherits: false; + initial-value: 101%; +} + +@property --y-6 { + syntax: ""; + inherits: false; + initial-value: 16%; +} + +@property --s-start-6 { + syntax: ""; + inherits: false; + initial-value: 13.173642363290591%; +} + +@property --s-end-6 { + syntax: ""; + inherits: false; + initial-value: 31.747336520355095%; +} + +@property --c-6 { + syntax: ""; + inherits: false; + initial-value: hsla(212, 100%, 50%, 0.19); +} + +@property --y-7 { + syntax: ""; + inherits: false; + initial-value: 13%; +} + +@property --s-start-7 { + syntax: ""; + inherits: false; + initial-value: 1%; +} + +@property --s-end-7 { + syntax: ""; + inherits: false; + initial-value: 31%; +} + +@property --x-7 { + syntax: ""; + inherits: false; + initial-value: 90%; +} + +@property --c-7 { + syntax: ""; + inherits: false; + initial-value: hsla(227, 98%, 53%, 1); +} + +@property --y-8 { + syntax: ""; + inherits: false; + initial-value: 56%; +} + +@property --s-start-8 { + syntax: ""; + inherits: false; + initial-value: 3.985353824694249%; +} + +@property --s-end-8 { + syntax: ""; + inherits: false; + initial-value: 13.103042116379756%; +} + +@property --c-8 { + syntax: ""; + inherits: false; + initial-value: hsla(166, 71%, 60%, 0.32); +} + +@property --x-8 { + syntax: ""; + inherits: false; + initial-value: 104%; +} + +@property --c-9 { + syntax: ""; + inherits: false; + initial-value: hsla(219, 83%, 23%, 0.18); +} + +@property --s-start-9 { + syntax: ""; + inherits: false; + initial-value: 18.597054544690312%; +} + +@property --s-end-9 { + syntax: ""; + inherits: false; + initial-value: 31%; +} + +@property --x-9 { + syntax: ""; + inherits: false; + initial-value: 97%; +} + +@property --y-9 { + syntax: ""; + inherits: false; + initial-value: 19%; +} + +.app-profile-banner { + --c-0: hsla(212, 0%, 0%, 1); + --y-0: 93%; + --x-0: 93%; + --c-1: hsla(212, 0%, 0%, 1); + --y-1: 9%; + --x-1: 26%; + --x-2: 15%; + --c-2: hsla(257, 91%, 27%, 0.35); + --y-2: 79%; + --x-3: 40%; + --y-3: 104%; + --c-3: hsla(212, 100%, 50%, 0.5); + --y-4: 60%; + --x-4: 0%; + --c-4: hsla(224, 72%, 36%, 1); + --y-5: 37%; + --c-5: hsla(248, 52%, 24%, 1); + --x-5: 92%; + --x-6: 101%; + --y-6: 16%; + --c-6: hsla(212, 100%, 50%, 0.19); + --y-7: 13%; + --x-7: 90%; + --c-7: hsla(227, 98%, 53%, 1); + --y-8: 56%; + --c-8: hsla(166, 71%, 60%, 0.32); + --x-8: 104%; + --c-9: hsla(219, 83%, 23%, 0.18); + --x-9: 97%; + --y-9: 19%; + background-color: hsla(305, 0%, 0%, 1); + background-image: + radial-gradient( + circle at var(--x-0) var(--y-0), + var(--c-0) var(--s-start-0), + transparent var(--s-end-0) + ), + radial-gradient( + circle at var(--x-1) var(--y-1), + var(--c-1) var(--s-start-1), + transparent var(--s-end-1) + ), + radial-gradient( + circle at var(--x-2) var(--y-2), + var(--c-2) var(--s-start-2), + transparent var(--s-end-2) + ), + radial-gradient( + circle at var(--x-3) var(--y-3), + var(--c-3) var(--s-start-3), + transparent var(--s-end-3) + ), + radial-gradient( + circle at var(--x-4) var(--y-4), + var(--c-4) var(--s-start-4), + transparent var(--s-end-4) + ), + radial-gradient( + circle at var(--x-5) var(--y-5), + var(--c-5) var(--s-start-5), + transparent var(--s-end-5) + ), + radial-gradient( + circle at var(--x-6) var(--y-6), + var(--c-6) var(--s-start-6), + transparent var(--s-end-6) + ), + radial-gradient( + circle at var(--x-7) var(--y-7), + var(--c-7) var(--s-start-7), + transparent var(--s-end-7) + ), + radial-gradient( + circle at var(--x-8) var(--y-8), + var(--c-8) var(--s-start-8), + transparent var(--s-end-8) + ), + radial-gradient( + circle at var(--x-9) var(--y-9), + var(--c-9) var(--s-start-9), + transparent var(--s-end-9) + ); + animation: ani-app-profile-banner 10s linear infinite alternate; + background-blend-mode: + normal, normal, normal, normal, normal, normal, normal, normal, normal, + normal; + will-change: transform, opacity; + contain: paint; + height: 160px; +} diff --git a/web/css/components/app-search.css b/web/css/components/app-search.css new file mode 100644 index 0000000..cfb21f5 --- /dev/null +++ b/web/css/components/app-search.css @@ -0,0 +1,137 @@ +.app-search { + padding: 0 var(--app-spacing); +} + +ul.app-search-results { + padding: 0; + margin: 0; +} + +ul.app-search-results > li > a { + justify-content: space-between; +} + +ul.app-search-results .badge { + font-size: 10px; + padding: 1px; + min-width: 20px; + text-align: center; + border-radius: 999px; + background: var(--app-accordion-border-color); + display: inline-flex; + justify-content: center; + align-items: center; + height: 20px; +} + +ul.app-search-preview { + position: relative; + font-size: 11px; + padding: 0 0 0 20px; + margin: 6px 0 1.5rem 10px; + opacity: 0.75; + list-style: none; +} + +/* Hide preview rows (detail results) */ +.search-details-hidden ul.app-search-preview { + display: none; +} +ul.app-search-preview::before { + content: ""; + position: absolute; + left: 9px; + top: 2px; + bottom: 20px; + width: 1px; + background: var(--app-border); + border-radius: 999px; +} + +ul.app-search-preview li { + position: relative; + padding: 0; +} + +ul.app-search-preview li::before { + content: ""; + position: absolute; + left: -11px; + bottom: 11px; + width: 8px; + height: 10px; + background: transparent; + border-left: 1px solid var(--app-border); + border-bottom: 1px solid var(--app-border); + border-bottom-left-radius: 6px; +} + +ul.app-search-preview a { + padding-inline: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: block; + border: none; +} + +ul.app-search-preview a:hover { + border: none; +} + +input#side-search { + --app-form-element-spacing-horizontal: 10px; + --app-form-element-spacing-vertical: 6px; + height: auto; + font-size: 13px; +} + +ul.app-search-preview:has(li) { + margin-bottom: 1rem!important; +} + +.search-result-row { + display: flex; + gap: 12px; + align-items: flex-start; +} + +.search-reuslt-title-container { + display: flex; + align-items: center; + gap: 10px; + flex-wrap: wrap; +} + +.search-result-avatar, +.search-result-avatar-placeholder { + width: 40px; + height: 40px; + border-radius: 10px; + border: 1px solid var(--app-border); + background: var(--app-card-background-color); + display: inline-flex; + align-items: center; + justify-content: center; + color: var(--app-muted-color); + flex-shrink: 0; + object-fit: cover; +} + + + +.search-result-title { + font-weight: 600; + text-decoration: none; +} + +.search-result-desc { + margin: 0; + color: var(--app-muted-color); + font-size: small; +} + +.search-result-type { + color: var(--app-muted-color); + font-weight: 600; +} diff --git a/web/css/components/app-tabs.css b/web/css/components/app-tabs.css new file mode 100644 index 0000000..9eddcb2 --- /dev/null +++ b/web/css/components/app-tabs.css @@ -0,0 +1,53 @@ +:root { + --tabs-border: var(--app-border); + --tabs-active: var(--app-primary); + --tabs-muted: var(--app-muted-color); +} + +.app-tabs { + display: flex; + flex-direction: column; + gap: var(--app-spacing); +} + +.app-tabs-nav { + display: flex; + border-bottom: 1px solid var(--tabs-border); + overflow-x: auto; + -webkit-overflow-scrolling: touch; + padding-block-start: 2px; + padding-left: 2px; +} + +.app-tabs-nav button, +.app-tabs-nav a { + background: transparent; + border: 0; + padding: 5px 10px 5px 10px; + color: var(--tabs-muted) !important; + cursor: pointer; + font-weight: 500; + border-bottom: 2px solid transparent; + text-decoration: none; + border-radius: 0; + margin-bottom: 0; +} + +.app-tabs-nav button:hover, +.app-tabs-nav button:focus-visible, +.app-tabs-nav a:hover, +.app-tabs-nav a:focus-visible { + --app-color: inherit; + color: var(--app-color) !important; +} + +.app-tabs-nav button.is-active, +.app-tabs-nav a.is-active { + --app-color: inherit; + color: var(--app-color) !important; + border-color: var(--tabs-active); +} + +[data-tab-panel][hidden] { + display: none; +} diff --git a/web/css/components/app-tile.css b/web/css/components/app-tile.css new file mode 100644 index 0000000..f80c3f6 --- /dev/null +++ b/web/css/components/app-tile.css @@ -0,0 +1,111 @@ +:root { + --app-tile-bg: var(--app-card-background-color); + --app-tile-border: var(--app-muted-border-color); + --app-tile-shadow: var(--app-box-shadow); + --app-tile-icon-bg: rgba(0, 0, 0, 0.04); + --app-tile-icon-color: var(--app-contrast); + --app-tile-count-color: var(--app-contrast); + --app-tile-label-color: var(--app-color); + --app-tile-link-color: var(--app-muted-color); +} + +[data-theme="dark"] { + --app-tile-bg: rgba(20, 24, 32, 0.6); + --app-tile-border: rgba(255, 255, 255, 0.08); + --app-tile-shadow: 0 10px 30px rgba(0, 0, 0, 0.25); + --app-tile-icon-bg: rgba(255, 255, 255, 0.08); + --app-tile-icon-color: #e6ecff; + --app-tile-count-color: #f1f5ff; + --app-tile-label-color: #d1d7e3; + --app-tile-link-color: #98a2b3; +} + + +.app-tiles { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); + gap: calc(var(--app-spacing) * 1); + margin-bottom: calc(var(--app-spacing) * 2); +} + + +.app-stats-table { + overflow: auto; + border: 1px solid var(--app-border); + border-radius: var(--app-border-radius); + margin-bottom: calc(var(--app-spacing) * 1); +} + +.app-stats-table th { + border-top: 0; +} + +.app-stats-table table { + margin: 0; +} + +.app-stats-table table tr:last-child td { + border-bottom: 0; +} + +.app-tile { + --tile-icon-bg: var(--app-tile-icon-bg); + --tile-icon-color: var(--app-tile-icon-color); + --tile-count-color: var(--app-tile-count-color); + --tile-label-color: var(--app-tile-label-color); + --tile-link-color: var(--app-tile-link-color); + position: relative; + display: block; + padding: calc(var(--app-spacing) * 1); + border: 1px solid var(--app-tile-border); + border-radius: calc(var(--app-border-radius) * 1.1); + background: var(--app-tile-bg); + color: var(--app-tile-label-color); + text-decoration: none; + transition: transform var(--app-transition), box-shadow var(--app-transition), border-color var(--app-transition); +} + +.app-tile:hover { + box-shadow: 0 12px 30px rgba(0, 0, 0, 0.08); +} + +.app-tile-icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 36px; + height: 36px; + border-radius: 10px; + background: var(--tile-icon-bg); + color: var(--tile-icon-color); + font-size: 1.1rem; +} + +.app-tile-count { + position: absolute; + top: calc(var(--app-spacing) * 1); + right: calc(var(--app-spacing) * 1); + font-weight: 700; + color: var(--tile-count-color); +} + +.app-tile-label { + display: block; + margin-top: calc(var(--app-spacing) * 1); + font-weight: 600; + color: var(--tile-label-color); +} + +.app-tile-link { + position: absolute; + right: calc(var(--app-spacing) * 1); + bottom: calc(var(--app-spacing) * 1); + color: var(--tile-link-color); + font-size: 0.9rem; +} + +@media (max-width: 640px) { + .app-tiles { + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + } +} diff --git a/web/css/components/app-tooltips.css b/web/css/components/app-tooltips.css new file mode 100644 index 0000000..cd0d1ac --- /dev/null +++ b/web/css/components/app-tooltips.css @@ -0,0 +1,108 @@ +:root { + --tooltip-bg: var(--app-card-background-color); + --tooltip-color: var(--app-color); + --tooltip-border: var(--app-border); + --tooltip-shadow: 0 6px 18px rgba(0, 0, 0, 0.12); + --tooltip-radius: 8px; + --tooltip-offset: 8px; +} + +[data-tooltip] { + --app-card-background-color: inherit; + position: relative; +} + +[data-tooltip]::after, +[data-tooltip]::before { + pointer-events: none; + opacity: 0; + transition: opacity 0.15s ease, transform 0.15s ease; + position: absolute; + z-index: 40; + text-decoration: none; +} + +[data-tooltip]::after { + content: attr(data-tooltip); + background: var(--tooltip-bg); + color: var(--tooltip-color); + border: 1px solid var(--tooltip-border); + border-radius: var(--tooltip-radius); + box-shadow: var(--tooltip-shadow); + font-size: 0.75rem; + padding: 0.35rem 0.6rem; + white-space: nowrap; +} + +[data-tooltip]::before { + content: ''; + width: 8px; + height: 8px; + background: var(--tooltip-bg); + border-left: 1px solid var(--tooltip-border); + border-top: 1px solid var(--tooltip-border); + transform: rotate(45deg); +} + +[data-tooltip]:hover::after, +[data-tooltip]:hover::before, +[data-tooltip]:focus-visible::after, +[data-tooltip]:focus-visible::before { + opacity: 1; +} + +[data-tooltip]::after, +[data-tooltip]::before { + top: 50%; + left: 100%; +} + +[data-tooltip]::after { + transform: translate(var(--tooltip-offset), -50%); +} + +[data-tooltip]::before { + transform: translate(calc(var(--tooltip-offset) - 4px), -50%) rotate(45deg); +} + +[data-tooltip][data-tooltip-pos="top"]::after, +[data-tooltip][data-tooltip-pos="center"]::after { + bottom: 100%; + left: 50%; + top: auto; + transform: translate(-50%, calc(-1 * var(--tooltip-offset))); +} + +[data-tooltip][data-tooltip-pos="top"]::before, +[data-tooltip][data-tooltip-pos="center"]::before { + bottom: 100%; + left: 50%; + top: auto; + transform: translate(-50%, calc(-1 * (var(--tooltip-offset) - 2px))) rotate(45deg); +} + +[data-tooltip][data-tooltip-pos="bottom"]::after { + top: 100%; + left: 50%; + transform: translate(-50%, var(--tooltip-offset)); +} + +[data-tooltip][data-tooltip-pos="bottom"]::before { + top: 100%; + left: 50%; + transform: translate(-50%, calc(var(--tooltip-offset) - 2px)) rotate(45deg); +} + +[data-tooltip][data-tooltip-pos="left"]::after { + top: 50%; + right: 100%; + left: auto; + transform: translate(calc(-1 * var(--tooltip-offset)), -50%); +} + +[data-tooltip][data-tooltip-pos="left"]::before { + top: 50%; + right: 100%; + left: auto; + transform: translate(calc(-1 * (var(--tooltip-offset) - 2px)), -50%) rotate(45deg); +} diff --git a/web/css/components/vendor-editorjs.css b/web/css/components/vendor-editorjs.css new file mode 100644 index 0000000..0f8a3b6 --- /dev/null +++ b/web/css/components/vendor-editorjs.css @@ -0,0 +1,74 @@ +.codex-editor { + font-family: var(--app-font-family); + color: var(--app-color); +} + +.ce-block__content { + max-width: 90%; +} + +.ce-toolbar__content, +.ce-inline-toolbar { + border-radius: var(--app-border-radius); +} + +.ce-inline-toolbar { + box-shadow: var(--app-box-shadow); +} + +.ce-toolbar__content { + max-width: 90%; +} + +input.cdx-search-field__input { + margin: 0; + padding: 5px; + height: auto; + border-radius: 0; +} + +.cdx-search-field__icon { + width: 36px; + height: 36px; + margin-right: 0; +} + +.ce-popover__items button { + background: transparent; + color: inherit; + padding: inherit; + border: 0; + align-items: center; + justify-content: center; + display: flex; + margin: 0; +} + +input.ce-inline-tool-input.ce-inline-tool-input--showed { + margin: 0; +} + +table.tc-table { + margin: 0; +} + +.tc-cell { + border-left: 1px solid var(--color-border); +} + +.ce-toolbar__actions { + right: calc(100% + 10px)!important; + background-color: white!important; +} + +.ce-block--selected .ce-block__content { + background: var(--app-table-row-stripped-background-color); +} + +.ce-inline-tool svg { + color: black; +} + +.ce-popover--inline .ce-popover-item__icon svg { + color: black; +} \ No newline at end of file diff --git a/web/css/components/vendor-gridjs.css b/web/css/components/vendor-gridjs.css new file mode 100644 index 0000000..d6967b2 --- /dev/null +++ b/web/css/components/vendor-gridjs.css @@ -0,0 +1,207 @@ +.gridjs-container { + color: var(--app-color); + width: 100%; + padding: 0; +} + +.gridjs-wrapper { + border: 0; + border-radius: 0; + box-shadow: none; + background-color: var(--app-background-color); + border-top: var(--app-border-width) solid var(--app-table-border-color); + padding-block-end: 1rem; + min-height: 515px; +} + +.gridjs-footer { + background-color: var(--app-background-color); + border: 0; + border-top: 0; + box-shadow: none; + color: var(--app-muted-color); + padding: 1rem 0 0; +} + +.gridjs-table { + color: var(--app-color); +} + +th.gridjs-th { + padding: calc(var(--app-spacing) / 2) var(--app-spacing); + border: none; + border-bottom: var(--app-border-width) solid var(--app-table-border-color); + background-color: var(--app-background-color); + color: var(--app-color); + font-weight: var(--app-font-weight); + text-align: left; + text-align: start; +} + +button.gridjs-sort { + height: 15px; +} + +th.gridjs-th-sort:hover, +th.gridjs-th-sort:focus { + background-color: var(--app-table-row-stripped-background-color); +} + +td.gridjs-td { + background-color: var(--app-background-color); + border: none; + border-color: var(--app-table-border-color); + padding: calc(var(--app-spacing) / 2) var(--app-spacing); + border-bottom: var(--app-border-width) solid var(--app-table-border-color); + background-color: var(--app-background-color); + color: var(--app-color); + font-weight: var(--app-font-weight); + text-align: left; + text-align: start; +} + +.gridjs-search { + float: none; +} + +.gridjs-search-input { + width: min(320px, 100%); +} + +input.gridjs-input { + background-color: var(--app-background-color); + border: var(--app-border-width) solid var(--app-form-element-border-color); + border-radius: var(--app-border-radius); + color: var(--app-color); + font-size: 0.95rem; + padding: 0.5rem 0.75rem; +} + +input.gridjs-input:focus { + border-color: var(--app-primary); + box-shadow: 0 0 0 var(--app-outline-width) var(--app-primary-focus); +} + +.gridjs-pagination { + color: var(--app-muted-color); +} + +.gridjs-pagination .gridjs-pages button { + background-color: var(--app-background-color); + border: var(--app-border-width) solid var(--app-table-border-color); + color: var(--app-color); + padding: 0.4rem 0.7rem; +} + +.gridjs-pagination .gridjs-pages button:hover { + background-color: var(--app-primary-hover-background); + border-color: var(--app-primary-hover-border); + color: var(--app-primary-inverse); +} + +.gridjs-pagination .gridjs-pages button:focus { + box-shadow: 0 0 0 var(--app-outline-width) var(--app-primary-focus); +} + +.gridjs-pagination .gridjs-pages button.gridjs-currentPage { + background-color: var(--app-primary) !important; + font-weight: 400; + padding: 2px 10px; + color: var(--app-secondary-inverse) !important; +} + +.gridjs-pagination .gridjs-pages button:disabled, .gridjs-pagination .gridjs-pages button[disabled] { + background-color: var(--app-background-color); + color: var(--app-muted-color); + cursor: default; + padding: 2px 10px; + border: 0; +} + +.gridjs-pagination .gridjs-pages { + display: inline-flex; + gap: 5px; +} + +.gridjs-loading-bar { + background-color: var(--app-background-color); + opacity: 0.7; +} + +.grid-avatar { + width: 36px; + height: 36px; + border-radius: 999px; + border: 1px solid var(--app-muted-border-color); + background: var(--app-card-background-color); + object-fit: contain; + display: inline-flex; +} + +.grid-avatar-placeholder { + align-items: center; + justify-content: center; + font-weight: 600; + color: var(--app-muted-color); + font-size: 11px; + background: var(--app-background-color); +} + +.gridjs-loading-bar:after { + background-image: linear-gradient( + 90deg, + transparent, + var(--app-primary-focus), + transparent + ); +} + + /* .gridjs-container:not(.gridjs-has-loaded) .gridjs-message.gridjs-notfound { + display: none; + } */ + +.gridjs-container.gridjs-is-updating .gridjs-message.gridjs-notfound { + display: none; +} + +.gridjs-pages button { + background: var(--app-form-element-background-color) !important; + color: var(--app-contrast) !important; +} + +.gridjs-summary { + font-size: small; +} + +tr.gridjs-tr { + cursor: pointer; +} + +tr.gridjs-tr:hover td { + background: var(--app-table-row-stripped-background-color); +} + +html[data-theme=dark] button.gridjs-sort, +html[data-theme=dark] button.gridjs-sort-neutral { + filter: invert(1); +} + +.gridjs-tbody, td.gridjs-td { + background-color: var(--app-background-color) +} + +.gridjs-table input[data-grid-select-all] { + width: 1em; + height: 1em; + margin: 0; + border-radius: 4px; + border-width: .5px; +} + +.gridjs-th-content:has(input[data-grid-select-all]) { + text-align: center; +} + +.gridjs-pagination .gridjs-pages button:last-child { + border-right: none; +} \ No newline at end of file diff --git a/web/css/components/vendor-multi-select.css b/web/css/components/vendor-multi-select.css new file mode 100644 index 0000000..fc6af21 --- /dev/null +++ b/web/css/components/vendor-multi-select.css @@ -0,0 +1,130 @@ + +:root { + --spacing-smaller: 3px; + --spacing-small: 5px; + --spacing-medium: 7px; + --spacing-large: 12px; + --font-size: 12px; + --font-size-large: 14px; + --font-size-larger: 16px; + --line-height: 16px; + --line-height-larger: 20px; + --primary-color: var(--app-primary); + --text-color-dark: #212529; + --text-color: #585858; + --text-color-light: #65727e; + --border-color: #bebebe; + --border-color-light: #f1f3f5; + --input-placeholder: #65727e; + --input-background: #e9e9ed; + --input-border: #dee2e6; + --input-border-active: #c1c9d0; + --input-border-invalid: #e44e4e; + --input-outline-invalid: rgba(219, 138, 138, 0.5); + --input-color: #e9e9ed; + --input-disabled: #f7f7f7; + --input-min-height: 45px; + --options-height: 40dvh; + --option-background: #f3f4f7; + --border-radius: 5px; + --icon-size: 12px; + --icon-space: 30px; + --checkbox-size: 16px; + --checkbox-radius: 4px; + --checkbox-border: #ced4da; + --checkbox-background: #fff; + --checkbox-active: #fff; + --checkbox-thickness: 2px; +} +/* Overrides for MultiSelect */ +.multi-select { + --spacing-smaller: 3px; + --spacing-small: 5px; + --spacing-medium: 7px; + --spacing-large: 12px; + --font-size: 12px; + --font-size-large: 14px; + --font-size-larger: 16px; + --line-height: 16px; + --line-height-larger: 20px; + --primary-color: var(--app-primary); + --text-color-dark: var(--app-contrast); + --text-color: var(--app-muted-color); + --text-color-light: var(--app-muted-color); + --border-color: var(--app-form-element-border-color); + --border-color-light: var(--app-muted-border-color); + --input-placeholder: var(--app-form-element-placeholder-color); + --input-background: var(--app-form-element-background-color); + --input-border: var(--app-form-element-border-color); + --input-border-active: var(--app-primary-focus); + --input-border-invalid: var(--app-form-element-invalid-border-color); + --input-outline-invalid: var(--app-form-element-invalid-active-shadow); + --input-color: var(--app-form-element-color); + --input-disabled: var(--app-form-element-disabled-background-color); + --input-min-height: calc( + 1rem * var(--app-line-height) + var(--app-form-element-spacing-vertical) * + 2 + var(--app-border-width) * 2 + ); + --options-height: 40dvh; + --option-background: var(--badge-neutral-bg); + --border-radius: var(--app-border-radius); + --icon-size: 12px; + --icon-space: 30px; + --checkbox-size: 16px; + --checkbox-radius: 4px; + --checkbox-border: var(--app-form-element-border-color); + --checkbox-background: var(--app-form-element-background-color); + --checkbox-active: var(--app-form-element-background-color); + --checkbox-thickness: 2px; +} + +.multi-select + .multi-select-options + .multi-select-option + .multi-select-option-radio, +.multi-select + .multi-select-options + .multi-select-all + .multi-select-option-radio { + padding: 2px; +} +.multi-select + .multi-select-options + .multi-select-option + .multi-select-option-radio, +.multi-select + .multi-select-options + .multi-select-all + .multi-select-option-radio { + padding: 2px; +} + +.multi-select { + margin-bottom: var(--app-spacing); +} + +.multi-select.disabled { + opacity: 0.65; + cursor: not-allowed; +} + +.multi-select.disabled .multi-select-header, +.multi-select.disabled .multi-select-options { + pointer-events: none; +} + +.multi-select .multi-select-header { + background: var(--app-form-element-background-color); +} + +.multi-select .multi-select-options { + background: var(--app-form-element-background-color); +} + +.multi-select .multi-select-header .multi-select-header-option { + border: 1px solid var(--app-border); +} + +.multi-select .multi-select-header { + padding-left: 7px; +} diff --git a/web/css/layout/app-aside-icon-bar.css b/web/css/layout/app-aside-icon-bar.css new file mode 100644 index 0000000..91ebaf2 --- /dev/null +++ b/web/css/layout/app-aside-icon-bar.css @@ -0,0 +1,60 @@ +aside.aside-icon-bar { + display: none; +} + +aside.aside-icon-bar ul { + margin: 0; + padding: 0; + display: grid; + gap: 0; +} + +aside.aside-icon-bar li { + margin: 0; + padding: 0; +} +aside.aside-icon-bar li a, +aside.aside-icon-bar li button { + margin: 0; + padding: 0.5rem; + font-size: 20px; + text-align: center; + color: var(--app-muted-color); + border-radius: 0; + background: transparent; + border: 0; + border-left: 3px solid transparent; + display: block; + width: 100%; + cursor: pointer; +} +aside.aside-icon-bar li a:hover, aside.aside-icon-bar li a.active, aside.aside-icon-bar li button:hover, aside.aside-icon-bar li button.active { + border-left: 3px solid var(--app-primary); + color: var(--app-contrast); + background: var(--app-accordion-border-color); +} + +aside.aside-icon-bar nav { + display: flex; + flex-direction: column; + justify-content: space-between; + height: calc(100vh - var(--app-spacing)); +} + +/* aside.aside-icon-bar ul.aside-icon-group li:first-child { + margin-bottom: 1rem; +} */ + +@media (min-width: 768px) { + aside.aside-icon-bar { + border-right: 1px solid var(--app-border); + display: block; + position: sticky; + top: 0; + z-index: 11; + padding-top: var(--app-spacing); + } + .is-sidebar-collapsed aside.aside-icon-bar { + border-right: 0; + } +} diff --git a/web/css/layout/app-shell.css b/web/css/layout/app-shell.css new file mode 100644 index 0000000..9416fe9 --- /dev/null +++ b/web/css/layout/app-shell.css @@ -0,0 +1,2978 @@ +@charset "UTF-8"; + +a { + --app-text-decoration: underline; +} + +a.contrast, +a.secondary { + --app-text-decoration: underline; +} + +small { + --app-font-size: 0.875em; +} + +div#debugger-bar { + display: none; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + --app-font-weight: 700; +} + +h1 { + --app-font-size: 1.8rem; + --app-line-height: 1.125; + --app-typography-spacing-top: 3rem; +} + +h2 { + --app-font-size: 1.6rem; + --app-line-height: 1.15; + --app-typography-spacing-top: 2.625rem; +} + +h3 { + --app-font-size: 1.3rem; + --app-line-height: 1.175; + --app-typography-spacing-top: 2.25rem; +} + +h4 { + --app-font-size: 1.2rem; + --app-line-height: 1.2; + --app-typography-spacing-top: 1.874rem; +} + +h5 { + --app-font-size: 1.1rem; + --app-line-height: 1.225; + --app-typography-spacing-top: 1.6875rem; +} + +h6 { + --app-font-size: 1rem; + --app-line-height: 1.25; + --app-typography-spacing-top: 1.5rem; +} + +tfoot td, +tfoot th, +thead td, +thead th { + --app-font-weight: 600; + --app-border-width: 2px; +} + +code, +kbd, +pre, +samp { + --app-font-family: var(--app-font-family-monospace); +} + +kbd { + --app-font-weight: bolder; +} + +:where(select, textarea), +input:not( + [type="submit"], + [type="button"], + [type="reset"], + [type="checkbox"], + [type="radio"], + [type="file"] +) { + --app-outline-width: 0.0625rem; +} + +[type="checkbox"], +[type="radio"] { + --app-border-width: 0.125rem; +} + +[type="checkbox"][role="switch"] { + --app-border-width: 0.1875rem; +} + +details.dropdown summary:not([role="button"]) { + --app-outline-width: 0.0625rem; +} + +nav details.dropdown summary:focus-visible { + --app-outline-width: 0.125rem; +} + +[role="search"] { + --app-border-radius: 5rem; +} + +[role="group"]:has( + button.secondary:focus, + [type="submit"].secondary:focus, + [type="button"].secondary:focus, + [role="button"].secondary:focus +), +[role="search"]:has( + button.secondary:focus, + [type="submit"].secondary:focus, + [type="button"].secondary:focus, + [role="button"].secondary:focus +) { + --app-group-box-shadow-focus-with-button: 0 0 0 var(--app-outline-width) + var(--app-secondary-focus); +} + +[role="group"]:has( + button.contrast:focus, + [type="submit"].contrast:focus, + [type="button"].contrast:focus, + [role="button"].contrast:focus +), +[role="search"]:has( + button.contrast:focus, + [type="submit"].contrast:focus, + [type="button"].contrast:focus, + [role="button"].contrast:focus +) { + --app-group-box-shadow-focus-with-button: 0 0 0 var(--app-outline-width) + var(--app-contrast-focus); +} + +[role="group"] [role="button"], +[role="group"] [type="button"], +[role="group"] [type="submit"], +[role="group"] button, +[role="search"] [role="button"], +[role="search"] [type="button"], +[role="search"] [type="submit"], +[role="search"] button { + --app-form-element-spacing-horizontal: 2rem; +} + +[role="group"] form:last-child button { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +table td [role="group"] { + margin: 0; +} + +th { + text-transform: uppercase; + font-size: 11px; + letter-spacing: 0.4px; + border-top: 1px solid var(--app-border); +} + +table td .grid-actions button, +table td .grid-actions [role="button"] { + padding: 4px 10px; + color: var(--app-muted-color); + border: 1px solid var(--app-border); + font-size: small; + background: var(--app-form-element-active-background-color); + box-shadow: var(--app-group-box-shadow); +} + +table td .grid-actions button:has(i), +table td .grid-actions [role="button"]:has(i) { + max-width: 42px; +} + +table td .grid-actions button:hover, +table td .grid-actions [role="button"]:hover { + color: var(--app-contrast); +} + +details summary[role="button"]:not(.outline)::after { + filter: brightness(0) invert(1); +} + +[aria-busy="true"]:not(input, select, textarea):is( + button, + [type="submit"], + [type="button"], + [type="reset"], + [role="button"] + ):not(.outline)::before { + filter: brightness(0) invert(1); +} + +@media only screen and (prefers-color-scheme: dark) { + :host(:not([data-theme])) + details + summary[role="button"].contrast:not(.outline)::after, + :root:not([data-theme]) + details + summary[role="button"].contrast:not(.outline)::after { + filter: brightness(0); + } + + :host(:not([data-theme])) + [aria-busy="true"]:not(input, select, textarea).contrast:is( + button, + [type="submit"], + [type="button"], + [type="reset"], + [role="button"] + ):not(.outline)::before, + :root:not([data-theme]) + [aria-busy="true"]:not(input, select, textarea).contrast:is( + button, + [type="submit"], + [type="button"], + [type="reset"], + [role="button"] + ):not(.outline)::before { + filter: brightness(0); + } +} + +[data-theme="dark"] + details + summary[role="button"].contrast:not(.outline)::after { + filter: brightness(0); +} + +[data-theme="dark"] + [aria-busy="true"]:not(input, select, textarea).contrast:is( + button, + [type="submit"], + [type="button"], + [type="reset"], + [role="button"] + ):not(.outline)::before { + filter: brightness(0); +} + +[type="checkbox"], +[type="radio"], +[type="range"], +progress { + accent-color: var(--app-primary); +} + +*, +::after, +::before { + box-sizing: border-box; + background-repeat: no-repeat; +} + +::after, +::before { + text-decoration: inherit; + vertical-align: inherit; +} + +:where(:host), +:where(:root) { + -webkit-tap-highlight-color: transparent; + -webkit-text-size-adjust: 100%; + -moz-text-size-adjust: 100%; + text-size-adjust: 100%; + background-color: var(--app-background-color); + color: var(--app-color); + font-weight: var(--app-font-weight); + font-size: var(--app-font-size); + line-height: var(--app-line-height); + font-family: var(--app-font-family); + text-underline-offset: var(--app-text-underline-offset); + text-rendering: optimizeLegibility; + overflow-wrap: break-word; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; +} + +body { + width: 100%; + margin: 0; +} + +main { + display: block; +} + +body > footer, +body > main { + padding-block: var(--app-block-spacing-vertical); +} + +body > footer { + padding-inline: calc(var(--app-spacing) * 2); +} + +footer.site-footer { + padding-inline: calc(var(--app-spacing) * 2); + border-top: 1px solid var(--app-border); +} + +footer.site-footer a { + color: inherit; +} + +body > footer a { + color: inherit; +} +header[data-align="center"], +hgroup[data-align="center"] > h1, +hgroup[data-align="center"] > h2, +hgroup[data-align="center"] > h3, +hgroup[data-align="center"] > p, +hgroup[data-align="center"] > *, +hgroup[data-align="center"] { + text-align: center; + justify-content: center; +} + +section { + margin-bottom: var(--app-block-spacing-vertical); +} + +.container-small { + max-width: 420px; + margin-right: auto; + margin-left: auto; +} + +.container, +.container-fluid { + width: 100%; + margin-right: auto; + margin-left: auto; + padding-right: var(--app-spacing); + padding-left: var(--app-spacing); +} + +.app-main-content { + padding-inline: calc(var(--app-spacing) * 1); +} + +@media (min-width: 576px) { + .container { + max-width: 510px; + padding-right: 0; + padding-left: 0; + } +} + +@media (min-width: 768px) { + .container { + max-width: 700px; + } + .app-container:has(.aside-icon-bar):has(.app-sidebar) { + display: grid; + min-height: 100dvh; + align-items: flex-start; + grid-template-columns: minmax(0, 60px) minmax(0, 220px) minmax(0, 1fr); + } + .app-container.is-sidebar-collapsed:has(.aside-icon-bar):has(.app-sidebar) { + display: grid; + min-height: 100dvh; + align-items: flex-start; + grid-template-columns: minmax(0, 60px) minmax(0, 1fr); + } + + .app-container.is-sidebar-collapsed { + grid-template-columns: minmax(0, 60px) minmax(0, 1fr); + } + + .sidebar-collapsed .app-container { + grid-template-columns: minmax(0, 60px) minmax(0, 1fr); + } + + .app-main { + border-left: 1px solid var(--app-border); + min-height: 100dvh; + background: var(--app-background-color); + } + + .app-main-content { + padding-inline: calc(var(--app-spacing) * 2); + margin-bottom: calc(var(--app-spacing) * 2); + } + .app-main-content:has(.app-details-container) { + margin-bottom: 0; + padding: 0; + } +} + +@media (min-width: 1024px) { + .container { + max-width: 950px; + } +} + +@media (min-width: 1280px) { + .container { + max-width: 1200px; + } +} + +@media (min-width: 1536px) { + .container { + max-width: 1450px; + } +} + +.grid { + grid-column-gap: var(--app-grid-column-gap); + grid-row-gap: var(--app-grid-row-gap); + display: grid; + --app-grid-template-columns: 1fr; + grid-template-columns: var(--app-grid-template-columns); +} + +.flex { + display: flex; + flex-wrap: wrap; + gap: var(--app-flex-gap); +} + +.flex h1, +.flex h2, +.flex h3, +.flex h4, +.flex h5, +.flex h6 { + margin-bottom: 0; +} + +.align-center { + align-items: center; +} + +.align-flex-start { + align-items: flex-start; +} + +.justify-space-between { + justify-content: space-between; +} + +@media (min-width: 768px) { + .grid { + --app-grid-template-columns: repeat(auto-fit, minmax(0%, 1fr)); + } + + .grid.grid-2, + .grid.grid-1-1 { + --app-grid-template-columns: repeat(2, minmax(0%, 1fr)); + } + + .grid.grid-3 { + --app-grid-template-columns: repeat(3, minmax(0%, 1fr)); + } + + .grid.grid-4 { + --app-grid-template-columns: repeat(4, minmax(0%, 1fr)); + } + + .grid.grid-5 { + --app-grid-template-columns: repeat(5, minmax(0%, 1fr)); + } + + .grid.grid-6 { + --app-grid-template-columns: repeat(6, minmax(0%, 1fr)); + } + + .grid.grid-1-2 { + --app-grid-template-columns: minmax(0%, 1fr) minmax(0%, 2fr); + } + + .grid.grid-2-1 { + --app-grid-template-columns: minmax(0%, 2fr) minmax(0%, 1fr); + } + + .grid.grid-1-3 { + --app-grid-template-columns: minmax(0%, 1fr) minmax(0%, 3fr); + } + + .grid.grid-3-1 { + --app-grid-template-columns: minmax(0%, 3fr) minmax(0%, 1fr); + } +} + +.grid > * { + min-width: 0; +} + +.overflow-auto { + overflow: auto; +} + +b, +strong { + font-weight: bolder; +} + +sub, +sup { + position: relative; + font-size: 0.75em; + line-height: 0; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +address, +blockquote, +dl, +ol, +p, +pre, +table, +ul { + margin-top: 0; + margin-bottom: var(--app-typography-spacing-vertical); + color: var(--app-color); + font-style: normal; + font-weight: var(--app-font-weight); +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin-top: 0; + margin-bottom: var(--app-typography-spacing-vertical); + color: var(--app-color); + font-weight: var(--app-font-weight); + font-size: var(--app-font-size); + line-height: var(--app-line-height); + font-family: var(--app-font-family); +} + +h1 { + --app-color: var(--app-h1-color); +} + +h2 { + --app-color: var(--app-h2-color); +} + +h3 { + --app-color: var(--app-h3-color); +} + +h4 { + --app-color: var(--app-h4-color); +} + +h5 { + --app-color: var(--app-h5-color); +} + +h6 { + --app-color: var(--app-h6-color); +} + +:where(article, address, blockquote, dl, figure, form, ol, p, pre, table, ul) + ~ :is(h1, h2, h3, h4, h5, h6) { + margin-top: var(--app-typography-spacing-top); +} + +p { + margin-bottom: var(--app-typography-spacing-vertical); +} + +hgroup { + margin-bottom: var(--app-typography-spacing-vertical); +} + +.flex hgroup { + margin-bottom: 0; +} + +hgroup > * { + margin-top: 0; + margin-bottom: 0; +} + +hgroup > :not(:first-child):last-child { + --app-color: var(--app-muted-color); + --app-font-weight: unset; + font-size: 1rem; +} + +:where(ol, ul) li { + margin-bottom: calc(var(--app-typography-spacing-vertical) * 0.25); +} + +:where(dl, ol, ul) :where(dl, ol, ul) { + margin: 0; + margin-top: calc(var(--app-typography-spacing-vertical) * 0.25); +} + +ul li { + list-style: square; +} + +mark { + padding: 0.125rem 0.25rem; + background-color: var(--app-mark-background-color); + color: var(--app-mark-color); + vertical-align: baseline; +} + + +abbr[title] { + border-bottom: 1px dotted; + text-decoration: none; + cursor: help; +} + +ins { + color: var(--app-ins-color); + text-decoration: none; +} + +del { + color: var(--app-del-color); +} + +::-moz-selection { + background-color: var(--app-text-selection-color); +} + +::selection { + background-color: var(--app-text-selection-color); +} + +:where(a:not([role="button"])), +[role="link"] { + --app-color: var(--app-primary); + --app-background-color: transparent; + --app-underline: var(--app-primary-underline); + outline: 0; + background-color: var(--app-background-color); + color: var(--app-color); + -webkit-text-decoration: var(--app-text-decoration); + text-decoration: var(--app-text-decoration); + text-decoration-color: var(--app-underline); + text-underline-offset: 0.125em; + transition: + background-color var(--app-transition), + color var(--app-transition), + box-shadow var(--app-transition), + -webkit-text-decoration var(--app-transition); + transition: + background-color var(--app-transition), + color var(--app-transition), + text-decoration var(--app-transition), + box-shadow var(--app-transition); + transition: + background-color var(--app-transition), + color var(--app-transition), + text-decoration var(--app-transition), + box-shadow var(--app-transition), + -webkit-text-decoration var(--app-transition); +} + +:where(a:not([role="button"])):is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus +), +[role="link"]:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus +) { + --app-color: var(--app-primary-hover); + --app-underline: var(--app-primary-hover-underline); + --app-text-decoration: underline; +} + +:where(a:not([role="button"])):focus-visible, +[role="link"]:focus-visible { + box-shadow: 0 0 0 var(--app-outline-width) var(--app-primary-focus); +} + +:where(a:not([role="button"])).secondary, +[role="link"].secondary { + --app-color: var(--app-secondary); + --app-underline: var(--app-secondary-underline); +} + +:where(a:not([role="button"])).secondary:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ), +[role="link"].secondary:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + --app-color: var(--app-secondary-hover); + --app-underline: var(--app-secondary-hover-underline); +} + +:where(a:not([role="button"])).contrast, +[role="link"].contrast { + --app-color: var(--app-contrast); + --app-underline: var(--app-contrast-underline); +} + +:where(a:not([role="button"])).contrast:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ), +[role="link"].contrast:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + --app-color: var(--app-contrast-hover); + --app-underline: var(--app-contrast-hover-underline); +} + +a[role="button"] { + display: inline-block; +} + +button { + margin: 0; + overflow: visible; + font-family: inherit; + text-transform: none; +} + +a.transparent[role="button"], +button.transparent, +.transparent[role="button"] { + background: transparent; + border: none; + box-shadow: none; + color: var(--app-muted-color); +} +a.transparent[role="button"]:hover, +button.transparent:hover, +.transparent[role="button"]:hover { + background: var(--app-muted-border-color); + color: var(--app-contrast); +} + +[type="button"], +[type="reset"], +[type="submit"], +button { + -webkit-appearance: button; +} + +[role="button"], +[type="button"], +[type="file"]::file-selector-button, +[type="reset"], +[type="submit"], +button { + --app-background-color: var(--app-primary-background); + --app-border-color: var(--app-primary-border); + --app-color: var(--app-primary-inverse); + --app-box-shadow: var(--app-button-box-shadow, 0 0 0 rgba(0, 0, 0, 0)); + padding: var(--app-button-padding-vertical) + var(--app-button-padding-horizontal); + border: var(--app-border-width) solid var(--app-border-color); + border-radius: var(--app-border-radius); + outline: 0; + background-color: var(--app-background-color); + box-shadow: var(--app-box-shadow); + color: var(--app-color); + font-weight: var(--app-font-weight); + font-size: 1rem; + line-height: var(--app-line-height); + text-align: center; + text-decoration: none; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + transition: + background-color var(--app-transition), + border-color var(--app-transition), + color var(--app-transition), + box-shadow var(--app-transition); +} + +:where( + button, + [type="submit"], + [type="reset"], + [type="button"], + [role="button"] +).small { + --app-button-padding-vertical: var(--app-button-padding-vertical-small); + --app-button-padding-horizontal: var(--app-button-padding-horizontal-small); +} + +[role="button"]:is(:hover, :active, :focus), +[role="button"]:is([aria-current]:not([aria-current="false"])), +[type="button"]:is(:hover, :active, :focus), +[type="button"]:is([aria-current]:not([aria-current="false"])), +[type="file"]::file-selector-button:is(:hover, :active, :focus), +[type="file"]::file-selector-button:is( + [aria-current]:not([aria-current="false"]) + ), +[type="reset"]:is(:hover, :active, :focus), +[type="reset"]:is([aria-current]:not([aria-current="false"])), +[type="submit"]:is(:hover, :active, :focus), +[type="submit"]:is([aria-current]:not([aria-current="false"])), +button:is(:hover, :active, :focus), +button:is([aria-current]:not([aria-current="false"])) { + --app-background-color: var(--app-primary-hover-background); + --app-border-color: var(--app-primary-hover-border); + --app-box-shadow: var(--app-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)); + --app-color: var(--app-primary-inverse); +} + +[role="button"]:focus, +[role="button"]:is([aria-current]:not([aria-current="false"])):focus, +[type="button"]:focus, +[type="button"]:is([aria-current]:not([aria-current="false"])):focus, +[type="file"]::file-selector-button:focus, +[type="file"]::file-selector-button:is( + [aria-current]:not([aria-current="false"]) + ):focus, +[type="reset"]:focus, +[type="reset"]:is([aria-current]:not([aria-current="false"])):focus, +[type="submit"]:focus, +[type="submit"]:is([aria-current]:not([aria-current="false"])):focus, +button:focus, +button:is([aria-current]:not([aria-current="false"])):focus { + --app-box-shadow: + var(--app-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), + 0 0 0 var(--app-outline-width) var(--app-primary-focus); +} + +[type="button"], +[type="reset"] { + margin-bottom: var(--app-spacing); +} + +:is(button, [type="submit"], [type="button"], [role="button"]).secondary, +[type="file"]::file-selector-button, +[type="reset"] { + --app-background-color: var(--app-secondary-background); + --app-border-color: var(--app-secondary-border); + --app-color: var(--app-secondary-inverse); + cursor: pointer; +} + +:is(button, [type="submit"], [type="button"], [role="button"]).secondary:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ), +[type="file"]::file-selector-button:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ), +[type="reset"]:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus +) { + --app-background-color: var(--app-secondary-hover-background); + --app-border-color: var(--app-secondary-hover-border); + --app-color: var(--app-secondary-inverse); +} + +:is(button, [type="submit"], [type="button"], [role="button"]).secondary:focus, +:is(button, [type="submit"], [type="button"], [role="button"]).secondary:is( + [aria-current]:not([aria-current="false"]) + ):focus, +[type="file"]::file-selector-button:focus, +[type="file"]::file-selector-button:is( + [aria-current]:not([aria-current="false"]) + ):focus, +[type="reset"]:focus, +[type="reset"]:is([aria-current]:not([aria-current="false"])):focus { + --app-box-shadow: + var(--app-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), + 0 0 0 var(--app-outline-width) var(--app-secondary-focus); +} + +:is(button, [type="submit"], [type="button"], [role="button"]).contrast { + --app-background-color: var(--app-contrast-background); + --app-border-color: var(--app-contrast-border); + --app-color: var(--app-contrast-inverse); +} + +:is(button, [type="submit"], [type="button"], [role="button"]).contrast:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + --app-background-color: var(--app-contrast-hover-background); + --app-border-color: var(--app-contrast-hover-border); + --app-color: var(--app-contrast-inverse); +} + +:is(button, [type="submit"], [type="button"], [role="button"]).contrast:focus, +:is(button, [type="submit"], [type="button"], [role="button"]).contrast:is( + [aria-current]:not([aria-current="false"]) + ):focus { + --app-box-shadow: + var(--app-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), + 0 0 0 var(--app-outline-width) var(--app-contrast-focus); +} + +:is(button, [type="submit"], [type="button"], [role="button"]).outline, +[type="reset"].outline { + --app-background-color: transparent; + --app-color: var(--app-primary); + --app-border-color: var(--app-primary); +} + +:is(button, [type="submit"], [type="button"], [role="button"]).outline:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ), +[type="reset"].outline:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + --app-background-color: transparent; + --app-color: var(--app-primary-hover); + --app-border-color: var(--app-primary-hover); +} + +:is( + button, + [type="submit"], + [type="button"], + [role="button"] + ).outline.secondary, +[type="reset"].outline { + --app-color: var(--app-secondary); + --app-border-color: var(--app-secondary); +} + +:is( + button, + [type="submit"], + [type="button"], + [role="button"] + ).outline.secondary:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ), +[type="reset"].outline:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + --app-color: var(--app-secondary-hover); + --app-border-color: var(--app-secondary-hover); +} + +:is( + button, + [type="submit"], + [type="button"], + [role="button"] + ).outline.contrast { + --app-color: var(--app-contrast); + --app-border-color: var(--app-contrast); +} + +:is( + button, + [type="submit"], + [type="button"], + [role="button"] + ).outline.contrast:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + --app-color: var(--app-contrast-hover); + --app-border-color: var(--app-contrast-hover); +} + +:where( + button, + [type="submit"], + [type="reset"], + [type="button"], + [role="button"] +)[disabled], +:where(fieldset[disabled]) + :is( + button, + [type="submit"], + [type="button"], + [type="reset"], + [role="button"] + ) { + opacity: 0.5; + pointer-events: none; +} + +:where(table) { + width: 100%; + border-collapse: collapse; + border-spacing: 0; + text-indent: 0; +} + +td, +th { + padding: calc(var(--app-spacing) / 2) var(--app-spacing); + border-bottom: var(--app-border-width) solid var(--app-table-border-color); + background-color: var(--app-background-color); + color: var(--app-color); + font-weight: var(--app-font-weight); + text-align: left; + text-align: start; +} + +tfoot td, +tfoot th { + border-top: var(--app-border-width) solid var(--app-table-border-color); + border-bottom: 0; +} + +table.striped tbody tr:nth-child(odd) td, +table.striped tbody tr:nth-child(odd) th { + background-color: var(--app-table-row-stripped-background-color); +} + +:where(audio, canvas, iframe, img, svg, video) { + vertical-align: middle; +} + +audio, +video { + display: inline-block; +} + +audio:not([controls]) { + display: none; + height: 0; +} + +:where(iframe) { + border-style: none; +} + +img { + max-width: 100%; + height: auto; + border-style: none; +} + +img.rounded { + border-radius: 0.5rem; +} + +:where(svg:not([fill])) { + fill: currentColor; +} + +svg:not(:host), +svg:not(:root) { + overflow: hidden; +} + +code, +kbd, +pre, +samp { + font-size: 0.875em; + font-family: var(--app-font-family); +} + +pre code, +pre samp { + font-size: inherit; + font-family: inherit; +} + +pre { + -ms-overflow-style: scrollbar; + overflow: auto; +} + +code, +kbd, +pre, +samp { + border-radius: var(--app-border-radius); + background: var(--app-code-background-color); + color: var(--app-code-color); + font-weight: var(--app-font-weight); + line-height: initial; +} + +code, +kbd, +samp { + display: inline-block; + padding: 0.375rem; +} + +pre { + display: block; + margin-bottom: var(--app-spacing); + overflow-x: auto; +} + +pre > code, +pre > samp { + display: block; + padding: var(--app-spacing); + background: 0 0; + line-height: var(--app-line-height); +} + +.code-toolbar { + position: relative; + margin-block: var(--app-spacing); +} + +.code-toolbar > .toolbar { + position: absolute; + top: 0.5rem; + right: 0.5rem; + z-index: 1; +} + +.code-toolbar > .toolbar .toolbar-item { + display: inline-flex; +} + +.code-toolbar > .toolbar .copy-to-clipboard-button { + --app-background-color: transparent; + --app-border-color: var(--app-muted-border-color); + --app-color: var(--app-muted-color); + --app-box-shadow: none; + --app-button-padding-vertical: var(--app-button-padding-vertical-small); + --app-button-padding-horizontal: var(--app-button-padding-horizontal-small); + font-size: 0.75rem; +} + +.code-toolbar > .toolbar .copy-to-clipboard-button:is(:hover, :focus) { + --app-background-color: var(--app-card-sectioning-background-color); + --app-border-color: var(--app-muted-border-color); +} + +.code-toolbar > pre > code { + padding-top: calc(var(--app-spacing) * 2); +} + +kbd { + background-color: var(--app-code-kbd-background-color); + color: var(--app-code-kbd-color); + vertical-align: baseline; +} + +figure { + display: block; + margin: 0; + padding: 0; +} + +figure figcaption { + padding: calc(var(--app-spacing) * 0.5) 0; + color: var(--app-muted-color); +} + +hr { + height: 0; + margin: var(--app-typography-spacing-vertical) 0; + border: 0; + border-top: 1px solid var(--app-muted-border-color); + color: inherit; +} + +[hidden], +template { + display: none !important; +} + +canvas { + display: inline-block; +} + +input, +optgroup, +select, +textarea { + margin: 0; + font-size: 1rem; + line-height: var(--app-line-height); + font-family: inherit; + letter-spacing: inherit; +} + +input { + overflow: visible; +} + +select { + text-transform: none; +} + +legend { + max-width: 100%; + white-space: normal; + margin: 0; + display: block; + color: var(--app-color); + font-weight: var(--app-form-label-font-weight, var(--app-font-weight)); +} + +textarea { + overflow: auto; +} + +[type="checkbox"], +[type="radio"] { + padding: 0; +} + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +[type="search"] { + -webkit-appearance: textfield; + outline-offset: -2px; +} + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +::-webkit-file-upload-button { + -webkit-appearance: button; + font: inherit; +} + +::-moz-focus-inner { + padding: 0; + border-style: none; +} + +:-moz-focusring { + outline: 0; +} + +:-moz-ui-invalid { + box-shadow: none; +} + +::-ms-expand { + display: none; +} + +[type="file"], +[type="range"] { + padding: 0; + border-width: 0; +} + +input:not([type="checkbox"], [type="radio"], [type="range"]) { + height: calc( + 1rem * var(--app-line-height) + var(--app-form-element-spacing-vertical) * + 2 + var(--app-border-width) * 2 + ); +} + +fieldset { + width: 100%; + margin-bottom: var(--app-spacing); + border: 1px solid var(--app-form-element-border-color); + padding: var(--app-spacing); + border-radius: var(--app-border-radius); +} + +fieldset[role="group"] { + padding: 0; + border: 0; + border-radius: 0; +} + +label { + display: block; + margin-bottom: calc(var(--app-spacing) * 0.375); + color: var(--app-color); + font-weight: var(--app-form-label-font-weight, var(--app-font-weight)); + font-size: small; +} + +label:has(input[required]) span:after { + content: " *"; +} + +button[type="submit"], +input:not([type="checkbox"], [type="radio"]), +select, +textarea { + width: 100%; +} + +input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"]), +select, +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + padding: var(--app-form-element-spacing-vertical) + var(--app-form-element-spacing-horizontal); +} + +input, +select, +textarea { + --app-background-color: var(--app-form-element-background-color); + --app-border-color: var(--app-form-element-border-color); + --app-color: var(--app-form-element-color); + --app-box-shadow: none; + border: var(--app-border-width) solid var(--app-border-color); + border-radius: var(--app-border-radius); + outline: 0; + background-color: var(--app-background-color); + box-shadow: var(--app-box-shadow); + color: var(--app-color); + font-weight: var(--app-font-weight); + transition: + background-color var(--app-transition), + border-color var(--app-transition), + color var(--app-transition), + box-shadow var(--app-transition); +} + +:where(select, textarea):not([readonly]):is(:active, :focus), +input:not( + [type="submit"], + [type="button"], + [type="reset"], + [type="checkbox"], + [type="radio"], + [readonly] + ):is(:active, :focus) { + --app-background-color: var(--app-form-element-active-background-color); +} + +:where(select, textarea):not([readonly]):is(:active, :focus), +input:not( + [type="submit"], + [type="button"], + [type="reset"], + [role="switch"], + [readonly] + ):is(:active, :focus) { + --app-border-color: var(--app-form-element-active-border-color); +} + +:where(select, textarea):not([readonly]):focus, +input:not( + [type="submit"], + [type="button"], + [type="reset"], + [type="range"], + [type="file"], + [readonly] + ):focus { + --app-box-shadow: 0 0 0 var(--app-outline-width) + var(--app-form-element-focus-color); +} + +:where(fieldset[disabled]) + :is( + input:not([type="submit"], [type="button"], [type="reset"]), + select, + textarea + ), +input:not([type="submit"], [type="button"], [type="reset"])[disabled], +label[aria-disabled="true"], +select[disabled], +textarea[disabled] { + opacity: var(--app-form-element-disabled-opacity); + pointer-events: none; +} + +label[aria-disabled="true"] input[disabled] { + opacity: 1; +} + +:where(input, select, textarea):not( + [type="checkbox"], + [type="radio"], + [type="date"], + [type="datetime-local"], + [type="month"], + [type="time"], + [type="week"], + [type="range"] + )[aria-invalid] { + padding-right: calc( + var(--app-form-element-spacing-horizontal) + 1.5rem + ) !important; + padding-left: var(--app-form-element-spacing-horizontal); + padding-inline-start: var(--app-form-element-spacing-horizontal) !important; + padding-inline-end: calc( + var(--app-form-element-spacing-horizontal) + 1.5rem + ) !important; + background-position: center right 0.75rem; + background-size: 1rem auto; + background-repeat: no-repeat; +} + +:where(input, select, textarea):not( + [type="checkbox"], + [type="radio"], + [type="date"], + [type="datetime-local"], + [type="month"], + [type="time"], + [type="week"], + [type="range"] + )[aria-invalid="false"]:not(select) { + background-image: var(--app-icon-valid); +} + +:where(input, select, textarea):not( + [type="checkbox"], + [type="radio"], + [type="date"], + [type="datetime-local"], + [type="month"], + [type="time"], + [type="week"], + [type="range"] + )[aria-invalid="true"]:not(select) { + background-image: var(--app-icon-invalid); +} + +:where(input, select, textarea)[aria-invalid="false"] { + --app-border-color: var(--app-form-element-valid-border-color); +} + +:where(input, select, textarea)[aria-invalid="false"]:is(:active, :focus) { + --app-border-color: var( + --app-form-element-valid-active-border-color + ) !important +; +} + +:where(input, select, textarea)[aria-invalid="false"]:is(:active, :focus):not( + [type="checkbox"], + [type="radio"] + ) { + --app-box-shadow: 0 0 0 var(--app-outline-width) + var(--app-form-element-valid-focus-color) !important +; +} + +:where(input, select, textarea)[aria-invalid="true"] { + --app-border-color: var(--app-form-element-invalid-border-color); +} + +:where(input, select, textarea)[aria-invalid="true"]:is(:active, :focus) { + --app-border-color: var( + --app-form-element-invalid-active-border-color + ) !important +; +} + +:where(input, select, textarea)[aria-invalid="true"]:is(:active, :focus):not( + [type="checkbox"], + [type="radio"] + ) { + --app-box-shadow: 0 0 0 var(--app-outline-width) + var(--app-form-element-invalid-focus-color) !important +; +} + +[dir="rtl"] + :where(input, select, textarea):not([type="checkbox"], [type="radio"]):is( + [aria-invalid], + [aria-invalid="true"], + [aria-invalid="false"] + ) { + background-position: center left 0.75rem; +} + +input::-webkit-input-placeholder, +input::placeholder, +select:invalid, +textarea::-webkit-input-placeholder, +textarea::placeholder { + color: var(--app-form-element-placeholder-color); + opacity: 1; +} + +input:not([type="checkbox"], [type="radio"]), +select, +textarea { + margin-bottom: var(--app-spacing); +} + +select::-ms-expand { + border: 0; + background-color: transparent; +} + +select:not([multiple], [size]) { + padding-right: calc(var(--app-form-element-spacing-horizontal) + 1.5rem); + padding-left: var(--app-form-element-spacing-horizontal); + padding-inline-start: var(--app-form-element-spacing-horizontal); + padding-inline-end: calc(var(--app-form-element-spacing-horizontal) + 1.5rem); + background-image: var(--app-icon-chevron); + background-position: center right 0.75rem; + background-size: 1rem auto; + background-repeat: no-repeat; +} + +select[multiple] option:checked { + background: var(--app-form-element-selected-background-color); + color: var(--app-form-element-color); +} + +[dir="rtl"] select:not([multiple], [size]) { + background-position: center left 0.75rem; +} + +textarea { + display: block; + resize: vertical; +} + +textarea[aria-invalid] { + --app-icon-height: calc( + 1rem * var(--app-line-height) + var(--app-form-element-spacing-vertical) * + 2 + var(--app-border-width) * 2 + ); + background-position: top right 0.75rem !important; + background-size: 1rem var(--app-icon-height) !important; +} + +:where(input, select, textarea, fieldset, .grid) + small { + display: block; + width: 100%; + margin-top: calc(var(--app-spacing) * -0.75); + margin-bottom: var(--app-spacing); + color: var(--app-muted-color); +} + +:where(input, select, textarea, fieldset, .grid)[aria-invalid="false"] + small { + color: var(--app-ins-color); +} + +:where(input, select, textarea, fieldset, .grid)[aria-invalid="true"] + small { + color: var(--app-del-color); +} + +label > :where(input, select, textarea) { + margin-top: calc(var(--app-spacing) * 0.25); +} + +label:has([type="checkbox"], [type="radio"]) { + width: -moz-fit-content; + width: fit-content; + cursor: pointer; +} + +[type="checkbox"], +[type="radio"] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + width: 1.25em; + height: 1.25em; + margin-top: -0.125em; + margin-inline-end: 0.5em; + border-width: var(--app-border-width); + vertical-align: middle; + cursor: pointer; +} + +[type="checkbox"]::-ms-check, +[type="radio"]::-ms-check { + display: none; +} + +[type="checkbox"]:checked, +[type="checkbox"]:checked:active, +[type="checkbox"]:checked:focus, +[type="radio"]:checked, +[type="radio"]:checked:active, +[type="radio"]:checked:focus { + --app-background-color: var(--app-primary-background); + --app-border-color: var(--app-primary-border); + background-image: var(--app-icon-checkbox); + background-position: center; + background-size: 0.75em auto; + background-repeat: no-repeat; +} + +[type="checkbox"] ~ label, +[type="radio"] ~ label { + display: inline-block; + margin-bottom: 0; + cursor: pointer; +} + +[type="checkbox"] ~ label:not(:last-of-type), +[type="radio"] ~ label:not(:last-of-type) { + margin-inline-end: 1em; +} + +[type="checkbox"]:indeterminate { + --app-background-color: var(--app-primary-background); + --app-border-color: var(--app-primary-border); + background-image: var(--app-icon-minus); + background-position: center; + background-size: 0.75em auto; + background-repeat: no-repeat; +} + +[type="radio"] { + border-radius: 50%; +} + +[type="radio"]:checked, +[type="radio"]:checked:active, +[type="radio"]:checked:focus { + --app-background-color: var(--app-primary-inverse); + border-width: 0.35em; + background-image: none; +} + +[type="checkbox"][role="switch"] { + --app-background-color: var(--app-switch-background-color); + --app-color: var(--app-switch-color); + width: 2.25em; + height: 1.25em; + border: var(--app-border-width) solid var(--app-border-color); + border-radius: 1.25em; + background-color: var(--app-background-color); + line-height: 1.25em; +} + +[type="checkbox"][role="switch"]:not([aria-invalid]) { + --app-border-color: var(--app-switch-background-color); +} + +[type="checkbox"][role="switch"]:before { + display: block; + aspect-ratio: 1; + height: 100%; + border-radius: 50%; + background-color: var(--app-color); + box-shadow: var(--app-switch-thumb-box-shadow); + content: ""; + transition: margin 0.1s ease-in-out; +} + +[type="checkbox"][role="switch"]:focus { + --app-background-color: var(--app-switch-background-color); + --app-border-color: var(--app-switch-background-color); +} + +[type="checkbox"][role="switch"]:checked { + --app-background-color: var(--app-switch-checked-background-color); + --app-border-color: var(--app-switch-checked-background-color); + background-image: none; +} + +[type="checkbox"][role="switch"]:checked::before { + margin-inline-start: calc(2.25em - 1.25em); +} + +[type="checkbox"][role="switch"][disabled] { + --app-background-color: var(--app-border-color); +} + +[type="checkbox"][aria-invalid="false"]:checked, +[type="checkbox"][aria-invalid="false"]:checked:active, +[type="checkbox"][aria-invalid="false"]:checked:focus, +[type="checkbox"][role="switch"][aria-invalid="false"]:checked, +[type="checkbox"][role="switch"][aria-invalid="false"]:checked:active, +[type="checkbox"][role="switch"][aria-invalid="false"]:checked:focus { + --app-background-color: var(--app-form-element-valid-border-color); +} + +[type="checkbox"]:checked:active[aria-invalid="true"], +[type="checkbox"]:checked:focus[aria-invalid="true"], +[type="checkbox"]:checked[aria-invalid="true"], +[type="checkbox"][role="switch"]:checked:active[aria-invalid="true"], +[type="checkbox"][role="switch"]:checked:focus[aria-invalid="true"], +[type="checkbox"][role="switch"]:checked[aria-invalid="true"] { + --app-background-color: var(--app-form-element-invalid-border-color); +} + +[type="checkbox"][aria-invalid="false"]:checked, +[type="checkbox"][aria-invalid="false"]:checked:active, +[type="checkbox"][aria-invalid="false"]:checked:focus, +[type="checkbox"][role="switch"][aria-invalid="false"]:checked, +[type="checkbox"][role="switch"][aria-invalid="false"]:checked:active, +[type="checkbox"][role="switch"][aria-invalid="false"]:checked:focus, +[type="radio"][aria-invalid="false"]:checked, +[type="radio"][aria-invalid="false"]:checked:active, +[type="radio"][aria-invalid="false"]:checked:focus { + --app-border-color: var(--app-form-element-valid-border-color); +} + +[type="checkbox"]:checked:active[aria-invalid="true"], +[type="checkbox"]:checked:focus[aria-invalid="true"], +[type="checkbox"]:checked[aria-invalid="true"], +[type="checkbox"][role="switch"]:checked:active[aria-invalid="true"], +[type="checkbox"][role="switch"]:checked:focus[aria-invalid="true"], +[type="checkbox"][role="switch"]:checked[aria-invalid="true"], +[type="radio"]:checked:active[aria-invalid="true"], +[type="radio"]:checked:focus[aria-invalid="true"], +[type="radio"]:checked[aria-invalid="true"] { + --app-border-color: var(--app-form-element-invalid-border-color); +} + +[type="color"]::-webkit-color-swatch-wrapper { + padding: 0; +} + +[type="color"]::-moz-focus-inner { + padding: 0; +} + +[type="color"]::-webkit-color-swatch { + border: 0; + border-radius: calc(var(--app-border-radius) * 0.5); +} + +[type="color"]::-moz-color-swatch { + border: 0; + border-radius: calc(var(--app-border-radius) * 0.5); +} + +input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"]):is( + [type="date"], + [type="datetime-local"], + [type="month"], + [type="time"], + [type="week"] + ) { + --app-icon-position: 0.75rem; + --app-icon-width: 1rem; + padding-right: calc(var(--app-icon-width) + var(--app-icon-position)); + background-image: var(--app-icon-date); + background-position: center right var(--app-icon-position); + background-size: var(--app-icon-width) auto; + background-repeat: no-repeat; +} + +input:not( + [type="checkbox"], + [type="radio"], + [type="range"], + [type="file"] + )[type="time"] { + background-image: var(--app-icon-time); +} + +[type="date"]::-webkit-calendar-picker-indicator, +[type="datetime-local"]::-webkit-calendar-picker-indicator, +[type="month"]::-webkit-calendar-picker-indicator, +[type="time"]::-webkit-calendar-picker-indicator, +[type="week"]::-webkit-calendar-picker-indicator { + width: var(--app-icon-width); + margin-right: calc(var(--app-icon-width) * -1); + margin-left: var(--app-icon-position); + opacity: 0; +} + +@-moz-document url-prefix() { + [type="date"], + [type="datetime-local"], + [type="month"], + [type="time"], + [type="week"] { + padding-right: var(--app-form-element-spacing-horizontal) !important; + background-image: none !important; + } +} + +[dir="rtl"] + :is( + [type="date"], + [type="datetime-local"], + [type="month"], + [type="time"], + [type="week"] + ) { + text-align: right; +} + +[type="file"] { + --app-color: var(--app-muted-color); + margin-left: calc(var(--app-outline-width) * -1); + background: 0 0; + border: 2px dashed var(--app-form-element-border-color); + padding: 1.5rem; + height: auto !important; +} + +[type="file"]::file-selector-button { + margin-right: calc(var(--app-spacing) / 2); + padding: calc(var(--app-form-element-spacing-vertical) * 0.5) + var(--app-form-element-spacing-horizontal); +} + +[type="file"]:is(:hover, :active, :focus)::file-selector-button { + --app-background-color: var(--app-secondary-hover-background); + --app-border-color: var(--app-secondary-hover-border); +} + +[type="file"]:focus::file-selector-button { + --app-box-shadow: + var(--app-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), + 0 0 0 var(--app-outline-width) var(--app-secondary-focus); +} + +[type="range"] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + width: 100%; + height: 1.25rem; + background: 0 0; +} + +[type="range"]::-webkit-slider-runnable-track { + width: 100%; + height: 0.375rem; + border-radius: var(--app-border-radius); + background-color: var(--app-range-border-color); + -webkit-transition: + background-color var(--app-transition), + box-shadow var(--app-transition); + transition: + background-color var(--app-transition), + box-shadow var(--app-transition); +} + +[type="range"]::-moz-range-track { + width: 100%; + height: 0.375rem; + border-radius: var(--app-border-radius); + background-color: var(--app-range-border-color); + -moz-transition: + background-color var(--app-transition), + box-shadow var(--app-transition); + transition: + background-color var(--app-transition), + box-shadow var(--app-transition); +} + +[type="range"]::-ms-track { + width: 100%; + height: 0.375rem; + border-radius: var(--app-border-radius); + background-color: var(--app-range-border-color); + -ms-transition: + background-color var(--app-transition), + box-shadow var(--app-transition); + transition: + background-color var(--app-transition), + box-shadow var(--app-transition); +} + +[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; + width: 1.25rem; + height: 1.25rem; + margin-top: -0.4375rem; + border: 2px solid var(--app-range-thumb-border-color); + border-radius: 50%; + background-color: var(--app-range-thumb-color); + cursor: pointer; + -webkit-transition: + background-color var(--app-transition), + transform var(--app-transition); + transition: + background-color var(--app-transition), + transform var(--app-transition); +} + +[type="range"]::-moz-range-thumb { + -webkit-appearance: none; + width: 1.25rem; + height: 1.25rem; + margin-top: -0.4375rem; + border: 2px solid var(--app-range-thumb-border-color); + border-radius: 50%; + background-color: var(--app-range-thumb-color); + cursor: pointer; + -moz-transition: + background-color var(--app-transition), + transform var(--app-transition); + transition: + background-color var(--app-transition), + transform var(--app-transition); +} + +[type="range"]::-ms-thumb { + -webkit-appearance: none; + width: 1.25rem; + height: 1.25rem; + margin-top: -0.4375rem; + border: 2px solid var(--app-range-thumb-border-color); + border-radius: 50%; + background-color: var(--app-range-thumb-color); + cursor: pointer; + -ms-transition: + background-color var(--app-transition), + transform var(--app-transition); + transition: + background-color var(--app-transition), + transform var(--app-transition); +} + +[type="range"]:active, +[type="range"]:focus-within { + --app-range-border-color: var(--app-range-active-border-color); + --app-range-thumb-color: var(--app-range-thumb-active-color); +} + +[type="range"]:active::-webkit-slider-thumb { + transform: scale(1.25); +} + +[type="range"]:active::-moz-range-thumb { + transform: scale(1.25); +} + +[type="range"]:active::-ms-thumb { + transform: scale(1.25); +} + +input:not( + [type="checkbox"], + [type="radio"], + [type="range"], + [type="file"] + )[type="search"] { + padding-inline-start: calc( + var(--app-form-element-spacing-horizontal) + 1.75rem + ); + background-image: var(--app-icon-search); + background-position: center left + calc(var(--app-form-element-spacing-horizontal) + 0.125rem); + background-size: 1rem auto; + background-repeat: no-repeat; +} + +input:not( + [type="checkbox"], + [type="radio"], + [type="range"], + [type="file"] + )[type="search"][aria-invalid] { + padding-inline-start: calc( + var(--app-form-element-spacing-horizontal) + 1.75rem + ) !important; + background-position: + center left 1.125rem, + center right 0.75rem; +} + +input:not( + [type="checkbox"], + [type="radio"], + [type="range"], + [type="file"] + )[type="search"][aria-invalid="false"] { + background-image: var(--app-icon-search), var(--app-icon-valid); +} + +input:not( + [type="checkbox"], + [type="radio"], + [type="range"], + [type="file"] + )[type="search"][aria-invalid="true"] { + background-image: var(--app-icon-search), var(--app-icon-invalid); +} + +[dir="rtl"] + :where(input):not( + [type="checkbox"], + [type="radio"], + [type="range"], + [type="file"] + )[type="search"] { + background-position: center right 1.125rem; +} + +[dir="rtl"] + :where(input):not( + [type="checkbox"], + [type="radio"], + [type="range"], + [type="file"] + )[type="search"][aria-invalid] { + background-position: + center right 1.125rem, + center left 0.75rem; +} + +details { + display: block; + margin-bottom: var(--app-spacing); +} + +details summary { + line-height: 1rem; + list-style-type: none; + cursor: pointer; + transition: color var(--app-transition); +} + +details summary:not([role]) { + color: var(--app-accordion-close-summary-color); +} + +details summary::-webkit-details-marker { + display: none; +} + +details summary::marker { + display: none; +} + +details summary::-moz-list-bullet { + list-style-type: none; +} + +details summary::after { + display: block; + width: 1rem; + height: 1rem; + margin-inline-start: calc(var(--app-spacing, 1rem) * 0.5); + float: right; + transform: rotate(-90deg); + background-image: var(--app-icon-chevron); + background-position: right center; + background-size: 1rem auto; + background-repeat: no-repeat; + content: ""; + transition: transform var(--app-transition); +} + +details summary:focus { + outline: 0; +} + +details summary:focus:not([role]) { + color: var(--app-accordion-active-summary-color); +} + +details summary:focus-visible:not([role]) { + outline: var(--app-outline-width) solid var(--app-primary-focus); + outline-offset: calc(var(--app-spacing, 1rem) * 0.5); + color: var(--app-primary); +} + +details summary[role="button"] { + width: 100%; + text-align: left; +} + +details summary[role="button"]::after { + height: calc(1rem * var(--app-line-height, 1.5)); +} + +details[open] > summary { + margin-bottom: calc(var(--app-spacing) * 0.5); +} + +details[open] > summary:not([role]):not(:focus) { + color: var(--app-accordion-close-summary-color); +} + +details[open] > summary::after { + transform: rotate(0); +} + +[dir="rtl"] details summary { + text-align: right; +} + +[dir="rtl"] details summary::after { + float: left; + background-position: left center; +} + +article { + margin-bottom: var(--app-block-spacing-vertical); + padding: var(--app-block-spacing-vertical) var(--app-block-spacing-horizontal); + border-radius: var(--app-border-radius); + background: var(--app-card-background-color); + box-shadow: var(--app-card-box-shadow); +} + +article:not(:has(footer)) p:last-child { + margin: 0; +} + +article > footer, +article > header { + margin-right: calc(var(--app-block-spacing-horizontal) * -1); + margin-left: calc(var(--app-block-spacing-horizontal) * -1); + padding: calc(var(--app-block-spacing-vertical) * 1) + var(--app-block-spacing-horizontal); + background-color: var(--app-card-sectioning-background-color); +} + +article > header { + margin-top: calc(var(--app-block-spacing-vertical) * -1); + margin-bottom: var(--app-block-spacing-vertical); + border-bottom: var(--app-border-width) solid var(--app-card-border-color); + border-top-right-radius: var(--app-border-radius); + border-top-left-radius: var(--app-border-radius); +} + +article > header > hgroup { + margin: 0; +} + +article > footer { + margin-top: var(--app-block-spacing-vertical); + margin-bottom: calc(var(--app-block-spacing-vertical) * -1); + border-top: var(--app-border-width) solid var(--app-card-border-color); + border-bottom-right-radius: var(--app-border-radius); + border-bottom-left-radius: var(--app-border-radius); +} + +details.dropdown { + position: relative; + border-bottom: none; +} + +details.dropdown > a::after, +details.dropdown > button::after, +details.dropdown > summary::after { + display: block; + width: 1rem; + height: calc(1rem * var(--app-line-height, 1.5)); + margin-inline-start: 0.25rem; + float: right; + transform: rotate(0) translateX(0.2rem); + background-image: var(--app-icon-chevron); + background-position: right center; + background-size: 1rem auto; + background-repeat: no-repeat; + content: ""; +} + +nav details.dropdown { + margin-bottom: 0; +} + +details.dropdown > summary:not([role]) { + height: calc( + 1rem * var(--app-line-height) + var(--app-form-element-spacing-vertical) * + 2 + var(--app-border-width) * 2 + ); + padding: var(--app-form-element-spacing-vertical) + var(--app-form-element-spacing-horizontal); + border: var(--app-border-width) solid var(--app-form-element-border-color); + border-radius: var(--app-border-radius); + background-color: var(--app-form-element-background-color); + color: var(--app-form-element-placeholder-color); + line-height: inherit; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + transition: + background-color var(--app-transition), + border-color var(--app-transition), + color var(--app-transition), + box-shadow var(--app-transition); +} + +details.dropdown > summary:not([role]):active, +details.dropdown > summary:not([role]):focus { + border-color: var(--app-form-element-active-border-color); + background-color: var(--app-form-element-active-background-color); +} + +details.dropdown > summary:not([role]):focus { + box-shadow: 0 0 0 var(--app-outline-width) var(--app-form-element-focus-color); +} + +details.dropdown > summary:not([role]):focus-visible { + outline: 0; +} + +details.dropdown > summary:not([role])[aria-invalid="false"] { + --app-form-element-border-color: var(--app-form-element-valid-border-color); + --app-form-element-active-border-color: var( + --app-form-element-valid-focus-color + ); + --app-form-element-focus-color: var(--app-form-element-valid-focus-color); +} + +details.dropdown > summary:not([role])[aria-invalid="true"] { + --app-form-element-border-color: var(--app-form-element-invalid-border-color); + --app-form-element-active-border-color: var( + --app-form-element-invalid-focus-color + ); + --app-form-element-focus-color: var(--app-form-element-invalid-focus-color); +} + +nav details.dropdown { + display: inline; + margin: calc(var(--app-nav-element-spacing-vertical) * -1) 0; +} + +nav details.dropdown > summary::after { + transform: rotate(0) translateX(0); +} + +nav details.dropdown > summary:not([role]) { + height: calc( + 1rem * var(--app-line-height) + var(--app-nav-link-spacing-vertical) * 2 + ); + padding: calc( + var(--app-nav-link-spacing-vertical) - var(--app-border-width) * 2 + ) + var(--app-nav-link-spacing-horizontal); +} + +nav details.dropdown > summary:not([role]):focus-visible { + box-shadow: 0 0 0 var(--app-outline-width) var(--app-primary-focus); +} + +details.dropdown > summary + ul { + display: flex; + z-index: 99; + position: absolute; + left: 0; + flex-direction: column; + width: 100%; + min-width: -moz-fit-content; + min-width: fit-content; + margin: 0; + margin-top: var(--app-outline-width); + padding: 0; + border: var(--app-border-width) solid var(--app-dropdown-border-color); + border-radius: var(--app-border-radius); + background-color: var(--app-dropdown-background-color); + box-shadow: var(--app-dropdown-box-shadow); + color: var(--app-dropdown-color); + white-space: nowrap; + opacity: 0; + transition: + opacity var(--app-transition), + transform 0s ease-in-out 1s; +} + +details.dropdown > summary + ul[dir="rtl"] { + right: 0; + left: auto; +} + +details.dropdown > summary + ul li { + width: 100%; + margin-bottom: 0; + padding: calc(var(--app-form-element-spacing-vertical) * 0.5) + var(--app-form-element-spacing-horizontal); + list-style: none; +} + +details.dropdown > summary + ul li:first-of-type { + margin-top: calc(var(--app-form-element-spacing-vertical) * 0.5); +} + +details.dropdown > summary + ul li:last-of-type { + margin-bottom: calc(var(--app-form-element-spacing-vertical) * 0.5); +} + +details.dropdown > summary + ul li a { + display: block; + margin: calc(var(--app-form-element-spacing-vertical) * -0.5) + calc(var(--app-form-element-spacing-horizontal) * -1); + padding: calc(var(--app-form-element-spacing-vertical) * 0.5) + var(--app-form-element-spacing-horizontal); + overflow: hidden; + border-radius: 0; + color: var(--app-dropdown-color); + text-decoration: none; + text-overflow: ellipsis; +} + +details.dropdown > summary + ul li a:active, +details.dropdown > summary + ul li a:focus, +details.dropdown > summary + ul li a:focus-visible, +details.dropdown > summary + ul li a:hover, +details.dropdown > summary + ul li a[aria-current]:not([aria-current="false"]) { + background-color: var(--app-dropdown-hover-background-color); +} + +details.dropdown > summary + ul li label { + width: 100%; +} + +details.dropdown > summary + ul li:has(label):hover { + background-color: var(--app-dropdown-hover-background-color); +} + +details.dropdown[open] > summary { + margin-bottom: 0; +} + +details.dropdown[open] > summary + ul { + transform: scaleY(1); + opacity: 1; + transition: + opacity var(--app-transition), + transform 0s ease-in-out 0s; +} + +details.dropdown[open] > summary::before { + display: block; + z-index: 1; + position: fixed; + width: 100vw; + height: 100vh; + inset: 0; + background: 0 0; + content: ""; + cursor: default; +} + +label > details.dropdown { + margin-top: calc(var(--app-spacing) * 0.25); +} + +[role="group"], +[role="search"] { + display: inline-flex; + position: relative; + width: 100%; + margin-bottom: var(--app-spacing); + border-radius: var(--app-border-radius); + box-shadow: var(--app-group-box-shadow, 0 0 0 transparent); + vertical-align: middle; + transition: box-shadow var(--app-transition); +} + +[role="group"] input:not([type="checkbox"], [type="radio"]), +[role="group"] select, +[role="group"] > *, +[role="search"] input:not([type="checkbox"], [type="radio"]), +[role="search"] select, +[role="search"] > * { + position: relative; + flex: 1 1 auto; + margin-bottom: 0; +} + +[role="group"] input:not([type="checkbox"], [type="radio"]):not(:first-child), +[role="group"] select:not(:first-child), +[role="group"] > :not(:first-child), +[role="search"] input:not([type="checkbox"], [type="radio"]):not(:first-child), +[role="search"] select:not(:first-child), +[role="search"] > :not(:first-child) { + margin-left: 0; + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +[role="group"] input:not([type="checkbox"], [type="radio"]):not(:last-child), +[role="group"] select:not(:last-child), +[role="group"] > :not(:last-child), +[role="search"] input:not([type="checkbox"], [type="radio"]):not(:last-child), +[role="search"] select:not(:last-child), +[role="search"] > :not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +[role="group"] input:not([type="checkbox"], [type="radio"]):focus, +[role="group"] select:focus, +[role="group"] > :focus, +[role="search"] input:not([type="checkbox"], [type="radio"]):focus, +[role="search"] select:focus, +[role="search"] > :focus { + z-index: 2; +} + +[role="group"] [role="button"]:not(:first-child), +[role="group"] [type="button"]:not(:first-child), +[role="group"] [type="reset"]:not(:first-child), +[role="group"] [type="submit"]:not(:first-child), +[role="group"] button:not(:first-child), +[role="group"] input:not([type="checkbox"], [type="radio"]):not(:first-child), +[role="group"] select:not(:first-child), +[role="search"] [role="button"]:not(:first-child), +[role="search"] [type="button"]:not(:first-child), +[role="search"] [type="reset"]:not(:first-child), +[role="search"] [type="submit"]:not(:first-child), +[role="search"] button:not(:first-child), +[role="search"] input:not([type="checkbox"], [type="radio"]):not(:first-child), +[role="search"] select:not(:first-child) { + margin-left: calc(var(--app-border-width) * -1); +} + +[role="group"] [role="button"], +[role="group"] [type="button"], +[role="group"] [type="reset"], +[role="group"] [type="submit"], +[role="group"] button, +[role="search"] [role="button"], +[role="search"] [type="button"], +[role="search"] [type="reset"], +[role="search"] [type="submit"], +[role="search"] button { + width: auto; +} + +@supports selector(:has(*)) { + [role="group"]:has( + button:focus, + [type="submit"]:focus, + [type="button"]:focus, + [role="button"]:focus + ), + [role="search"]:has( + button:focus, + [type="submit"]:focus, + [type="button"]:focus, + [role="button"]:focus + ) { + --app-group-box-shadow: var(--app-group-box-shadow-focus-with-button); + } + + [role="group"]:has( + button:focus, + [type="submit"]:focus, + [type="button"]:focus, + [role="button"]:focus + ) + input:not([type="checkbox"], [type="radio"]), + [role="group"]:has( + button:focus, + [type="submit"]:focus, + [type="button"]:focus, + [role="button"]:focus + ) + select, + [role="search"]:has( + button:focus, + [type="submit"]:focus, + [type="button"]:focus, + [role="button"]:focus + ) + input:not([type="checkbox"], [type="radio"]), + [role="search"]:has( + button:focus, + [type="submit"]:focus, + [type="button"]:focus, + [role="button"]:focus + ) + select { + border-color: transparent; + } + + [role="group"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ), + [role="search"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) { + --app-group-box-shadow: var(--app-group-box-shadow-focus-with-input); + } + + [role="group"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) + [role="button"], + [role="group"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) + [type="button"], + [role="group"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) + [type="submit"], + [role="group"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) + button, + [role="search"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) + [role="button"], + [role="search"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) + [type="button"], + [role="search"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) + [type="submit"], + [role="search"]:has( + input:not([type="submit"], [type="button"]):focus, + select:focus + ) + button { + --app-button-box-shadow: 0 0 0 var(--app-border-width) + var(--app-primary-border); + --app-button-hover-box-shadow: 0 0 0 var(--app-border-width) + var(--app-primary-hover-border); + } + + [role="group"] [role="button"]:focus, + [role="group"] [type="button"]:focus, + [role="group"] [type="reset"]:focus, + [role="group"] [type="submit"]:focus, + [role="group"] button:focus, + [role="search"] [role="button"]:focus, + [role="search"] [type="button"]:focus, + [role="search"] [type="reset"]:focus, + [role="search"] [type="submit"]:focus, + [role="search"] button:focus { + box-shadow: none; + } +} + +[role="search"] > :first-child { + border-top-left-radius: 5rem; + border-bottom-left-radius: 5rem; +} + +[role="search"] > :last-child { + border-top-right-radius: 5rem; + border-bottom-right-radius: 5rem; +} + +html { + scroll-behavior: smooth; + background: var(--app-sidebar-background-color); +} + +.white-space-nowrap { + white-space: nowrap; +} + +[aria-busy="true"]:not(input, select, textarea, html, form) { + white-space: nowrap; +} + +[aria-busy="true"]:not(input, select, textarea, html, form)::before { + display: inline-block; + width: 1em; + height: 1em; + background-image: var(--app-icon-loading); + background-size: 1em auto; + background-repeat: no-repeat; + content: ""; + vertical-align: -0.125em; +} + +[aria-busy="true"]:not(input, select, textarea, html, form):not( + :empty + )::before { + margin-inline-end: calc(var(--app-spacing) * 0.5); +} + +[aria-busy="true"]:not(input, select, textarea, html, form):empty { + text-align: center; +} + +[role="button"][aria-busy="true"], +[type="button"][aria-busy="true"], +[type="reset"][aria-busy="true"], +[type="submit"][aria-busy="true"], +a[aria-busy="true"], +button[aria-busy="true"] { + pointer-events: none; +} + +dialog { + display: flex; + z-index: 999; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + align-items: center; + justify-content: center; + width: inherit; + min-width: 100%; + height: inherit; + min-height: 100%; + padding: 0; + border: 0; + -webkit-backdrop-filter: var(--app-modal-overlay-backdrop-filter); + backdrop-filter: var(--app-modal-overlay-backdrop-filter); + background-color: var(--app-modal-overlay-background-color); + color: var(--app-color); +} + +dialog > article { + width: 100%; + max-height: calc(100vh - var(--app-spacing) * 2); + margin: var(--app-spacing); + overflow: auto; +} + +@media (min-width: 576px) { + dialog > article { + max-width: 510px; + } +} + +@media (min-width: 768px) { + dialog > article { + max-width: 700px; + } +} + +dialog > article > header > * { + margin-bottom: 0; +} + +dialog > article > header .close, +dialog > article > header :is(a, button)[rel="prev"] { + margin: 0; + margin-left: var(--app-spacing); + padding: 0; + float: right; +} + +dialog > article > footer { + text-align: right; +} + +dialog > article > footer [role="button"], +dialog > article > footer button { + margin-bottom: 0; +} + +dialog > article > footer [role="button"]:not(:first-of-type), +dialog > article > footer button:not(:first-of-type) { + margin-left: calc(var(--app-spacing) * 0.5); +} + +dialog > article .close, +dialog > article :is(a, button)[rel="prev"] { + display: block; + width: 1rem; + height: 1rem; + margin-top: calc(var(--app-spacing) * -1); + margin-bottom: var(--app-spacing); + margin-left: auto; + border: none; + background-image: var(--app-icon-close); + background-position: center; + background-size: auto 1rem; + background-repeat: no-repeat; + background-color: transparent; + opacity: 0.5; + transition: opacity var(--app-transition); +} + +dialog + > article + .close:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ), +dialog + > article + :is(a, button)[rel="prev"]:is( + [aria-current]:not([aria-current="false"]), + :hover, + :active, + :focus + ) { + opacity: 1; +} + +dialog:not([open]), +dialog[open="false"] { + display: none; +} + +.modal-is-open { + padding-right: var(--app-scrollbar-width, 0); + overflow: hidden; + pointer-events: none; + touch-action: none; +} + +.modal-is-open dialog { + pointer-events: auto; + touch-action: auto; +} + +:where(.modal-is-opening, .modal-is-closing) dialog, +:where(.modal-is-opening, .modal-is-closing) dialog > article { + animation-duration: 0.2s; + animation-timing-function: ease-in-out; + animation-fill-mode: both; +} + +:where(.modal-is-opening, .modal-is-closing) dialog { + animation-duration: 0.8s; + animation-name: modal-overlay; +} + +:where(.modal-is-opening, .modal-is-closing) dialog > article { + animation-delay: 0.2s; + animation-name: modal; +} + +.modal-is-closing dialog, +.modal-is-closing dialog > article { + animation-delay: 0s; + animation-direction: reverse; +} + +@keyframes modal-overlay { + from { + -webkit-backdrop-filter: none; + backdrop-filter: none; + background-color: transparent; + } +} + +@keyframes modal { + from { + transform: translateY(-100%); + opacity: 0; + } +} + +:where(nav li)::before { + float: left; + content: "​"; +} + +nav, +nav ul { + display: flex; +} + +nav { + justify-content: space-between; + overflow: visible; +} + +nav ol, +nav ul { + align-items: center; + margin-bottom: 0; + padding: 0; + list-style: none; +} + +nav ol:first-of-type, +nav ul:first-of-type { + margin-left: calc(var(--app-nav-element-spacing-horizontal) * -1); +} + +nav ol:last-of-type, +nav ul:last-of-type { + margin-right: calc(var(--app-nav-element-spacing-horizontal) * -1); +} + +nav li { + display: inline-block; + margin: 0; + padding: var(--app-nav-element-spacing-vertical) + var(--app-nav-element-spacing-horizontal); +} + +nav li :where(a, [role="link"]) { + display: inline-block; + margin: calc(var(--app-nav-link-spacing-vertical) * -1) + calc(var(--app-nav-link-spacing-horizontal) * -1); + padding: var(--app-nav-link-spacing-vertical) + var(--app-nav-link-spacing-horizontal); + border-radius: var(--app-border-radius); +} + +nav li :where(a, [role="link"]):not(:hover) { + text-decoration: none; +} + +nav li [role="button"], +nav li [type="button"], +nav li button, +nav + li + input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"]), +nav li select { + height: auto; + margin-right: inherit; + margin-bottom: 0; + margin-left: inherit; + padding: calc( + var(--app-nav-link-spacing-vertical) - var(--app-border-width) * 2 + ) + var(--app-nav-link-spacing-horizontal); +} + +nav[aria-label="breadcrumb"] { + --app-breadcrumb-separator-size: 0.75rem; + --app-nav-element-spacing-vertical: 0.25rem; + --app-nav-element-spacing-horizontal: 0.25rem; + --app-nav-link-spacing-vertical: 0.25rem; + --app-nav-link-spacing-horizontal: 0.25rem; + align-items: center; + justify-content: start; + font-size: 0.875em; +} + +nav[aria-label="breadcrumb"] ol, +nav[aria-label="breadcrumb"] ul { + margin: 0; +} + +nav[aria-label="breadcrumb"] :is(ol, ul) li { + padding: 0; +} + +nav[aria-label="breadcrumb"] :is(ol, ul) li:not(:first-child) { + margin-inline-start: 0; +} + +nav[aria-label="breadcrumb"] :is(ol, ul) li a { + margin: calc(var(--app-nav-link-spacing-vertical) * -1) 0; + margin-inline-start: calc(var(--app-nav-link-spacing-horizontal) * -1); +} + +nav[aria-label="breadcrumb"] :is(ol, ul) li:not(:last-child)::after { + display: inline-block; + width: var(--app-breadcrumb-separator-size); + height: var(--app-breadcrumb-separator-size); + margin-inline: calc(var(--app-nav-link-spacing-horizontal) * 0.75); + content: ""; + background-image: var(--app-icon-chevron); + background-size: var(--app-breadcrumb-separator-size) auto; + background-repeat: no-repeat; + opacity: 0.7; + transform: rotate(-90deg); +} + +nav[aria-label="breadcrumb"] a[aria-current]:not([aria-current="false"]) { + background-color: transparent; + color: inherit; + text-decoration: none; + pointer-events: none; +} + +aside li, +aside nav, +aside ol, +aside ul { + display: block; +} + +aside li { + padding: calc(var(--app-nav-element-spacing-vertical) * 0.5) + var(--app-nav-element-spacing-horizontal); +} + +aside li a { + display: block; +} + +aside li [role="button"] { + margin: inherit; +} + +.text-align-center { + text-align: center; +} + +.primary { + box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 2px; +} + +.secondary { + border: 1px solid var(--app-border); + color: var(--app-muted-color); + box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 2px; +} +.secondary:hover { + border: 1px solid var(--app-contrast); + color: var(--app-contrast); +} + +/* Loading state - global cursor and interaction blocking */ +body.is-loading { + cursor: wait; +} + +body.is-loading * { + cursor: wait !important; +} + +body.is-loading button, +body.is-loading a, +body.is-loading input, +body.is-loading select, +body.is-loading textarea { + pointer-events: none; +} diff --git a/web/css/layout/app-sidebar.css b/web/css/layout/app-sidebar.css new file mode 100644 index 0000000..52bc886 --- /dev/null +++ b/web/css/layout/app-sidebar.css @@ -0,0 +1,208 @@ +.app-sidebar { + background: var(--app-sidebar-background-color); +} + +.app-sidebar .brand { + padding: var(--app-spacing); +} + +.app-sidebar-titlebar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.5rem; + padding: 0px var(--app-spacing) 0px var(--app-spacing); + margin-bottom: 0; + min-height: 30px; +} + +.app-sidebar .app-sidebar-panel { + display: block; +} + +.app-sidebar .app-sidebar-panel[hidden] { + display: none !important; +} + +.app-sidebar.is-collapsed { + display: none; +} + +.sidebar-collapsed .app-sidebar { + display: none; +} + +.app-sidebar-tenant-logo { + display: flex; + align-items: center; + justify-content: space-between; + gap: 5px; + padding: var(--app-spacing) var(--app-spacing) 10px var(--app-spacing); +} + + +.app-sidebar .app-sidebar-tenant-logo a:hover { + background: transparent; + border: 0; +} + +.app-sidebar .app-sidebar-tenant-logo > a { + padding: 0; + flex: 1; + border: 0; +} + + + + + +.app-sidebar-tenant-name { + flex: 1; + font-weight: 600; + font-size: 14px; + color: var(--app-contrast); + padding: 8px 12px; + border-radius: var(--app-border-radius); + text-align: left; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + border: 1px solid var(--app-border); +} + +.app-sidebar-title { + text-transform: uppercase; + font-size: 10px; + color: var(--app-muted-color); + display: none; +} + +.app-sidebar-tools { + display: flex; + align-items: center; + gap: 0.35rem; +} + +.app-sidebar-tools .icon-button { + border: 0; + background: transparent; + color: var(--app-muted-color); + padding: 0.25rem; + font-size: 0.9rem; + cursor: pointer; + margin-bottom: 0; +} + +.app-sidebar-tools .icon-button:hover { + color: var(--app-contrast); +} + +@media (min-width: 768px) { + .app-sidebar .brand { + margin-bottom: 1rem; + padding-block-start: 0.5rem; + } + .app-sidebar-title { + display: block; + } + + .app-sidebar { + position: sticky; + top: 0; + z-index: 1; + } +} + +.app-sidebar a { + color: inherit; + display: flex; + align-items: center; + gap: 10px; + text-decoration: none; + padding: 5px var(--app-spacing); + border-radius: 0; + margin: 0; + border-left: 2px solid transparent; + width: 100%; +} + +.app-sidebar a:hover, +.app-sidebar .active { + color: var(--app-primary); + --app-background-color: inherit; + background: var(--app-background-color); + border-left: 2px solid var(--app-primary); +} + +aside.app-sidebar ul { + margin: 0; +} + +.app-sidebar small { + margin-top: 2rem; + margin-bottom: 5px; + display: block; + padding-inline: var(--app-spacing); + opacity: 0.7; +} +.app-sidebar .app-sidebar-group small { + margin-top: 0; + margin-bottom: 0; + display: block; + padding-inline: 0; + opacity: 1; +} + +.app-sidebar li { + padding-block: 0; + padding: 0; +} + +.app-sidebar .app-sidebar-group { + list-style: none; +} + +.app-sidebar .app-sidebar-group details { + padding: 0; + margin: 0; +} + +.app-sidebar .app-sidebar-group summary { + padding: 0 var(--app-spacing); + font-size: 12px; + color: var(--app-muted-color); + line-height: 1; +} + +nav#aside-panel-people { + margin-top: var(--app-spacing); +} + +.app-sidebar .app-sidebar-group summary::-webkit-details-marker { + display: none; +} + +.app-sidebar .app-sidebar-group details > ul { + margin: 0; + padding: 0; +} + +.app-sidebar .app-sidebar-group summary > span { + text-overflow: ellipsis; + display: inline-block; + max-width: 157px; + overflow: hidden; + white-space: nowrap; +} + +.app-sidebar .app-sidebar-group details > ul li:first-child { + margin-top: 10px; +} + +.app-sidebar .app-sidebar-group details > ul li a { + padding-block: 2px; + opacity: .7; +} +.app-sidebar .app-sidebar-group details > ul li a:hover { + opacity: 1; +} \ No newline at end of file diff --git a/web/css/layout/app-topbar.css b/web/css/layout/app-topbar.css new file mode 100644 index 0000000..31cc406 --- /dev/null +++ b/web/css/layout/app-topbar.css @@ -0,0 +1,87 @@ +.app-header nav li { + padding: 0; +} + +form:has(input#app-search) { + flex: 1; +} + +.app-header nav { + gap: var(--app-spacing); +} + +.app-header { + padding-block-start: 0; + padding-left: var(--app-spacing); + padding-right: var(--app-spacing); + margin-bottom: calc(var(--app-spacing) * 2); + color: var(--app-contrast); + border-bottom: 1px solid var(--app-border); +} + +main:has(.app-details-container) .app-header { + margin-bottom: 0; +} + +li:has(#toggle-main-content-aside) { + display: none; +} + +main:has(#app-details-aside-section) li:has(#toggle-main-content-aside) { + display: block; +} + +.app-header nav > ul { + display: flex; + gap: 8px; + align-items: center; + color: var(--app-muted-color); +} + +.app-header details.dropdown > summary:not([role]) { + border: none; + height: auto; + padding: 5px; + border-radius: 0; + background: transparent; +} + +.app-header details.dropdown > summary:not([role]):after { + display: none; +} + +.app-header nav > ul li a { + padding: 5px; + color: var(--app-form-element-placeholder-color); + display: block; + margin: 0; +} + +.app-header button { + padding: 5px; + color: var(--app-form-element-placeholder-color); + display: block; + margin: 0; + background: transparent; + border: none; + border-radius: 0; +} +.app-header #global-back.is-disabled, +.app-header #global-forward.is-disabled { + opacity: 0.4; + cursor: not-allowed; + pointer-events: none; +} + +@media (min-width: 768px) { + header.app-header { + position: sticky; + top: 0; + background: var(--app-background-color); + z-index: 10; + } +} + +.app-header details.dropdown[open] > summary::before { + display: none; +} \ No newline at end of file diff --git a/web/css/pages/app-login.css b/web/css/pages/app-login.css new file mode 100644 index 0000000..ca961f4 --- /dev/null +++ b/web/css/pages/app-login.css @@ -0,0 +1,10 @@ +.back_to_login { + margin-bottom: 1rem; +} + +@media (min-width: 600px) { + main { + min-height: 90vh; + place-content: center; + } +} diff --git a/web/favicon/apple-touch-icon.png b/web/favicon/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..aaa57dc7ac9330e5ecc4c828717f4fe6e8ea1817 GIT binary patch literal 4827 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 literal 0 HcmV?d00001 diff --git a/web/favicon/favicon-16x16.png b/web/favicon/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..9aa0ec32fabbf5a8a84515340982c70b95cb7d28 GIT binary patch literal 451 zcmV;!0X+VRP)PI-=A~N_g(Hah~ca2|54ZYzV&DsX;te;M)2Sn&kd0=RA75~?suWFI&j z2gbMi4sZ=v<3fHR&*sWzmdF6u-Yr&Y#&NYg2i$#+7opSdV@@wIJ2RiEptP=qN^V=g z*>AE4L!O*A7%qj}I#bqEn#KljY61uGtkzJs9i&o78PaIgv(^AOGJj{9o=0~$jN)G4 z^WJ&M5-_cJR9@ibvZ)r`ULXf&2cPKEn9$WIG5c6AdC% zc)d~93SR;(-^UGtL{V$7KSb(Okw9Mv8XY&a*y#yIQvE>(vu-;mo%9HV#1Ar`^F&}U tO716>#_`3!Wcc}+BDA{#ss7r0f=?UEpimW%p$`B6002ovPDHLkV1k4`zl{I@ literal 0 HcmV?d00001 diff --git a/web/favicon/favicon-32x32.png b/web/favicon/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..92133472a9ccc510b82b0f961297a928895bbd9a GIT binary patch literal 816 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 + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/favicon/site.webmanifest b/web/favicon/site.webmanifest new file mode 100644 index 0000000..2a08603 --- /dev/null +++ b/web/favicon/site.webmanifest @@ -0,0 +1,21 @@ +{ + "name": "IVMS", + "short_name": "IVMS", + "icons": [ + { + "src": "/favicon/web-app-manifest-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/favicon/web-app-manifest-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/web/favicon/tenants/21a17705-d67e-4e20-8cc3-cf994bcfc7bb/apple-touch-icon.png b/web/favicon/tenants/21a17705-d67e-4e20-8cc3-cf994bcfc7bb/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..55784159ec27c34bf2a1931a29a2fa7eff8adc43 GIT binary patch literal 6025 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 LNkvXXu0mjf6N2PI literal 0 HcmV?d00001 diff --git a/web/favicon/tenants/21a17705-d67e-4e20-8cc3-cf994bcfc7bb/favicon-32x32.png b/web/favicon/tenants/21a17705-d67e-4e20-8cc3-cf994bcfc7bb/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..c51bd49f8426c9bc28ee81573c1696b098f3a4e4 GIT binary patch literal 1005 zcmVTH4r*41LNaFls3saClA}kpXmpB)rn2ix$VU)qpO$S)IxmTIn z+S~5l>mQ}fWNj^@WB>U5>pXtv{66RY&hMUc1Y=RI$_z@JN$39q07Tr~keaM#)9Q^u z2kkp?h=JQf(*w|NAK<5R&8*5@!D}yW@wI<>q?VS8rx}wRjEs$j#W{cwEDIW|>PVZH zily@krd?aZ=5(Th?g3k0F96qj{+t%);3otVES*<;b*CipZAI+Aixu^6W=(qO=?QdvlVrbY7Kyjgo`E!%Q3!tdMj}Jvr=)QHs<3JF} z&R7&)fKW6M(Yu)+7(j$ZL#93rfH9|o3mt6_7T~4)4aDhYqo@iW*P6LK`gcIvkg_0D zMMp+aQn-no#cy)C>ni30U(jkf7j#Tm03tLR*5|EdXUPr*?1SvCuH?io-{T4rd#}P0 zf^k`<{^tft-g}+qw$r@2zL?g1Kk(u9w@FHPc=`dnTC;Q|lFNl@*H+rQI(WIDh-04} zB+Ia1Y5<}TI-f=q*<4TrfYT-Mesu+^s*)I&fVs3BK@jd8K&RD(46^b0b)?OE)K~Am zb%Won-2fO46yNcFJXHiuZoi>(JZD#=3vTifaF3BZAGdZE69*XppCATXy z0BfI(!C^ZUU+?id06br3QJN8e@0uH_I=t7{*E8U`#Arm3Ono{4imK4w)e#!Nwd}&~`MG)MlTvu$xdI~Z#8*)jPM&YU`j?I9sA#e?vM?GR zvJ0cCsupI6Q>YC519==x4!*W0Vm`_}&9v&G^%7 b#sU5Tu?abux{88600000NkvXXu0mjf(|X;h literal 0 HcmV?d00001 diff --git a/web/favicon/tenants/21a17705-d67e-4e20-8cc3-cf994bcfc7bb/favicon-96x96.png b/web/favicon/tenants/21a17705-d67e-4e20-8cc3-cf994bcfc7bb/favicon-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..74a164f13f192d5699946e12cf0ed4a64ae043f2 GIT binary patch literal 2881 zcmV-H3%>M;P)trsYYNYQEGQIDj-Q5Sr_6=iN6s2=Xg1=V?d$MO!G2g;tz2}$ zBjHTI9Y!V(#padoL&ETFAW0HW{c#CSUM%7=wMWAFDCkJhah$(;i81ETnWN&(Z-a9I z6u^3OzbQDtby|;wmwCXAic-dQwr_|x!Ha?FxYT91Sm0cMMZwyo7>11NDN%pKgGh%sTa+ZfwbzA6mtlf*}A*hxF=b~~&#D_YDZ z7+Q?b8x3f&m_T;HZyrwq?2PTv;gQ(->Uus>(_%C=qq@EZ<<*tAUUm~DrPpxo>LuJP zF9k^nCx#aRok^>$6*tQ7A9cwH0!q0O0cwA!lzxy(rBM5-ppH~Q8ySOP1Jm!uHs~8s zaJCS+Cy(H8(J@#%c~&lnfJQ?TcIJHzLfZZjL=Xf*14EDy8;>A$AnUa%Yjv3X;w*=4 zQi%jAUlpReMT~j@F9omDBcYlUP1N}gP zOE@n@06>%`0(qOha@ba{Z$!rYv0zIom-%37<|M3~{{nm!O4_(vRb?2nB^O%I1Lh880>?c9d#d%oa(#MWhB$XIQy_|L%{tlGGS+v~PkvHQqgOnPA^ z_7@&<7~}7!#`3w(Vfz~&AxIs-Y5rf+Wd+<}?}=Pg)KqeQ-4?S6FTB4B`9;TQV^R|a z;fuGnBG{k(PocYXc>yFv@m9FAlXkqa;ZLa7H_*n!M#W&`iobx661?=G%L@R2pDS|BF{`2#(7?k5YQR?TycvvCP5p|d0tUK z8#N8JtTEj~!XTA!d&@)tZM0ZStT6;ZK&eo0npYIihBMC@ilSgAnJc}nA_{23PvOfN zqc<90wQ^f66$P}>JygRQbM^Lh)*_;-hyvP(jq1f3bNt*X&hv@_07w7~?mK`n#%{Oc z+hhAV&n*f7&@(&=eYJfUV|E|;4rSHcS7k*30A`J!&bYF>rm+rd|Fwaa++HsrE?SFO z*)wR{O=c68zPFsQWZet1T(s6D33)wgq4mMd8$? zA8_zwJ`Q|;2s(yk^qs{6DWI&n969;lqNMa1lHw9DxbFZY#U(=SQvxFP(oN1=vXvm9;ul*6NUV`X~TErSwC3QVIse_lJxi zFl=Btw2?80iRg(jLoxvX^-T@PJ#_>*`QMIk>?KD&a~2mpYYkUf&rB9G{`~0&Sn}R-n9Poc zp6UHkkhAtvj7}ZFOTWBEKvv3d1kx;op=E=wEqxyy3`I{1Vk~MC8zdP-7Svs2_cnY z&7warZt$byrV|Tw6CZxWoo=;*mphRVOTUU(CX*o|%<=9-E?GQd0n+*ncI&gcI`+dv zqBIelY+K@7fKsl&(Ee$RF~bLDaGmx(W{sbYB{QCJ`|~X{v*LSE_{iP*cKsU81NF0AeZ^zn2V;WGuWwzh%-1*_Exv(=0yqXE~-Zb0E9$Jn$?ESmN- z9*$;TV#tQVi9-kNz5%TWFVvj6mmHfas?v7 z!Z9#D32!W1;nGl(jUXrX1zW6E#$$P$#bp6w(?;RdXI=tDQJ_F|XvYXa5J>Ac*zJcU zUxbHtXN@V-m2| z{+!g79?P7B*%KaTjQQ~2TX5)1L5FkQOP3cA8ySOsES1Me!^XLNeF=VfWA^6aRkTw` zilXqh9ht z^>}UbJJ?s4=hC&Eg_lG7I*J59?}r}7%BOyhbSGCKG#DDO?(o>RJr@Bup+2{kbode&zgLvEAUhLB0N-sgxJ1_ zi`KeT(X`oZxUH)|O+yWuO(saC5-5BW2n`HIk8a(eW~sv3Njvh3j$=#CrzkEt@5XQC z8iESw-7^+@*6k1~{avaXYH|Lji#UGnBo3a+M@>Urr{xw@K%hDR*%?`#nv*0+n5|Zr zEGAUf*P^_p0(DIdow5?z5nb{b;7xS-Vd#U7C_rFD0Rkfm5ExN_z=#3_Mid}0q5y#r f1qh5NKw$n4tbcYAY~p^Z00000NkvXXu0mjfj7d$V literal 0 HcmV?d00001 diff --git a/web/favicon/tenants/21a17705-d67e-4e20-8cc3-cf994bcfc7bb/web-app-manifest-192x192.png b/web/favicon/tenants/21a17705-d67e-4e20-8cc3-cf994bcfc7bb/web-app-manifest-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..9b311feef99078e2453c852acf6e39d9b0d2faf4 GIT binary patch literal 5938 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 Pf&;2b8j6+j=3)O25!gP@ literal 0 HcmV?d00001 diff --git a/web/favicon/tenants/21a17705-d67e-4e20-8cc3-cf994bcfc7bb/web-app-manifest-512x512.png b/web/favicon/tenants/21a17705-d67e-4e20-8cc3-cf994bcfc7bb/web-app-manifest-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..255b2baff60a67d20a02d6aaf5ae3335139dca27 GIT binary patch literal 22668 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 literal 0 HcmV?d00001 diff --git a/web/favicon/web-app-manifest-192x192.png b/web/favicon/web-app-manifest-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..4b8dd40df0ae55d4b30e7412e97bd41d45254b90 GIT binary patch literal 5226 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 Hmze(ng@J+M literal 0 HcmV?d00001 diff --git a/web/favicon/web-app-manifest-512x512.png b/web/favicon/web-app-manifest-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..8d7c28f6dee01f266e0a635eb6bd778608c09fe4 GIT binary patch literal 16667 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 Zm`9Z?LgD8#VQ>SGuBH*{t-AC5{|B6a=ehs@ literal 0 HcmV?d00001 diff --git a/web/img/favicon.ico b/web/img/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..f9c244c11e45d7132e58dbdd193dbb0f3aff961f GIT binary patch literal 1150 zcma)4T}V_>5FXbkh#(2+HR-|3w%Rr$i9o5B2#Re{*H-(}s2-$$3JhtBq9A(+A}CA4 zAcz7fq?d|(FsKN8@WH)zS98@cm0h$gNObS?&8c%a1-ahK+&O1vzVFO@=Mv@M&C4Tv z3+UJaqUA(X1Vads-*LEkKN)stOZ?!fmZC*t5#o!(y+} z@24e}jbQ&!lgDdUwrHIAP~tq_nt04>tcrKp@N2EA8zxrPFTZv3=GZ>zW4il$&*J}a zY>L(TP?It7M@Fu2^LV?O;Sbjg`e@r4uUqynkHk&v##jx%O@ETU6~3(hFt?_jt2MOg zgSPpaIO6WT(TWboaTG;q{6L|JZ5qA9SH~W> zwSIdqV|I5hwT00DqsLMqz}@WB`0!98%h`G_UiKe;^z!!pqkqLQTZ`bKd#%*%`h0@l zq(3t5(5<_h?BENdw;7tLoYq6?p+jQU$q@drI@#ZxcqBb(Y&tl2<~X$Jlbo2$-=6B! zdF6KuG~@#x)-~`Mobd#AULd`d*fqt7P3ipg@iqph%YpO!(8mYNQ}lfnS}L4i^|QgM zE;l(Ire5%=FU^Vr+Li0NxjfGCV%}ceM`hxi#&4SoXXbVfoLq=m8^9COJbpW@?$E5u xw!Y7u1bvFvTcIlamrG_Z5>1v7b&0JYiY$WVf<-LHFf2W=r7(`bx?n$vegR8ZrnvwB literal 0 HcmV?d00001 diff --git a/web/img/forkme_right_red_aa0000.png b/web/img/forkme_right_red_aa0000.png new file mode 100644 index 0000000000000000000000000000000000000000..1e19c21262bccf6ae951636758b99708de331f27 GIT binary patch literal 7927 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 VW=p$pVk+5ycXG0W literal 0 HcmV?d00001 diff --git a/web/img/minty_square.png b/web/img/minty_square.png new file mode 100644 index 0000000000000000000000000000000000000000..250db3af5ca760da21f99f909f7da09187b9bfdc GIT binary patch literal 132166 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

    e;2Q-tr5eu7#J-IzFfulTFruKt)cNM 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 VKPvs?vS+7%TT@q~~B8Z62 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

    s!r7u8qGG<*R8T5JCo_{TG1}?6jiajGB^q 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 SuxUr@N2rpparseUri($originalUri); +$pathWithoutLocale = $parsedUri['pathWithoutLocale']; +$requestedLocale = $parsedUri['locale']; +$_SERVER['MINTY_LOCALE'] = $requestedLocale; + +// Rewrite REQUEST_URI without locale segment for router +if ($parsedUri['hadLocaleInUrl']) { + $_SERVER['REQUEST_URI'] = $localeResolver->buildUriWithoutLocale( + $pathWithoutLocale, + $parsedUri['query'] + ); +} + +// Resolve effective locale from URL > Session > Cookie > Default +I18n::$locale = $localeResolver->resolveLocale( + $requestedLocale, + $_SESSION['user']['locale'] ?? null, + $_COOKIE['locale'] ?? null +); + +$isAssetRequest = AssetDetector::isAssetRequest($pathWithoutLocale); + +// Refresh tenant context if stale or missing (skip for assets) +if (!empty($_SESSION['user']['id']) && !$isAssetRequest) { + $userId = (int) ($_SESSION['user']['id'] ?? 0); + if ($userId > 0) { + $ttl = defined('TENANT_SNAPSHOT_TTL') ? (int) TENANT_SNAPSHOT_TTL : 120; + $lastRefresh = (int) ($_SESSION['tenant_snapshot_at'] ?? 0); + $needsRefresh = empty($_SESSION['current_tenant']) || empty($_SESSION['available_tenants']); + if ($ttl > 0 && (time() - $lastRefresh) >= $ttl) { + $needsRefresh = true; + } + if ($needsRefresh) { + \MintyPHP\Service\AuthService::loadTenantDataIntoSession($userId); + $_SESSION['tenant_snapshot_at'] = time(); + } + } +} + +if ($requestedLocale === '' && !$isAssetRequest) { + $method = strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET')); + if (in_array($method, ['GET', 'HEAD'], true)) { + $target = Request::withLocale($pathWithoutLocale, I18n::$locale ?? I18n::$defaultLocale); + $target .= $parsedUri['query'] !== '' ? '?' . $parsedUri['query'] : ''; + Router::redirect($target); + } +} + +// Guard: restrict non-public pages to logged-in users +$accessControl = new AccessControl(); +$accessControl->requireAuthOrRedirect($pathWithoutLocale, !empty($_SESSION['user']['id'])); + +// Analyze the PHP code +if (Debugger::$enabled) { + Analyzer::execute(); +} + +// Load the action into body +ob_start(); +if (Router::getTemplateAction()) { + require Router::getTemplateAction(); +} +if (ob_get_contents()) { + ob_end_flush(); + trigger_error('MintyPHP template action"' . Router::getTemplateAction() . '" should not send output. Error raised ', E_USER_WARNING); +} else { + ob_end_clean(); +} + +ob_start(); +if (Router::getAction()) { + extract(Router::getParameters()); + require Router::getAction(); +} +if (ob_get_contents()) { + ob_end_flush(); + trigger_error('MintyPHP action "' . Router::getAction() . '" should not send output. Error raised ', E_USER_WARNING); +} else { + ob_end_clean(); +} + +// End the session +Session::end(); + +// Close the database connection +DB::close(); + +if (Router::getTemplateView()) { + Buffer::start('html'); + if (Router::getView()) { + require Router::getView(); + } + + // Show developer toolbar + if (Debugger::$enabled) { + Debugger::toolbar(); + } + + Buffer::end('html'); + // Load body into template + require Router::getTemplateView(); +} else { // Handle the 'none' template case + if (Router::getView()) { + require Router::getView(); + } +} diff --git a/web/js/app-init.js b/web/js/app-init.js new file mode 100644 index 0000000..902fc25 --- /dev/null +++ b/web/js/app-init.js @@ -0,0 +1,21 @@ +import './components/app-flash-auto-dismiss.js'; +import './components/app-fslightbox-refresh.js'; +import './components/app-password-hints.js'; +import './components/app-copy-badge.js'; +import './components/app-multiselect-init.js'; +import './components/app-nav-history.js'; +import './components/app-toggle-sidebar.js'; +import './components/app-toggle-aside-panels.js'; +import './components/app-toggle-details-aside.js'; +import './components/app-global-search.js'; +import './components/app-theme-toggle.js'; +import './components/app-tenant-switcher.js'; +import './components/app-tabs.js'; +import './components/app-color-default-toggle.js'; + +// Ensure fslightbox is refreshed once the vendor script is loaded. +if (typeof window.refreshFsLightbox === 'function') { + window.refreshFsLightbox(); +} else { + window.__fsLightboxRefreshPending = true; +} diff --git a/web/js/app-login-init.js b/web/js/app-login-init.js new file mode 100644 index 0000000..e483ae8 --- /dev/null +++ b/web/js/app-login-init.js @@ -0,0 +1,2 @@ +import './components/app-flash-auto-dismiss.js'; +import './components/app-password-hints.js'; diff --git a/web/js/components/app-async-flash.js b/web/js/components/app-async-flash.js new file mode 100644 index 0000000..71c5375 --- /dev/null +++ b/web/js/components/app-async-flash.js @@ -0,0 +1,89 @@ +/** + * Async Flash Messages & Loading State + * Renders flash messages into #async-messages for JS-triggered notifications + * Provides loading cursor state management + */ + +/** + * Set global loading state (cursor + pointer-events) + * @param {boolean} loading - Whether to show loading state + */ +export function setLoading(loading) { + if (loading) { + document.body.classList.add('is-loading'); + } else { + document.body.classList.remove('is-loading'); + } +} + +/** + * Execute an async function with loading state + * @param {Function} fn - Async function to execute + * @returns {Promise} - Result of the function + */ +export async function withLoading(fn) { + setLoading(true); + try { + return await fn(); + } finally { + setLoading(false); + } +} + +const defaultTimeouts = { + success: 10000, + info: 10000, + warning: 10000, + error: 0 +}; + +/** + * Show an async flash message + * @param {string} type - Message type: 'success', 'info', 'warning', 'error' + * @param {string} message - The message text + * @param {number} [timeout] - Auto-dismiss timeout in ms (0 = no auto-dismiss) + */ +export function showAsyncFlash(type, message, timeout) { + const container = document.getElementById('async-messages'); + if (!container) { + console.warn('async-messages container not found'); + return null; + } + + const effectiveTimeout = timeout ?? defaultTimeouts[type] ?? 5000; + + const notice = document.createElement('div'); + notice.className = 'notice'; + notice.setAttribute('data-variant', type); + + const messageSpan = document.createElement('span'); + messageSpan.textContent = message; + notice.appendChild(messageSpan); + + const closeButton = document.createElement('button'); + closeButton.type = 'button'; + closeButton.className = 'contrast outline small'; + closeButton.innerHTML = ''; + closeButton.addEventListener('click', () => notice.remove()); + notice.appendChild(closeButton); + + container.appendChild(notice); + + if (effectiveTimeout > 0) { + notice.style.setProperty('--flash-timeout', `${effectiveTimeout}ms`); + notice.classList.add('flash-timed'); + setTimeout(() => notice.remove(), effectiveTimeout); + } + + return notice; +} + +/** + * Clear all async flash messages + */ +export function clearAsyncFlash() { + const container = document.getElementById('async-messages'); + if (container) { + container.innerHTML = ''; + } +} diff --git a/web/js/components/app-bulk-selection.js b/web/js/components/app-bulk-selection.js new file mode 100644 index 0000000..13bcc59 --- /dev/null +++ b/web/js/components/app-bulk-selection.js @@ -0,0 +1,26 @@ +export function bindBulkVisibility({ + containerSelector, + buttonSelector, + selectedRowSelector = '.gridjs-tr-selected' +} = {}) { + const container = document.querySelector(containerSelector); + const buttons = Array.from(document.querySelectorAll(buttonSelector)); + if (!container || !buttons.length) return { update: () => {} }; + + const update = () => { + const selected = container.querySelectorAll(selectedRowSelector).length > 0; + buttons.forEach((button) => { + button.hidden = !selected; + }); + }; + + const observer = new MutationObserver(() => update()); + observer.observe(container, { + subtree: true, + attributes: true, + attributeFilter: ['class'] + }); + + update(); + return { update, destroy: () => observer.disconnect() }; +} diff --git a/web/js/components/app-color-default-toggle.js b/web/js/components/app-color-default-toggle.js new file mode 100644 index 0000000..01e6a86 --- /dev/null +++ b/web/js/components/app-color-default-toggle.js @@ -0,0 +1,43 @@ +const toggles = document.querySelectorAll('[data-color-default-toggle]'); + +const syncToggle = (toggle) => { + const targetSelector = toggle.dataset.colorTarget || ''; + if (!targetSelector) { + return; + } + const target = document.querySelector(targetSelector); + if (!target) { + return; + } + const defaultValue = toggle.dataset.colorDefault || '#2fa4a4'; + if (toggle.checked) { + if (!target.dataset.customValue) { + target.dataset.customValue = target.value; + } + target.value = defaultValue; + target.setAttribute('disabled', 'disabled'); + } else { + target.removeAttribute('disabled'); + if (target.dataset.customValue) { + target.value = target.dataset.customValue; + } + } +}; + +toggles.forEach((toggle) => { + const targetSelector = toggle.dataset.colorTarget || ''; + const target = targetSelector ? document.querySelector(targetSelector) : null; + + toggle.addEventListener('change', () => syncToggle(toggle)); + + if (target) { + target.addEventListener('input', () => { + if (toggle.checked) { + toggle.checked = false; + target.removeAttribute('disabled'); + } + }); + } + + syncToggle(toggle); +}); diff --git a/web/js/components/app-copy-badge.js b/web/js/components/app-copy-badge.js new file mode 100644 index 0000000..b6ceab1 --- /dev/null +++ b/web/js/components/app-copy-badge.js @@ -0,0 +1,66 @@ +const COPY_SELECTOR = '.badge[data-copy="true"]'; +const COPIED_CLASS = 'is-copied'; + +const getCopyValue = (badge) => { + const explicit = badge.getAttribute('data-copy-value'); + if (explicit !== null && explicit !== '') { + return explicit; + } + return (badge.textContent || '').trim(); +}; + +const copyText = async (value) => { + if (!value) return false; + if (navigator.clipboard?.writeText) { + await navigator.clipboard.writeText(value); + return true; + } + const textarea = document.createElement('textarea'); + textarea.value = value; + textarea.setAttribute('readonly', 'true'); + textarea.style.position = 'fixed'; + textarea.style.opacity = '0'; + document.body.appendChild(textarea); + textarea.select(); + const ok = document.execCommand('copy'); + document.body.removeChild(textarea); + return ok; +}; + +const enhanceBadge = (badge) => { + if (badge.querySelector('.badge-copy-icon')) return; + const icon = document.createElement('span'); + icon.className = 'badge-copy-icon'; + icon.setAttribute('aria-hidden', 'true'); + icon.innerHTML = ''; + badge.appendChild(icon); + badge.setAttribute('role', 'button'); + badge.setAttribute('tabindex', '0'); + if (!badge.hasAttribute('aria-label')) { + badge.setAttribute('aria-label', 'Copy to clipboard'); + } + const handler = async (event) => { + event.preventDefault(); + const value = getCopyValue(badge); + const ok = await copyText(value); + if (!ok) return; + badge.classList.add(COPIED_CLASS); + window.setTimeout(() => badge.classList.remove(COPIED_CLASS), 1200); + }; + badge.addEventListener('click', handler); + badge.addEventListener('keydown', (event) => { + if (event.key === 'Enter' || event.key === ' ') { + handler(event); + } + }); +}; + +const initBadgeCopy = () => { + document.querySelectorAll(COPY_SELECTOR).forEach(enhanceBadge); +}; + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initBadgeCopy); +} else { + initBadgeCopy(); +} diff --git a/web/js/components/app-flash-auto-dismiss.js b/web/js/components/app-flash-auto-dismiss.js new file mode 100644 index 0000000..0a64ddc --- /dev/null +++ b/web/js/components/app-flash-auto-dismiss.js @@ -0,0 +1,53 @@ +export function initFlashAutoDismiss(options = {}) { + const { + selector = '.flash-stack .notice[data-flash-timeout]', + defaultTimeout = 0 + } = options; + + const notices = document.querySelectorAll(selector); + if (!notices.length) { + return; + } + + const postForm = async (form) => { + const action = form.getAttribute('action'); + if (!action) return null; + const body = new URLSearchParams(new FormData(form)); + return fetch(action, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'X-Requested-With': 'fetch' + }, + body + }); + }; + + notices.forEach((notice) => { + const timeout = Number.parseInt( + notice.dataset.flashTimeout || `${defaultTimeout}`, + 10 + ); + if (!timeout || timeout <= 0) { + return; + } + notice.style.setProperty('--flash-timeout', `${timeout}ms`); + notice.classList.add('flash-timed'); + window.setTimeout(async () => { + const form = notice.querySelector('form'); + if (form) { + const response = await postForm(form); + if (!response || !response.ok) { + return; + } + } + notice.remove(); + }, timeout); + }); +} + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => initFlashAutoDismiss()); +} else { + initFlashAutoDismiss(); +} diff --git a/web/js/components/app-fslightbox-refresh.js b/web/js/components/app-fslightbox-refresh.js new file mode 100644 index 0000000..f4e415a --- /dev/null +++ b/web/js/components/app-fslightbox-refresh.js @@ -0,0 +1,48 @@ +const refreshFsLightbox = () => { + if (typeof window.refreshFsLightbox === 'function') { + window.refreshFsLightbox(); + return true; + } + return false; +}; + +let refreshTimer = null; +const scheduleRefresh = () => { + if (refreshTimer) return; + refreshTimer = window.setTimeout(() => { + refreshTimer = null; + refreshFsLightbox(); + }, 30); +}; + +const initObserver = () => { + if (!document.body || typeof MutationObserver === 'undefined') { + return; + } + const observer = new MutationObserver((mutations) => { + for (const mutation of mutations) { + for (const node of mutation.addedNodes) { + if (!(node instanceof HTMLElement)) continue; + if (node.matches?.('[data-fslightbox]') || node.querySelector?.('[data-fslightbox]')) { + scheduleRefresh(); + return; + } + } + } + }); + observer.observe(document.body, { childList: true, subtree: true }); +}; + +if (!refreshFsLightbox()) { + scheduleRefresh(); +} + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => { + refreshFsLightbox(); + initObserver(); + }); +} else { + refreshFsLightbox(); + initObserver(); +} diff --git a/web/js/components/app-global-search.js b/web/js/components/app-global-search.js new file mode 100644 index 0000000..ba34865 --- /dev/null +++ b/web/js/components/app-global-search.js @@ -0,0 +1,168 @@ +const input = document.querySelector('#side-search'); +const resultsEl = document.querySelector('[data-global-search-results]'); + +if (!input || !resultsEl) { + if (!input) console.warn('[GlobalSearch] #side-search input not found'); + if (!resultsEl) console.warn('[GlobalSearch] [data-global-search-results] container not found'); +} else { + const panel = document.querySelector('#aside-panel-search'); + const toggleButton = document.querySelector('[data-search-details-toggle]'); + const toggleIcon = document.querySelector('[data-search-details-icon]'); + const appBase = window.APP_BASE || document.baseURI; + const endpoint = new URL('admin/search/data', appBase); + const resultsPage = new URL('search', appBase); + const minLength = 2; + let pending = null; + + const itemsByKey = new Map(); + resultsEl.querySelectorAll('[data-search-key]').forEach((item) => { + const key = item.getAttribute('data-search-key'); + if (key) itemsByKey.set(key, item); + }); + if (itemsByKey.size === 0) { + console.warn('[GlobalSearch] No [data-search-key] elements found in results container'); + } + + const setLoadingState = (value) => { + resultsEl.querySelectorAll('[data-search-count]').forEach((el) => { + el.textContent = value; + }); + }; + + const render = (items, query) => { + items.forEach((item) => { + const li = itemsByKey.get(item.key); + if (!li) { + console.warn('[GlobalSearch] No element found for key:', item.key); + return; + } + const countEl = li.querySelector('[data-search-count]'); + const link = li.querySelector('a'); + const previewEl = li.querySelector('[data-search-preview]'); + const base = item.key === 'pages' && item.url ? item.url : (li.getAttribute('data-search-base') || item.url); + const url = new URL(base, appBase); + if (item.key !== 'pages') { + url.searchParams.set('search', query); + } + if (countEl) countEl.textContent = item.count.toString(); + if (link) { + link.href = item.count > 0 ? url.toString() : base; + link.setAttribute('aria-disabled', item.count > 0 ? 'false' : 'true'); + } + if (previewEl) { + previewEl.innerHTML = ''; + if (Array.isArray(item.items) && item.items.length > 0) { + item.items.forEach((previewItem, idx) => { + if (!previewItem || !previewItem.url) { + console.warn('[GlobalSearch] Preview item missing url at index', idx, 'for key:', item.key, previewItem); + return; + } + const previewLi = document.createElement('li'); + const previewLink = document.createElement('a'); + previewLink.href = previewItem.url; + previewLink.textContent = previewItem.label || ''; + previewLi.appendChild(previewLink); + previewEl.appendChild(previewLi); + }); + } + } + if (item.count > 0) { + li.hidden = false; + } else { + li.hidden = true; + } + }); + }; + + const clear = () => { + setLoadingState('0'); + resultsEl.querySelectorAll('a').forEach((link) => { + link.setAttribute('aria-disabled', 'true'); + const base = link.closest('[data-search-base]')?.getAttribute('data-search-base'); + link.setAttribute('href', base || '#'); + }); + resultsEl.querySelectorAll('[data-search-preview]').forEach((list) => { + list.innerHTML = ''; + }); + resultsEl.querySelectorAll('[data-search-key]').forEach((li) => { + li.hidden = false; + }); + }; + + const fetchCounts = async (value) => { + const url = new URL(endpoint.toString()); + url.searchParams.set('q', value); + setLoadingState('…'); + const response = await fetch(url.toString(), { headers: { 'Accept': 'application/json' } }); + if (!response.ok) { + console.warn('[GlobalSearch] Fetch failed with status:', response.status, response.statusText); + clear(); + return; + } + const data = await response.json(); + if (Array.isArray(data)) { + render(data, value); + } else { + console.warn('[GlobalSearch] Invalid response format, expected array but got:', typeof data, data); + clear(); + } + }; + + const onInput = () => { + const value = input.value.trim(); + if (value.length < minLength) { + clear(); + return; + } + if (pending) window.clearTimeout(pending); + pending = window.setTimeout(() => { + fetchCounts(value).catch((err) => { + console.warn('[GlobalSearch] Fetch error:', err); + clear(); + }); + }, 300); + }; + + input.addEventListener('input', onInput); + const submitSearch = () => { + const value = input.value.trim(); + if (value.length < minLength) return; + resultsPage.searchParams.set('search', value); + window.location.href = resultsPage.toString(); + }; + + input.addEventListener('keydown', (event) => { + if (event.key !== 'Enter') return; + event.preventDefault(); + submitSearch(); + }); + + const form = input.closest('form'); + if (form) { + form.addEventListener('submit', (event) => { + event.preventDefault(); + submitSearch(); + }); + } + + if (toggleButton && panel) { + toggleButton.addEventListener('click', () => { + panel.classList.toggle('search-details-hidden'); + if (toggleIcon) { + toggleIcon.classList.toggle('bi-dash-square'); + toggleIcon.classList.toggle('bi-plus-square'); + } + }); + } else if (toggleButton || panel) { + if (!toggleButton) console.warn('[GlobalSearch] [data-search-details-toggle] button not found'); + if (!panel) console.warn('[GlobalSearch] #aside-panel-search panel not found'); + } + + // Seed from current URL search param if present + const currentUrl = new URL(window.location.href); + const preset = currentUrl.searchParams.get('search'); + if (preset && !input.value) { + input.value = preset; + onInput(); + } +} diff --git a/web/js/components/app-multiselect-init.js b/web/js/components/app-multiselect-init.js new file mode 100644 index 0000000..d6a8b8e --- /dev/null +++ b/web/js/components/app-multiselect-init.js @@ -0,0 +1,109 @@ +let multiSelectLoader = null; + +const resolveScriptUrl = (script) => { + if (script) return script; + const assetBase = window.APP_ASSET_BASE || document.baseURI; + return new URL('vendor/multi-select/MultiSelect.js', assetBase).toString(); +}; + +const ensureMultiSelect = async (script) => { + if (typeof window.MultiSelect !== 'undefined') { + return window.MultiSelect; + } + if (!multiSelectLoader) { + multiSelectLoader = new Promise((resolve, reject) => { + const tag = document.createElement('script'); + tag.src = resolveScriptUrl(script); + tag.async = true; + tag.onload = () => resolve(window.MultiSelect); + tag.onerror = (event) => reject(event); + document.head.appendChild(tag); + }); + } + return multiSelectLoader; +}; + +export const initMultiSelect = async (target = '[data-multi-select]') => { + const elements = typeof target === 'string' ? document.querySelectorAll(target) : [target]; + if (!elements.length) return []; + + const MultiSelect = await ensureMultiSelect(); + const instances = []; + elements.forEach((element) => { + if (!element || element.dataset.multiSelectInit === '1') return; + const syncTarget = element.dataset.syncTarget; + const syncInput = syncTarget ? document.querySelector(syncTarget) : null; + const options = {}; + const placeholder = element.dataset.placeholder; + if (placeholder) options.placeholder = placeholder; + if (element.dataset.search !== undefined) { + options.search = element.dataset.search === 'true'; + } + if (element.dataset.selectAll !== undefined) { + options.selectAll = element.dataset.selectAll === 'true'; + } + if (element.dataset.disabled !== undefined) { + options.disabled = element.dataset.disabled === 'true'; + } + if (element.disabled) { + options.disabled = true; + } + if (element.dataset.listAll !== undefined) { + options.listAll = element.dataset.listAll === 'true'; + } + if (element.dataset.selectedLabel) { + options.selectedLabel = element.dataset.selectedLabel; + } + if (element.dataset.searchPlaceholder) { + options.searchPlaceholder = element.dataset.searchPlaceholder; + } + if (element.dataset.selectAllLabel) { + options.selectAllLabel = element.dataset.selectAllLabel; + } + let isSyncing = false; + let instance; + try { + instance = new MultiSelect(element, options); + } catch (error) { + console.error('[multi-select] init failed', element, error); + return; + } + if (element.dataset.disabled === 'true' || element.disabled) { + instance.disable(); + } + element.dataset.multiSelectInit = '1'; + instances.push(instance); + if (syncInput) { + syncInput._multiSelectInstance = instance; + const syncValues = () => { + if (!syncInput || isSyncing) return; + isSyncing = true; + const values = instance.selectedValues || []; + syncInput.value = Array.isArray(values) ? values.join(',') : ''; + syncInput.dispatchEvent(new Event('change', { bubbles: true })); + isSyncing = false; + }; + instance.element.addEventListener('multi-select:change', syncValues); + const values = instance.selectedValues || []; + syncInput.value = Array.isArray(values) ? values.join(',') : ''; + syncInput.addEventListener('change', () => { + if (isSyncing) return; + const nextValues = syncInput.value + ? syncInput.value.split(',').map((item) => item.trim()).filter(Boolean) + : []; + instance.setValues(nextValues); + }); + } + }); + return instances; +}; + +const autoInit = () => { + initMultiSelect().catch(() => {}); +}; + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', autoInit); +} else { + autoInit(); +} diff --git a/web/js/components/app-nav-history.js b/web/js/components/app-nav-history.js new file mode 100644 index 0000000..0fbd1ad --- /dev/null +++ b/web/js/components/app-nav-history.js @@ -0,0 +1,48 @@ +const updateHistoryButtons = () => { + const back = document.querySelector('#global-back'); + const forward = document.querySelector('#global-forward'); + if (!back && !forward) return; + + const hasHistory = window.history.length > 1; + + if (back) { + back.setAttribute('aria-disabled', hasHistory ? 'false' : 'true'); + back.classList.toggle('is-disabled', !hasHistory); + } + if (forward) { + forward.setAttribute('aria-disabled', hasHistory ? 'false' : 'true'); + forward.classList.toggle('is-disabled', !hasHistory); + } +}; + +const initHistoryButtons = () => { + const back = document.querySelector('#global-back'); + const forward = document.querySelector('#global-forward'); + + if (back) { + back.addEventListener('click', (event) => { + if (window.history.length > 1) { + event.preventDefault(); + window.history.back(); + } + }); + } + + if (forward) { + forward.addEventListener('click', (event) => { + if (window.history.length > 1) { + event.preventDefault(); + window.history.forward(); + } + }); + } + + updateHistoryButtons(); + window.addEventListener('popstate', updateHistoryButtons); +}; + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initHistoryButtons); +} else { + initHistoryButtons(); +} diff --git a/web/js/components/app-page-editor.js b/web/js/components/app-page-editor.js new file mode 100644 index 0000000..c720c4c --- /dev/null +++ b/web/js/components/app-page-editor.js @@ -0,0 +1,185 @@ +import EditorJS from '../../vendor/editorjs/editorjs.mjs'; + +const form = document.querySelector('[data-page-editor]'); +if (form) { + const holder = form.querySelector('[data-editor-holder]'); + if (!holder) { + // No holder available, skip initialization. + } else { + const contentField = form.querySelector('#page-content'); + const toggleButton = document.querySelector('[data-editor-toggle]'); + const saveButton = document.querySelector('[data-editor-save]'); + const canEdit = form.dataset.canEdit === '1'; + + const parseData = (value) => { + if (!value) { + return { blocks: [] }; + } + try { + const parsed = JSON.parse(value); + if (parsed && typeof parsed === 'object') { + if (!Array.isArray(parsed.blocks)) { + parsed.blocks = []; + } + return parsed; + } + } catch (error) { + // ignore invalid JSON + } + return { blocks: [] }; + }; + + const setToggleLabel = (mode) => { + if (!toggleButton) { + return; + } + const viewLabel = toggleButton.dataset.viewLabel || ''; + const editLabel = toggleButton.dataset.editLabel || ''; + const text = mode === 'edit' ? viewLabel : editLabel; + const icon = toggleButton.querySelector('[data-editor-icon]'); + + if (icon) { + icon.className = mode === 'edit' ? 'bi bi-eye-fill' : 'bi bi-pencil-square'; + } + toggleButton.setAttribute('aria-label', text); + toggleButton.dataset.tooltip = text; + }; + + let mode = form.dataset.editMode === 'edit' && canEdit ? 'edit' : 'view'; + form.dataset.editMode = mode; + setToggleLabel(mode); + + const HeaderTool = window.Header || window.EditorJSHeader || null; + const ListTool = window.EditorjsList || window.List || null; + const ChecklistTool = window.Checklist || window.EditorJSChecklist || null; + const TableTool = window.Table || window.EditorJSTable || null; + const ColumnsTool = window.editorjsColumns || window.Columns || null; + const MarkerTool = window.Marker || null; + + const tools = {}; + if (HeaderTool) { + tools.header = { + class: HeaderTool, + inlineToolbar: true, + config: { + placeholder: form.dataset.headerPlaceholder || 'Heading', + levels: [1, 2, 3, 4], + defaultLevel: 1, + }, + }; + } + if (ListTool) { + tools.list = { + class: ListTool, + inlineToolbar: true, + config: { + defaultStyle: 'unordered', + }, + }; + } + if (ChecklistTool) { + tools.checklist = { + class: ChecklistTool, + inlineToolbar: true, + }; + } + if (TableTool) { + tools.table = { + class: TableTool, + inlineToolbar: true, + config: { + rows: 2, + cols: 2, + }, + }; + } + if (ColumnsTool) { + const innerTools = { ...tools }; + tools.columns = { + class: ColumnsTool, + config: { + EditorJsLibrary: EditorJS, + tools: innerTools, + }, + }; + } + if (MarkerTool) { + tools.marker = { + class: MarkerTool, + shortcut: 'CMD+SHIFT+M', + }; + } + + const inlineTools = ['bold', 'italic', 'link']; + if (MarkerTool) { + inlineTools.unshift('marker'); + } + + const editor = new EditorJS({ + holder, + data: parseData(contentField ? contentField.value : ''), + readOnly: mode !== 'edit', + autofocus: mode === 'edit', + placeholder: form.dataset.placeholder || undefined, + tools, + inlineToolbar: inlineTools, + }); + + const toggleMode = async (nextMode) => { + if (!canEdit || mode === nextMode) { + return; + } + mode = nextMode; + form.dataset.editMode = mode; + setToggleLabel(mode); + if (editor.readOnly && editor.readOnly.toggle) { + await editor.readOnly.toggle(mode !== 'edit'); + } + if (saveButton) { + saveButton.disabled = mode !== 'edit'; + } + }; + + if (toggleButton && canEdit) { + toggleButton.addEventListener('click', () => { + toggleMode(mode === 'edit' ? 'view' : 'edit'); + }); + } + + if (form && contentField && canEdit) { + form.addEventListener('submit', async (event) => { + if (form.dataset.submitting === '1') { + return; + } + event.preventDefault(); + const output = await editor.save(); + contentField.value = JSON.stringify(output); + form.dataset.submitting = '1'; + + try { + const formData = new FormData(form); + const response = await fetch(form.action || window.location.pathname, { + method: 'POST', + headers: { + 'X-Requested-With': 'XMLHttpRequest', + Accept: 'application/json', + }, + body: formData, + }); + if (response.redirected) { + window.location.href = response.url; + return; + } + const data = await response.json().catch(() => null); + if (data && data.redirect) { + window.location.href = data.redirect; + return; + } + window.location.reload(); + } catch (error) { + form.submit(); + } + }); + } + } +} diff --git a/web/js/components/app-password-hints.js b/web/js/components/app-password-hints.js new file mode 100644 index 0000000..88afa2d --- /dev/null +++ b/web/js/components/app-password-hints.js @@ -0,0 +1,76 @@ +const rules = { + min: (value, min) => value.length >= min, + upper: (value) => /[A-Z]/.test(value), + lower: (value) => /[a-z]/.test(value), + number: (value) => /\d/.test(value), + symbol: (value) => /[^a-zA-Z0-9]/.test(value), + email: (value, _min, email) => { + if (!email) return true; + return !value.toLowerCase().includes(email.toLowerCase()); + }, + match: (_value, _min, _email, confirm) => { + if (!confirm) return false; + return true; + } +}; + +export function initPasswordHints() { + const containers = document.querySelectorAll('[data-password-hints]'); + if (!containers.length) return; + + containers.forEach((container) => { + const passwordSelector = container.dataset.passwordInput; + const confirmSelector = container.dataset.confirmInput; + const emailSelector = container.dataset.emailInput; + const passwordInput = passwordSelector ? document.querySelector(passwordSelector) : null; + const confirmInput = confirmSelector ? document.querySelector(confirmSelector) : null; + const emailInput = emailSelector ? document.querySelector(emailSelector) : null; + const minLength = Number.parseInt(container.dataset.minLength || '12', 10); + const items = container.querySelectorAll('[data-rule]'); + + const setState = (item, state) => { + item.classList.remove('is-valid', 'is-invalid'); + if (state === 'valid') item.classList.add('is-valid'); + if (state === 'invalid') item.classList.add('is-invalid'); + }; + + const evaluate = () => { + const password = passwordInput?.value ?? ''; + const confirm = confirmInput?.value ?? ''; + const email = emailInput?.value ?? ''; + const hasValue = password.length > 0 || confirm.length > 0; + + items.forEach((item) => { + const rule = item.dataset.rule; + if (!rule) return; + if (!hasValue) { + setState(item, 'neutral'); + return; + } + if (rule === 'match') { + if (password === '' || confirm === '') { + setState(item, 'neutral'); + return; + } + setState(item, password === confirm ? 'valid' : 'invalid'); + return; + } + const check = rules[rule]; + if (!check) return; + const ok = check(password, minLength, email, confirm); + setState(item, ok ? 'valid' : 'invalid'); + }); + }; + + if (passwordInput) passwordInput.addEventListener('input', evaluate); + if (confirmInput) confirmInput.addEventListener('input', evaluate); + if (emailInput) emailInput.addEventListener('input', evaluate); + evaluate(); + }); +} + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initPasswordHints); +} else { + initPasswordHints(); +} diff --git a/web/js/components/app-tabs.js b/web/js/components/app-tabs.js new file mode 100644 index 0000000..f1b12cb --- /dev/null +++ b/web/js/components/app-tabs.js @@ -0,0 +1,118 @@ +/** + * Initializes tab navigation + * Usage: + * - Tab buttons: + * - Tab panels:

    ...
    + * - Container:
    ...
    + * - URL param: ?tab=system + */ +export function initTabs(root = document) { + const containers = root.querySelectorAll('[data-tabs]'); + + containers.forEach((container) => { + if (container.dataset.tabsBound === '1') return; + container.dataset.tabsBound = '1'; + + const tabs = Array.from(container.querySelectorAll('[data-tab]')); + const panels = Array.from(container.querySelectorAll('[data-tab-panel]')); + + if (!tabs.length || !panels.length) return; + + const storageKey = container.dataset.tabsStorageKey || (container.id ? `tabs:${container.id}` : null); + const urlParamName = container.dataset.tabsParam || 'tab'; + + // Helper to get URL parameter + const getUrlParam = (name) => { + const params = new URLSearchParams(window.location.search); + return params.get(name); + }; + + // Helper to set URL parameter + const setUrlParam = (name, value) => { + const url = new URL(window.location); + url.searchParams.set(name, value); + window.history.replaceState({}, '', url); + }; + + // Get initial active tab from URL param, localStorage, or data-tab-default + let activeTab = null; + const urlTab = getUrlParam(urlParamName); + if (urlTab && panels.some(p => p.dataset.tabPanel === urlTab)) { + activeTab = urlTab; + } else if (storageKey) { + try { + const stored = localStorage.getItem(storageKey); + if (stored && panels.some(p => p.dataset.tabPanel === stored)) { + activeTab = stored; + } + } catch (e) { + // localStorage not available + } + } + if (!activeTab) { + const defaultTab = container.querySelector('[data-tab-default]'); + activeTab = defaultTab?.dataset.tab || tabs[0]?.dataset.tab; + } + + const activateTab = (tabName) => { + tabs.forEach(tab => { + const isActive = tab.dataset.tab === tabName; + tab.classList.toggle('is-active', isActive); + tab.setAttribute('aria-selected', isActive ? 'true' : 'false'); + }); + + panels.forEach(panel => { + const isVisible = panel.dataset.tabPanel === tabName; + panel.hidden = !isVisible; + panel.setAttribute('aria-hidden', isVisible ? 'false' : 'true'); + }); + + // Update URL parameter + setUrlParam(urlParamName, tabName); + + // Save to localStorage + if (storageKey) { + try { + localStorage.setItem(storageKey, tabName); + } catch (e) { + // localStorage not available + } + } + }; + + // Initialize tabs + tabs.forEach(tab => { + tab.setAttribute('role', 'tab'); + tab.addEventListener('click', (e) => { + e.preventDefault(); + activateTab(tab.dataset.tab); + }); + }); + + panels.forEach(panel => { + panel.setAttribute('role', 'tabpanel'); + }); + + container.setAttribute('role', 'tablist'); + + // Activate initial tab + if (activeTab) { + activateTab(activeTab); + } + + // Listen for popstate (back/forward navigation) + window.addEventListener('popstate', () => { + const newTab = getUrlParam(urlParamName); + if (newTab && panels.some(p => p.dataset.tabPanel === newTab)) { + activateTab(newTab); + } + }); + }); +} + +// Auto-initialize on load +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => initTabs()); +} else { + initTabs(); +} diff --git a/web/js/components/app-tenant-switcher.js b/web/js/components/app-tenant-switcher.js new file mode 100644 index 0000000..765b6af --- /dev/null +++ b/web/js/components/app-tenant-switcher.js @@ -0,0 +1,71 @@ +const switchTenant = async (link) => { + const tenantId = link.dataset.switchTenant; + const csrfKey = link.dataset.csrfKey; + const csrfToken = link.dataset.csrfToken; + const errorMessage = link.dataset.errorMessage || 'Failed to switch tenant'; + + if (!tenantId || !csrfKey || !csrfToken) { + console.error('Missing tenant ID or CSRF token'); + return; + } + + // Disable link during request + link.style.pointerEvents = 'none'; + link.style.opacity = '0.5'; + + try { + const body = new URLSearchParams({ + tenant_id: tenantId, + [csrfKey]: csrfToken + }); + + const response = await fetch('admin/users/switch-tenant', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': 'application/json', + 'X-Requested-With': 'fetch' + }, + body + }); + + if (response.ok) { + const data = await response.json(); + if (data.ok) { + window.location.reload(); + } else { + console.error('Tenant switch failed:', data.error); + alert(errorMessage); + link.style.pointerEvents = ''; + link.style.opacity = ''; + } + } else { + console.error('Server error:', response.status); + alert(errorMessage); + link.style.pointerEvents = ''; + link.style.opacity = ''; + } + } catch (error) { + console.error('Network error:', error); + alert(errorMessage); + link.style.pointerEvents = ''; + link.style.opacity = ''; + } +}; + +const initTenantSwitcher = () => { + const tenantLinks = document.querySelectorAll('[data-switch-tenant]'); + + tenantLinks.forEach(link => { + link.addEventListener('click', (e) => { + e.preventDefault(); + switchTenant(link); + }); + }); +}; + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initTenantSwitcher); +} else { + initTenantSwitcher(); +} diff --git a/web/js/components/app-theme-toggle.js b/web/js/components/app-theme-toggle.js new file mode 100644 index 0000000..012edfd --- /dev/null +++ b/web/js/components/app-theme-toggle.js @@ -0,0 +1,57 @@ +const setTheme = (theme) => { + const root = document.documentElement; + root.dataset.theme = theme; +}; + +const setIcon = (button, theme) => { + const icon = button.querySelector('i'); + if (!icon) return; + icon.classList.remove('bi-sun-fill', 'bi-moon-stars-fill'); + icon.classList.add(theme === 'dark' ? 'bi-moon-stars-fill' : 'bi-sun-fill'); +}; + +const updateTheme = async (button, theme) => { + const url = button.dataset.themeUrl; + const csrfKey = button.dataset.csrfKey; + const csrfToken = button.dataset.csrfToken; + if (!url || !csrfKey || !csrfToken) { + return true; + } + const body = new URLSearchParams({ theme, [csrfKey]: csrfToken }); + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': 'application/json', + 'X-Requested-With': 'fetch' + }, + body + }); + return response.ok; +}; + +const initThemeToggle = () => { + const button = document.querySelector('[data-theme-toggle]'); + if (!button) return; + const root = document.documentElement; + const getCurrent = () => (root.dataset.theme === 'dark' ? 'dark' : 'light'); + setIcon(button, getCurrent()); + + button.addEventListener('click', async () => { + const current = getCurrent(); + const next = current === 'dark' ? 'light' : 'dark'; + setTheme(next); + setIcon(button, next); + const ok = await updateTheme(button, next); + if (!ok) { + setTheme(current); + setIcon(button, current); + } + }); +}; + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initThemeToggle); +} else { + initThemeToggle(); +} diff --git a/web/js/components/app-toggle-aside-panels.js b/web/js/components/app-toggle-aside-panels.js new file mode 100644 index 0000000..bc17e42 --- /dev/null +++ b/web/js/components/app-toggle-aside-panels.js @@ -0,0 +1,191 @@ +export function initAsidePanels(options = {}) { + const { + barSelector = '.aside-icon-bar', + panelSelector = '.app-sidebar-panel', + titleSelector = '.app-sidebar-title', + toolsSelector = '[data-aside-tools]', + revealSidebarOnActivate = true, + persistSidebarStateOnActivate = true + } = options; + + const bar = document.querySelector(barSelector); + if (!bar) return; + + const tabs = Array.from(bar.querySelectorAll('[data-aside-target]')); + if (!tabs.length) return; + + const panels = Array.from(document.querySelectorAll(panelSelector)); + const titleEl = document.querySelector(titleSelector); + const toolsHost = document.querySelector(toolsSelector); + const sidebarController = window.AppSidebar || null; + const defaultTitle = titleEl?.dataset.asideTitleDefault || titleEl?.textContent || ''; + const storageKey = bar.dataset.asideStorage || ''; + + const getPanelKey = (panel) => panel?.dataset?.asidePanel || ''; + const getTabKey = (tab) => tab?.dataset?.asideTarget || ''; + const getPanelTools = (panel) => panel?.querySelector('[data-aside-panel-tools]') || null; + const getTabHref = (tab) => tab?.dataset?.asideHref || ''; + + const initPanelDetails = (panel) => { + if (!panel || panel.dataset.detailsBound === '1') return; + const storageKey = panel.dataset.asideDetailsStorage || ''; + if (!storageKey) return; + const detailsEls = Array.from(panel.querySelectorAll('details[data-details-key]')); + if (!detailsEls.length) return; + + const readStored = () => { + try { + const raw = window.localStorage.getItem(storageKey); + return raw ? JSON.parse(raw) : []; + } catch (error) { + return []; + } + }; + + const writeStored = (value) => { + try { + const list = Array.isArray(value) ? value : []; + window.localStorage.setItem(storageKey, JSON.stringify(list)); + } catch (error) { + // ignore storage errors + } + }; + + const applyStored = () => { + const stored = readStored(); + if (!stored.length) return; + detailsEls.forEach((details) => { + details.open = stored.includes(details.dataset.detailsKey || ''); + }); + }; + + detailsEls.forEach((details) => { + details.addEventListener('toggle', () => { + const openKeys = detailsEls + .filter((item) => item.open) + .map((item) => item.dataset.detailsKey || '') + .filter(Boolean); + writeStored(openKeys); + }); + }); + + applyStored(); + panel.dataset.detailsBound = '1'; + }; + + const readStored = () => { + if (!storageKey) return null; + try { + return window.localStorage.getItem(storageKey); + } catch (error) { + return null; + } + }; + + const writeStored = (key) => { + if (!storageKey) return; + try { + window.localStorage.setItem(storageKey, key); + } catch (error) { + // ignore storage errors + } + }; + + const syncTools = (panel) => { + if (!toolsHost) return; + toolsHost.innerHTML = ''; + const tools = getPanelTools(panel); + if (!tools) return; + toolsHost.innerHTML = tools.innerHTML; + }; + + const openSidebar = (persist) => { + if (!revealSidebarOnActivate || !sidebarController) return; + if (!sidebarController.isCollapsed()) return; + sidebarController.open({ persist }); + }; + + const setActive = (key, { fromUser = false } = {}) => { + if (!key) return; + + let activePanel = null; + panels.forEach((panel) => { + const isActive = getPanelKey(panel) === key; + if (isActive) activePanel = panel; + panel.hidden = !isActive; + panel.setAttribute('aria-hidden', isActive ? 'false' : 'true'); + }); + + tabs.forEach((tab) => { + const isActive = getTabKey(tab) === key; + tab.classList.toggle('active', isActive); + tab.setAttribute('aria-selected', isActive ? 'true' : 'false'); + tab.setAttribute('tabindex', isActive ? '0' : '-1'); + }); + + if (titleEl) { + const nextTitle = activePanel?.dataset?.asideTitle || defaultTitle; + if (nextTitle) { + titleEl.textContent = nextTitle; + } + } + if (activePanel) { + syncTools(activePanel); + initPanelDetails(activePanel); + } + writeStored(key); + if (fromUser) { + openSidebar(persistSidebarStateOnActivate); + } + }; + + const getInitialKey = () => { + const stored = readStored(); + if (stored && panels.some((panel) => getPanelKey(panel) === stored)) { + return stored; + } + const activeTab = tabs.find((tab) => tab.classList.contains('active')); + if (activeTab) return getTabKey(activeTab); + const visiblePanel = panels.find((panel) => !panel.hidden); + if (visiblePanel) return getPanelKey(visiblePanel); + return getTabKey(tabs[0]); + }; + + setActive(getInitialKey(), { fromUser: false }); + + tabs.forEach((tab) => { + tab.addEventListener('click', (event) => { + event.preventDefault(); + const key = getTabKey(tab); + const isActive = tab.classList.contains('active'); + const href = getTabHref(tab); + if (href) { + const base = document.baseURI || window.location.origin; + const targetUrl = new URL(href, base); + const currentUrl = new URL(window.location.href); + const isSame = targetUrl.pathname === currentUrl.pathname && targetUrl.search === currentUrl.search; + if (!isSame) { + setActive(key, { fromUser: true }); + window.location.href = targetUrl.toString(); + return; + } + } + if (sidebarController && sidebarController.isCollapsed()) { + sidebarController.open({ persist: persistSidebarStateOnActivate }); + setActive(key, { fromUser: true }); + return; + } + if (isActive && sidebarController) { + sidebarController.close({ persist: true }); + return; + } + setActive(key, { fromUser: true }); + }); + }); +} + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => initAsidePanels()); +} else { + initAsidePanels(); +} diff --git a/web/js/components/app-toggle-details-aside.js b/web/js/components/app-toggle-details-aside.js new file mode 100644 index 0000000..9f402d9 --- /dev/null +++ b/web/js/components/app-toggle-details-aside.js @@ -0,0 +1,66 @@ +export function initDetailsAsideToggle(options = {}) { + const { + buttonSelector = '#toggle-main-content-aside', + asideSelector = '#app-details-aside-section', + containerSelector = '.app-details-container', + storageKey = 'app-details-aside-collapsed' + } = options; + + const button = document.querySelector(buttonSelector); + const aside = document.querySelector(asideSelector); + if (!button || !aside) return; + + const container = aside.closest(containerSelector) || document.querySelector(containerSelector); + if (!container) return; + + if (!button.getAttribute('aria-controls')) { + button.setAttribute('aria-controls', aside.id || 'app-details-aside-section'); + } + + const readStored = () => { + try { + return window.localStorage.getItem(storageKey); + } catch (error) { + return null; + } + }; + + const writeStored = (collapsed) => { + try { + window.localStorage.setItem(storageKey, collapsed ? '1' : '0'); + } catch (error) { + // ignore storage errors + } + }; + + const applyState = (collapsed, persist = false) => { + container.classList.toggle('is-aside-collapsed', collapsed); + aside.hidden = collapsed; + button.setAttribute('aria-expanded', collapsed ? 'false' : 'true'); + if (persist) { + writeStored(collapsed); + } + }; + + const getInitialState = () => { + const stored = readStored(); + if (stored === '1' || stored === '0') { + return stored === '1'; + } + return false; + }; + + applyState(getInitialState(), false); + + button.addEventListener('click', (event) => { + event.preventDefault(); + const collapsed = !container.classList.contains('is-aside-collapsed'); + applyState(collapsed, true); + }); +} + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => initDetailsAsideToggle()); +} else { + initDetailsAsideToggle(); +} diff --git a/web/js/components/app-toggle-sidebar.js b/web/js/components/app-toggle-sidebar.js new file mode 100644 index 0000000..65cfeae --- /dev/null +++ b/web/js/components/app-toggle-sidebar.js @@ -0,0 +1,95 @@ +export function initSidebarToggle(options = {}) { + const { + buttonSelector = '#toggle-aside', + asideSelector = '#app-sidebar', + containerSelector = '.app-container', + storageKey = 'app-sidebar-collapsed' + } = options; + + const aside = document.querySelector(asideSelector); + if (!aside) return null; + + const buttons = Array.from(document.querySelectorAll(buttonSelector)); + const container = document.querySelector(containerSelector); + const root = document.documentElement; + + const readStored = () => { + try { + return window.localStorage.getItem(storageKey); + } catch (error) { + return null; + } + }; + + const writeStored = (collapsed) => { + try { + window.localStorage.setItem(storageKey, collapsed ? '1' : '0'); + } catch (error) { + // ignore storage errors + } + }; + + const applyState = (collapsed, { persist = false } = {}) => { + aside.classList.toggle('is-collapsed', collapsed); + if (container) { + container.classList.toggle('is-sidebar-collapsed', collapsed); + } + if (root) { + root.classList.toggle('sidebar-collapsed', collapsed); + } + buttons.forEach((button) => { + if (!button.getAttribute('aria-controls')) { + button.setAttribute('aria-controls', aside.id || 'app-sidebar'); + } + button.setAttribute('aria-expanded', collapsed ? 'false' : 'true'); + }); + if (persist) { + writeStored(collapsed); + } + }; + + const isCollapsed = () => aside.classList.contains('is-collapsed'); + + const getInitialState = () => { + const stored = readStored(); + if (stored === '1' || stored === '0') { + return stored === '1'; + } + return root?.classList.contains('sidebar-collapsed') ?? false; + }; + + const controller = { + isCollapsed, + open: ({ persist = true } = {}) => applyState(false, { persist }), + close: ({ persist = true } = {}) => applyState(true, { persist }), + toggle: ({ persist = true } = {}) => applyState(!isCollapsed(), { persist }), + apply: (collapsed, { persist = false } = {}) => applyState(!!collapsed, { persist }) + }; + + applyState(getInitialState(), { persist: false }); + + buttons.forEach((button) => { + button.addEventListener('click', (event) => { + event.preventDefault(); + controller.toggle({ persist: true }); + }); + }); + + document.addEventListener('app:sidebar', (event) => { + const detail = event.detail || {}; + const action = detail.action; + const persist = detail.persist ?? false; + if (action === 'open') controller.open({ persist }); + if (action === 'close') controller.close({ persist }); + if (action === 'toggle') controller.toggle({ persist }); + }); + + window.AppSidebar = controller; + return controller; +} + +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => initSidebarToggle()); +} else { + initSidebarToggle(); +} diff --git a/web/js/components/app-toggle-toolbar.js b/web/js/components/app-toggle-toolbar.js new file mode 100644 index 0000000..5a3a3ea --- /dev/null +++ b/web/js/components/app-toggle-toolbar.js @@ -0,0 +1,86 @@ +export function initToolbarToggles(root = document) { + const toggles = root.querySelectorAll('[data-toolbar-toggle]'); + toggles.forEach((toggle) => { + if (toggle.dataset.toolbarBound === '1') { + return; + } + toggle.dataset.toolbarBound = '1'; + if (!toggle.hasAttribute('type')) { + toggle.setAttribute('type', 'button'); + } + + const targetSelector = toggle.dataset.toolbarTarget || toggle.getAttribute('aria-controls'); + if (!targetSelector) { + return; + } + + const targets = Array.from(root.querySelectorAll(targetSelector)).filter(Boolean); + if (!targets.length) { + return; + } + + const labelTarget = toggle.querySelector('[data-toolbar-label]'); + const showLabel = toggle.dataset.toolbarTextShow; + const hideLabel = toggle.dataset.toolbarTextHide; + const storageKey = + toggle.dataset.toolbarStorageKey || + (targets.length === 1 && targets[0].id + ? `toolbar:${targets[0].id}` + : `toolbar:${targetSelector}`); + + if (!toggle.getAttribute('aria-controls') && targets.length === 1 && targets[0].id) { + toggle.setAttribute('aria-controls', targets[0].id); + } + + targets.forEach((target) => { + if (target.dataset.toolbarInitialized === '1') { + return; + } + const initial = target.dataset.toolbarInitial; + if (initial === 'hidden') { + target.hidden = true; + } else if (initial === 'shown') { + target.hidden = false; + } + target.dataset.toolbarInitialized = '1'; + }); + + if (storageKey) { + try { + const stored = localStorage.getItem(storageKey); + if (stored === 'hidden' || stored === 'shown') { + const shouldShow = stored === 'shown'; + targets.forEach((target) => { + target.hidden = !shouldShow; + }); + } + } catch (error) { + // localStorage not available + } + } + + const getExpanded = () => targets.every((target) => !target.hidden); + const setExpanded = (expanded) => { + targets.forEach((target) => { + target.hidden = !expanded; + }); + toggle.setAttribute('aria-expanded', expanded ? 'true' : 'false'); + if (labelTarget && (showLabel || hideLabel)) { + labelTarget.textContent = expanded ? (hideLabel || labelTarget.textContent) : (showLabel || labelTarget.textContent); + } + if (storageKey) { + try { + localStorage.setItem(storageKey, expanded ? 'shown' : 'hidden'); + } catch (error) { + // localStorage not available + } + } + }; + + setExpanded(getExpanded()); + + toggle.addEventListener('click', () => { + setExpanded(!getExpanded()); + }); + }); +} diff --git a/web/js/core/app-grid-factory.js b/web/js/core/app-grid-factory.js new file mode 100644 index 0000000..252c353 --- /dev/null +++ b/web/js/core/app-grid-factory.js @@ -0,0 +1,604 @@ +export function createServerGrid(options) { + const { + container, + dataUrl, + appBase = '/', + columns, + mapData, + total = (data) => data.total, + sortColumns = [], + paginationLimit = 10, + language = {}, + search = null, + filters = [], + urlSync = true, + gridjs, + rowDblClick = null, + actions = null, + rowDataset = null, + selection = null + } = options || {}; + + const gridjsLib = gridjs || window.gridjs; + const containerEl = typeof container === 'string' ? document.querySelector(container) : container; + if (!containerEl || !gridjsLib) { + return null; + } + + const params = new URLSearchParams(window.location.search); + const resolveUrl = (path) => new URL(path, appBase).toString(); + const addParam = (url, key, value) => { + const nextUrl = new URL(url); + nextUrl.searchParams.set(key, value); + return nextUrl.toString(); + }; + + const getInput = (input) => { + if (!input) return null; + return typeof input === 'string' ? document.querySelector(input) : input; + }; + + const getInputValue = (input) => { + if (!input) return ''; + if (input.type === 'checkbox') { + return input.checked ? (input.value || '1') : ''; + } + if (input.tagName === 'SELECT' && input.multiple) { + return Array.from(input.selectedOptions || []).map((option) => option.value).filter(Boolean); + } + return (input.value ?? '').toString(); + }; + + const setInputValue = (input, value) => { + if (!input) return; + if (input.type === 'checkbox') { + input.checked = value === true || value === 'true' || value === '1'; + } else if (input.tagName === 'SELECT' && input.multiple) { + const values = Array.isArray(value) + ? value.map((item) => item.toString()) + : value + ? value.toString().split(',').map((item) => item.trim()).filter(Boolean) + : []; + Array.from(input.options || []).forEach((option) => { + option.selected = values.includes(option.value); + }); + } else { + input.value = value; + } + if (input._multiSelectInstance && typeof input._multiSelectInstance.setValues === 'function') { + const values = Array.isArray(value) + ? value.map((item) => item.toString()) + : value + ? value.toString().split(',').map((item) => item.trim()).filter(Boolean) + : []; + input._multiSelectInstance.setValues(values); + } + }; + + let searchValue = ''; + let searchParam = 'search'; + let searchInput = null; + let searchDebounce = 250; + if (search) { + searchInput = getInput(search.input); + searchParam = search.param || searchParam; + searchDebounce = search.debounce ?? searchDebounce; + const initial = params.get(searchParam) ?? search.default ?? ''; + searchValue = initial || ''; + if (searchInput) { + setInputValue(searchInput, initial); + } + } + + const filterState = filters.map((filter) => { + const input = getInput(filter.input); + const initial = params.get(filter.param); + const value = initial !== null ? initial : (filter.default ?? ''); + if (input) { + const parsed = typeof filter.parse === 'function' ? filter.parse(value) : value; + setInputValue(input, parsed); + } + return { ...filter, input, value }; + }); + + const normalizeValue = (filter, value) => { + if (typeof filter.normalize === 'function') { + return filter.normalize(value); + } + return value; + }; + + const buildParams = () => { + const query = new URLSearchParams(); + if (searchValue) { + query.set(searchParam, searchValue); + } + filterState.forEach((filter) => { + const raw = getInputValue(filter.input) || filter.value || ''; + const normalized = normalizeValue(filter, raw); + if (Array.isArray(normalized)) { + const list = normalized.map((item) => item.toString()).filter(Boolean); + if (list.length) { + query.set(filter.param, list.join(',')); + } + return; + } + if (normalized !== '' && normalized !== null && typeof normalized !== 'undefined') { + query.set(filter.param, normalized); + } + }); + return query; + }; + + const baseUrl = () => { + const url = new URL(dataUrl, appBase); + const query = buildParams(); + query.forEach((value, key) => url.searchParams.set(key, value)); + return url.toString(); + }; + + const updateUrl = () => { + if (!urlSync) return; + const url = new URL(window.location.href); + if (searchParam) { + url.searchParams.delete(searchParam); + } + filterState.forEach((filter) => url.searchParams.delete(filter.param)); + const query = buildParams(); + query.forEach((value, key) => url.searchParams.set(key, value)); + window.history.replaceState({}, '', url.toString()); + }; + + const actionConfig = actions && actions.enabled ? { + label: actions.label || 'Actions', + index: Number.isInteger(actions.index) ? actions.index : null, + items: Array.isArray(actions.items) ? actions.items : [], + getRowId: typeof actions.getRowId === 'function' ? actions.getRowId : null, + wrapperClass: actions.wrapperClass || 'grid-actions', + onAction: typeof actions.onAction === 'function' ? actions.onAction : null + } : null; + const selectionConfig = selection && selection.enabled ? { + id: selection.id || 'selectRow', + index: Number.isInteger(selection.index) ? selection.index : 0, + component: selection.component || null, + props: selection.props || null, + onChange: typeof selection.onChange === 'function' ? selection.onChange : null, + getSelectedIds: typeof selection.getSelectedIds === 'function' ? selection.getSelectedIds : null, + selectAllLabel: selection.selectAllLabel || 'Select all', + selectAllEnabled: selection.selectAllEnabled !== false + } : null; + + const insertActionColumn = (cols) => { + if (!actionConfig) return cols; + const actionColumn = { + name: actionConfig.label, + sort: false, + formatter: (_cell, row) => { + const id = actionConfig.getRowId ? actionConfig.getRowId(row) : null; + if (!id) { + return gridjsLib.html(''); + } + const buttons = actionConfig.items.map((item) => { + if (!item || !item.key) return ''; + const label = typeof item.label === 'function' ? item.label(row, id) : item.label; + if (!label) return ''; + const className = item.className ? ` ${item.className}` : ''; + const type = item.type || 'button'; + if (type === 'link') { + const href = typeof item.href === 'function' ? item.href({ row, id }) : item.href; + const url = href || '#'; + return `${label}`; + } + return ``; + }).join(''); + return gridjsLib.html(`
    ${buttons}
    `); + } + }; + + const next = [...cols]; + const index = actionConfig.index === null ? next.length : Math.min(Math.max(actionConfig.index, 0), next.length); + next.splice(index, 0, actionColumn); + return next; + }; + + const insertSelectionColumn = (cols) => { + if (!selectionConfig) return cols; + const headerLabel = selectionConfig.selectAllLabel || 'Select all'; + const header = selectionConfig.selectAllEnabled + ? gridjsLib.html(``) + : ''; + const selectionColumn = { + id: selectionConfig.id, + name: header, + sort: false, + plugin: { + id: selectionConfig.id + } + }; + + const next = [...cols]; + const index = Math.min(Math.max(selectionConfig.index ?? 0, 0), next.length); + next.splice(index, 0, selectionColumn); + return next; + }; + + const insertActionSort = (cols) => { + if (!actionConfig || !cols.length) return cols; + const next = [...cols]; + const index = actionConfig.index === null ? next.length : Math.min(Math.max(actionConfig.index, 0), next.length); + next.splice(index, 0, null); + return next; + }; + + const insertSelectionSort = (cols) => { + if (!selectionConfig || !cols.length) return cols; + const next = [...cols]; + const index = Math.min(Math.max(selectionConfig.index ?? 0, 0), next.length); + next.splice(index, 0, null); + return next; + }; + + const mapDataWithActions = (data) => { + const rows = mapData ? mapData(data) : []; + if (!actionConfig || !Array.isArray(rows)) { + return rows; + } + const index = actionConfig.index === null ? null : Math.min(Math.max(actionConfig.index, 0), Infinity); + return rows.map((row) => { + if (!Array.isArray(row)) return row; + const next = [...row]; + const insertAt = index === null ? next.length : Math.min(index, next.length); + next.splice(insertAt, 0, null); + return next; + }); + }; + + const serverConfig = { + url: baseUrl(), + then: mapDataWithActions, + total + }; + + let finalSortColumns = sortColumns; + if (selectionConfig) { + finalSortColumns = insertSelectionSort(finalSortColumns); + } + if (actionConfig) { + finalSortColumns = insertActionSort(finalSortColumns); + } + let currentSort = null; + const sortConfig = finalSortColumns.length ? { + enabled: true, + server: { + url: (prev, columns) => { + if (!columns.length) { + currentSort = null; + return prev; + } + const column = columns[0]; + const key = finalSortColumns[column.index]; + if (!key) { + currentSort = null; + return prev; + } + const direction = column.direction === 1 ? 'asc' : 'desc'; + currentSort = { order: key, dir: direction }; + return addParam(addParam(prev, 'order', key), 'dir', direction); + } + } + } : { enabled: false }; + + const paginationConfig = { + limit: paginationLimit, + server: { + url: (prev, page, limit) => { + const offset = page * limit; + return addParam(addParam(prev, 'limit', limit), 'offset', offset); + } + } + }; + + const plugins = []; + if (selectionConfig?.component) { + plugins.push({ + id: selectionConfig.id, + component: selectionConfig.component, + props: selectionConfig.props || {} + }); + } + + const grid = new gridjsLib.Grid({ + columns: insertActionColumn(insertSelectionColumn(columns)), + server: serverConfig, + search: false, + sort: sortConfig, + pagination: paginationConfig, + language, + plugins + }); + + grid.render(containerEl); + setTimeout(() => { + initSelectAll(); + }, 0); + + // Prevent empty-state flash before data arrives. + let hasLoadedOnce = false; + const markLoadedOnce = () => { + if (hasLoadedOnce) return; + hasLoadedOnce = true; + containerEl.classList.add('gridjs-has-loaded'); + }; + const setUpdating = () => containerEl.classList.add('gridjs-is-updating'); + const clearUpdating = () => containerEl.classList.remove('gridjs-is-updating'); + + const store = grid?.config?.store; + if (store?.subscribe) { + store.subscribe((state) => { + if (!state) return; + // Grid.js status: 0=Init, 1=Loading, 2=Loaded, 3=Rendered, 4=Error + if (state.status === 1) { + setUpdating(); + } else { + clearUpdating(); + } + if (state.status >= 2) { + markLoadedOnce(); + } + if (state.status >= 3) { + initSelectAll(); + } + }); + } + + const applyRowDataset = () => { + if (typeof rowDataset !== 'function') return; + const rowEls = containerEl.querySelectorAll('.gridjs-tbody .gridjs-tr'); + const dataRows = grid.config.store.getState().data?.rows || []; + rowEls.forEach((rowEl, index) => { + const rowData = dataRows[index] || null; + if (!rowData) return; + const attrs = rowDataset(rowData, index) || {}; + Object.keys(attrs).forEach((key) => { + const value = attrs[key]; + const attr = `data-${key}`; + if (value === null || typeof value === 'undefined' || value === '') { + rowEl.removeAttribute(attr); + } else { + rowEl.setAttribute(attr, String(value)); + } + }); + }); + }; + + const initSelectAll = () => { + if (!selectionConfig?.component || !selectionConfig.selectAllEnabled) return; + const header = containerEl.querySelector(`th[data-column-id="${selectionConfig.id}"] input[data-grid-select-all]`); + if (!header) return; + if (header.dataset.bound === '1') { + return; + } + header.dataset.bound = '1'; + + const getRowCheckboxes = () => Array.from( + containerEl.querySelectorAll(`td[data-column-id="${selectionConfig.id}"] input[type="checkbox"]`) + ); + + const updateHeaderState = () => { + const boxes = getRowCheckboxes(); + const total = boxes.length; + const checked = boxes.filter((box) => box.checked).length; + header.indeterminate = total > 0 && checked > 0 && checked < total; + header.checked = total > 0 && checked === total; + header.disabled = total === 0; + }; + + header.addEventListener('change', () => { + const boxes = getRowCheckboxes(); + boxes.forEach((box) => { + if (box.checked !== header.checked) { + box.click(); + } + }); + updateHeaderState(); + }); + + updateHeaderState(); + }; + + if (typeof rowDataset === 'function') { + const observer = new MutationObserver(() => applyRowDataset()); + observer.observe(containerEl, { childList: true, subtree: true }); + applyRowDataset(); + } + + const getRowDataByElement = (rowEl) => { + if (!rowEl) return null; + const rows = Array.from(rowEl.parentElement?.children || []); + const rowIndex = rows.indexOf(rowEl); + if (rowIndex < 0) return null; + const dataRows = grid.config.store.getState().data?.rows || []; + const rowData = dataRows[rowIndex] || null; + if (!rowData) return null; + return { rowData, rowIndex }; + }; + + if (rowDblClick) { + const excludeSelector = rowDblClick.exclude || '.grid-actions, button, a, input, select, textarea'; + containerEl.addEventListener('dblclick', (event) => { + if (excludeSelector && event.target.closest(excludeSelector)) { + return; + } + const rowEl = event.target.closest('.gridjs-tr'); + const rowInfo = getRowDataByElement(rowEl); + if (!rowInfo) { + return; + } + const { rowData, rowIndex } = rowInfo; + const getUrl = rowDblClick.getUrl; + if (typeof getUrl !== 'function') { + return; + } + const url = getUrl(rowData, rowIndex); + if (url) { + window.location.href = url; + } + }); + } + + if (actionConfig) { + containerEl.addEventListener('click', async (event) => { + const actionEl = event.target.closest('[data-grid-action]'); + if (!actionEl) { + return; + } + const rowEl = actionEl.closest('.gridjs-tr'); + const rowInfo = getRowDataByElement(rowEl); + if (!rowInfo) { + return; + } + const { rowData } = rowInfo; + const actionKey = actionEl.getAttribute('data-grid-action') || ''; + const actionItem = actionConfig.items.find((item) => item && item.key === actionKey); + if (!actionItem) { + return; + } + const id = actionConfig.getRowId ? actionConfig.getRowId(rowData) : null; + if (!id) { + return; + } + const confirmText = typeof actionItem.confirm === 'function' + ? actionItem.confirm({ row: rowData, id }) + : actionItem.confirm; + if (confirmText && !window.confirm(confirmText)) { + return; + } + if (actionItem.type === 'link') { + const href = typeof actionItem.href === 'function' + ? actionItem.href({ row: rowData, id }) + : actionItem.href; + if (href) { + event.preventDefault(); + window.location.href = href; + } + return; + } + if (actionConfig.onAction) { + event.preventDefault(); + await actionConfig.onAction({ action: actionKey, id, row: rowData, event, grid, container: containerEl }); + } + }); + } + + const updateGrid = () => { + updateUrl(); + grid.updateConfig({ + server: { ...serverConfig, url: baseUrl() } + }).forceRender(); + }; + + const debounce = (fn, delay = 250) => { + let timer; + return (...args) => { + clearTimeout(timer); + timer = setTimeout(() => fn(...args), delay); + }; + }; + + if (searchInput) { + searchInput.addEventListener('input', debounce((event) => { + searchValue = event.target.value.trim(); + updateGrid(); + }, searchDebounce)); + } + + filterState.forEach((filter) => { + if (!filter.input) return; + const eventName = filter.event || 'change'; + filter.input.addEventListener(eventName, () => { + filter.value = getInputValue(filter.input); + updateGrid(); + }); + }); + + const resetFilters = () => { + if (search) { + const defaultValue = search.default ?? ''; + searchValue = defaultValue; + if (searchInput) { + setInputValue(searchInput, defaultValue); + } + } + filterState.forEach((filter) => { + const defaultValue = filter.default ?? ''; + filter.value = defaultValue; + if (filter.input) { + setInputValue(filter.input, defaultValue); + } + }); + updateGrid(); + }; + + const getSortParams = () => (currentSort ? { ...currentSort } : null); + const selectionApi = selectionConfig && selectionConfig.component ? { + getSelectedIds: () => { + if (selectionConfig.getSelectedIds) { + return selectionConfig.getSelectedIds({ grid, container: containerEl }); + } + const plugin = grid?.config?.plugin?.get?.(selectionConfig.id); + const store = plugin?.props?.store; + const state = store?.state ?? store?.getState?.(); + if (!state) return []; + if (Array.isArray(state.selected)) return state.selected; + if (Array.isArray(state.ids)) return state.ids; + if (state.rows && typeof state.rows === 'object') { + return Object.keys(state.rows).filter((key) => state.rows[key]); + } + if (state instanceof Set) return Array.from(state); + if (Array.isArray(state)) return state; + if (typeof state === 'object') { + return Object.keys(state).filter((key) => state[key]); + } + return []; + }, + clear: () => { + const plugin = grid?.config?.plugin?.get?.(selectionConfig.id); + const store = plugin?.props?.store; + if (store?.dispatch) { + store.dispatch('reset'); + } else if (store?.reset) { + store.reset(); + } + } + } : null; + + if (selectionConfig?.onChange && selectionConfig.component) { + grid.on('ready', () => { + const plugin = grid?.config?.plugin?.get?.(selectionConfig.id); + const store = plugin?.props?.store; + const sync = () => { + selectionConfig.onChange(selectionApi?.getSelectedIds?.() || []); + }; + if (store?.on) store.on('updated', sync); + if (store?.subscribe) store.subscribe(sync); + sync(); + }); + } + + grid.on('ready', () => { + initSelectAll(); + setTimeout(() => { + if (typeof window.requestFsLightboxRefresh === 'function') { + window.requestFsLightboxRefresh(); + return; + } + if (typeof window.refreshFsLightbox === 'function') { + window.refreshFsLightbox(); + } else { + window.__fsLightboxRefreshPending = true; + } + }, 0); + }); + + return { grid, container: containerEl, updateGrid, updateUrl, baseUrl, resolveUrl, getSortParams, resetFilters, selection: selectionApi }; +} diff --git a/web/js/pages/app-list-utils.js b/web/js/pages/app-list-utils.js new file mode 100644 index 0000000..5433c97 --- /dev/null +++ b/web/js/pages/app-list-utils.js @@ -0,0 +1,19 @@ +export const buildUrl = (appBase, path) => new URL(path, appBase).toString(); + +export const postAction = async (url, csrf, data = {}) => { + const body = new URLSearchParams({ ...data, [csrf.key]: csrf.token }); + return fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': 'application/json', + 'X-Requested-With': 'fetch' + }, + body + }); +}; + +export const badgeHtml = (gridjs, value = '') => { + const safe = value ?? ''; + return gridjs.html(`${safe}`); +}; diff --git a/web/js/pages/app-users-list.js b/web/js/pages/app-users-list.js new file mode 100644 index 0000000..eaf6823 --- /dev/null +++ b/web/js/pages/app-users-list.js @@ -0,0 +1,127 @@ +export function initUsersListPage(options = {}) { + const { + gridConfig, + appBase, + csrf, + labels = {}, + selectors = {}, + exportPath = 'admin/users/export', + listPath = 'admin/users', + buildBulkUrl, + showFlash, + withLoading + } = options; + + if (!gridConfig) return; + + const exportSelector = selectors.exportButton || '[data-users-export]'; + const resetSelector = selectors.resetButton || '[data-users-reset]'; + const bulkSelector = selectors.bulkButtons || '[data-users-bulk]'; + + const resolveBulkUrl = buildBulkUrl + ? buildBulkUrl + : (action) => new URL(`admin/users/bulk/${action}`, appBase).toString(); + + const postAction = async (url, data = {}) => { + const body = new URLSearchParams({ ...data, [csrf.key]: csrf.token }); + return fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Accept': 'application/json', + 'X-Requested-With': 'fetch' + }, + body + }); + }; + + const exportButton = document.querySelector(exportSelector); + if (exportButton) { + exportButton.addEventListener('click', () => { + const exportUrl = new URL(exportPath, appBase); + const dataUrl = new URL(gridConfig.baseUrl()); + dataUrl.searchParams.forEach((value, key) => exportUrl.searchParams.set(key, value)); + const sortParams = gridConfig.getSortParams ? gridConfig.getSortParams() : null; + if (sortParams && sortParams.order) { + exportUrl.searchParams.set('order', sortParams.order); + exportUrl.searchParams.set('dir', sortParams.dir || 'asc'); + } + window.location.href = exportUrl.toString(); + }); + } + + const resetButton = document.querySelector(resetSelector); + if (resetButton) { + resetButton.addEventListener('click', () => { + if (typeof gridConfig.resetFilters === 'function') { + gridConfig.resetFilters(); + } else { + gridConfig.updateGrid(); + } + }); + } + + const bulkButtons = Array.from(document.querySelectorAll(bulkSelector)); + if (bulkButtons.length) { + bulkButtons.forEach((button) => { + button.addEventListener('click', async () => { + const action = button.getAttribute('data-users-bulk') || ''; + const ids = gridConfig.selection?.getSelectedIds?.() || []; + const validActions = ['activate', 'deactivate', 'delete', 'send-access']; + if (!ids.length || !validActions.includes(action)) { + return; + } + const confirmTexts = { + 'activate': labels.bulkActivateConfirm, + 'deactivate': labels.bulkDeactivateConfirm, + 'delete': labels.bulkDeleteConfirm, + 'send-access': labels.bulkSendAccessConfirm + }; + const confirmText = confirmTexts[action]; + if (confirmText && !window.confirm(confirmText)) { + return; + } + + const executeBulk = async () => { + const url = resolveBulkUrl(action); + const response = await postAction(url, { uuids: ids.join(',') }); + const data = await response.json().catch(() => null); + if (response.ok && data && data.ok) { + gridConfig.selection?.clear?.(); + gridConfig.grid?.forceRender(); + + if (showFlash && labels.bulkMessages) { + const msg = labels.bulkMessages[action]; + if (msg) { + const count = data.count ?? 0; + const failed = data.failed ?? 0; + let text = msg.success.replace('%d', count); + if (failed > 0 && msg.partial) { + text = msg.partial.replace('%d', count).replace('%f', failed); + } + showFlash('success', text); + } + } + } else { + if (showFlash && labels.bulkMessages) { + const msg = labels.bulkMessages[action]; + if (msg?.error) { + showFlash('error', msg.error); + } else { + window.location.href = new URL(listPath, appBase).toString(); + } + } else { + window.location.href = new URL(listPath, appBase).toString(); + } + } + }; + + if (withLoading) { + await withLoading(executeBulk); + } else { + await executeBulk(); + } + }); + }); + } +} diff --git a/web/vendor/bootstrap-icons/0-circle-fill.svg b/web/vendor/bootstrap-icons/0-circle-fill.svg new file mode 100644 index 0000000..2f5f026 --- /dev/null +++ b/web/vendor/bootstrap-icons/0-circle-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/0-circle.svg b/web/vendor/bootstrap-icons/0-circle.svg new file mode 100644 index 0000000..5e84c8c --- /dev/null +++ b/web/vendor/bootstrap-icons/0-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/0-square-fill.svg b/web/vendor/bootstrap-icons/0-square-fill.svg new file mode 100644 index 0000000..cca049b --- /dev/null +++ b/web/vendor/bootstrap-icons/0-square-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/0-square.svg b/web/vendor/bootstrap-icons/0-square.svg new file mode 100644 index 0000000..73b7bc1 --- /dev/null +++ b/web/vendor/bootstrap-icons/0-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/1-circle-fill.svg b/web/vendor/bootstrap-icons/1-circle-fill.svg new file mode 100644 index 0000000..b10d0f3 --- /dev/null +++ b/web/vendor/bootstrap-icons/1-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/1-circle.svg b/web/vendor/bootstrap-icons/1-circle.svg new file mode 100644 index 0000000..2aa21f9 --- /dev/null +++ b/web/vendor/bootstrap-icons/1-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/1-square-fill.svg b/web/vendor/bootstrap-icons/1-square-fill.svg new file mode 100644 index 0000000..2ce792f --- /dev/null +++ b/web/vendor/bootstrap-icons/1-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/1-square.svg b/web/vendor/bootstrap-icons/1-square.svg new file mode 100644 index 0000000..773534a --- /dev/null +++ b/web/vendor/bootstrap-icons/1-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/123.svg b/web/vendor/bootstrap-icons/123.svg new file mode 100644 index 0000000..277d405 --- /dev/null +++ b/web/vendor/bootstrap-icons/123.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/2-circle-fill.svg b/web/vendor/bootstrap-icons/2-circle-fill.svg new file mode 100644 index 0000000..169df3a --- /dev/null +++ b/web/vendor/bootstrap-icons/2-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/2-circle.svg b/web/vendor/bootstrap-icons/2-circle.svg new file mode 100644 index 0000000..00260b6 --- /dev/null +++ b/web/vendor/bootstrap-icons/2-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/2-square-fill.svg b/web/vendor/bootstrap-icons/2-square-fill.svg new file mode 100644 index 0000000..2760ca7 --- /dev/null +++ b/web/vendor/bootstrap-icons/2-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/2-square.svg b/web/vendor/bootstrap-icons/2-square.svg new file mode 100644 index 0000000..4a79ed6 --- /dev/null +++ b/web/vendor/bootstrap-icons/2-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/3-circle-fill.svg b/web/vendor/bootstrap-icons/3-circle-fill.svg new file mode 100644 index 0000000..9aedc47 --- /dev/null +++ b/web/vendor/bootstrap-icons/3-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/3-circle.svg b/web/vendor/bootstrap-icons/3-circle.svg new file mode 100644 index 0000000..c2fc517 --- /dev/null +++ b/web/vendor/bootstrap-icons/3-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/3-square-fill.svg b/web/vendor/bootstrap-icons/3-square-fill.svg new file mode 100644 index 0000000..20c71a7 --- /dev/null +++ b/web/vendor/bootstrap-icons/3-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/3-square.svg b/web/vendor/bootstrap-icons/3-square.svg new file mode 100644 index 0000000..f0907cc --- /dev/null +++ b/web/vendor/bootstrap-icons/3-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/4-circle-fill.svg b/web/vendor/bootstrap-icons/4-circle-fill.svg new file mode 100644 index 0000000..51dc8a5 --- /dev/null +++ b/web/vendor/bootstrap-icons/4-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/4-circle.svg b/web/vendor/bootstrap-icons/4-circle.svg new file mode 100644 index 0000000..e25df51 --- /dev/null +++ b/web/vendor/bootstrap-icons/4-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/4-square-fill.svg b/web/vendor/bootstrap-icons/4-square-fill.svg new file mode 100644 index 0000000..ce3aa94 --- /dev/null +++ b/web/vendor/bootstrap-icons/4-square-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/4-square.svg b/web/vendor/bootstrap-icons/4-square.svg new file mode 100644 index 0000000..769102d --- /dev/null +++ b/web/vendor/bootstrap-icons/4-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/5-circle-fill.svg b/web/vendor/bootstrap-icons/5-circle-fill.svg new file mode 100644 index 0000000..915462d --- /dev/null +++ b/web/vendor/bootstrap-icons/5-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/5-circle.svg b/web/vendor/bootstrap-icons/5-circle.svg new file mode 100644 index 0000000..5ef620d --- /dev/null +++ b/web/vendor/bootstrap-icons/5-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/5-square-fill.svg b/web/vendor/bootstrap-icons/5-square-fill.svg new file mode 100644 index 0000000..2b066bb --- /dev/null +++ b/web/vendor/bootstrap-icons/5-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/5-square.svg b/web/vendor/bootstrap-icons/5-square.svg new file mode 100644 index 0000000..ad3e281 --- /dev/null +++ b/web/vendor/bootstrap-icons/5-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/6-circle-fill.svg b/web/vendor/bootstrap-icons/6-circle-fill.svg new file mode 100644 index 0000000..21b601a --- /dev/null +++ b/web/vendor/bootstrap-icons/6-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/6-circle.svg b/web/vendor/bootstrap-icons/6-circle.svg new file mode 100644 index 0000000..fc036b0 --- /dev/null +++ b/web/vendor/bootstrap-icons/6-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/6-square-fill.svg b/web/vendor/bootstrap-icons/6-square-fill.svg new file mode 100644 index 0000000..908706d --- /dev/null +++ b/web/vendor/bootstrap-icons/6-square-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/6-square.svg b/web/vendor/bootstrap-icons/6-square.svg new file mode 100644 index 0000000..ce28209 --- /dev/null +++ b/web/vendor/bootstrap-icons/6-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/7-circle-fill.svg b/web/vendor/bootstrap-icons/7-circle-fill.svg new file mode 100644 index 0000000..0f4f6d9 --- /dev/null +++ b/web/vendor/bootstrap-icons/7-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/7-circle.svg b/web/vendor/bootstrap-icons/7-circle.svg new file mode 100644 index 0000000..796f45c --- /dev/null +++ b/web/vendor/bootstrap-icons/7-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/7-square-fill.svg b/web/vendor/bootstrap-icons/7-square-fill.svg new file mode 100644 index 0000000..604186d --- /dev/null +++ b/web/vendor/bootstrap-icons/7-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/7-square.svg b/web/vendor/bootstrap-icons/7-square.svg new file mode 100644 index 0000000..f269032 --- /dev/null +++ b/web/vendor/bootstrap-icons/7-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/8-circle-fill.svg b/web/vendor/bootstrap-icons/8-circle-fill.svg new file mode 100644 index 0000000..579846b --- /dev/null +++ b/web/vendor/bootstrap-icons/8-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/8-circle.svg b/web/vendor/bootstrap-icons/8-circle.svg new file mode 100644 index 0000000..2dbb93e --- /dev/null +++ b/web/vendor/bootstrap-icons/8-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/8-square-fill.svg b/web/vendor/bootstrap-icons/8-square-fill.svg new file mode 100644 index 0000000..f8efe93 --- /dev/null +++ b/web/vendor/bootstrap-icons/8-square-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/8-square.svg b/web/vendor/bootstrap-icons/8-square.svg new file mode 100644 index 0000000..f29d225 --- /dev/null +++ b/web/vendor/bootstrap-icons/8-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/9-circle-fill.svg b/web/vendor/bootstrap-icons/9-circle-fill.svg new file mode 100644 index 0000000..b19b3f5 --- /dev/null +++ b/web/vendor/bootstrap-icons/9-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/9-circle.svg b/web/vendor/bootstrap-icons/9-circle.svg new file mode 100644 index 0000000..ff91949 --- /dev/null +++ b/web/vendor/bootstrap-icons/9-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/9-square-fill.svg b/web/vendor/bootstrap-icons/9-square-fill.svg new file mode 100644 index 0000000..e2ca2c3 --- /dev/null +++ b/web/vendor/bootstrap-icons/9-square-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/9-square.svg b/web/vendor/bootstrap-icons/9-square.svg new file mode 100644 index 0000000..3410f7b --- /dev/null +++ b/web/vendor/bootstrap-icons/9-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/activity.svg b/web/vendor/bootstrap-icons/activity.svg new file mode 100644 index 0000000..1ca946e --- /dev/null +++ b/web/vendor/bootstrap-icons/activity.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/airplane-engines-fill.svg b/web/vendor/bootstrap-icons/airplane-engines-fill.svg new file mode 100644 index 0000000..3d8f185 --- /dev/null +++ b/web/vendor/bootstrap-icons/airplane-engines-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/airplane-engines.svg b/web/vendor/bootstrap-icons/airplane-engines.svg new file mode 100644 index 0000000..2efc31e --- /dev/null +++ b/web/vendor/bootstrap-icons/airplane-engines.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/airplane-fill.svg b/web/vendor/bootstrap-icons/airplane-fill.svg new file mode 100644 index 0000000..b1e4fa3 --- /dev/null +++ b/web/vendor/bootstrap-icons/airplane-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/airplane.svg b/web/vendor/bootstrap-icons/airplane.svg new file mode 100644 index 0000000..5f937e1 --- /dev/null +++ b/web/vendor/bootstrap-icons/airplane.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/alarm-fill.svg b/web/vendor/bootstrap-icons/alarm-fill.svg new file mode 100644 index 0000000..a53c88f --- /dev/null +++ b/web/vendor/bootstrap-icons/alarm-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/alarm.svg b/web/vendor/bootstrap-icons/alarm.svg new file mode 100644 index 0000000..27160b3 --- /dev/null +++ b/web/vendor/bootstrap-icons/alarm.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/alexa.svg b/web/vendor/bootstrap-icons/alexa.svg new file mode 100644 index 0000000..0827c41 --- /dev/null +++ b/web/vendor/bootstrap-icons/alexa.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/align-bottom.svg b/web/vendor/bootstrap-icons/align-bottom.svg new file mode 100644 index 0000000..5c2569f --- /dev/null +++ b/web/vendor/bootstrap-icons/align-bottom.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/align-center.svg b/web/vendor/bootstrap-icons/align-center.svg new file mode 100644 index 0000000..ea4290b --- /dev/null +++ b/web/vendor/bootstrap-icons/align-center.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/align-end.svg b/web/vendor/bootstrap-icons/align-end.svg new file mode 100644 index 0000000..15429bb --- /dev/null +++ b/web/vendor/bootstrap-icons/align-end.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/align-middle.svg b/web/vendor/bootstrap-icons/align-middle.svg new file mode 100644 index 0000000..82f6801 --- /dev/null +++ b/web/vendor/bootstrap-icons/align-middle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/align-start.svg b/web/vendor/bootstrap-icons/align-start.svg new file mode 100644 index 0000000..75dca50 --- /dev/null +++ b/web/vendor/bootstrap-icons/align-start.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/align-top.svg b/web/vendor/bootstrap-icons/align-top.svg new file mode 100644 index 0000000..f354fc5 --- /dev/null +++ b/web/vendor/bootstrap-icons/align-top.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/alipay.svg b/web/vendor/bootstrap-icons/alipay.svg new file mode 100644 index 0000000..30b6fe7 --- /dev/null +++ b/web/vendor/bootstrap-icons/alipay.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/alphabet-uppercase.svg b/web/vendor/bootstrap-icons/alphabet-uppercase.svg new file mode 100644 index 0000000..d0887b5 --- /dev/null +++ b/web/vendor/bootstrap-icons/alphabet-uppercase.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/alphabet.svg b/web/vendor/bootstrap-icons/alphabet.svg new file mode 100644 index 0000000..5d097d7 --- /dev/null +++ b/web/vendor/bootstrap-icons/alphabet.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/alt.svg b/web/vendor/bootstrap-icons/alt.svg new file mode 100644 index 0000000..2141bcb --- /dev/null +++ b/web/vendor/bootstrap-icons/alt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/amazon.svg b/web/vendor/bootstrap-icons/amazon.svg new file mode 100644 index 0000000..0752545 --- /dev/null +++ b/web/vendor/bootstrap-icons/amazon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/amd.svg b/web/vendor/bootstrap-icons/amd.svg new file mode 100644 index 0000000..ef0757c --- /dev/null +++ b/web/vendor/bootstrap-icons/amd.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/android.svg b/web/vendor/bootstrap-icons/android.svg new file mode 100644 index 0000000..4c1f097 --- /dev/null +++ b/web/vendor/bootstrap-icons/android.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/android2.svg b/web/vendor/bootstrap-icons/android2.svg new file mode 100644 index 0000000..f49c14e --- /dev/null +++ b/web/vendor/bootstrap-icons/android2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/anthropic.svg b/web/vendor/bootstrap-icons/anthropic.svg new file mode 100644 index 0000000..eed7edf --- /dev/null +++ b/web/vendor/bootstrap-icons/anthropic.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/app-indicator.svg b/web/vendor/bootstrap-icons/app-indicator.svg new file mode 100644 index 0000000..b28e219 --- /dev/null +++ b/web/vendor/bootstrap-icons/app-indicator.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/app.svg b/web/vendor/bootstrap-icons/app.svg new file mode 100644 index 0000000..b361308 --- /dev/null +++ b/web/vendor/bootstrap-icons/app.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/apple-music.svg b/web/vendor/bootstrap-icons/apple-music.svg new file mode 100644 index 0000000..325e3a7 --- /dev/null +++ b/web/vendor/bootstrap-icons/apple-music.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/apple.svg b/web/vendor/bootstrap-icons/apple.svg new file mode 100644 index 0000000..58235c3 --- /dev/null +++ b/web/vendor/bootstrap-icons/apple.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/archive-fill.svg b/web/vendor/bootstrap-icons/archive-fill.svg new file mode 100644 index 0000000..e5ea32b --- /dev/null +++ b/web/vendor/bootstrap-icons/archive-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/archive.svg b/web/vendor/bootstrap-icons/archive.svg new file mode 100644 index 0000000..7bc5eb2 --- /dev/null +++ b/web/vendor/bootstrap-icons/archive.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-90deg-down.svg b/web/vendor/bootstrap-icons/arrow-90deg-down.svg new file mode 100644 index 0000000..7459597 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-90deg-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-90deg-left.svg b/web/vendor/bootstrap-icons/arrow-90deg-left.svg new file mode 100644 index 0000000..4e17ab4 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-90deg-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-90deg-right.svg b/web/vendor/bootstrap-icons/arrow-90deg-right.svg new file mode 100644 index 0000000..9fb6363 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-90deg-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-90deg-up.svg b/web/vendor/bootstrap-icons/arrow-90deg-up.svg new file mode 100644 index 0000000..11be0de --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-90deg-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-bar-down.svg b/web/vendor/bootstrap-icons/arrow-bar-down.svg new file mode 100644 index 0000000..1b212d5 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-bar-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-bar-left.svg b/web/vendor/bootstrap-icons/arrow-bar-left.svg new file mode 100644 index 0000000..621bf2a --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-bar-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-bar-right.svg b/web/vendor/bootstrap-icons/arrow-bar-right.svg new file mode 100644 index 0000000..0210410 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-bar-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-bar-up.svg b/web/vendor/bootstrap-icons/arrow-bar-up.svg new file mode 100644 index 0000000..d5510da --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-bar-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-clockwise.svg b/web/vendor/bootstrap-icons/arrow-clockwise.svg new file mode 100644 index 0000000..324d5af --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-clockwise.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-counterclockwise.svg b/web/vendor/bootstrap-icons/arrow-counterclockwise.svg new file mode 100644 index 0000000..3d9ff62 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-counterclockwise.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-down-circle-fill.svg b/web/vendor/bootstrap-icons/arrow-down-circle-fill.svg new file mode 100644 index 0000000..242eb58 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-down-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-down-circle.svg b/web/vendor/bootstrap-icons/arrow-down-circle.svg new file mode 100644 index 0000000..42e96b5 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-down-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-down-left-circle-fill.svg b/web/vendor/bootstrap-icons/arrow-down-left-circle-fill.svg new file mode 100644 index 0000000..e7f4735 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-down-left-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-down-left-circle.svg b/web/vendor/bootstrap-icons/arrow-down-left-circle.svg new file mode 100644 index 0000000..f67491f --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-down-left-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-down-left-square-fill.svg b/web/vendor/bootstrap-icons/arrow-down-left-square-fill.svg new file mode 100644 index 0000000..6e03bf2 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-down-left-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-down-left-square.svg b/web/vendor/bootstrap-icons/arrow-down-left-square.svg new file mode 100644 index 0000000..1278d39 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-down-left-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-down-left.svg b/web/vendor/bootstrap-icons/arrow-down-left.svg new file mode 100644 index 0000000..4011c77 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-down-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-down-right-circle-fill.svg b/web/vendor/bootstrap-icons/arrow-down-right-circle-fill.svg new file mode 100644 index 0000000..4ff73b6 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-down-right-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-down-right-circle.svg b/web/vendor/bootstrap-icons/arrow-down-right-circle.svg new file mode 100644 index 0000000..054e83f --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-down-right-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-down-right-square-fill.svg b/web/vendor/bootstrap-icons/arrow-down-right-square-fill.svg new file mode 100644 index 0000000..a556e06 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-down-right-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-down-right-square.svg b/web/vendor/bootstrap-icons/arrow-down-right-square.svg new file mode 100644 index 0000000..4bfb679 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-down-right-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-down-right.svg b/web/vendor/bootstrap-icons/arrow-down-right.svg new file mode 100644 index 0000000..08aef16 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-down-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-down-short.svg b/web/vendor/bootstrap-icons/arrow-down-short.svg new file mode 100644 index 0000000..66b7fa1 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-down-short.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-down-square-fill.svg b/web/vendor/bootstrap-icons/arrow-down-square-fill.svg new file mode 100644 index 0000000..c9020dc --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-down-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-down-square.svg b/web/vendor/bootstrap-icons/arrow-down-square.svg new file mode 100644 index 0000000..c492b71 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-down-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-down-up.svg b/web/vendor/bootstrap-icons/arrow-down-up.svg new file mode 100644 index 0000000..04cb3a5 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-down-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-down.svg b/web/vendor/bootstrap-icons/arrow-down.svg new file mode 100644 index 0000000..f66f74b --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-left-circle-fill.svg b/web/vendor/bootstrap-icons/arrow-left-circle-fill.svg new file mode 100644 index 0000000..ae19d97 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-left-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-left-circle.svg b/web/vendor/bootstrap-icons/arrow-left-circle.svg new file mode 100644 index 0000000..f3246ea --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-left-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-left-right.svg b/web/vendor/bootstrap-icons/arrow-left-right.svg new file mode 100644 index 0000000..89c4003 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-left-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-left-short.svg b/web/vendor/bootstrap-icons/arrow-left-short.svg new file mode 100644 index 0000000..abb15dd --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-left-short.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-left-square-fill.svg b/web/vendor/bootstrap-icons/arrow-left-square-fill.svg new file mode 100644 index 0000000..3ee717e --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-left-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-left-square.svg b/web/vendor/bootstrap-icons/arrow-left-square.svg new file mode 100644 index 0000000..8f09a48 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-left-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-left.svg b/web/vendor/bootstrap-icons/arrow-left.svg new file mode 100644 index 0000000..587d4fe --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-repeat.svg b/web/vendor/bootstrap-icons/arrow-repeat.svg new file mode 100644 index 0000000..b17dba4 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-repeat.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-return-left.svg b/web/vendor/bootstrap-icons/arrow-return-left.svg new file mode 100644 index 0000000..3c13fc4 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-return-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-return-right.svg b/web/vendor/bootstrap-icons/arrow-return-right.svg new file mode 100644 index 0000000..60d282c --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-return-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-right-circle-fill.svg b/web/vendor/bootstrap-icons/arrow-right-circle-fill.svg new file mode 100644 index 0000000..32c21ea --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-right-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-right-circle.svg b/web/vendor/bootstrap-icons/arrow-right-circle.svg new file mode 100644 index 0000000..ad7293e --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-right-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-right-short.svg b/web/vendor/bootstrap-icons/arrow-right-short.svg new file mode 100644 index 0000000..fa238ff --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-right-short.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-right-square-fill.svg b/web/vendor/bootstrap-icons/arrow-right-square-fill.svg new file mode 100644 index 0000000..c7c8eec --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-right-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-right-square.svg b/web/vendor/bootstrap-icons/arrow-right-square.svg new file mode 100644 index 0000000..7a4b78b --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-right-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-right.svg b/web/vendor/bootstrap-icons/arrow-right.svg new file mode 100644 index 0000000..2362904 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-through-heart-fill.svg b/web/vendor/bootstrap-icons/arrow-through-heart-fill.svg new file mode 100644 index 0000000..e98bce1 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-through-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-through-heart.svg b/web/vendor/bootstrap-icons/arrow-through-heart.svg new file mode 100644 index 0000000..daf397b --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-through-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-up-circle-fill.svg b/web/vendor/bootstrap-icons/arrow-up-circle-fill.svg new file mode 100644 index 0000000..9e7ef36 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-up-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-up-circle.svg b/web/vendor/bootstrap-icons/arrow-up-circle.svg new file mode 100644 index 0000000..e18a689 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-up-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-up-left-circle-fill.svg b/web/vendor/bootstrap-icons/arrow-up-left-circle-fill.svg new file mode 100644 index 0000000..e1e2e97 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-up-left-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-up-left-circle.svg b/web/vendor/bootstrap-icons/arrow-up-left-circle.svg new file mode 100644 index 0000000..3101b65 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-up-left-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-up-left-square-fill.svg b/web/vendor/bootstrap-icons/arrow-up-left-square-fill.svg new file mode 100644 index 0000000..e699865 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-up-left-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-up-left-square.svg b/web/vendor/bootstrap-icons/arrow-up-left-square.svg new file mode 100644 index 0000000..4f31190 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-up-left-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-up-left.svg b/web/vendor/bootstrap-icons/arrow-up-left.svg new file mode 100644 index 0000000..938d0d0 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-up-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-up-right-circle-fill.svg b/web/vendor/bootstrap-icons/arrow-up-right-circle-fill.svg new file mode 100644 index 0000000..0eb9b54 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-up-right-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-up-right-circle.svg b/web/vendor/bootstrap-icons/arrow-up-right-circle.svg new file mode 100644 index 0000000..ed6ae41 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-up-right-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-up-right-square-fill.svg b/web/vendor/bootstrap-icons/arrow-up-right-square-fill.svg new file mode 100644 index 0000000..c2246ec --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-up-right-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-up-right-square.svg b/web/vendor/bootstrap-icons/arrow-up-right-square.svg new file mode 100644 index 0000000..b14940f --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-up-right-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-up-right.svg b/web/vendor/bootstrap-icons/arrow-up-right.svg new file mode 100644 index 0000000..7b3794b --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-up-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-up-short.svg b/web/vendor/bootstrap-icons/arrow-up-short.svg new file mode 100644 index 0000000..543089a --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-up-short.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-up-square-fill.svg b/web/vendor/bootstrap-icons/arrow-up-square-fill.svg new file mode 100644 index 0000000..9d7f65f --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-up-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-up-square.svg b/web/vendor/bootstrap-icons/arrow-up-square.svg new file mode 100644 index 0000000..bec15c4 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-up-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrow-up.svg b/web/vendor/bootstrap-icons/arrow-up.svg new file mode 100644 index 0000000..951521a --- /dev/null +++ b/web/vendor/bootstrap-icons/arrow-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrows-angle-contract.svg b/web/vendor/bootstrap-icons/arrows-angle-contract.svg new file mode 100644 index 0000000..1aa7875 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrows-angle-contract.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrows-angle-expand.svg b/web/vendor/bootstrap-icons/arrows-angle-expand.svg new file mode 100644 index 0000000..578d3b6 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrows-angle-expand.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrows-collapse-vertical.svg b/web/vendor/bootstrap-icons/arrows-collapse-vertical.svg new file mode 100644 index 0000000..0fc4477 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrows-collapse-vertical.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrows-collapse.svg b/web/vendor/bootstrap-icons/arrows-collapse.svg new file mode 100644 index 0000000..ca055c3 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrows-collapse.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrows-expand-vertical.svg b/web/vendor/bootstrap-icons/arrows-expand-vertical.svg new file mode 100644 index 0000000..9dbfac4 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrows-expand-vertical.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrows-expand.svg b/web/vendor/bootstrap-icons/arrows-expand.svg new file mode 100644 index 0000000..99eb276 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrows-expand.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrows-fullscreen.svg b/web/vendor/bootstrap-icons/arrows-fullscreen.svg new file mode 100644 index 0000000..7633e3f --- /dev/null +++ b/web/vendor/bootstrap-icons/arrows-fullscreen.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrows-move.svg b/web/vendor/bootstrap-icons/arrows-move.svg new file mode 100644 index 0000000..ef2b885 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrows-move.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrows-vertical.svg b/web/vendor/bootstrap-icons/arrows-vertical.svg new file mode 100644 index 0000000..22f60fd --- /dev/null +++ b/web/vendor/bootstrap-icons/arrows-vertical.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/arrows.svg b/web/vendor/bootstrap-icons/arrows.svg new file mode 100644 index 0000000..a6bd3d7 --- /dev/null +++ b/web/vendor/bootstrap-icons/arrows.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/aspect-ratio-fill.svg b/web/vendor/bootstrap-icons/aspect-ratio-fill.svg new file mode 100644 index 0000000..6d6cb8d --- /dev/null +++ b/web/vendor/bootstrap-icons/aspect-ratio-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/aspect-ratio.svg b/web/vendor/bootstrap-icons/aspect-ratio.svg new file mode 100644 index 0000000..ee634b0 --- /dev/null +++ b/web/vendor/bootstrap-icons/aspect-ratio.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/asterisk.svg b/web/vendor/bootstrap-icons/asterisk.svg new file mode 100644 index 0000000..fbc13b7 --- /dev/null +++ b/web/vendor/bootstrap-icons/asterisk.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/at.svg b/web/vendor/bootstrap-icons/at.svg new file mode 100644 index 0000000..3cab29e --- /dev/null +++ b/web/vendor/bootstrap-icons/at.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/award-fill.svg b/web/vendor/bootstrap-icons/award-fill.svg new file mode 100644 index 0000000..f996790 --- /dev/null +++ b/web/vendor/bootstrap-icons/award-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/award.svg b/web/vendor/bootstrap-icons/award.svg new file mode 100644 index 0000000..67c760b --- /dev/null +++ b/web/vendor/bootstrap-icons/award.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/back.svg b/web/vendor/bootstrap-icons/back.svg new file mode 100644 index 0000000..9f55340 --- /dev/null +++ b/web/vendor/bootstrap-icons/back.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/backpack-fill.svg b/web/vendor/bootstrap-icons/backpack-fill.svg new file mode 100644 index 0000000..ec737a9 --- /dev/null +++ b/web/vendor/bootstrap-icons/backpack-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/backpack.svg b/web/vendor/bootstrap-icons/backpack.svg new file mode 100644 index 0000000..819aa29 --- /dev/null +++ b/web/vendor/bootstrap-icons/backpack.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/backpack2-fill.svg b/web/vendor/bootstrap-icons/backpack2-fill.svg new file mode 100644 index 0000000..3c9b4da --- /dev/null +++ b/web/vendor/bootstrap-icons/backpack2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/backpack2.svg b/web/vendor/bootstrap-icons/backpack2.svg new file mode 100644 index 0000000..e0e4fe5 --- /dev/null +++ b/web/vendor/bootstrap-icons/backpack2.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/backpack3-fill.svg b/web/vendor/bootstrap-icons/backpack3-fill.svg new file mode 100644 index 0000000..4583c4f --- /dev/null +++ b/web/vendor/bootstrap-icons/backpack3-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/backpack3.svg b/web/vendor/bootstrap-icons/backpack3.svg new file mode 100644 index 0000000..819f8df --- /dev/null +++ b/web/vendor/bootstrap-icons/backpack3.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/backpack4-fill.svg b/web/vendor/bootstrap-icons/backpack4-fill.svg new file mode 100644 index 0000000..a3bba3a --- /dev/null +++ b/web/vendor/bootstrap-icons/backpack4-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/backpack4.svg b/web/vendor/bootstrap-icons/backpack4.svg new file mode 100644 index 0000000..140a12d --- /dev/null +++ b/web/vendor/bootstrap-icons/backpack4.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/backspace-fill.svg b/web/vendor/bootstrap-icons/backspace-fill.svg new file mode 100644 index 0000000..0787578 --- /dev/null +++ b/web/vendor/bootstrap-icons/backspace-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/backspace-reverse-fill.svg b/web/vendor/bootstrap-icons/backspace-reverse-fill.svg new file mode 100644 index 0000000..41c8dbb --- /dev/null +++ b/web/vendor/bootstrap-icons/backspace-reverse-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/backspace-reverse.svg b/web/vendor/bootstrap-icons/backspace-reverse.svg new file mode 100644 index 0000000..7b3fafd --- /dev/null +++ b/web/vendor/bootstrap-icons/backspace-reverse.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/backspace.svg b/web/vendor/bootstrap-icons/backspace.svg new file mode 100644 index 0000000..39b688f --- /dev/null +++ b/web/vendor/bootstrap-icons/backspace.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-3d-fill.svg b/web/vendor/bootstrap-icons/badge-3d-fill.svg new file mode 100644 index 0000000..750598c --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-3d-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-3d.svg b/web/vendor/bootstrap-icons/badge-3d.svg new file mode 100644 index 0000000..b3153f2 --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-3d.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-4k-fill.svg b/web/vendor/bootstrap-icons/badge-4k-fill.svg new file mode 100644 index 0000000..72f34b9 --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-4k-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-4k.svg b/web/vendor/bootstrap-icons/badge-4k.svg new file mode 100644 index 0000000..3dfc9b1 --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-4k.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-8k-fill.svg b/web/vendor/bootstrap-icons/badge-8k-fill.svg new file mode 100644 index 0000000..4bd9b80 --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-8k-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-8k.svg b/web/vendor/bootstrap-icons/badge-8k.svg new file mode 100644 index 0000000..d11f82d --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-8k.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-ad-fill.svg b/web/vendor/bootstrap-icons/badge-ad-fill.svg new file mode 100644 index 0000000..023f210 --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-ad-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-ad.svg b/web/vendor/bootstrap-icons/badge-ad.svg new file mode 100644 index 0000000..616ad74 --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-ad.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-ar-fill.svg b/web/vendor/bootstrap-icons/badge-ar-fill.svg new file mode 100644 index 0000000..48aee0f --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-ar-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-ar.svg b/web/vendor/bootstrap-icons/badge-ar.svg new file mode 100644 index 0000000..0fc1975 --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-ar.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-cc-fill.svg b/web/vendor/bootstrap-icons/badge-cc-fill.svg new file mode 100644 index 0000000..0f3d1f9 --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-cc-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-cc.svg b/web/vendor/bootstrap-icons/badge-cc.svg new file mode 100644 index 0000000..d5f42e1 --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-cc.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-hd-fill.svg b/web/vendor/bootstrap-icons/badge-hd-fill.svg new file mode 100644 index 0000000..96f0875 --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-hd-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-hd.svg b/web/vendor/bootstrap-icons/badge-hd.svg new file mode 100644 index 0000000..5689042 --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-hd.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-sd-fill.svg b/web/vendor/bootstrap-icons/badge-sd-fill.svg new file mode 100644 index 0000000..a37154a --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-sd-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-sd.svg b/web/vendor/bootstrap-icons/badge-sd.svg new file mode 100644 index 0000000..df8d029 --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-sd.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-tm-fill.svg b/web/vendor/bootstrap-icons/badge-tm-fill.svg new file mode 100644 index 0000000..632b569 --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-tm-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-tm.svg b/web/vendor/bootstrap-icons/badge-tm.svg new file mode 100644 index 0000000..33de5c2 --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-tm.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-vo-fill.svg b/web/vendor/bootstrap-icons/badge-vo-fill.svg new file mode 100644 index 0000000..1d27b07 --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-vo-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-vo.svg b/web/vendor/bootstrap-icons/badge-vo.svg new file mode 100644 index 0000000..f5e2ece --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-vo.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-vr-fill.svg b/web/vendor/bootstrap-icons/badge-vr-fill.svg new file mode 100644 index 0000000..e614af6 --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-vr-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-vr.svg b/web/vendor/bootstrap-icons/badge-vr.svg new file mode 100644 index 0000000..c1c73dc --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-vr.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-wc-fill.svg b/web/vendor/bootstrap-icons/badge-wc-fill.svg new file mode 100644 index 0000000..d16436a --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-wc-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/badge-wc.svg b/web/vendor/bootstrap-icons/badge-wc.svg new file mode 100644 index 0000000..ea459ba --- /dev/null +++ b/web/vendor/bootstrap-icons/badge-wc.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bag-check-fill.svg b/web/vendor/bootstrap-icons/bag-check-fill.svg new file mode 100644 index 0000000..9976d5c --- /dev/null +++ b/web/vendor/bootstrap-icons/bag-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bag-check.svg b/web/vendor/bootstrap-icons/bag-check.svg new file mode 100644 index 0000000..a4e3278 --- /dev/null +++ b/web/vendor/bootstrap-icons/bag-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bag-dash-fill.svg b/web/vendor/bootstrap-icons/bag-dash-fill.svg new file mode 100644 index 0000000..ccb5589 --- /dev/null +++ b/web/vendor/bootstrap-icons/bag-dash-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bag-dash.svg b/web/vendor/bootstrap-icons/bag-dash.svg new file mode 100644 index 0000000..0997f33 --- /dev/null +++ b/web/vendor/bootstrap-icons/bag-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bag-fill.svg b/web/vendor/bootstrap-icons/bag-fill.svg new file mode 100644 index 0000000..812fcfc --- /dev/null +++ b/web/vendor/bootstrap-icons/bag-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bag-heart-fill.svg b/web/vendor/bootstrap-icons/bag-heart-fill.svg new file mode 100644 index 0000000..4938b83 --- /dev/null +++ b/web/vendor/bootstrap-icons/bag-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bag-heart.svg b/web/vendor/bootstrap-icons/bag-heart.svg new file mode 100644 index 0000000..e7b906a --- /dev/null +++ b/web/vendor/bootstrap-icons/bag-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bag-plus-fill.svg b/web/vendor/bootstrap-icons/bag-plus-fill.svg new file mode 100644 index 0000000..b98f6b2 --- /dev/null +++ b/web/vendor/bootstrap-icons/bag-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bag-plus.svg b/web/vendor/bootstrap-icons/bag-plus.svg new file mode 100644 index 0000000..0d7ddc6 --- /dev/null +++ b/web/vendor/bootstrap-icons/bag-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bag-x-fill.svg b/web/vendor/bootstrap-icons/bag-x-fill.svg new file mode 100644 index 0000000..cbe77df --- /dev/null +++ b/web/vendor/bootstrap-icons/bag-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bag-x.svg b/web/vendor/bootstrap-icons/bag-x.svg new file mode 100644 index 0000000..4f38008 --- /dev/null +++ b/web/vendor/bootstrap-icons/bag-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bag.svg b/web/vendor/bootstrap-icons/bag.svg new file mode 100644 index 0000000..acd0287 --- /dev/null +++ b/web/vendor/bootstrap-icons/bag.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/balloon-fill.svg b/web/vendor/bootstrap-icons/balloon-fill.svg new file mode 100644 index 0000000..2d57e2d --- /dev/null +++ b/web/vendor/bootstrap-icons/balloon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/balloon-heart-fill.svg b/web/vendor/bootstrap-icons/balloon-heart-fill.svg new file mode 100644 index 0000000..ab17865 --- /dev/null +++ b/web/vendor/bootstrap-icons/balloon-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/balloon-heart.svg b/web/vendor/bootstrap-icons/balloon-heart.svg new file mode 100644 index 0000000..0e056cb --- /dev/null +++ b/web/vendor/bootstrap-icons/balloon-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/balloon.svg b/web/vendor/bootstrap-icons/balloon.svg new file mode 100644 index 0000000..6906cb3 --- /dev/null +++ b/web/vendor/bootstrap-icons/balloon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ban-fill.svg b/web/vendor/bootstrap-icons/ban-fill.svg new file mode 100644 index 0000000..0bb7df0 --- /dev/null +++ b/web/vendor/bootstrap-icons/ban-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ban.svg b/web/vendor/bootstrap-icons/ban.svg new file mode 100644 index 0000000..5acfd41 --- /dev/null +++ b/web/vendor/bootstrap-icons/ban.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bandaid-fill.svg b/web/vendor/bootstrap-icons/bandaid-fill.svg new file mode 100644 index 0000000..052ad73 --- /dev/null +++ b/web/vendor/bootstrap-icons/bandaid-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bandaid.svg b/web/vendor/bootstrap-icons/bandaid.svg new file mode 100644 index 0000000..e09850e --- /dev/null +++ b/web/vendor/bootstrap-icons/bandaid.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bank.svg b/web/vendor/bootstrap-icons/bank.svg new file mode 100644 index 0000000..2e7f4f0 --- /dev/null +++ b/web/vendor/bootstrap-icons/bank.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bank2.svg b/web/vendor/bootstrap-icons/bank2.svg new file mode 100644 index 0000000..acc8ef9 --- /dev/null +++ b/web/vendor/bootstrap-icons/bank2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bar-chart-fill.svg b/web/vendor/bootstrap-icons/bar-chart-fill.svg new file mode 100644 index 0000000..7e4ebee --- /dev/null +++ b/web/vendor/bootstrap-icons/bar-chart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bar-chart-line-fill.svg b/web/vendor/bootstrap-icons/bar-chart-line-fill.svg new file mode 100644 index 0000000..6808e6f --- /dev/null +++ b/web/vendor/bootstrap-icons/bar-chart-line-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bar-chart-line.svg b/web/vendor/bootstrap-icons/bar-chart-line.svg new file mode 100644 index 0000000..567a808 --- /dev/null +++ b/web/vendor/bootstrap-icons/bar-chart-line.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bar-chart-steps.svg b/web/vendor/bootstrap-icons/bar-chart-steps.svg new file mode 100644 index 0000000..346e97b --- /dev/null +++ b/web/vendor/bootstrap-icons/bar-chart-steps.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bar-chart.svg b/web/vendor/bootstrap-icons/bar-chart.svg new file mode 100644 index 0000000..8e57c80 --- /dev/null +++ b/web/vendor/bootstrap-icons/bar-chart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/basket-fill.svg b/web/vendor/bootstrap-icons/basket-fill.svg new file mode 100644 index 0000000..b2e01f5 --- /dev/null +++ b/web/vendor/bootstrap-icons/basket-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/basket.svg b/web/vendor/bootstrap-icons/basket.svg new file mode 100644 index 0000000..418a5f9 --- /dev/null +++ b/web/vendor/bootstrap-icons/basket.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/basket2-fill.svg b/web/vendor/bootstrap-icons/basket2-fill.svg new file mode 100644 index 0000000..03c7079 --- /dev/null +++ b/web/vendor/bootstrap-icons/basket2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/basket2.svg b/web/vendor/bootstrap-icons/basket2.svg new file mode 100644 index 0000000..9b78be2 --- /dev/null +++ b/web/vendor/bootstrap-icons/basket2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/basket3-fill.svg b/web/vendor/bootstrap-icons/basket3-fill.svg new file mode 100644 index 0000000..e26f0ee --- /dev/null +++ b/web/vendor/bootstrap-icons/basket3-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/basket3.svg b/web/vendor/bootstrap-icons/basket3.svg new file mode 100644 index 0000000..57fa6a0 --- /dev/null +++ b/web/vendor/bootstrap-icons/basket3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/battery-charging.svg b/web/vendor/bootstrap-icons/battery-charging.svg new file mode 100644 index 0000000..4ae74d2 --- /dev/null +++ b/web/vendor/bootstrap-icons/battery-charging.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/battery-full.svg b/web/vendor/bootstrap-icons/battery-full.svg new file mode 100644 index 0000000..bff6a3f --- /dev/null +++ b/web/vendor/bootstrap-icons/battery-full.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/battery-half.svg b/web/vendor/bootstrap-icons/battery-half.svg new file mode 100644 index 0000000..de57848 --- /dev/null +++ b/web/vendor/bootstrap-icons/battery-half.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/battery-low.svg b/web/vendor/bootstrap-icons/battery-low.svg new file mode 100644 index 0000000..b99e758 --- /dev/null +++ b/web/vendor/bootstrap-icons/battery-low.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/battery.svg b/web/vendor/bootstrap-icons/battery.svg new file mode 100644 index 0000000..2bacfa8 --- /dev/null +++ b/web/vendor/bootstrap-icons/battery.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/beaker-fill.svg b/web/vendor/bootstrap-icons/beaker-fill.svg new file mode 100644 index 0000000..3bf39d5 --- /dev/null +++ b/web/vendor/bootstrap-icons/beaker-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/beaker.svg b/web/vendor/bootstrap-icons/beaker.svg new file mode 100644 index 0000000..f1958c6 --- /dev/null +++ b/web/vendor/bootstrap-icons/beaker.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/behance.svg b/web/vendor/bootstrap-icons/behance.svg new file mode 100644 index 0000000..805f142 --- /dev/null +++ b/web/vendor/bootstrap-icons/behance.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bell-fill.svg b/web/vendor/bootstrap-icons/bell-fill.svg new file mode 100644 index 0000000..a537c3a --- /dev/null +++ b/web/vendor/bootstrap-icons/bell-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bell-slash-fill.svg b/web/vendor/bootstrap-icons/bell-slash-fill.svg new file mode 100644 index 0000000..534dd13 --- /dev/null +++ b/web/vendor/bootstrap-icons/bell-slash-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bell-slash.svg b/web/vendor/bootstrap-icons/bell-slash.svg new file mode 100644 index 0000000..7817e2b --- /dev/null +++ b/web/vendor/bootstrap-icons/bell-slash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bell.svg b/web/vendor/bootstrap-icons/bell.svg new file mode 100644 index 0000000..a71eba3 --- /dev/null +++ b/web/vendor/bootstrap-icons/bell.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bezier.svg b/web/vendor/bootstrap-icons/bezier.svg new file mode 100644 index 0000000..075b721 --- /dev/null +++ b/web/vendor/bootstrap-icons/bezier.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bezier2.svg b/web/vendor/bootstrap-icons/bezier2.svg new file mode 100644 index 0000000..8a59238 --- /dev/null +++ b/web/vendor/bootstrap-icons/bezier2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bicycle.svg b/web/vendor/bootstrap-icons/bicycle.svg new file mode 100644 index 0000000..3956545 --- /dev/null +++ b/web/vendor/bootstrap-icons/bicycle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bing.svg b/web/vendor/bootstrap-icons/bing.svg new file mode 100644 index 0000000..9368917 --- /dev/null +++ b/web/vendor/bootstrap-icons/bing.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/binoculars-fill.svg b/web/vendor/bootstrap-icons/binoculars-fill.svg new file mode 100644 index 0000000..d6d6dc0 --- /dev/null +++ b/web/vendor/bootstrap-icons/binoculars-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/binoculars.svg b/web/vendor/bootstrap-icons/binoculars.svg new file mode 100644 index 0000000..015d622 --- /dev/null +++ b/web/vendor/bootstrap-icons/binoculars.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/blockquote-left.svg b/web/vendor/bootstrap-icons/blockquote-left.svg new file mode 100644 index 0000000..f8b6b2d --- /dev/null +++ b/web/vendor/bootstrap-icons/blockquote-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/blockquote-right.svg b/web/vendor/bootstrap-icons/blockquote-right.svg new file mode 100644 index 0000000..afc81c9 --- /dev/null +++ b/web/vendor/bootstrap-icons/blockquote-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bluesky.svg b/web/vendor/bootstrap-icons/bluesky.svg new file mode 100644 index 0000000..a070aea --- /dev/null +++ b/web/vendor/bootstrap-icons/bluesky.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bluetooth.svg b/web/vendor/bootstrap-icons/bluetooth.svg new file mode 100644 index 0000000..8726e22 --- /dev/null +++ b/web/vendor/bootstrap-icons/bluetooth.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/body-text.svg b/web/vendor/bootstrap-icons/body-text.svg new file mode 100644 index 0000000..fd5e435 --- /dev/null +++ b/web/vendor/bootstrap-icons/body-text.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/book-fill.svg b/web/vendor/bootstrap-icons/book-fill.svg new file mode 100644 index 0000000..ddb0000 --- /dev/null +++ b/web/vendor/bootstrap-icons/book-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/book-half.svg b/web/vendor/bootstrap-icons/book-half.svg new file mode 100644 index 0000000..8eabe81 --- /dev/null +++ b/web/vendor/bootstrap-icons/book-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/book.svg b/web/vendor/bootstrap-icons/book.svg new file mode 100644 index 0000000..302acf0 --- /dev/null +++ b/web/vendor/bootstrap-icons/book.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bookmark-check-fill.svg b/web/vendor/bootstrap-icons/bookmark-check-fill.svg new file mode 100644 index 0000000..325fbde --- /dev/null +++ b/web/vendor/bootstrap-icons/bookmark-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bookmark-check.svg b/web/vendor/bootstrap-icons/bookmark-check.svg new file mode 100644 index 0000000..f4c9149 --- /dev/null +++ b/web/vendor/bootstrap-icons/bookmark-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bookmark-dash-fill.svg b/web/vendor/bootstrap-icons/bookmark-dash-fill.svg new file mode 100644 index 0000000..dbf9cc1 --- /dev/null +++ b/web/vendor/bootstrap-icons/bookmark-dash-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bookmark-dash.svg b/web/vendor/bootstrap-icons/bookmark-dash.svg new file mode 100644 index 0000000..115b448 --- /dev/null +++ b/web/vendor/bootstrap-icons/bookmark-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bookmark-fill.svg b/web/vendor/bootstrap-icons/bookmark-fill.svg new file mode 100644 index 0000000..3c237a9 --- /dev/null +++ b/web/vendor/bootstrap-icons/bookmark-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bookmark-heart-fill.svg b/web/vendor/bootstrap-icons/bookmark-heart-fill.svg new file mode 100644 index 0000000..6647b7c --- /dev/null +++ b/web/vendor/bootstrap-icons/bookmark-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bookmark-heart.svg b/web/vendor/bootstrap-icons/bookmark-heart.svg new file mode 100644 index 0000000..c368f5d --- /dev/null +++ b/web/vendor/bootstrap-icons/bookmark-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bookmark-plus-fill.svg b/web/vendor/bootstrap-icons/bookmark-plus-fill.svg new file mode 100644 index 0000000..41e0733 --- /dev/null +++ b/web/vendor/bootstrap-icons/bookmark-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bookmark-plus.svg b/web/vendor/bootstrap-icons/bookmark-plus.svg new file mode 100644 index 0000000..37b137c --- /dev/null +++ b/web/vendor/bootstrap-icons/bookmark-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bookmark-star-fill.svg b/web/vendor/bootstrap-icons/bookmark-star-fill.svg new file mode 100644 index 0000000..89fd335 --- /dev/null +++ b/web/vendor/bootstrap-icons/bookmark-star-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bookmark-star.svg b/web/vendor/bootstrap-icons/bookmark-star.svg new file mode 100644 index 0000000..2f792de --- /dev/null +++ b/web/vendor/bootstrap-icons/bookmark-star.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bookmark-x-fill.svg b/web/vendor/bootstrap-icons/bookmark-x-fill.svg new file mode 100644 index 0000000..acac0cf --- /dev/null +++ b/web/vendor/bootstrap-icons/bookmark-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bookmark-x.svg b/web/vendor/bootstrap-icons/bookmark-x.svg new file mode 100644 index 0000000..eb85c76 --- /dev/null +++ b/web/vendor/bootstrap-icons/bookmark-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bookmark.svg b/web/vendor/bootstrap-icons/bookmark.svg new file mode 100644 index 0000000..a21b14b --- /dev/null +++ b/web/vendor/bootstrap-icons/bookmark.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bookmarks-fill.svg b/web/vendor/bootstrap-icons/bookmarks-fill.svg new file mode 100644 index 0000000..abf5800 --- /dev/null +++ b/web/vendor/bootstrap-icons/bookmarks-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bookmarks.svg b/web/vendor/bootstrap-icons/bookmarks.svg new file mode 100644 index 0000000..ceb92bb --- /dev/null +++ b/web/vendor/bootstrap-icons/bookmarks.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bookshelf.svg b/web/vendor/bootstrap-icons/bookshelf.svg new file mode 100644 index 0000000..7f435d5 --- /dev/null +++ b/web/vendor/bootstrap-icons/bookshelf.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/boombox-fill.svg b/web/vendor/bootstrap-icons/boombox-fill.svg new file mode 100644 index 0000000..299e95e --- /dev/null +++ b/web/vendor/bootstrap-icons/boombox-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/boombox.svg b/web/vendor/bootstrap-icons/boombox.svg new file mode 100644 index 0000000..35af807 --- /dev/null +++ b/web/vendor/bootstrap-icons/boombox.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bootstrap-fill.svg b/web/vendor/bootstrap-icons/bootstrap-fill.svg new file mode 100644 index 0000000..21253b0 --- /dev/null +++ b/web/vendor/bootstrap-icons/bootstrap-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bootstrap-icons.css b/web/vendor/bootstrap-icons/bootstrap-icons.css new file mode 100644 index 0000000..5f7ae28 --- /dev/null +++ b/web/vendor/bootstrap-icons/bootstrap-icons.css @@ -0,0 +1,2106 @@ +/*! + * Bootstrap Icons v1.13.1 (https://icons.getbootstrap.com/) + * Copyright 2019-2024 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/icons/blob/main/LICENSE) + */ + +@font-face { + font-display: block; + font-family: "bootstrap-icons"; + src: url("./fonts/bootstrap-icons.woff2?e34853135f9e39acf64315236852cd5a") format("woff2"), +url("./fonts/bootstrap-icons.woff?e34853135f9e39acf64315236852cd5a") format("woff"); +} + +.bi::before, +[class^="bi-"]::before, +[class*=" bi-"]::before { + display: inline-block; + font-family: bootstrap-icons !important; + font-style: normal; + font-weight: normal !important; + font-variant: normal; + text-transform: none; + line-height: 1; + vertical-align: -.125em; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.bi-123::before { content: "\f67f"; } +.bi-alarm-fill::before { content: "\f101"; } +.bi-alarm::before { content: "\f102"; } +.bi-align-bottom::before { content: "\f103"; } +.bi-align-center::before { content: "\f104"; } +.bi-align-end::before { content: "\f105"; } +.bi-align-middle::before { content: "\f106"; } +.bi-align-start::before { content: "\f107"; } +.bi-align-top::before { content: "\f108"; } +.bi-alt::before { content: "\f109"; } +.bi-app-indicator::before { content: "\f10a"; } +.bi-app::before { content: "\f10b"; } +.bi-archive-fill::before { content: "\f10c"; } +.bi-archive::before { content: "\f10d"; } +.bi-arrow-90deg-down::before { content: "\f10e"; } +.bi-arrow-90deg-left::before { content: "\f10f"; } +.bi-arrow-90deg-right::before { content: "\f110"; } +.bi-arrow-90deg-up::before { content: "\f111"; } +.bi-arrow-bar-down::before { content: "\f112"; } +.bi-arrow-bar-left::before { content: "\f113"; } +.bi-arrow-bar-right::before { content: "\f114"; } +.bi-arrow-bar-up::before { content: "\f115"; } +.bi-arrow-clockwise::before { content: "\f116"; } +.bi-arrow-counterclockwise::before { content: "\f117"; } +.bi-arrow-down-circle-fill::before { content: "\f118"; } +.bi-arrow-down-circle::before { content: "\f119"; } +.bi-arrow-down-left-circle-fill::before { content: "\f11a"; } +.bi-arrow-down-left-circle::before { content: "\f11b"; } +.bi-arrow-down-left-square-fill::before { content: "\f11c"; } +.bi-arrow-down-left-square::before { content: "\f11d"; } +.bi-arrow-down-left::before { content: "\f11e"; } +.bi-arrow-down-right-circle-fill::before { content: "\f11f"; } +.bi-arrow-down-right-circle::before { content: "\f120"; } +.bi-arrow-down-right-square-fill::before { content: "\f121"; } +.bi-arrow-down-right-square::before { content: "\f122"; } +.bi-arrow-down-right::before { content: "\f123"; } +.bi-arrow-down-short::before { content: "\f124"; } +.bi-arrow-down-square-fill::before { content: "\f125"; } +.bi-arrow-down-square::before { content: "\f126"; } +.bi-arrow-down-up::before { content: "\f127"; } +.bi-arrow-down::before { content: "\f128"; } +.bi-arrow-left-circle-fill::before { content: "\f129"; } +.bi-arrow-left-circle::before { content: "\f12a"; } +.bi-arrow-left-right::before { content: "\f12b"; } +.bi-arrow-left-short::before { content: "\f12c"; } +.bi-arrow-left-square-fill::before { content: "\f12d"; } +.bi-arrow-left-square::before { content: "\f12e"; } +.bi-arrow-left::before { content: "\f12f"; } +.bi-arrow-repeat::before { content: "\f130"; } +.bi-arrow-return-left::before { content: "\f131"; } +.bi-arrow-return-right::before { content: "\f132"; } +.bi-arrow-right-circle-fill::before { content: "\f133"; } +.bi-arrow-right-circle::before { content: "\f134"; } +.bi-arrow-right-short::before { content: "\f135"; } +.bi-arrow-right-square-fill::before { content: "\f136"; } +.bi-arrow-right-square::before { content: "\f137"; } +.bi-arrow-right::before { content: "\f138"; } +.bi-arrow-up-circle-fill::before { content: "\f139"; } +.bi-arrow-up-circle::before { content: "\f13a"; } +.bi-arrow-up-left-circle-fill::before { content: "\f13b"; } +.bi-arrow-up-left-circle::before { content: "\f13c"; } +.bi-arrow-up-left-square-fill::before { content: "\f13d"; } +.bi-arrow-up-left-square::before { content: "\f13e"; } +.bi-arrow-up-left::before { content: "\f13f"; } +.bi-arrow-up-right-circle-fill::before { content: "\f140"; } +.bi-arrow-up-right-circle::before { content: "\f141"; } +.bi-arrow-up-right-square-fill::before { content: "\f142"; } +.bi-arrow-up-right-square::before { content: "\f143"; } +.bi-arrow-up-right::before { content: "\f144"; } +.bi-arrow-up-short::before { content: "\f145"; } +.bi-arrow-up-square-fill::before { content: "\f146"; } +.bi-arrow-up-square::before { content: "\f147"; } +.bi-arrow-up::before { content: "\f148"; } +.bi-arrows-angle-contract::before { content: "\f149"; } +.bi-arrows-angle-expand::before { content: "\f14a"; } +.bi-arrows-collapse::before { content: "\f14b"; } +.bi-arrows-expand::before { content: "\f14c"; } +.bi-arrows-fullscreen::before { content: "\f14d"; } +.bi-arrows-move::before { content: "\f14e"; } +.bi-aspect-ratio-fill::before { content: "\f14f"; } +.bi-aspect-ratio::before { content: "\f150"; } +.bi-asterisk::before { content: "\f151"; } +.bi-at::before { content: "\f152"; } +.bi-award-fill::before { content: "\f153"; } +.bi-award::before { content: "\f154"; } +.bi-back::before { content: "\f155"; } +.bi-backspace-fill::before { content: "\f156"; } +.bi-backspace-reverse-fill::before { content: "\f157"; } +.bi-backspace-reverse::before { content: "\f158"; } +.bi-backspace::before { content: "\f159"; } +.bi-badge-3d-fill::before { content: "\f15a"; } +.bi-badge-3d::before { content: "\f15b"; } +.bi-badge-4k-fill::before { content: "\f15c"; } +.bi-badge-4k::before { content: "\f15d"; } +.bi-badge-8k-fill::before { content: "\f15e"; } +.bi-badge-8k::before { content: "\f15f"; } +.bi-badge-ad-fill::before { content: "\f160"; } +.bi-badge-ad::before { content: "\f161"; } +.bi-badge-ar-fill::before { content: "\f162"; } +.bi-badge-ar::before { content: "\f163"; } +.bi-badge-cc-fill::before { content: "\f164"; } +.bi-badge-cc::before { content: "\f165"; } +.bi-badge-hd-fill::before { content: "\f166"; } +.bi-badge-hd::before { content: "\f167"; } +.bi-badge-tm-fill::before { content: "\f168"; } +.bi-badge-tm::before { content: "\f169"; } +.bi-badge-vo-fill::before { content: "\f16a"; } +.bi-badge-vo::before { content: "\f16b"; } +.bi-badge-vr-fill::before { content: "\f16c"; } +.bi-badge-vr::before { content: "\f16d"; } +.bi-badge-wc-fill::before { content: "\f16e"; } +.bi-badge-wc::before { content: "\f16f"; } +.bi-bag-check-fill::before { content: "\f170"; } +.bi-bag-check::before { content: "\f171"; } +.bi-bag-dash-fill::before { content: "\f172"; } +.bi-bag-dash::before { content: "\f173"; } +.bi-bag-fill::before { content: "\f174"; } +.bi-bag-plus-fill::before { content: "\f175"; } +.bi-bag-plus::before { content: "\f176"; } +.bi-bag-x-fill::before { content: "\f177"; } +.bi-bag-x::before { content: "\f178"; } +.bi-bag::before { content: "\f179"; } +.bi-bar-chart-fill::before { content: "\f17a"; } +.bi-bar-chart-line-fill::before { content: "\f17b"; } +.bi-bar-chart-line::before { content: "\f17c"; } +.bi-bar-chart-steps::before { content: "\f17d"; } +.bi-bar-chart::before { content: "\f17e"; } +.bi-basket-fill::before { content: "\f17f"; } +.bi-basket::before { content: "\f180"; } +.bi-basket2-fill::before { content: "\f181"; } +.bi-basket2::before { content: "\f182"; } +.bi-basket3-fill::before { content: "\f183"; } +.bi-basket3::before { content: "\f184"; } +.bi-battery-charging::before { content: "\f185"; } +.bi-battery-full::before { content: "\f186"; } +.bi-battery-half::before { content: "\f187"; } +.bi-battery::before { content: "\f188"; } +.bi-bell-fill::before { content: "\f189"; } +.bi-bell::before { content: "\f18a"; } +.bi-bezier::before { content: "\f18b"; } +.bi-bezier2::before { content: "\f18c"; } +.bi-bicycle::before { content: "\f18d"; } +.bi-binoculars-fill::before { content: "\f18e"; } +.bi-binoculars::before { content: "\f18f"; } +.bi-blockquote-left::before { content: "\f190"; } +.bi-blockquote-right::before { content: "\f191"; } +.bi-book-fill::before { content: "\f192"; } +.bi-book-half::before { content: "\f193"; } +.bi-book::before { content: "\f194"; } +.bi-bookmark-check-fill::before { content: "\f195"; } +.bi-bookmark-check::before { content: "\f196"; } +.bi-bookmark-dash-fill::before { content: "\f197"; } +.bi-bookmark-dash::before { content: "\f198"; } +.bi-bookmark-fill::before { content: "\f199"; } +.bi-bookmark-heart-fill::before { content: "\f19a"; } +.bi-bookmark-heart::before { content: "\f19b"; } +.bi-bookmark-plus-fill::before { content: "\f19c"; } +.bi-bookmark-plus::before { content: "\f19d"; } +.bi-bookmark-star-fill::before { content: "\f19e"; } +.bi-bookmark-star::before { content: "\f19f"; } +.bi-bookmark-x-fill::before { content: "\f1a0"; } +.bi-bookmark-x::before { content: "\f1a1"; } +.bi-bookmark::before { content: "\f1a2"; } +.bi-bookmarks-fill::before { content: "\f1a3"; } +.bi-bookmarks::before { content: "\f1a4"; } +.bi-bookshelf::before { content: "\f1a5"; } +.bi-bootstrap-fill::before { content: "\f1a6"; } +.bi-bootstrap-reboot::before { content: "\f1a7"; } +.bi-bootstrap::before { content: "\f1a8"; } +.bi-border-all::before { content: "\f1a9"; } +.bi-border-bottom::before { content: "\f1aa"; } +.bi-border-center::before { content: "\f1ab"; } +.bi-border-inner::before { content: "\f1ac"; } +.bi-border-left::before { content: "\f1ad"; } +.bi-border-middle::before { content: "\f1ae"; } +.bi-border-outer::before { content: "\f1af"; } +.bi-border-right::before { content: "\f1b0"; } +.bi-border-style::before { content: "\f1b1"; } +.bi-border-top::before { content: "\f1b2"; } +.bi-border-width::before { content: "\f1b3"; } +.bi-border::before { content: "\f1b4"; } +.bi-bounding-box-circles::before { content: "\f1b5"; } +.bi-bounding-box::before { content: "\f1b6"; } +.bi-box-arrow-down-left::before { content: "\f1b7"; } +.bi-box-arrow-down-right::before { content: "\f1b8"; } +.bi-box-arrow-down::before { content: "\f1b9"; } +.bi-box-arrow-in-down-left::before { content: "\f1ba"; } +.bi-box-arrow-in-down-right::before { content: "\f1bb"; } +.bi-box-arrow-in-down::before { content: "\f1bc"; } +.bi-box-arrow-in-left::before { content: "\f1bd"; } +.bi-box-arrow-in-right::before { content: "\f1be"; } +.bi-box-arrow-in-up-left::before { content: "\f1bf"; } +.bi-box-arrow-in-up-right::before { content: "\f1c0"; } +.bi-box-arrow-in-up::before { content: "\f1c1"; } +.bi-box-arrow-left::before { content: "\f1c2"; } +.bi-box-arrow-right::before { content: "\f1c3"; } +.bi-box-arrow-up-left::before { content: "\f1c4"; } +.bi-box-arrow-up-right::before { content: "\f1c5"; } +.bi-box-arrow-up::before { content: "\f1c6"; } +.bi-box-seam::before { content: "\f1c7"; } +.bi-box::before { content: "\f1c8"; } +.bi-braces::before { content: "\f1c9"; } +.bi-bricks::before { content: "\f1ca"; } +.bi-briefcase-fill::before { content: "\f1cb"; } +.bi-briefcase::before { content: "\f1cc"; } +.bi-brightness-alt-high-fill::before { content: "\f1cd"; } +.bi-brightness-alt-high::before { content: "\f1ce"; } +.bi-brightness-alt-low-fill::before { content: "\f1cf"; } +.bi-brightness-alt-low::before { content: "\f1d0"; } +.bi-brightness-high-fill::before { content: "\f1d1"; } +.bi-brightness-high::before { content: "\f1d2"; } +.bi-brightness-low-fill::before { content: "\f1d3"; } +.bi-brightness-low::before { content: "\f1d4"; } +.bi-broadcast-pin::before { content: "\f1d5"; } +.bi-broadcast::before { content: "\f1d6"; } +.bi-brush-fill::before { content: "\f1d7"; } +.bi-brush::before { content: "\f1d8"; } +.bi-bucket-fill::before { content: "\f1d9"; } +.bi-bucket::before { content: "\f1da"; } +.bi-bug-fill::before { content: "\f1db"; } +.bi-bug::before { content: "\f1dc"; } +.bi-building::before { content: "\f1dd"; } +.bi-bullseye::before { content: "\f1de"; } +.bi-calculator-fill::before { content: "\f1df"; } +.bi-calculator::before { content: "\f1e0"; } +.bi-calendar-check-fill::before { content: "\f1e1"; } +.bi-calendar-check::before { content: "\f1e2"; } +.bi-calendar-date-fill::before { content: "\f1e3"; } +.bi-calendar-date::before { content: "\f1e4"; } +.bi-calendar-day-fill::before { content: "\f1e5"; } +.bi-calendar-day::before { content: "\f1e6"; } +.bi-calendar-event-fill::before { content: "\f1e7"; } +.bi-calendar-event::before { content: "\f1e8"; } +.bi-calendar-fill::before { content: "\f1e9"; } +.bi-calendar-minus-fill::before { content: "\f1ea"; } +.bi-calendar-minus::before { content: "\f1eb"; } +.bi-calendar-month-fill::before { content: "\f1ec"; } +.bi-calendar-month::before { content: "\f1ed"; } +.bi-calendar-plus-fill::before { content: "\f1ee"; } +.bi-calendar-plus::before { content: "\f1ef"; } +.bi-calendar-range-fill::before { content: "\f1f0"; } +.bi-calendar-range::before { content: "\f1f1"; } +.bi-calendar-week-fill::before { content: "\f1f2"; } +.bi-calendar-week::before { content: "\f1f3"; } +.bi-calendar-x-fill::before { content: "\f1f4"; } +.bi-calendar-x::before { content: "\f1f5"; } +.bi-calendar::before { content: "\f1f6"; } +.bi-calendar2-check-fill::before { content: "\f1f7"; } +.bi-calendar2-check::before { content: "\f1f8"; } +.bi-calendar2-date-fill::before { content: "\f1f9"; } +.bi-calendar2-date::before { content: "\f1fa"; } +.bi-calendar2-day-fill::before { content: "\f1fb"; } +.bi-calendar2-day::before { content: "\f1fc"; } +.bi-calendar2-event-fill::before { content: "\f1fd"; } +.bi-calendar2-event::before { content: "\f1fe"; } +.bi-calendar2-fill::before { content: "\f1ff"; } +.bi-calendar2-minus-fill::before { content: "\f200"; } +.bi-calendar2-minus::before { content: "\f201"; } +.bi-calendar2-month-fill::before { content: "\f202"; } +.bi-calendar2-month::before { content: "\f203"; } +.bi-calendar2-plus-fill::before { content: "\f204"; } +.bi-calendar2-plus::before { content: "\f205"; } +.bi-calendar2-range-fill::before { content: "\f206"; } +.bi-calendar2-range::before { content: "\f207"; } +.bi-calendar2-week-fill::before { content: "\f208"; } +.bi-calendar2-week::before { content: "\f209"; } +.bi-calendar2-x-fill::before { content: "\f20a"; } +.bi-calendar2-x::before { content: "\f20b"; } +.bi-calendar2::before { content: "\f20c"; } +.bi-calendar3-event-fill::before { content: "\f20d"; } +.bi-calendar3-event::before { content: "\f20e"; } +.bi-calendar3-fill::before { content: "\f20f"; } +.bi-calendar3-range-fill::before { content: "\f210"; } +.bi-calendar3-range::before { content: "\f211"; } +.bi-calendar3-week-fill::before { content: "\f212"; } +.bi-calendar3-week::before { content: "\f213"; } +.bi-calendar3::before { content: "\f214"; } +.bi-calendar4-event::before { content: "\f215"; } +.bi-calendar4-range::before { content: "\f216"; } +.bi-calendar4-week::before { content: "\f217"; } +.bi-calendar4::before { content: "\f218"; } +.bi-camera-fill::before { content: "\f219"; } +.bi-camera-reels-fill::before { content: "\f21a"; } +.bi-camera-reels::before { content: "\f21b"; } +.bi-camera-video-fill::before { content: "\f21c"; } +.bi-camera-video-off-fill::before { content: "\f21d"; } +.bi-camera-video-off::before { content: "\f21e"; } +.bi-camera-video::before { content: "\f21f"; } +.bi-camera::before { content: "\f220"; } +.bi-camera2::before { content: "\f221"; } +.bi-capslock-fill::before { content: "\f222"; } +.bi-capslock::before { content: "\f223"; } +.bi-card-checklist::before { content: "\f224"; } +.bi-card-heading::before { content: "\f225"; } +.bi-card-image::before { content: "\f226"; } +.bi-card-list::before { content: "\f227"; } +.bi-card-text::before { content: "\f228"; } +.bi-caret-down-fill::before { content: "\f229"; } +.bi-caret-down-square-fill::before { content: "\f22a"; } +.bi-caret-down-square::before { content: "\f22b"; } +.bi-caret-down::before { content: "\f22c"; } +.bi-caret-left-fill::before { content: "\f22d"; } +.bi-caret-left-square-fill::before { content: "\f22e"; } +.bi-caret-left-square::before { content: "\f22f"; } +.bi-caret-left::before { content: "\f230"; } +.bi-caret-right-fill::before { content: "\f231"; } +.bi-caret-right-square-fill::before { content: "\f232"; } +.bi-caret-right-square::before { content: "\f233"; } +.bi-caret-right::before { content: "\f234"; } +.bi-caret-up-fill::before { content: "\f235"; } +.bi-caret-up-square-fill::before { content: "\f236"; } +.bi-caret-up-square::before { content: "\f237"; } +.bi-caret-up::before { content: "\f238"; } +.bi-cart-check-fill::before { content: "\f239"; } +.bi-cart-check::before { content: "\f23a"; } +.bi-cart-dash-fill::before { content: "\f23b"; } +.bi-cart-dash::before { content: "\f23c"; } +.bi-cart-fill::before { content: "\f23d"; } +.bi-cart-plus-fill::before { content: "\f23e"; } +.bi-cart-plus::before { content: "\f23f"; } +.bi-cart-x-fill::before { content: "\f240"; } +.bi-cart-x::before { content: "\f241"; } +.bi-cart::before { content: "\f242"; } +.bi-cart2::before { content: "\f243"; } +.bi-cart3::before { content: "\f244"; } +.bi-cart4::before { content: "\f245"; } +.bi-cash-stack::before { content: "\f246"; } +.bi-cash::before { content: "\f247"; } +.bi-cast::before { content: "\f248"; } +.bi-chat-dots-fill::before { content: "\f249"; } +.bi-chat-dots::before { content: "\f24a"; } +.bi-chat-fill::before { content: "\f24b"; } +.bi-chat-left-dots-fill::before { content: "\f24c"; } +.bi-chat-left-dots::before { content: "\f24d"; } +.bi-chat-left-fill::before { content: "\f24e"; } +.bi-chat-left-quote-fill::before { content: "\f24f"; } +.bi-chat-left-quote::before { content: "\f250"; } +.bi-chat-left-text-fill::before { content: "\f251"; } +.bi-chat-left-text::before { content: "\f252"; } +.bi-chat-left::before { content: "\f253"; } +.bi-chat-quote-fill::before { content: "\f254"; } +.bi-chat-quote::before { content: "\f255"; } +.bi-chat-right-dots-fill::before { content: "\f256"; } +.bi-chat-right-dots::before { content: "\f257"; } +.bi-chat-right-fill::before { content: "\f258"; } +.bi-chat-right-quote-fill::before { content: "\f259"; } +.bi-chat-right-quote::before { content: "\f25a"; } +.bi-chat-right-text-fill::before { content: "\f25b"; } +.bi-chat-right-text::before { content: "\f25c"; } +.bi-chat-right::before { content: "\f25d"; } +.bi-chat-square-dots-fill::before { content: "\f25e"; } +.bi-chat-square-dots::before { content: "\f25f"; } +.bi-chat-square-fill::before { content: "\f260"; } +.bi-chat-square-quote-fill::before { content: "\f261"; } +.bi-chat-square-quote::before { content: "\f262"; } +.bi-chat-square-text-fill::before { content: "\f263"; } +.bi-chat-square-text::before { content: "\f264"; } +.bi-chat-square::before { content: "\f265"; } +.bi-chat-text-fill::before { content: "\f266"; } +.bi-chat-text::before { content: "\f267"; } +.bi-chat::before { content: "\f268"; } +.bi-check-all::before { content: "\f269"; } +.bi-check-circle-fill::before { content: "\f26a"; } +.bi-check-circle::before { content: "\f26b"; } +.bi-check-square-fill::before { content: "\f26c"; } +.bi-check-square::before { content: "\f26d"; } +.bi-check::before { content: "\f26e"; } +.bi-check2-all::before { content: "\f26f"; } +.bi-check2-circle::before { content: "\f270"; } +.bi-check2-square::before { content: "\f271"; } +.bi-check2::before { content: "\f272"; } +.bi-chevron-bar-contract::before { content: "\f273"; } +.bi-chevron-bar-down::before { content: "\f274"; } +.bi-chevron-bar-expand::before { content: "\f275"; } +.bi-chevron-bar-left::before { content: "\f276"; } +.bi-chevron-bar-right::before { content: "\f277"; } +.bi-chevron-bar-up::before { content: "\f278"; } +.bi-chevron-compact-down::before { content: "\f279"; } +.bi-chevron-compact-left::before { content: "\f27a"; } +.bi-chevron-compact-right::before { content: "\f27b"; } +.bi-chevron-compact-up::before { content: "\f27c"; } +.bi-chevron-contract::before { content: "\f27d"; } +.bi-chevron-double-down::before { content: "\f27e"; } +.bi-chevron-double-left::before { content: "\f27f"; } +.bi-chevron-double-right::before { content: "\f280"; } +.bi-chevron-double-up::before { content: "\f281"; } +.bi-chevron-down::before { content: "\f282"; } +.bi-chevron-expand::before { content: "\f283"; } +.bi-chevron-left::before { content: "\f284"; } +.bi-chevron-right::before { content: "\f285"; } +.bi-chevron-up::before { content: "\f286"; } +.bi-circle-fill::before { content: "\f287"; } +.bi-circle-half::before { content: "\f288"; } +.bi-circle-square::before { content: "\f289"; } +.bi-circle::before { content: "\f28a"; } +.bi-clipboard-check::before { content: "\f28b"; } +.bi-clipboard-data::before { content: "\f28c"; } +.bi-clipboard-minus::before { content: "\f28d"; } +.bi-clipboard-plus::before { content: "\f28e"; } +.bi-clipboard-x::before { content: "\f28f"; } +.bi-clipboard::before { content: "\f290"; } +.bi-clock-fill::before { content: "\f291"; } +.bi-clock-history::before { content: "\f292"; } +.bi-clock::before { content: "\f293"; } +.bi-cloud-arrow-down-fill::before { content: "\f294"; } +.bi-cloud-arrow-down::before { content: "\f295"; } +.bi-cloud-arrow-up-fill::before { content: "\f296"; } +.bi-cloud-arrow-up::before { content: "\f297"; } +.bi-cloud-check-fill::before { content: "\f298"; } +.bi-cloud-check::before { content: "\f299"; } +.bi-cloud-download-fill::before { content: "\f29a"; } +.bi-cloud-download::before { content: "\f29b"; } +.bi-cloud-drizzle-fill::before { content: "\f29c"; } +.bi-cloud-drizzle::before { content: "\f29d"; } +.bi-cloud-fill::before { content: "\f29e"; } +.bi-cloud-fog-fill::before { content: "\f29f"; } +.bi-cloud-fog::before { content: "\f2a0"; } +.bi-cloud-fog2-fill::before { content: "\f2a1"; } +.bi-cloud-fog2::before { content: "\f2a2"; } +.bi-cloud-hail-fill::before { content: "\f2a3"; } +.bi-cloud-hail::before { content: "\f2a4"; } +.bi-cloud-haze-fill::before { content: "\f2a6"; } +.bi-cloud-haze::before { content: "\f2a7"; } +.bi-cloud-haze2-fill::before { content: "\f2a8"; } +.bi-cloud-lightning-fill::before { content: "\f2a9"; } +.bi-cloud-lightning-rain-fill::before { content: "\f2aa"; } +.bi-cloud-lightning-rain::before { content: "\f2ab"; } +.bi-cloud-lightning::before { content: "\f2ac"; } +.bi-cloud-minus-fill::before { content: "\f2ad"; } +.bi-cloud-minus::before { content: "\f2ae"; } +.bi-cloud-moon-fill::before { content: "\f2af"; } +.bi-cloud-moon::before { content: "\f2b0"; } +.bi-cloud-plus-fill::before { content: "\f2b1"; } +.bi-cloud-plus::before { content: "\f2b2"; } +.bi-cloud-rain-fill::before { content: "\f2b3"; } +.bi-cloud-rain-heavy-fill::before { content: "\f2b4"; } +.bi-cloud-rain-heavy::before { content: "\f2b5"; } +.bi-cloud-rain::before { content: "\f2b6"; } +.bi-cloud-slash-fill::before { content: "\f2b7"; } +.bi-cloud-slash::before { content: "\f2b8"; } +.bi-cloud-sleet-fill::before { content: "\f2b9"; } +.bi-cloud-sleet::before { content: "\f2ba"; } +.bi-cloud-snow-fill::before { content: "\f2bb"; } +.bi-cloud-snow::before { content: "\f2bc"; } +.bi-cloud-sun-fill::before { content: "\f2bd"; } +.bi-cloud-sun::before { content: "\f2be"; } +.bi-cloud-upload-fill::before { content: "\f2bf"; } +.bi-cloud-upload::before { content: "\f2c0"; } +.bi-cloud::before { content: "\f2c1"; } +.bi-clouds-fill::before { content: "\f2c2"; } +.bi-clouds::before { content: "\f2c3"; } +.bi-cloudy-fill::before { content: "\f2c4"; } +.bi-cloudy::before { content: "\f2c5"; } +.bi-code-slash::before { content: "\f2c6"; } +.bi-code-square::before { content: "\f2c7"; } +.bi-code::before { content: "\f2c8"; } +.bi-collection-fill::before { content: "\f2c9"; } +.bi-collection-play-fill::before { content: "\f2ca"; } +.bi-collection-play::before { content: "\f2cb"; } +.bi-collection::before { content: "\f2cc"; } +.bi-columns-gap::before { content: "\f2cd"; } +.bi-columns::before { content: "\f2ce"; } +.bi-command::before { content: "\f2cf"; } +.bi-compass-fill::before { content: "\f2d0"; } +.bi-compass::before { content: "\f2d1"; } +.bi-cone-striped::before { content: "\f2d2"; } +.bi-cone::before { content: "\f2d3"; } +.bi-controller::before { content: "\f2d4"; } +.bi-cpu-fill::before { content: "\f2d5"; } +.bi-cpu::before { content: "\f2d6"; } +.bi-credit-card-2-back-fill::before { content: "\f2d7"; } +.bi-credit-card-2-back::before { content: "\f2d8"; } +.bi-credit-card-2-front-fill::before { content: "\f2d9"; } +.bi-credit-card-2-front::before { content: "\f2da"; } +.bi-credit-card-fill::before { content: "\f2db"; } +.bi-credit-card::before { content: "\f2dc"; } +.bi-crop::before { content: "\f2dd"; } +.bi-cup-fill::before { content: "\f2de"; } +.bi-cup-straw::before { content: "\f2df"; } +.bi-cup::before { content: "\f2e0"; } +.bi-cursor-fill::before { content: "\f2e1"; } +.bi-cursor-text::before { content: "\f2e2"; } +.bi-cursor::before { content: "\f2e3"; } +.bi-dash-circle-dotted::before { content: "\f2e4"; } +.bi-dash-circle-fill::before { content: "\f2e5"; } +.bi-dash-circle::before { content: "\f2e6"; } +.bi-dash-square-dotted::before { content: "\f2e7"; } +.bi-dash-square-fill::before { content: "\f2e8"; } +.bi-dash-square::before { content: "\f2e9"; } +.bi-dash::before { content: "\f2ea"; } +.bi-diagram-2-fill::before { content: "\f2eb"; } +.bi-diagram-2::before { content: "\f2ec"; } +.bi-diagram-3-fill::before { content: "\f2ed"; } +.bi-diagram-3::before { content: "\f2ee"; } +.bi-diamond-fill::before { content: "\f2ef"; } +.bi-diamond-half::before { content: "\f2f0"; } +.bi-diamond::before { content: "\f2f1"; } +.bi-dice-1-fill::before { content: "\f2f2"; } +.bi-dice-1::before { content: "\f2f3"; } +.bi-dice-2-fill::before { content: "\f2f4"; } +.bi-dice-2::before { content: "\f2f5"; } +.bi-dice-3-fill::before { content: "\f2f6"; } +.bi-dice-3::before { content: "\f2f7"; } +.bi-dice-4-fill::before { content: "\f2f8"; } +.bi-dice-4::before { content: "\f2f9"; } +.bi-dice-5-fill::before { content: "\f2fa"; } +.bi-dice-5::before { content: "\f2fb"; } +.bi-dice-6-fill::before { content: "\f2fc"; } +.bi-dice-6::before { content: "\f2fd"; } +.bi-disc-fill::before { content: "\f2fe"; } +.bi-disc::before { content: "\f2ff"; } +.bi-discord::before { content: "\f300"; } +.bi-display-fill::before { content: "\f301"; } +.bi-display::before { content: "\f302"; } +.bi-distribute-horizontal::before { content: "\f303"; } +.bi-distribute-vertical::before { content: "\f304"; } +.bi-door-closed-fill::before { content: "\f305"; } +.bi-door-closed::before { content: "\f306"; } +.bi-door-open-fill::before { content: "\f307"; } +.bi-door-open::before { content: "\f308"; } +.bi-dot::before { content: "\f309"; } +.bi-download::before { content: "\f30a"; } +.bi-droplet-fill::before { content: "\f30b"; } +.bi-droplet-half::before { content: "\f30c"; } +.bi-droplet::before { content: "\f30d"; } +.bi-earbuds::before { content: "\f30e"; } +.bi-easel-fill::before { content: "\f30f"; } +.bi-easel::before { content: "\f310"; } +.bi-egg-fill::before { content: "\f311"; } +.bi-egg-fried::before { content: "\f312"; } +.bi-egg::before { content: "\f313"; } +.bi-eject-fill::before { content: "\f314"; } +.bi-eject::before { content: "\f315"; } +.bi-emoji-angry-fill::before { content: "\f316"; } +.bi-emoji-angry::before { content: "\f317"; } +.bi-emoji-dizzy-fill::before { content: "\f318"; } +.bi-emoji-dizzy::before { content: "\f319"; } +.bi-emoji-expressionless-fill::before { content: "\f31a"; } +.bi-emoji-expressionless::before { content: "\f31b"; } +.bi-emoji-frown-fill::before { content: "\f31c"; } +.bi-emoji-frown::before { content: "\f31d"; } +.bi-emoji-heart-eyes-fill::before { content: "\f31e"; } +.bi-emoji-heart-eyes::before { content: "\f31f"; } +.bi-emoji-laughing-fill::before { content: "\f320"; } +.bi-emoji-laughing::before { content: "\f321"; } +.bi-emoji-neutral-fill::before { content: "\f322"; } +.bi-emoji-neutral::before { content: "\f323"; } +.bi-emoji-smile-fill::before { content: "\f324"; } +.bi-emoji-smile-upside-down-fill::before { content: "\f325"; } +.bi-emoji-smile-upside-down::before { content: "\f326"; } +.bi-emoji-smile::before { content: "\f327"; } +.bi-emoji-sunglasses-fill::before { content: "\f328"; } +.bi-emoji-sunglasses::before { content: "\f329"; } +.bi-emoji-wink-fill::before { content: "\f32a"; } +.bi-emoji-wink::before { content: "\f32b"; } +.bi-envelope-fill::before { content: "\f32c"; } +.bi-envelope-open-fill::before { content: "\f32d"; } +.bi-envelope-open::before { content: "\f32e"; } +.bi-envelope::before { content: "\f32f"; } +.bi-eraser-fill::before { content: "\f330"; } +.bi-eraser::before { content: "\f331"; } +.bi-exclamation-circle-fill::before { content: "\f332"; } +.bi-exclamation-circle::before { content: "\f333"; } +.bi-exclamation-diamond-fill::before { content: "\f334"; } +.bi-exclamation-diamond::before { content: "\f335"; } +.bi-exclamation-octagon-fill::before { content: "\f336"; } +.bi-exclamation-octagon::before { content: "\f337"; } +.bi-exclamation-square-fill::before { content: "\f338"; } +.bi-exclamation-square::before { content: "\f339"; } +.bi-exclamation-triangle-fill::before { content: "\f33a"; } +.bi-exclamation-triangle::before { content: "\f33b"; } +.bi-exclamation::before { content: "\f33c"; } +.bi-exclude::before { content: "\f33d"; } +.bi-eye-fill::before { content: "\f33e"; } +.bi-eye-slash-fill::before { content: "\f33f"; } +.bi-eye-slash::before { content: "\f340"; } +.bi-eye::before { content: "\f341"; } +.bi-eyedropper::before { content: "\f342"; } +.bi-eyeglasses::before { content: "\f343"; } +.bi-facebook::before { content: "\f344"; } +.bi-file-arrow-down-fill::before { content: "\f345"; } +.bi-file-arrow-down::before { content: "\f346"; } +.bi-file-arrow-up-fill::before { content: "\f347"; } +.bi-file-arrow-up::before { content: "\f348"; } +.bi-file-bar-graph-fill::before { content: "\f349"; } +.bi-file-bar-graph::before { content: "\f34a"; } +.bi-file-binary-fill::before { content: "\f34b"; } +.bi-file-binary::before { content: "\f34c"; } +.bi-file-break-fill::before { content: "\f34d"; } +.bi-file-break::before { content: "\f34e"; } +.bi-file-check-fill::before { content: "\f34f"; } +.bi-file-check::before { content: "\f350"; } +.bi-file-code-fill::before { content: "\f351"; } +.bi-file-code::before { content: "\f352"; } +.bi-file-diff-fill::before { content: "\f353"; } +.bi-file-diff::before { content: "\f354"; } +.bi-file-earmark-arrow-down-fill::before { content: "\f355"; } +.bi-file-earmark-arrow-down::before { content: "\f356"; } +.bi-file-earmark-arrow-up-fill::before { content: "\f357"; } +.bi-file-earmark-arrow-up::before { content: "\f358"; } +.bi-file-earmark-bar-graph-fill::before { content: "\f359"; } +.bi-file-earmark-bar-graph::before { content: "\f35a"; } +.bi-file-earmark-binary-fill::before { content: "\f35b"; } +.bi-file-earmark-binary::before { content: "\f35c"; } +.bi-file-earmark-break-fill::before { content: "\f35d"; } +.bi-file-earmark-break::before { content: "\f35e"; } +.bi-file-earmark-check-fill::before { content: "\f35f"; } +.bi-file-earmark-check::before { content: "\f360"; } +.bi-file-earmark-code-fill::before { content: "\f361"; } +.bi-file-earmark-code::before { content: "\f362"; } +.bi-file-earmark-diff-fill::before { content: "\f363"; } +.bi-file-earmark-diff::before { content: "\f364"; } +.bi-file-earmark-easel-fill::before { content: "\f365"; } +.bi-file-earmark-easel::before { content: "\f366"; } +.bi-file-earmark-excel-fill::before { content: "\f367"; } +.bi-file-earmark-excel::before { content: "\f368"; } +.bi-file-earmark-fill::before { content: "\f369"; } +.bi-file-earmark-font-fill::before { content: "\f36a"; } +.bi-file-earmark-font::before { content: "\f36b"; } +.bi-file-earmark-image-fill::before { content: "\f36c"; } +.bi-file-earmark-image::before { content: "\f36d"; } +.bi-file-earmark-lock-fill::before { content: "\f36e"; } +.bi-file-earmark-lock::before { content: "\f36f"; } +.bi-file-earmark-lock2-fill::before { content: "\f370"; } +.bi-file-earmark-lock2::before { content: "\f371"; } +.bi-file-earmark-medical-fill::before { content: "\f372"; } +.bi-file-earmark-medical::before { content: "\f373"; } +.bi-file-earmark-minus-fill::before { content: "\f374"; } +.bi-file-earmark-minus::before { content: "\f375"; } +.bi-file-earmark-music-fill::before { content: "\f376"; } +.bi-file-earmark-music::before { content: "\f377"; } +.bi-file-earmark-person-fill::before { content: "\f378"; } +.bi-file-earmark-person::before { content: "\f379"; } +.bi-file-earmark-play-fill::before { content: "\f37a"; } +.bi-file-earmark-play::before { content: "\f37b"; } +.bi-file-earmark-plus-fill::before { content: "\f37c"; } +.bi-file-earmark-plus::before { content: "\f37d"; } +.bi-file-earmark-post-fill::before { content: "\f37e"; } +.bi-file-earmark-post::before { content: "\f37f"; } +.bi-file-earmark-ppt-fill::before { content: "\f380"; } +.bi-file-earmark-ppt::before { content: "\f381"; } +.bi-file-earmark-richtext-fill::before { content: "\f382"; } +.bi-file-earmark-richtext::before { content: "\f383"; } +.bi-file-earmark-ruled-fill::before { content: "\f384"; } +.bi-file-earmark-ruled::before { content: "\f385"; } +.bi-file-earmark-slides-fill::before { content: "\f386"; } +.bi-file-earmark-slides::before { content: "\f387"; } +.bi-file-earmark-spreadsheet-fill::before { content: "\f388"; } +.bi-file-earmark-spreadsheet::before { content: "\f389"; } +.bi-file-earmark-text-fill::before { content: "\f38a"; } +.bi-file-earmark-text::before { content: "\f38b"; } +.bi-file-earmark-word-fill::before { content: "\f38c"; } +.bi-file-earmark-word::before { content: "\f38d"; } +.bi-file-earmark-x-fill::before { content: "\f38e"; } +.bi-file-earmark-x::before { content: "\f38f"; } +.bi-file-earmark-zip-fill::before { content: "\f390"; } +.bi-file-earmark-zip::before { content: "\f391"; } +.bi-file-earmark::before { content: "\f392"; } +.bi-file-easel-fill::before { content: "\f393"; } +.bi-file-easel::before { content: "\f394"; } +.bi-file-excel-fill::before { content: "\f395"; } +.bi-file-excel::before { content: "\f396"; } +.bi-file-fill::before { content: "\f397"; } +.bi-file-font-fill::before { content: "\f398"; } +.bi-file-font::before { content: "\f399"; } +.bi-file-image-fill::before { content: "\f39a"; } +.bi-file-image::before { content: "\f39b"; } +.bi-file-lock-fill::before { content: "\f39c"; } +.bi-file-lock::before { content: "\f39d"; } +.bi-file-lock2-fill::before { content: "\f39e"; } +.bi-file-lock2::before { content: "\f39f"; } +.bi-file-medical-fill::before { content: "\f3a0"; } +.bi-file-medical::before { content: "\f3a1"; } +.bi-file-minus-fill::before { content: "\f3a2"; } +.bi-file-minus::before { content: "\f3a3"; } +.bi-file-music-fill::before { content: "\f3a4"; } +.bi-file-music::before { content: "\f3a5"; } +.bi-file-person-fill::before { content: "\f3a6"; } +.bi-file-person::before { content: "\f3a7"; } +.bi-file-play-fill::before { content: "\f3a8"; } +.bi-file-play::before { content: "\f3a9"; } +.bi-file-plus-fill::before { content: "\f3aa"; } +.bi-file-plus::before { content: "\f3ab"; } +.bi-file-post-fill::before { content: "\f3ac"; } +.bi-file-post::before { content: "\f3ad"; } +.bi-file-ppt-fill::before { content: "\f3ae"; } +.bi-file-ppt::before { content: "\f3af"; } +.bi-file-richtext-fill::before { content: "\f3b0"; } +.bi-file-richtext::before { content: "\f3b1"; } +.bi-file-ruled-fill::before { content: "\f3b2"; } +.bi-file-ruled::before { content: "\f3b3"; } +.bi-file-slides-fill::before { content: "\f3b4"; } +.bi-file-slides::before { content: "\f3b5"; } +.bi-file-spreadsheet-fill::before { content: "\f3b6"; } +.bi-file-spreadsheet::before { content: "\f3b7"; } +.bi-file-text-fill::before { content: "\f3b8"; } +.bi-file-text::before { content: "\f3b9"; } +.bi-file-word-fill::before { content: "\f3ba"; } +.bi-file-word::before { content: "\f3bb"; } +.bi-file-x-fill::before { content: "\f3bc"; } +.bi-file-x::before { content: "\f3bd"; } +.bi-file-zip-fill::before { content: "\f3be"; } +.bi-file-zip::before { content: "\f3bf"; } +.bi-file::before { content: "\f3c0"; } +.bi-files-alt::before { content: "\f3c1"; } +.bi-files::before { content: "\f3c2"; } +.bi-film::before { content: "\f3c3"; } +.bi-filter-circle-fill::before { content: "\f3c4"; } +.bi-filter-circle::before { content: "\f3c5"; } +.bi-filter-left::before { content: "\f3c6"; } +.bi-filter-right::before { content: "\f3c7"; } +.bi-filter-square-fill::before { content: "\f3c8"; } +.bi-filter-square::before { content: "\f3c9"; } +.bi-filter::before { content: "\f3ca"; } +.bi-flag-fill::before { content: "\f3cb"; } +.bi-flag::before { content: "\f3cc"; } +.bi-flower1::before { content: "\f3cd"; } +.bi-flower2::before { content: "\f3ce"; } +.bi-flower3::before { content: "\f3cf"; } +.bi-folder-check::before { content: "\f3d0"; } +.bi-folder-fill::before { content: "\f3d1"; } +.bi-folder-minus::before { content: "\f3d2"; } +.bi-folder-plus::before { content: "\f3d3"; } +.bi-folder-symlink-fill::before { content: "\f3d4"; } +.bi-folder-symlink::before { content: "\f3d5"; } +.bi-folder-x::before { content: "\f3d6"; } +.bi-folder::before { content: "\f3d7"; } +.bi-folder2-open::before { content: "\f3d8"; } +.bi-folder2::before { content: "\f3d9"; } +.bi-fonts::before { content: "\f3da"; } +.bi-forward-fill::before { content: "\f3db"; } +.bi-forward::before { content: "\f3dc"; } +.bi-front::before { content: "\f3dd"; } +.bi-fullscreen-exit::before { content: "\f3de"; } +.bi-fullscreen::before { content: "\f3df"; } +.bi-funnel-fill::before { content: "\f3e0"; } +.bi-funnel::before { content: "\f3e1"; } +.bi-gear-fill::before { content: "\f3e2"; } +.bi-gear-wide-connected::before { content: "\f3e3"; } +.bi-gear-wide::before { content: "\f3e4"; } +.bi-gear::before { content: "\f3e5"; } +.bi-gem::before { content: "\f3e6"; } +.bi-geo-alt-fill::before { content: "\f3e7"; } +.bi-geo-alt::before { content: "\f3e8"; } +.bi-geo-fill::before { content: "\f3e9"; } +.bi-geo::before { content: "\f3ea"; } +.bi-gift-fill::before { content: "\f3eb"; } +.bi-gift::before { content: "\f3ec"; } +.bi-github::before { content: "\f3ed"; } +.bi-globe::before { content: "\f3ee"; } +.bi-globe2::before { content: "\f3ef"; } +.bi-google::before { content: "\f3f0"; } +.bi-graph-down::before { content: "\f3f1"; } +.bi-graph-up::before { content: "\f3f2"; } +.bi-grid-1x2-fill::before { content: "\f3f3"; } +.bi-grid-1x2::before { content: "\f3f4"; } +.bi-grid-3x2-gap-fill::before { content: "\f3f5"; } +.bi-grid-3x2-gap::before { content: "\f3f6"; } +.bi-grid-3x2::before { content: "\f3f7"; } +.bi-grid-3x3-gap-fill::before { content: "\f3f8"; } +.bi-grid-3x3-gap::before { content: "\f3f9"; } +.bi-grid-3x3::before { content: "\f3fa"; } +.bi-grid-fill::before { content: "\f3fb"; } +.bi-grid::before { content: "\f3fc"; } +.bi-grip-horizontal::before { content: "\f3fd"; } +.bi-grip-vertical::before { content: "\f3fe"; } +.bi-hammer::before { content: "\f3ff"; } +.bi-hand-index-fill::before { content: "\f400"; } +.bi-hand-index-thumb-fill::before { content: "\f401"; } +.bi-hand-index-thumb::before { content: "\f402"; } +.bi-hand-index::before { content: "\f403"; } +.bi-hand-thumbs-down-fill::before { content: "\f404"; } +.bi-hand-thumbs-down::before { content: "\f405"; } +.bi-hand-thumbs-up-fill::before { content: "\f406"; } +.bi-hand-thumbs-up::before { content: "\f407"; } +.bi-handbag-fill::before { content: "\f408"; } +.bi-handbag::before { content: "\f409"; } +.bi-hash::before { content: "\f40a"; } +.bi-hdd-fill::before { content: "\f40b"; } +.bi-hdd-network-fill::before { content: "\f40c"; } +.bi-hdd-network::before { content: "\f40d"; } +.bi-hdd-rack-fill::before { content: "\f40e"; } +.bi-hdd-rack::before { content: "\f40f"; } +.bi-hdd-stack-fill::before { content: "\f410"; } +.bi-hdd-stack::before { content: "\f411"; } +.bi-hdd::before { content: "\f412"; } +.bi-headphones::before { content: "\f413"; } +.bi-headset::before { content: "\f414"; } +.bi-heart-fill::before { content: "\f415"; } +.bi-heart-half::before { content: "\f416"; } +.bi-heart::before { content: "\f417"; } +.bi-heptagon-fill::before { content: "\f418"; } +.bi-heptagon-half::before { content: "\f419"; } +.bi-heptagon::before { content: "\f41a"; } +.bi-hexagon-fill::before { content: "\f41b"; } +.bi-hexagon-half::before { content: "\f41c"; } +.bi-hexagon::before { content: "\f41d"; } +.bi-hourglass-bottom::before { content: "\f41e"; } +.bi-hourglass-split::before { content: "\f41f"; } +.bi-hourglass-top::before { content: "\f420"; } +.bi-hourglass::before { content: "\f421"; } +.bi-house-door-fill::before { content: "\f422"; } +.bi-house-door::before { content: "\f423"; } +.bi-house-fill::before { content: "\f424"; } +.bi-house::before { content: "\f425"; } +.bi-hr::before { content: "\f426"; } +.bi-hurricane::before { content: "\f427"; } +.bi-image-alt::before { content: "\f428"; } +.bi-image-fill::before { content: "\f429"; } +.bi-image::before { content: "\f42a"; } +.bi-images::before { content: "\f42b"; } +.bi-inbox-fill::before { content: "\f42c"; } +.bi-inbox::before { content: "\f42d"; } +.bi-inboxes-fill::before { content: "\f42e"; } +.bi-inboxes::before { content: "\f42f"; } +.bi-info-circle-fill::before { content: "\f430"; } +.bi-info-circle::before { content: "\f431"; } +.bi-info-square-fill::before { content: "\f432"; } +.bi-info-square::before { content: "\f433"; } +.bi-info::before { content: "\f434"; } +.bi-input-cursor-text::before { content: "\f435"; } +.bi-input-cursor::before { content: "\f436"; } +.bi-instagram::before { content: "\f437"; } +.bi-intersect::before { content: "\f438"; } +.bi-journal-album::before { content: "\f439"; } +.bi-journal-arrow-down::before { content: "\f43a"; } +.bi-journal-arrow-up::before { content: "\f43b"; } +.bi-journal-bookmark-fill::before { content: "\f43c"; } +.bi-journal-bookmark::before { content: "\f43d"; } +.bi-journal-check::before { content: "\f43e"; } +.bi-journal-code::before { content: "\f43f"; } +.bi-journal-medical::before { content: "\f440"; } +.bi-journal-minus::before { content: "\f441"; } +.bi-journal-plus::before { content: "\f442"; } +.bi-journal-richtext::before { content: "\f443"; } +.bi-journal-text::before { content: "\f444"; } +.bi-journal-x::before { content: "\f445"; } +.bi-journal::before { content: "\f446"; } +.bi-journals::before { content: "\f447"; } +.bi-joystick::before { content: "\f448"; } +.bi-justify-left::before { content: "\f449"; } +.bi-justify-right::before { content: "\f44a"; } +.bi-justify::before { content: "\f44b"; } +.bi-kanban-fill::before { content: "\f44c"; } +.bi-kanban::before { content: "\f44d"; } +.bi-key-fill::before { content: "\f44e"; } +.bi-key::before { content: "\f44f"; } +.bi-keyboard-fill::before { content: "\f450"; } +.bi-keyboard::before { content: "\f451"; } +.bi-ladder::before { content: "\f452"; } +.bi-lamp-fill::before { content: "\f453"; } +.bi-lamp::before { content: "\f454"; } +.bi-laptop-fill::before { content: "\f455"; } +.bi-laptop::before { content: "\f456"; } +.bi-layer-backward::before { content: "\f457"; } +.bi-layer-forward::before { content: "\f458"; } +.bi-layers-fill::before { content: "\f459"; } +.bi-layers-half::before { content: "\f45a"; } +.bi-layers::before { content: "\f45b"; } +.bi-layout-sidebar-inset-reverse::before { content: "\f45c"; } +.bi-layout-sidebar-inset::before { content: "\f45d"; } +.bi-layout-sidebar-reverse::before { content: "\f45e"; } +.bi-layout-sidebar::before { content: "\f45f"; } +.bi-layout-split::before { content: "\f460"; } +.bi-layout-text-sidebar-reverse::before { content: "\f461"; } +.bi-layout-text-sidebar::before { content: "\f462"; } +.bi-layout-text-window-reverse::before { content: "\f463"; } +.bi-layout-text-window::before { content: "\f464"; } +.bi-layout-three-columns::before { content: "\f465"; } +.bi-layout-wtf::before { content: "\f466"; } +.bi-life-preserver::before { content: "\f467"; } +.bi-lightbulb-fill::before { content: "\f468"; } +.bi-lightbulb-off-fill::before { content: "\f469"; } +.bi-lightbulb-off::before { content: "\f46a"; } +.bi-lightbulb::before { content: "\f46b"; } +.bi-lightning-charge-fill::before { content: "\f46c"; } +.bi-lightning-charge::before { content: "\f46d"; } +.bi-lightning-fill::before { content: "\f46e"; } +.bi-lightning::before { content: "\f46f"; } +.bi-link-45deg::before { content: "\f470"; } +.bi-link::before { content: "\f471"; } +.bi-linkedin::before { content: "\f472"; } +.bi-list-check::before { content: "\f473"; } +.bi-list-nested::before { content: "\f474"; } +.bi-list-ol::before { content: "\f475"; } +.bi-list-stars::before { content: "\f476"; } +.bi-list-task::before { content: "\f477"; } +.bi-list-ul::before { content: "\f478"; } +.bi-list::before { content: "\f479"; } +.bi-lock-fill::before { content: "\f47a"; } +.bi-lock::before { content: "\f47b"; } +.bi-mailbox::before { content: "\f47c"; } +.bi-mailbox2::before { content: "\f47d"; } +.bi-map-fill::before { content: "\f47e"; } +.bi-map::before { content: "\f47f"; } +.bi-markdown-fill::before { content: "\f480"; } +.bi-markdown::before { content: "\f481"; } +.bi-mask::before { content: "\f482"; } +.bi-megaphone-fill::before { content: "\f483"; } +.bi-megaphone::before { content: "\f484"; } +.bi-menu-app-fill::before { content: "\f485"; } +.bi-menu-app::before { content: "\f486"; } +.bi-menu-button-fill::before { content: "\f487"; } +.bi-menu-button-wide-fill::before { content: "\f488"; } +.bi-menu-button-wide::before { content: "\f489"; } +.bi-menu-button::before { content: "\f48a"; } +.bi-menu-down::before { content: "\f48b"; } +.bi-menu-up::before { content: "\f48c"; } +.bi-mic-fill::before { content: "\f48d"; } +.bi-mic-mute-fill::before { content: "\f48e"; } +.bi-mic-mute::before { content: "\f48f"; } +.bi-mic::before { content: "\f490"; } +.bi-minecart-loaded::before { content: "\f491"; } +.bi-minecart::before { content: "\f492"; } +.bi-moisture::before { content: "\f493"; } +.bi-moon-fill::before { content: "\f494"; } +.bi-moon-stars-fill::before { content: "\f495"; } +.bi-moon-stars::before { content: "\f496"; } +.bi-moon::before { content: "\f497"; } +.bi-mouse-fill::before { content: "\f498"; } +.bi-mouse::before { content: "\f499"; } +.bi-mouse2-fill::before { content: "\f49a"; } +.bi-mouse2::before { content: "\f49b"; } +.bi-mouse3-fill::before { content: "\f49c"; } +.bi-mouse3::before { content: "\f49d"; } +.bi-music-note-beamed::before { content: "\f49e"; } +.bi-music-note-list::before { content: "\f49f"; } +.bi-music-note::before { content: "\f4a0"; } +.bi-music-player-fill::before { content: "\f4a1"; } +.bi-music-player::before { content: "\f4a2"; } +.bi-newspaper::before { content: "\f4a3"; } +.bi-node-minus-fill::before { content: "\f4a4"; } +.bi-node-minus::before { content: "\f4a5"; } +.bi-node-plus-fill::before { content: "\f4a6"; } +.bi-node-plus::before { content: "\f4a7"; } +.bi-nut-fill::before { content: "\f4a8"; } +.bi-nut::before { content: "\f4a9"; } +.bi-octagon-fill::before { content: "\f4aa"; } +.bi-octagon-half::before { content: "\f4ab"; } +.bi-octagon::before { content: "\f4ac"; } +.bi-option::before { content: "\f4ad"; } +.bi-outlet::before { content: "\f4ae"; } +.bi-paint-bucket::before { content: "\f4af"; } +.bi-palette-fill::before { content: "\f4b0"; } +.bi-palette::before { content: "\f4b1"; } +.bi-palette2::before { content: "\f4b2"; } +.bi-paperclip::before { content: "\f4b3"; } +.bi-paragraph::before { content: "\f4b4"; } +.bi-patch-check-fill::before { content: "\f4b5"; } +.bi-patch-check::before { content: "\f4b6"; } +.bi-patch-exclamation-fill::before { content: "\f4b7"; } +.bi-patch-exclamation::before { content: "\f4b8"; } +.bi-patch-minus-fill::before { content: "\f4b9"; } +.bi-patch-minus::before { content: "\f4ba"; } +.bi-patch-plus-fill::before { content: "\f4bb"; } +.bi-patch-plus::before { content: "\f4bc"; } +.bi-patch-question-fill::before { content: "\f4bd"; } +.bi-patch-question::before { content: "\f4be"; } +.bi-pause-btn-fill::before { content: "\f4bf"; } +.bi-pause-btn::before { content: "\f4c0"; } +.bi-pause-circle-fill::before { content: "\f4c1"; } +.bi-pause-circle::before { content: "\f4c2"; } +.bi-pause-fill::before { content: "\f4c3"; } +.bi-pause::before { content: "\f4c4"; } +.bi-peace-fill::before { content: "\f4c5"; } +.bi-peace::before { content: "\f4c6"; } +.bi-pen-fill::before { content: "\f4c7"; } +.bi-pen::before { content: "\f4c8"; } +.bi-pencil-fill::before { content: "\f4c9"; } +.bi-pencil-square::before { content: "\f4ca"; } +.bi-pencil::before { content: "\f4cb"; } +.bi-pentagon-fill::before { content: "\f4cc"; } +.bi-pentagon-half::before { content: "\f4cd"; } +.bi-pentagon::before { content: "\f4ce"; } +.bi-people-fill::before { content: "\f4cf"; } +.bi-people::before { content: "\f4d0"; } +.bi-percent::before { content: "\f4d1"; } +.bi-person-badge-fill::before { content: "\f4d2"; } +.bi-person-badge::before { content: "\f4d3"; } +.bi-person-bounding-box::before { content: "\f4d4"; } +.bi-person-check-fill::before { content: "\f4d5"; } +.bi-person-check::before { content: "\f4d6"; } +.bi-person-circle::before { content: "\f4d7"; } +.bi-person-dash-fill::before { content: "\f4d8"; } +.bi-person-dash::before { content: "\f4d9"; } +.bi-person-fill::before { content: "\f4da"; } +.bi-person-lines-fill::before { content: "\f4db"; } +.bi-person-plus-fill::before { content: "\f4dc"; } +.bi-person-plus::before { content: "\f4dd"; } +.bi-person-square::before { content: "\f4de"; } +.bi-person-x-fill::before { content: "\f4df"; } +.bi-person-x::before { content: "\f4e0"; } +.bi-person::before { content: "\f4e1"; } +.bi-phone-fill::before { content: "\f4e2"; } +.bi-phone-landscape-fill::before { content: "\f4e3"; } +.bi-phone-landscape::before { content: "\f4e4"; } +.bi-phone-vibrate-fill::before { content: "\f4e5"; } +.bi-phone-vibrate::before { content: "\f4e6"; } +.bi-phone::before { content: "\f4e7"; } +.bi-pie-chart-fill::before { content: "\f4e8"; } +.bi-pie-chart::before { content: "\f4e9"; } +.bi-pin-angle-fill::before { content: "\f4ea"; } +.bi-pin-angle::before { content: "\f4eb"; } +.bi-pin-fill::before { content: "\f4ec"; } +.bi-pin::before { content: "\f4ed"; } +.bi-pip-fill::before { content: "\f4ee"; } +.bi-pip::before { content: "\f4ef"; } +.bi-play-btn-fill::before { content: "\f4f0"; } +.bi-play-btn::before { content: "\f4f1"; } +.bi-play-circle-fill::before { content: "\f4f2"; } +.bi-play-circle::before { content: "\f4f3"; } +.bi-play-fill::before { content: "\f4f4"; } +.bi-play::before { content: "\f4f5"; } +.bi-plug-fill::before { content: "\f4f6"; } +.bi-plug::before { content: "\f4f7"; } +.bi-plus-circle-dotted::before { content: "\f4f8"; } +.bi-plus-circle-fill::before { content: "\f4f9"; } +.bi-plus-circle::before { content: "\f4fa"; } +.bi-plus-square-dotted::before { content: "\f4fb"; } +.bi-plus-square-fill::before { content: "\f4fc"; } +.bi-plus-square::before { content: "\f4fd"; } +.bi-plus::before { content: "\f4fe"; } +.bi-power::before { content: "\f4ff"; } +.bi-printer-fill::before { content: "\f500"; } +.bi-printer::before { content: "\f501"; } +.bi-puzzle-fill::before { content: "\f502"; } +.bi-puzzle::before { content: "\f503"; } +.bi-question-circle-fill::before { content: "\f504"; } +.bi-question-circle::before { content: "\f505"; } +.bi-question-diamond-fill::before { content: "\f506"; } +.bi-question-diamond::before { content: "\f507"; } +.bi-question-octagon-fill::before { content: "\f508"; } +.bi-question-octagon::before { content: "\f509"; } +.bi-question-square-fill::before { content: "\f50a"; } +.bi-question-square::before { content: "\f50b"; } +.bi-question::before { content: "\f50c"; } +.bi-rainbow::before { content: "\f50d"; } +.bi-receipt-cutoff::before { content: "\f50e"; } +.bi-receipt::before { content: "\f50f"; } +.bi-reception-0::before { content: "\f510"; } +.bi-reception-1::before { content: "\f511"; } +.bi-reception-2::before { content: "\f512"; } +.bi-reception-3::before { content: "\f513"; } +.bi-reception-4::before { content: "\f514"; } +.bi-record-btn-fill::before { content: "\f515"; } +.bi-record-btn::before { content: "\f516"; } +.bi-record-circle-fill::before { content: "\f517"; } +.bi-record-circle::before { content: "\f518"; } +.bi-record-fill::before { content: "\f519"; } +.bi-record::before { content: "\f51a"; } +.bi-record2-fill::before { content: "\f51b"; } +.bi-record2::before { content: "\f51c"; } +.bi-reply-all-fill::before { content: "\f51d"; } +.bi-reply-all::before { content: "\f51e"; } +.bi-reply-fill::before { content: "\f51f"; } +.bi-reply::before { content: "\f520"; } +.bi-rss-fill::before { content: "\f521"; } +.bi-rss::before { content: "\f522"; } +.bi-rulers::before { content: "\f523"; } +.bi-save-fill::before { content: "\f524"; } +.bi-save::before { content: "\f525"; } +.bi-save2-fill::before { content: "\f526"; } +.bi-save2::before { content: "\f527"; } +.bi-scissors::before { content: "\f528"; } +.bi-screwdriver::before { content: "\f529"; } +.bi-search::before { content: "\f52a"; } +.bi-segmented-nav::before { content: "\f52b"; } +.bi-server::before { content: "\f52c"; } +.bi-share-fill::before { content: "\f52d"; } +.bi-share::before { content: "\f52e"; } +.bi-shield-check::before { content: "\f52f"; } +.bi-shield-exclamation::before { content: "\f530"; } +.bi-shield-fill-check::before { content: "\f531"; } +.bi-shield-fill-exclamation::before { content: "\f532"; } +.bi-shield-fill-minus::before { content: "\f533"; } +.bi-shield-fill-plus::before { content: "\f534"; } +.bi-shield-fill-x::before { content: "\f535"; } +.bi-shield-fill::before { content: "\f536"; } +.bi-shield-lock-fill::before { content: "\f537"; } +.bi-shield-lock::before { content: "\f538"; } +.bi-shield-minus::before { content: "\f539"; } +.bi-shield-plus::before { content: "\f53a"; } +.bi-shield-shaded::before { content: "\f53b"; } +.bi-shield-slash-fill::before { content: "\f53c"; } +.bi-shield-slash::before { content: "\f53d"; } +.bi-shield-x::before { content: "\f53e"; } +.bi-shield::before { content: "\f53f"; } +.bi-shift-fill::before { content: "\f540"; } +.bi-shift::before { content: "\f541"; } +.bi-shop-window::before { content: "\f542"; } +.bi-shop::before { content: "\f543"; } +.bi-shuffle::before { content: "\f544"; } +.bi-signpost-2-fill::before { content: "\f545"; } +.bi-signpost-2::before { content: "\f546"; } +.bi-signpost-fill::before { content: "\f547"; } +.bi-signpost-split-fill::before { content: "\f548"; } +.bi-signpost-split::before { content: "\f549"; } +.bi-signpost::before { content: "\f54a"; } +.bi-sim-fill::before { content: "\f54b"; } +.bi-sim::before { content: "\f54c"; } +.bi-skip-backward-btn-fill::before { content: "\f54d"; } +.bi-skip-backward-btn::before { content: "\f54e"; } +.bi-skip-backward-circle-fill::before { content: "\f54f"; } +.bi-skip-backward-circle::before { content: "\f550"; } +.bi-skip-backward-fill::before { content: "\f551"; } +.bi-skip-backward::before { content: "\f552"; } +.bi-skip-end-btn-fill::before { content: "\f553"; } +.bi-skip-end-btn::before { content: "\f554"; } +.bi-skip-end-circle-fill::before { content: "\f555"; } +.bi-skip-end-circle::before { content: "\f556"; } +.bi-skip-end-fill::before { content: "\f557"; } +.bi-skip-end::before { content: "\f558"; } +.bi-skip-forward-btn-fill::before { content: "\f559"; } +.bi-skip-forward-btn::before { content: "\f55a"; } +.bi-skip-forward-circle-fill::before { content: "\f55b"; } +.bi-skip-forward-circle::before { content: "\f55c"; } +.bi-skip-forward-fill::before { content: "\f55d"; } +.bi-skip-forward::before { content: "\f55e"; } +.bi-skip-start-btn-fill::before { content: "\f55f"; } +.bi-skip-start-btn::before { content: "\f560"; } +.bi-skip-start-circle-fill::before { content: "\f561"; } +.bi-skip-start-circle::before { content: "\f562"; } +.bi-skip-start-fill::before { content: "\f563"; } +.bi-skip-start::before { content: "\f564"; } +.bi-slack::before { content: "\f565"; } +.bi-slash-circle-fill::before { content: "\f566"; } +.bi-slash-circle::before { content: "\f567"; } +.bi-slash-square-fill::before { content: "\f568"; } +.bi-slash-square::before { content: "\f569"; } +.bi-slash::before { content: "\f56a"; } +.bi-sliders::before { content: "\f56b"; } +.bi-smartwatch::before { content: "\f56c"; } +.bi-snow::before { content: "\f56d"; } +.bi-snow2::before { content: "\f56e"; } +.bi-snow3::before { content: "\f56f"; } +.bi-sort-alpha-down-alt::before { content: "\f570"; } +.bi-sort-alpha-down::before { content: "\f571"; } +.bi-sort-alpha-up-alt::before { content: "\f572"; } +.bi-sort-alpha-up::before { content: "\f573"; } +.bi-sort-down-alt::before { content: "\f574"; } +.bi-sort-down::before { content: "\f575"; } +.bi-sort-numeric-down-alt::before { content: "\f576"; } +.bi-sort-numeric-down::before { content: "\f577"; } +.bi-sort-numeric-up-alt::before { content: "\f578"; } +.bi-sort-numeric-up::before { content: "\f579"; } +.bi-sort-up-alt::before { content: "\f57a"; } +.bi-sort-up::before { content: "\f57b"; } +.bi-soundwave::before { content: "\f57c"; } +.bi-speaker-fill::before { content: "\f57d"; } +.bi-speaker::before { content: "\f57e"; } +.bi-speedometer::before { content: "\f57f"; } +.bi-speedometer2::before { content: "\f580"; } +.bi-spellcheck::before { content: "\f581"; } +.bi-square-fill::before { content: "\f582"; } +.bi-square-half::before { content: "\f583"; } +.bi-square::before { content: "\f584"; } +.bi-stack::before { content: "\f585"; } +.bi-star-fill::before { content: "\f586"; } +.bi-star-half::before { content: "\f587"; } +.bi-star::before { content: "\f588"; } +.bi-stars::before { content: "\f589"; } +.bi-stickies-fill::before { content: "\f58a"; } +.bi-stickies::before { content: "\f58b"; } +.bi-sticky-fill::before { content: "\f58c"; } +.bi-sticky::before { content: "\f58d"; } +.bi-stop-btn-fill::before { content: "\f58e"; } +.bi-stop-btn::before { content: "\f58f"; } +.bi-stop-circle-fill::before { content: "\f590"; } +.bi-stop-circle::before { content: "\f591"; } +.bi-stop-fill::before { content: "\f592"; } +.bi-stop::before { content: "\f593"; } +.bi-stoplights-fill::before { content: "\f594"; } +.bi-stoplights::before { content: "\f595"; } +.bi-stopwatch-fill::before { content: "\f596"; } +.bi-stopwatch::before { content: "\f597"; } +.bi-subtract::before { content: "\f598"; } +.bi-suit-club-fill::before { content: "\f599"; } +.bi-suit-club::before { content: "\f59a"; } +.bi-suit-diamond-fill::before { content: "\f59b"; } +.bi-suit-diamond::before { content: "\f59c"; } +.bi-suit-heart-fill::before { content: "\f59d"; } +.bi-suit-heart::before { content: "\f59e"; } +.bi-suit-spade-fill::before { content: "\f59f"; } +.bi-suit-spade::before { content: "\f5a0"; } +.bi-sun-fill::before { content: "\f5a1"; } +.bi-sun::before { content: "\f5a2"; } +.bi-sunglasses::before { content: "\f5a3"; } +.bi-sunrise-fill::before { content: "\f5a4"; } +.bi-sunrise::before { content: "\f5a5"; } +.bi-sunset-fill::before { content: "\f5a6"; } +.bi-sunset::before { content: "\f5a7"; } +.bi-symmetry-horizontal::before { content: "\f5a8"; } +.bi-symmetry-vertical::before { content: "\f5a9"; } +.bi-table::before { content: "\f5aa"; } +.bi-tablet-fill::before { content: "\f5ab"; } +.bi-tablet-landscape-fill::before { content: "\f5ac"; } +.bi-tablet-landscape::before { content: "\f5ad"; } +.bi-tablet::before { content: "\f5ae"; } +.bi-tag-fill::before { content: "\f5af"; } +.bi-tag::before { content: "\f5b0"; } +.bi-tags-fill::before { content: "\f5b1"; } +.bi-tags::before { content: "\f5b2"; } +.bi-telegram::before { content: "\f5b3"; } +.bi-telephone-fill::before { content: "\f5b4"; } +.bi-telephone-forward-fill::before { content: "\f5b5"; } +.bi-telephone-forward::before { content: "\f5b6"; } +.bi-telephone-inbound-fill::before { content: "\f5b7"; } +.bi-telephone-inbound::before { content: "\f5b8"; } +.bi-telephone-minus-fill::before { content: "\f5b9"; } +.bi-telephone-minus::before { content: "\f5ba"; } +.bi-telephone-outbound-fill::before { content: "\f5bb"; } +.bi-telephone-outbound::before { content: "\f5bc"; } +.bi-telephone-plus-fill::before { content: "\f5bd"; } +.bi-telephone-plus::before { content: "\f5be"; } +.bi-telephone-x-fill::before { content: "\f5bf"; } +.bi-telephone-x::before { content: "\f5c0"; } +.bi-telephone::before { content: "\f5c1"; } +.bi-terminal-fill::before { content: "\f5c2"; } +.bi-terminal::before { content: "\f5c3"; } +.bi-text-center::before { content: "\f5c4"; } +.bi-text-indent-left::before { content: "\f5c5"; } +.bi-text-indent-right::before { content: "\f5c6"; } +.bi-text-left::before { content: "\f5c7"; } +.bi-text-paragraph::before { content: "\f5c8"; } +.bi-text-right::before { content: "\f5c9"; } +.bi-textarea-resize::before { content: "\f5ca"; } +.bi-textarea-t::before { content: "\f5cb"; } +.bi-textarea::before { content: "\f5cc"; } +.bi-thermometer-half::before { content: "\f5cd"; } +.bi-thermometer-high::before { content: "\f5ce"; } +.bi-thermometer-low::before { content: "\f5cf"; } +.bi-thermometer-snow::before { content: "\f5d0"; } +.bi-thermometer-sun::before { content: "\f5d1"; } +.bi-thermometer::before { content: "\f5d2"; } +.bi-three-dots-vertical::before { content: "\f5d3"; } +.bi-three-dots::before { content: "\f5d4"; } +.bi-toggle-off::before { content: "\f5d5"; } +.bi-toggle-on::before { content: "\f5d6"; } +.bi-toggle2-off::before { content: "\f5d7"; } +.bi-toggle2-on::before { content: "\f5d8"; } +.bi-toggles::before { content: "\f5d9"; } +.bi-toggles2::before { content: "\f5da"; } +.bi-tools::before { content: "\f5db"; } +.bi-tornado::before { content: "\f5dc"; } +.bi-trash-fill::before { content: "\f5dd"; } +.bi-trash::before { content: "\f5de"; } +.bi-trash2-fill::before { content: "\f5df"; } +.bi-trash2::before { content: "\f5e0"; } +.bi-tree-fill::before { content: "\f5e1"; } +.bi-tree::before { content: "\f5e2"; } +.bi-triangle-fill::before { content: "\f5e3"; } +.bi-triangle-half::before { content: "\f5e4"; } +.bi-triangle::before { content: "\f5e5"; } +.bi-trophy-fill::before { content: "\f5e6"; } +.bi-trophy::before { content: "\f5e7"; } +.bi-tropical-storm::before { content: "\f5e8"; } +.bi-truck-flatbed::before { content: "\f5e9"; } +.bi-truck::before { content: "\f5ea"; } +.bi-tsunami::before { content: "\f5eb"; } +.bi-tv-fill::before { content: "\f5ec"; } +.bi-tv::before { content: "\f5ed"; } +.bi-twitch::before { content: "\f5ee"; } +.bi-twitter::before { content: "\f5ef"; } +.bi-type-bold::before { content: "\f5f0"; } +.bi-type-h1::before { content: "\f5f1"; } +.bi-type-h2::before { content: "\f5f2"; } +.bi-type-h3::before { content: "\f5f3"; } +.bi-type-italic::before { content: "\f5f4"; } +.bi-type-strikethrough::before { content: "\f5f5"; } +.bi-type-underline::before { content: "\f5f6"; } +.bi-type::before { content: "\f5f7"; } +.bi-ui-checks-grid::before { content: "\f5f8"; } +.bi-ui-checks::before { content: "\f5f9"; } +.bi-ui-radios-grid::before { content: "\f5fa"; } +.bi-ui-radios::before { content: "\f5fb"; } +.bi-umbrella-fill::before { content: "\f5fc"; } +.bi-umbrella::before { content: "\f5fd"; } +.bi-union::before { content: "\f5fe"; } +.bi-unlock-fill::before { content: "\f5ff"; } +.bi-unlock::before { content: "\f600"; } +.bi-upc-scan::before { content: "\f601"; } +.bi-upc::before { content: "\f602"; } +.bi-upload::before { content: "\f603"; } +.bi-vector-pen::before { content: "\f604"; } +.bi-view-list::before { content: "\f605"; } +.bi-view-stacked::before { content: "\f606"; } +.bi-vinyl-fill::before { content: "\f607"; } +.bi-vinyl::before { content: "\f608"; } +.bi-voicemail::before { content: "\f609"; } +.bi-volume-down-fill::before { content: "\f60a"; } +.bi-volume-down::before { content: "\f60b"; } +.bi-volume-mute-fill::before { content: "\f60c"; } +.bi-volume-mute::before { content: "\f60d"; } +.bi-volume-off-fill::before { content: "\f60e"; } +.bi-volume-off::before { content: "\f60f"; } +.bi-volume-up-fill::before { content: "\f610"; } +.bi-volume-up::before { content: "\f611"; } +.bi-vr::before { content: "\f612"; } +.bi-wallet-fill::before { content: "\f613"; } +.bi-wallet::before { content: "\f614"; } +.bi-wallet2::before { content: "\f615"; } +.bi-watch::before { content: "\f616"; } +.bi-water::before { content: "\f617"; } +.bi-whatsapp::before { content: "\f618"; } +.bi-wifi-1::before { content: "\f619"; } +.bi-wifi-2::before { content: "\f61a"; } +.bi-wifi-off::before { content: "\f61b"; } +.bi-wifi::before { content: "\f61c"; } +.bi-wind::before { content: "\f61d"; } +.bi-window-dock::before { content: "\f61e"; } +.bi-window-sidebar::before { content: "\f61f"; } +.bi-window::before { content: "\f620"; } +.bi-wrench::before { content: "\f621"; } +.bi-x-circle-fill::before { content: "\f622"; } +.bi-x-circle::before { content: "\f623"; } +.bi-x-diamond-fill::before { content: "\f624"; } +.bi-x-diamond::before { content: "\f625"; } +.bi-x-octagon-fill::before { content: "\f626"; } +.bi-x-octagon::before { content: "\f627"; } +.bi-x-square-fill::before { content: "\f628"; } +.bi-x-square::before { content: "\f629"; } +.bi-x::before { content: "\f62a"; } +.bi-youtube::before { content: "\f62b"; } +.bi-zoom-in::before { content: "\f62c"; } +.bi-zoom-out::before { content: "\f62d"; } +.bi-bank::before { content: "\f62e"; } +.bi-bank2::before { content: "\f62f"; } +.bi-bell-slash-fill::before { content: "\f630"; } +.bi-bell-slash::before { content: "\f631"; } +.bi-cash-coin::before { content: "\f632"; } +.bi-check-lg::before { content: "\f633"; } +.bi-coin::before { content: "\f634"; } +.bi-currency-bitcoin::before { content: "\f635"; } +.bi-currency-dollar::before { content: "\f636"; } +.bi-currency-euro::before { content: "\f637"; } +.bi-currency-exchange::before { content: "\f638"; } +.bi-currency-pound::before { content: "\f639"; } +.bi-currency-yen::before { content: "\f63a"; } +.bi-dash-lg::before { content: "\f63b"; } +.bi-exclamation-lg::before { content: "\f63c"; } +.bi-file-earmark-pdf-fill::before { content: "\f63d"; } +.bi-file-earmark-pdf::before { content: "\f63e"; } +.bi-file-pdf-fill::before { content: "\f63f"; } +.bi-file-pdf::before { content: "\f640"; } +.bi-gender-ambiguous::before { content: "\f641"; } +.bi-gender-female::before { content: "\f642"; } +.bi-gender-male::before { content: "\f643"; } +.bi-gender-trans::before { content: "\f644"; } +.bi-headset-vr::before { content: "\f645"; } +.bi-info-lg::before { content: "\f646"; } +.bi-mastodon::before { content: "\f647"; } +.bi-messenger::before { content: "\f648"; } +.bi-piggy-bank-fill::before { content: "\f649"; } +.bi-piggy-bank::before { content: "\f64a"; } +.bi-pin-map-fill::before { content: "\f64b"; } +.bi-pin-map::before { content: "\f64c"; } +.bi-plus-lg::before { content: "\f64d"; } +.bi-question-lg::before { content: "\f64e"; } +.bi-recycle::before { content: "\f64f"; } +.bi-reddit::before { content: "\f650"; } +.bi-safe-fill::before { content: "\f651"; } +.bi-safe2-fill::before { content: "\f652"; } +.bi-safe2::before { content: "\f653"; } +.bi-sd-card-fill::before { content: "\f654"; } +.bi-sd-card::before { content: "\f655"; } +.bi-skype::before { content: "\f656"; } +.bi-slash-lg::before { content: "\f657"; } +.bi-translate::before { content: "\f658"; } +.bi-x-lg::before { content: "\f659"; } +.bi-safe::before { content: "\f65a"; } +.bi-apple::before { content: "\f65b"; } +.bi-microsoft::before { content: "\f65d"; } +.bi-windows::before { content: "\f65e"; } +.bi-behance::before { content: "\f65c"; } +.bi-dribbble::before { content: "\f65f"; } +.bi-line::before { content: "\f660"; } +.bi-medium::before { content: "\f661"; } +.bi-paypal::before { content: "\f662"; } +.bi-pinterest::before { content: "\f663"; } +.bi-signal::before { content: "\f664"; } +.bi-snapchat::before { content: "\f665"; } +.bi-spotify::before { content: "\f666"; } +.bi-stack-overflow::before { content: "\f667"; } +.bi-strava::before { content: "\f668"; } +.bi-wordpress::before { content: "\f669"; } +.bi-vimeo::before { content: "\f66a"; } +.bi-activity::before { content: "\f66b"; } +.bi-easel2-fill::before { content: "\f66c"; } +.bi-easel2::before { content: "\f66d"; } +.bi-easel3-fill::before { content: "\f66e"; } +.bi-easel3::before { content: "\f66f"; } +.bi-fan::before { content: "\f670"; } +.bi-fingerprint::before { content: "\f671"; } +.bi-graph-down-arrow::before { content: "\f672"; } +.bi-graph-up-arrow::before { content: "\f673"; } +.bi-hypnotize::before { content: "\f674"; } +.bi-magic::before { content: "\f675"; } +.bi-person-rolodex::before { content: "\f676"; } +.bi-person-video::before { content: "\f677"; } +.bi-person-video2::before { content: "\f678"; } +.bi-person-video3::before { content: "\f679"; } +.bi-person-workspace::before { content: "\f67a"; } +.bi-radioactive::before { content: "\f67b"; } +.bi-webcam-fill::before { content: "\f67c"; } +.bi-webcam::before { content: "\f67d"; } +.bi-yin-yang::before { content: "\f67e"; } +.bi-bandaid-fill::before { content: "\f680"; } +.bi-bandaid::before { content: "\f681"; } +.bi-bluetooth::before { content: "\f682"; } +.bi-body-text::before { content: "\f683"; } +.bi-boombox::before { content: "\f684"; } +.bi-boxes::before { content: "\f685"; } +.bi-dpad-fill::before { content: "\f686"; } +.bi-dpad::before { content: "\f687"; } +.bi-ear-fill::before { content: "\f688"; } +.bi-ear::before { content: "\f689"; } +.bi-envelope-check-fill::before { content: "\f68b"; } +.bi-envelope-check::before { content: "\f68c"; } +.bi-envelope-dash-fill::before { content: "\f68e"; } +.bi-envelope-dash::before { content: "\f68f"; } +.bi-envelope-exclamation-fill::before { content: "\f691"; } +.bi-envelope-exclamation::before { content: "\f692"; } +.bi-envelope-plus-fill::before { content: "\f693"; } +.bi-envelope-plus::before { content: "\f694"; } +.bi-envelope-slash-fill::before { content: "\f696"; } +.bi-envelope-slash::before { content: "\f697"; } +.bi-envelope-x-fill::before { content: "\f699"; } +.bi-envelope-x::before { content: "\f69a"; } +.bi-explicit-fill::before { content: "\f69b"; } +.bi-explicit::before { content: "\f69c"; } +.bi-git::before { content: "\f69d"; } +.bi-infinity::before { content: "\f69e"; } +.bi-list-columns-reverse::before { content: "\f69f"; } +.bi-list-columns::before { content: "\f6a0"; } +.bi-meta::before { content: "\f6a1"; } +.bi-nintendo-switch::before { content: "\f6a4"; } +.bi-pc-display-horizontal::before { content: "\f6a5"; } +.bi-pc-display::before { content: "\f6a6"; } +.bi-pc-horizontal::before { content: "\f6a7"; } +.bi-pc::before { content: "\f6a8"; } +.bi-playstation::before { content: "\f6a9"; } +.bi-plus-slash-minus::before { content: "\f6aa"; } +.bi-projector-fill::before { content: "\f6ab"; } +.bi-projector::before { content: "\f6ac"; } +.bi-qr-code-scan::before { content: "\f6ad"; } +.bi-qr-code::before { content: "\f6ae"; } +.bi-quora::before { content: "\f6af"; } +.bi-quote::before { content: "\f6b0"; } +.bi-robot::before { content: "\f6b1"; } +.bi-send-check-fill::before { content: "\f6b2"; } +.bi-send-check::before { content: "\f6b3"; } +.bi-send-dash-fill::before { content: "\f6b4"; } +.bi-send-dash::before { content: "\f6b5"; } +.bi-send-exclamation-fill::before { content: "\f6b7"; } +.bi-send-exclamation::before { content: "\f6b8"; } +.bi-send-fill::before { content: "\f6b9"; } +.bi-send-plus-fill::before { content: "\f6ba"; } +.bi-send-plus::before { content: "\f6bb"; } +.bi-send-slash-fill::before { content: "\f6bc"; } +.bi-send-slash::before { content: "\f6bd"; } +.bi-send-x-fill::before { content: "\f6be"; } +.bi-send-x::before { content: "\f6bf"; } +.bi-send::before { content: "\f6c0"; } +.bi-steam::before { content: "\f6c1"; } +.bi-terminal-dash::before { content: "\f6c3"; } +.bi-terminal-plus::before { content: "\f6c4"; } +.bi-terminal-split::before { content: "\f6c5"; } +.bi-ticket-detailed-fill::before { content: "\f6c6"; } +.bi-ticket-detailed::before { content: "\f6c7"; } +.bi-ticket-fill::before { content: "\f6c8"; } +.bi-ticket-perforated-fill::before { content: "\f6c9"; } +.bi-ticket-perforated::before { content: "\f6ca"; } +.bi-ticket::before { content: "\f6cb"; } +.bi-tiktok::before { content: "\f6cc"; } +.bi-window-dash::before { content: "\f6cd"; } +.bi-window-desktop::before { content: "\f6ce"; } +.bi-window-fullscreen::before { content: "\f6cf"; } +.bi-window-plus::before { content: "\f6d0"; } +.bi-window-split::before { content: "\f6d1"; } +.bi-window-stack::before { content: "\f6d2"; } +.bi-window-x::before { content: "\f6d3"; } +.bi-xbox::before { content: "\f6d4"; } +.bi-ethernet::before { content: "\f6d5"; } +.bi-hdmi-fill::before { content: "\f6d6"; } +.bi-hdmi::before { content: "\f6d7"; } +.bi-usb-c-fill::before { content: "\f6d8"; } +.bi-usb-c::before { content: "\f6d9"; } +.bi-usb-fill::before { content: "\f6da"; } +.bi-usb-plug-fill::before { content: "\f6db"; } +.bi-usb-plug::before { content: "\f6dc"; } +.bi-usb-symbol::before { content: "\f6dd"; } +.bi-usb::before { content: "\f6de"; } +.bi-boombox-fill::before { content: "\f6df"; } +.bi-displayport::before { content: "\f6e1"; } +.bi-gpu-card::before { content: "\f6e2"; } +.bi-memory::before { content: "\f6e3"; } +.bi-modem-fill::before { content: "\f6e4"; } +.bi-modem::before { content: "\f6e5"; } +.bi-motherboard-fill::before { content: "\f6e6"; } +.bi-motherboard::before { content: "\f6e7"; } +.bi-optical-audio-fill::before { content: "\f6e8"; } +.bi-optical-audio::before { content: "\f6e9"; } +.bi-pci-card::before { content: "\f6ea"; } +.bi-router-fill::before { content: "\f6eb"; } +.bi-router::before { content: "\f6ec"; } +.bi-thunderbolt-fill::before { content: "\f6ef"; } +.bi-thunderbolt::before { content: "\f6f0"; } +.bi-usb-drive-fill::before { content: "\f6f1"; } +.bi-usb-drive::before { content: "\f6f2"; } +.bi-usb-micro-fill::before { content: "\f6f3"; } +.bi-usb-micro::before { content: "\f6f4"; } +.bi-usb-mini-fill::before { content: "\f6f5"; } +.bi-usb-mini::before { content: "\f6f6"; } +.bi-cloud-haze2::before { content: "\f6f7"; } +.bi-device-hdd-fill::before { content: "\f6f8"; } +.bi-device-hdd::before { content: "\f6f9"; } +.bi-device-ssd-fill::before { content: "\f6fa"; } +.bi-device-ssd::before { content: "\f6fb"; } +.bi-displayport-fill::before { content: "\f6fc"; } +.bi-mortarboard-fill::before { content: "\f6fd"; } +.bi-mortarboard::before { content: "\f6fe"; } +.bi-terminal-x::before { content: "\f6ff"; } +.bi-arrow-through-heart-fill::before { content: "\f700"; } +.bi-arrow-through-heart::before { content: "\f701"; } +.bi-badge-sd-fill::before { content: "\f702"; } +.bi-badge-sd::before { content: "\f703"; } +.bi-bag-heart-fill::before { content: "\f704"; } +.bi-bag-heart::before { content: "\f705"; } +.bi-balloon-fill::before { content: "\f706"; } +.bi-balloon-heart-fill::before { content: "\f707"; } +.bi-balloon-heart::before { content: "\f708"; } +.bi-balloon::before { content: "\f709"; } +.bi-box2-fill::before { content: "\f70a"; } +.bi-box2-heart-fill::before { content: "\f70b"; } +.bi-box2-heart::before { content: "\f70c"; } +.bi-box2::before { content: "\f70d"; } +.bi-braces-asterisk::before { content: "\f70e"; } +.bi-calendar-heart-fill::before { content: "\f70f"; } +.bi-calendar-heart::before { content: "\f710"; } +.bi-calendar2-heart-fill::before { content: "\f711"; } +.bi-calendar2-heart::before { content: "\f712"; } +.bi-chat-heart-fill::before { content: "\f713"; } +.bi-chat-heart::before { content: "\f714"; } +.bi-chat-left-heart-fill::before { content: "\f715"; } +.bi-chat-left-heart::before { content: "\f716"; } +.bi-chat-right-heart-fill::before { content: "\f717"; } +.bi-chat-right-heart::before { content: "\f718"; } +.bi-chat-square-heart-fill::before { content: "\f719"; } +.bi-chat-square-heart::before { content: "\f71a"; } +.bi-clipboard-check-fill::before { content: "\f71b"; } +.bi-clipboard-data-fill::before { content: "\f71c"; } +.bi-clipboard-fill::before { content: "\f71d"; } +.bi-clipboard-heart-fill::before { content: "\f71e"; } +.bi-clipboard-heart::before { content: "\f71f"; } +.bi-clipboard-minus-fill::before { content: "\f720"; } +.bi-clipboard-plus-fill::before { content: "\f721"; } +.bi-clipboard-pulse::before { content: "\f722"; } +.bi-clipboard-x-fill::before { content: "\f723"; } +.bi-clipboard2-check-fill::before { content: "\f724"; } +.bi-clipboard2-check::before { content: "\f725"; } +.bi-clipboard2-data-fill::before { content: "\f726"; } +.bi-clipboard2-data::before { content: "\f727"; } +.bi-clipboard2-fill::before { content: "\f728"; } +.bi-clipboard2-heart-fill::before { content: "\f729"; } +.bi-clipboard2-heart::before { content: "\f72a"; } +.bi-clipboard2-minus-fill::before { content: "\f72b"; } +.bi-clipboard2-minus::before { content: "\f72c"; } +.bi-clipboard2-plus-fill::before { content: "\f72d"; } +.bi-clipboard2-plus::before { content: "\f72e"; } +.bi-clipboard2-pulse-fill::before { content: "\f72f"; } +.bi-clipboard2-pulse::before { content: "\f730"; } +.bi-clipboard2-x-fill::before { content: "\f731"; } +.bi-clipboard2-x::before { content: "\f732"; } +.bi-clipboard2::before { content: "\f733"; } +.bi-emoji-kiss-fill::before { content: "\f734"; } +.bi-emoji-kiss::before { content: "\f735"; } +.bi-envelope-heart-fill::before { content: "\f736"; } +.bi-envelope-heart::before { content: "\f737"; } +.bi-envelope-open-heart-fill::before { content: "\f738"; } +.bi-envelope-open-heart::before { content: "\f739"; } +.bi-envelope-paper-fill::before { content: "\f73a"; } +.bi-envelope-paper-heart-fill::before { content: "\f73b"; } +.bi-envelope-paper-heart::before { content: "\f73c"; } +.bi-envelope-paper::before { content: "\f73d"; } +.bi-filetype-aac::before { content: "\f73e"; } +.bi-filetype-ai::before { content: "\f73f"; } +.bi-filetype-bmp::before { content: "\f740"; } +.bi-filetype-cs::before { content: "\f741"; } +.bi-filetype-css::before { content: "\f742"; } +.bi-filetype-csv::before { content: "\f743"; } +.bi-filetype-doc::before { content: "\f744"; } +.bi-filetype-docx::before { content: "\f745"; } +.bi-filetype-exe::before { content: "\f746"; } +.bi-filetype-gif::before { content: "\f747"; } +.bi-filetype-heic::before { content: "\f748"; } +.bi-filetype-html::before { content: "\f749"; } +.bi-filetype-java::before { content: "\f74a"; } +.bi-filetype-jpg::before { content: "\f74b"; } +.bi-filetype-js::before { content: "\f74c"; } +.bi-filetype-jsx::before { content: "\f74d"; } +.bi-filetype-key::before { content: "\f74e"; } +.bi-filetype-m4p::before { content: "\f74f"; } +.bi-filetype-md::before { content: "\f750"; } +.bi-filetype-mdx::before { content: "\f751"; } +.bi-filetype-mov::before { content: "\f752"; } +.bi-filetype-mp3::before { content: "\f753"; } +.bi-filetype-mp4::before { content: "\f754"; } +.bi-filetype-otf::before { content: "\f755"; } +.bi-filetype-pdf::before { content: "\f756"; } +.bi-filetype-php::before { content: "\f757"; } +.bi-filetype-png::before { content: "\f758"; } +.bi-filetype-ppt::before { content: "\f75a"; } +.bi-filetype-psd::before { content: "\f75b"; } +.bi-filetype-py::before { content: "\f75c"; } +.bi-filetype-raw::before { content: "\f75d"; } +.bi-filetype-rb::before { content: "\f75e"; } +.bi-filetype-sass::before { content: "\f75f"; } +.bi-filetype-scss::before { content: "\f760"; } +.bi-filetype-sh::before { content: "\f761"; } +.bi-filetype-svg::before { content: "\f762"; } +.bi-filetype-tiff::before { content: "\f763"; } +.bi-filetype-tsx::before { content: "\f764"; } +.bi-filetype-ttf::before { content: "\f765"; } +.bi-filetype-txt::before { content: "\f766"; } +.bi-filetype-wav::before { content: "\f767"; } +.bi-filetype-woff::before { content: "\f768"; } +.bi-filetype-xls::before { content: "\f76a"; } +.bi-filetype-xml::before { content: "\f76b"; } +.bi-filetype-yml::before { content: "\f76c"; } +.bi-heart-arrow::before { content: "\f76d"; } +.bi-heart-pulse-fill::before { content: "\f76e"; } +.bi-heart-pulse::before { content: "\f76f"; } +.bi-heartbreak-fill::before { content: "\f770"; } +.bi-heartbreak::before { content: "\f771"; } +.bi-hearts::before { content: "\f772"; } +.bi-hospital-fill::before { content: "\f773"; } +.bi-hospital::before { content: "\f774"; } +.bi-house-heart-fill::before { content: "\f775"; } +.bi-house-heart::before { content: "\f776"; } +.bi-incognito::before { content: "\f777"; } +.bi-magnet-fill::before { content: "\f778"; } +.bi-magnet::before { content: "\f779"; } +.bi-person-heart::before { content: "\f77a"; } +.bi-person-hearts::before { content: "\f77b"; } +.bi-phone-flip::before { content: "\f77c"; } +.bi-plugin::before { content: "\f77d"; } +.bi-postage-fill::before { content: "\f77e"; } +.bi-postage-heart-fill::before { content: "\f77f"; } +.bi-postage-heart::before { content: "\f780"; } +.bi-postage::before { content: "\f781"; } +.bi-postcard-fill::before { content: "\f782"; } +.bi-postcard-heart-fill::before { content: "\f783"; } +.bi-postcard-heart::before { content: "\f784"; } +.bi-postcard::before { content: "\f785"; } +.bi-search-heart-fill::before { content: "\f786"; } +.bi-search-heart::before { content: "\f787"; } +.bi-sliders2-vertical::before { content: "\f788"; } +.bi-sliders2::before { content: "\f789"; } +.bi-trash3-fill::before { content: "\f78a"; } +.bi-trash3::before { content: "\f78b"; } +.bi-valentine::before { content: "\f78c"; } +.bi-valentine2::before { content: "\f78d"; } +.bi-wrench-adjustable-circle-fill::before { content: "\f78e"; } +.bi-wrench-adjustable-circle::before { content: "\f78f"; } +.bi-wrench-adjustable::before { content: "\f790"; } +.bi-filetype-json::before { content: "\f791"; } +.bi-filetype-pptx::before { content: "\f792"; } +.bi-filetype-xlsx::before { content: "\f793"; } +.bi-1-circle-fill::before { content: "\f796"; } +.bi-1-circle::before { content: "\f797"; } +.bi-1-square-fill::before { content: "\f798"; } +.bi-1-square::before { content: "\f799"; } +.bi-2-circle-fill::before { content: "\f79c"; } +.bi-2-circle::before { content: "\f79d"; } +.bi-2-square-fill::before { content: "\f79e"; } +.bi-2-square::before { content: "\f79f"; } +.bi-3-circle-fill::before { content: "\f7a2"; } +.bi-3-circle::before { content: "\f7a3"; } +.bi-3-square-fill::before { content: "\f7a4"; } +.bi-3-square::before { content: "\f7a5"; } +.bi-4-circle-fill::before { content: "\f7a8"; } +.bi-4-circle::before { content: "\f7a9"; } +.bi-4-square-fill::before { content: "\f7aa"; } +.bi-4-square::before { content: "\f7ab"; } +.bi-5-circle-fill::before { content: "\f7ae"; } +.bi-5-circle::before { content: "\f7af"; } +.bi-5-square-fill::before { content: "\f7b0"; } +.bi-5-square::before { content: "\f7b1"; } +.bi-6-circle-fill::before { content: "\f7b4"; } +.bi-6-circle::before { content: "\f7b5"; } +.bi-6-square-fill::before { content: "\f7b6"; } +.bi-6-square::before { content: "\f7b7"; } +.bi-7-circle-fill::before { content: "\f7ba"; } +.bi-7-circle::before { content: "\f7bb"; } +.bi-7-square-fill::before { content: "\f7bc"; } +.bi-7-square::before { content: "\f7bd"; } +.bi-8-circle-fill::before { content: "\f7c0"; } +.bi-8-circle::before { content: "\f7c1"; } +.bi-8-square-fill::before { content: "\f7c2"; } +.bi-8-square::before { content: "\f7c3"; } +.bi-9-circle-fill::before { content: "\f7c6"; } +.bi-9-circle::before { content: "\f7c7"; } +.bi-9-square-fill::before { content: "\f7c8"; } +.bi-9-square::before { content: "\f7c9"; } +.bi-airplane-engines-fill::before { content: "\f7ca"; } +.bi-airplane-engines::before { content: "\f7cb"; } +.bi-airplane-fill::before { content: "\f7cc"; } +.bi-airplane::before { content: "\f7cd"; } +.bi-alexa::before { content: "\f7ce"; } +.bi-alipay::before { content: "\f7cf"; } +.bi-android::before { content: "\f7d0"; } +.bi-android2::before { content: "\f7d1"; } +.bi-box-fill::before { content: "\f7d2"; } +.bi-box-seam-fill::before { content: "\f7d3"; } +.bi-browser-chrome::before { content: "\f7d4"; } +.bi-browser-edge::before { content: "\f7d5"; } +.bi-browser-firefox::before { content: "\f7d6"; } +.bi-browser-safari::before { content: "\f7d7"; } +.bi-c-circle-fill::before { content: "\f7da"; } +.bi-c-circle::before { content: "\f7db"; } +.bi-c-square-fill::before { content: "\f7dc"; } +.bi-c-square::before { content: "\f7dd"; } +.bi-capsule-pill::before { content: "\f7de"; } +.bi-capsule::before { content: "\f7df"; } +.bi-car-front-fill::before { content: "\f7e0"; } +.bi-car-front::before { content: "\f7e1"; } +.bi-cassette-fill::before { content: "\f7e2"; } +.bi-cassette::before { content: "\f7e3"; } +.bi-cc-circle-fill::before { content: "\f7e6"; } +.bi-cc-circle::before { content: "\f7e7"; } +.bi-cc-square-fill::before { content: "\f7e8"; } +.bi-cc-square::before { content: "\f7e9"; } +.bi-cup-hot-fill::before { content: "\f7ea"; } +.bi-cup-hot::before { content: "\f7eb"; } +.bi-currency-rupee::before { content: "\f7ec"; } +.bi-dropbox::before { content: "\f7ed"; } +.bi-escape::before { content: "\f7ee"; } +.bi-fast-forward-btn-fill::before { content: "\f7ef"; } +.bi-fast-forward-btn::before { content: "\f7f0"; } +.bi-fast-forward-circle-fill::before { content: "\f7f1"; } +.bi-fast-forward-circle::before { content: "\f7f2"; } +.bi-fast-forward-fill::before { content: "\f7f3"; } +.bi-fast-forward::before { content: "\f7f4"; } +.bi-filetype-sql::before { content: "\f7f5"; } +.bi-fire::before { content: "\f7f6"; } +.bi-google-play::before { content: "\f7f7"; } +.bi-h-circle-fill::before { content: "\f7fa"; } +.bi-h-circle::before { content: "\f7fb"; } +.bi-h-square-fill::before { content: "\f7fc"; } +.bi-h-square::before { content: "\f7fd"; } +.bi-indent::before { content: "\f7fe"; } +.bi-lungs-fill::before { content: "\f7ff"; } +.bi-lungs::before { content: "\f800"; } +.bi-microsoft-teams::before { content: "\f801"; } +.bi-p-circle-fill::before { content: "\f804"; } +.bi-p-circle::before { content: "\f805"; } +.bi-p-square-fill::before { content: "\f806"; } +.bi-p-square::before { content: "\f807"; } +.bi-pass-fill::before { content: "\f808"; } +.bi-pass::before { content: "\f809"; } +.bi-prescription::before { content: "\f80a"; } +.bi-prescription2::before { content: "\f80b"; } +.bi-r-circle-fill::before { content: "\f80e"; } +.bi-r-circle::before { content: "\f80f"; } +.bi-r-square-fill::before { content: "\f810"; } +.bi-r-square::before { content: "\f811"; } +.bi-repeat-1::before { content: "\f812"; } +.bi-repeat::before { content: "\f813"; } +.bi-rewind-btn-fill::before { content: "\f814"; } +.bi-rewind-btn::before { content: "\f815"; } +.bi-rewind-circle-fill::before { content: "\f816"; } +.bi-rewind-circle::before { content: "\f817"; } +.bi-rewind-fill::before { content: "\f818"; } +.bi-rewind::before { content: "\f819"; } +.bi-train-freight-front-fill::before { content: "\f81a"; } +.bi-train-freight-front::before { content: "\f81b"; } +.bi-train-front-fill::before { content: "\f81c"; } +.bi-train-front::before { content: "\f81d"; } +.bi-train-lightrail-front-fill::before { content: "\f81e"; } +.bi-train-lightrail-front::before { content: "\f81f"; } +.bi-truck-front-fill::before { content: "\f820"; } +.bi-truck-front::before { content: "\f821"; } +.bi-ubuntu::before { content: "\f822"; } +.bi-unindent::before { content: "\f823"; } +.bi-unity::before { content: "\f824"; } +.bi-universal-access-circle::before { content: "\f825"; } +.bi-universal-access::before { content: "\f826"; } +.bi-virus::before { content: "\f827"; } +.bi-virus2::before { content: "\f828"; } +.bi-wechat::before { content: "\f829"; } +.bi-yelp::before { content: "\f82a"; } +.bi-sign-stop-fill::before { content: "\f82b"; } +.bi-sign-stop-lights-fill::before { content: "\f82c"; } +.bi-sign-stop-lights::before { content: "\f82d"; } +.bi-sign-stop::before { content: "\f82e"; } +.bi-sign-turn-left-fill::before { content: "\f82f"; } +.bi-sign-turn-left::before { content: "\f830"; } +.bi-sign-turn-right-fill::before { content: "\f831"; } +.bi-sign-turn-right::before { content: "\f832"; } +.bi-sign-turn-slight-left-fill::before { content: "\f833"; } +.bi-sign-turn-slight-left::before { content: "\f834"; } +.bi-sign-turn-slight-right-fill::before { content: "\f835"; } +.bi-sign-turn-slight-right::before { content: "\f836"; } +.bi-sign-yield-fill::before { content: "\f837"; } +.bi-sign-yield::before { content: "\f838"; } +.bi-ev-station-fill::before { content: "\f839"; } +.bi-ev-station::before { content: "\f83a"; } +.bi-fuel-pump-diesel-fill::before { content: "\f83b"; } +.bi-fuel-pump-diesel::before { content: "\f83c"; } +.bi-fuel-pump-fill::before { content: "\f83d"; } +.bi-fuel-pump::before { content: "\f83e"; } +.bi-0-circle-fill::before { content: "\f83f"; } +.bi-0-circle::before { content: "\f840"; } +.bi-0-square-fill::before { content: "\f841"; } +.bi-0-square::before { content: "\f842"; } +.bi-rocket-fill::before { content: "\f843"; } +.bi-rocket-takeoff-fill::before { content: "\f844"; } +.bi-rocket-takeoff::before { content: "\f845"; } +.bi-rocket::before { content: "\f846"; } +.bi-stripe::before { content: "\f847"; } +.bi-subscript::before { content: "\f848"; } +.bi-superscript::before { content: "\f849"; } +.bi-trello::before { content: "\f84a"; } +.bi-envelope-at-fill::before { content: "\f84b"; } +.bi-envelope-at::before { content: "\f84c"; } +.bi-regex::before { content: "\f84d"; } +.bi-text-wrap::before { content: "\f84e"; } +.bi-sign-dead-end-fill::before { content: "\f84f"; } +.bi-sign-dead-end::before { content: "\f850"; } +.bi-sign-do-not-enter-fill::before { content: "\f851"; } +.bi-sign-do-not-enter::before { content: "\f852"; } +.bi-sign-intersection-fill::before { content: "\f853"; } +.bi-sign-intersection-side-fill::before { content: "\f854"; } +.bi-sign-intersection-side::before { content: "\f855"; } +.bi-sign-intersection-t-fill::before { content: "\f856"; } +.bi-sign-intersection-t::before { content: "\f857"; } +.bi-sign-intersection-y-fill::before { content: "\f858"; } +.bi-sign-intersection-y::before { content: "\f859"; } +.bi-sign-intersection::before { content: "\f85a"; } +.bi-sign-merge-left-fill::before { content: "\f85b"; } +.bi-sign-merge-left::before { content: "\f85c"; } +.bi-sign-merge-right-fill::before { content: "\f85d"; } +.bi-sign-merge-right::before { content: "\f85e"; } +.bi-sign-no-left-turn-fill::before { content: "\f85f"; } +.bi-sign-no-left-turn::before { content: "\f860"; } +.bi-sign-no-parking-fill::before { content: "\f861"; } +.bi-sign-no-parking::before { content: "\f862"; } +.bi-sign-no-right-turn-fill::before { content: "\f863"; } +.bi-sign-no-right-turn::before { content: "\f864"; } +.bi-sign-railroad-fill::before { content: "\f865"; } +.bi-sign-railroad::before { content: "\f866"; } +.bi-building-add::before { content: "\f867"; } +.bi-building-check::before { content: "\f868"; } +.bi-building-dash::before { content: "\f869"; } +.bi-building-down::before { content: "\f86a"; } +.bi-building-exclamation::before { content: "\f86b"; } +.bi-building-fill-add::before { content: "\f86c"; } +.bi-building-fill-check::before { content: "\f86d"; } +.bi-building-fill-dash::before { content: "\f86e"; } +.bi-building-fill-down::before { content: "\f86f"; } +.bi-building-fill-exclamation::before { content: "\f870"; } +.bi-building-fill-gear::before { content: "\f871"; } +.bi-building-fill-lock::before { content: "\f872"; } +.bi-building-fill-slash::before { content: "\f873"; } +.bi-building-fill-up::before { content: "\f874"; } +.bi-building-fill-x::before { content: "\f875"; } +.bi-building-fill::before { content: "\f876"; } +.bi-building-gear::before { content: "\f877"; } +.bi-building-lock::before { content: "\f878"; } +.bi-building-slash::before { content: "\f879"; } +.bi-building-up::before { content: "\f87a"; } +.bi-building-x::before { content: "\f87b"; } +.bi-buildings-fill::before { content: "\f87c"; } +.bi-buildings::before { content: "\f87d"; } +.bi-bus-front-fill::before { content: "\f87e"; } +.bi-bus-front::before { content: "\f87f"; } +.bi-ev-front-fill::before { content: "\f880"; } +.bi-ev-front::before { content: "\f881"; } +.bi-globe-americas::before { content: "\f882"; } +.bi-globe-asia-australia::before { content: "\f883"; } +.bi-globe-central-south-asia::before { content: "\f884"; } +.bi-globe-europe-africa::before { content: "\f885"; } +.bi-house-add-fill::before { content: "\f886"; } +.bi-house-add::before { content: "\f887"; } +.bi-house-check-fill::before { content: "\f888"; } +.bi-house-check::before { content: "\f889"; } +.bi-house-dash-fill::before { content: "\f88a"; } +.bi-house-dash::before { content: "\f88b"; } +.bi-house-down-fill::before { content: "\f88c"; } +.bi-house-down::before { content: "\f88d"; } +.bi-house-exclamation-fill::before { content: "\f88e"; } +.bi-house-exclamation::before { content: "\f88f"; } +.bi-house-gear-fill::before { content: "\f890"; } +.bi-house-gear::before { content: "\f891"; } +.bi-house-lock-fill::before { content: "\f892"; } +.bi-house-lock::before { content: "\f893"; } +.bi-house-slash-fill::before { content: "\f894"; } +.bi-house-slash::before { content: "\f895"; } +.bi-house-up-fill::before { content: "\f896"; } +.bi-house-up::before { content: "\f897"; } +.bi-house-x-fill::before { content: "\f898"; } +.bi-house-x::before { content: "\f899"; } +.bi-person-add::before { content: "\f89a"; } +.bi-person-down::before { content: "\f89b"; } +.bi-person-exclamation::before { content: "\f89c"; } +.bi-person-fill-add::before { content: "\f89d"; } +.bi-person-fill-check::before { content: "\f89e"; } +.bi-person-fill-dash::before { content: "\f89f"; } +.bi-person-fill-down::before { content: "\f8a0"; } +.bi-person-fill-exclamation::before { content: "\f8a1"; } +.bi-person-fill-gear::before { content: "\f8a2"; } +.bi-person-fill-lock::before { content: "\f8a3"; } +.bi-person-fill-slash::before { content: "\f8a4"; } +.bi-person-fill-up::before { content: "\f8a5"; } +.bi-person-fill-x::before { content: "\f8a6"; } +.bi-person-gear::before { content: "\f8a7"; } +.bi-person-lock::before { content: "\f8a8"; } +.bi-person-slash::before { content: "\f8a9"; } +.bi-person-up::before { content: "\f8aa"; } +.bi-scooter::before { content: "\f8ab"; } +.bi-taxi-front-fill::before { content: "\f8ac"; } +.bi-taxi-front::before { content: "\f8ad"; } +.bi-amd::before { content: "\f8ae"; } +.bi-database-add::before { content: "\f8af"; } +.bi-database-check::before { content: "\f8b0"; } +.bi-database-dash::before { content: "\f8b1"; } +.bi-database-down::before { content: "\f8b2"; } +.bi-database-exclamation::before { content: "\f8b3"; } +.bi-database-fill-add::before { content: "\f8b4"; } +.bi-database-fill-check::before { content: "\f8b5"; } +.bi-database-fill-dash::before { content: "\f8b6"; } +.bi-database-fill-down::before { content: "\f8b7"; } +.bi-database-fill-exclamation::before { content: "\f8b8"; } +.bi-database-fill-gear::before { content: "\f8b9"; } +.bi-database-fill-lock::before { content: "\f8ba"; } +.bi-database-fill-slash::before { content: "\f8bb"; } +.bi-database-fill-up::before { content: "\f8bc"; } +.bi-database-fill-x::before { content: "\f8bd"; } +.bi-database-fill::before { content: "\f8be"; } +.bi-database-gear::before { content: "\f8bf"; } +.bi-database-lock::before { content: "\f8c0"; } +.bi-database-slash::before { content: "\f8c1"; } +.bi-database-up::before { content: "\f8c2"; } +.bi-database-x::before { content: "\f8c3"; } +.bi-database::before { content: "\f8c4"; } +.bi-houses-fill::before { content: "\f8c5"; } +.bi-houses::before { content: "\f8c6"; } +.bi-nvidia::before { content: "\f8c7"; } +.bi-person-vcard-fill::before { content: "\f8c8"; } +.bi-person-vcard::before { content: "\f8c9"; } +.bi-sina-weibo::before { content: "\f8ca"; } +.bi-tencent-qq::before { content: "\f8cb"; } +.bi-wikipedia::before { content: "\f8cc"; } +.bi-alphabet-uppercase::before { content: "\f2a5"; } +.bi-alphabet::before { content: "\f68a"; } +.bi-amazon::before { content: "\f68d"; } +.bi-arrows-collapse-vertical::before { content: "\f690"; } +.bi-arrows-expand-vertical::before { content: "\f695"; } +.bi-arrows-vertical::before { content: "\f698"; } +.bi-arrows::before { content: "\f6a2"; } +.bi-ban-fill::before { content: "\f6a3"; } +.bi-ban::before { content: "\f6b6"; } +.bi-bing::before { content: "\f6c2"; } +.bi-cake::before { content: "\f6e0"; } +.bi-cake2::before { content: "\f6ed"; } +.bi-cookie::before { content: "\f6ee"; } +.bi-copy::before { content: "\f759"; } +.bi-crosshair::before { content: "\f769"; } +.bi-crosshair2::before { content: "\f794"; } +.bi-emoji-astonished-fill::before { content: "\f795"; } +.bi-emoji-astonished::before { content: "\f79a"; } +.bi-emoji-grimace-fill::before { content: "\f79b"; } +.bi-emoji-grimace::before { content: "\f7a0"; } +.bi-emoji-grin-fill::before { content: "\f7a1"; } +.bi-emoji-grin::before { content: "\f7a6"; } +.bi-emoji-surprise-fill::before { content: "\f7a7"; } +.bi-emoji-surprise::before { content: "\f7ac"; } +.bi-emoji-tear-fill::before { content: "\f7ad"; } +.bi-emoji-tear::before { content: "\f7b2"; } +.bi-envelope-arrow-down-fill::before { content: "\f7b3"; } +.bi-envelope-arrow-down::before { content: "\f7b8"; } +.bi-envelope-arrow-up-fill::before { content: "\f7b9"; } +.bi-envelope-arrow-up::before { content: "\f7be"; } +.bi-feather::before { content: "\f7bf"; } +.bi-feather2::before { content: "\f7c4"; } +.bi-floppy-fill::before { content: "\f7c5"; } +.bi-floppy::before { content: "\f7d8"; } +.bi-floppy2-fill::before { content: "\f7d9"; } +.bi-floppy2::before { content: "\f7e4"; } +.bi-gitlab::before { content: "\f7e5"; } +.bi-highlighter::before { content: "\f7f8"; } +.bi-marker-tip::before { content: "\f802"; } +.bi-nvme-fill::before { content: "\f803"; } +.bi-nvme::before { content: "\f80c"; } +.bi-opencollective::before { content: "\f80d"; } +.bi-pci-card-network::before { content: "\f8cd"; } +.bi-pci-card-sound::before { content: "\f8ce"; } +.bi-radar::before { content: "\f8cf"; } +.bi-send-arrow-down-fill::before { content: "\f8d0"; } +.bi-send-arrow-down::before { content: "\f8d1"; } +.bi-send-arrow-up-fill::before { content: "\f8d2"; } +.bi-send-arrow-up::before { content: "\f8d3"; } +.bi-sim-slash-fill::before { content: "\f8d4"; } +.bi-sim-slash::before { content: "\f8d5"; } +.bi-sourceforge::before { content: "\f8d6"; } +.bi-substack::before { content: "\f8d7"; } +.bi-threads-fill::before { content: "\f8d8"; } +.bi-threads::before { content: "\f8d9"; } +.bi-transparency::before { content: "\f8da"; } +.bi-twitter-x::before { content: "\f8db"; } +.bi-type-h4::before { content: "\f8dc"; } +.bi-type-h5::before { content: "\f8dd"; } +.bi-type-h6::before { content: "\f8de"; } +.bi-backpack-fill::before { content: "\f8df"; } +.bi-backpack::before { content: "\f8e0"; } +.bi-backpack2-fill::before { content: "\f8e1"; } +.bi-backpack2::before { content: "\f8e2"; } +.bi-backpack3-fill::before { content: "\f8e3"; } +.bi-backpack3::before { content: "\f8e4"; } +.bi-backpack4-fill::before { content: "\f8e5"; } +.bi-backpack4::before { content: "\f8e6"; } +.bi-brilliance::before { content: "\f8e7"; } +.bi-cake-fill::before { content: "\f8e8"; } +.bi-cake2-fill::before { content: "\f8e9"; } +.bi-duffle-fill::before { content: "\f8ea"; } +.bi-duffle::before { content: "\f8eb"; } +.bi-exposure::before { content: "\f8ec"; } +.bi-gender-neuter::before { content: "\f8ed"; } +.bi-highlights::before { content: "\f8ee"; } +.bi-luggage-fill::before { content: "\f8ef"; } +.bi-luggage::before { content: "\f8f0"; } +.bi-mailbox-flag::before { content: "\f8f1"; } +.bi-mailbox2-flag::before { content: "\f8f2"; } +.bi-noise-reduction::before { content: "\f8f3"; } +.bi-passport-fill::before { content: "\f8f4"; } +.bi-passport::before { content: "\f8f5"; } +.bi-person-arms-up::before { content: "\f8f6"; } +.bi-person-raised-hand::before { content: "\f8f7"; } +.bi-person-standing-dress::before { content: "\f8f8"; } +.bi-person-standing::before { content: "\f8f9"; } +.bi-person-walking::before { content: "\f8fa"; } +.bi-person-wheelchair::before { content: "\f8fb"; } +.bi-shadows::before { content: "\f8fc"; } +.bi-suitcase-fill::before { content: "\f8fd"; } +.bi-suitcase-lg-fill::before { content: "\f8fe"; } +.bi-suitcase-lg::before { content: "\f8ff"; } +.bi-suitcase::before { content: "\f900"; } +.bi-suitcase2-fill::before { content: "\f901"; } +.bi-suitcase2::before { content: "\f902"; } +.bi-vignette::before { content: "\f903"; } +.bi-bluesky::before { content: "\f7f9"; } +.bi-tux::before { content: "\f904"; } +.bi-beaker-fill::before { content: "\f905"; } +.bi-beaker::before { content: "\f906"; } +.bi-flask-fill::before { content: "\f907"; } +.bi-flask-florence-fill::before { content: "\f908"; } +.bi-flask-florence::before { content: "\f909"; } +.bi-flask::before { content: "\f90a"; } +.bi-leaf-fill::before { content: "\f90b"; } +.bi-leaf::before { content: "\f90c"; } +.bi-measuring-cup-fill::before { content: "\f90d"; } +.bi-measuring-cup::before { content: "\f90e"; } +.bi-unlock2-fill::before { content: "\f90f"; } +.bi-unlock2::before { content: "\f910"; } +.bi-battery-low::before { content: "\f911"; } +.bi-anthropic::before { content: "\f912"; } +.bi-apple-music::before { content: "\f913"; } +.bi-claude::before { content: "\f914"; } +.bi-openai::before { content: "\f915"; } +.bi-perplexity::before { content: "\f916"; } +.bi-css::before { content: "\f917"; } +.bi-javascript::before { content: "\f918"; } +.bi-typescript::before { content: "\f919"; } +.bi-fork-knife::before { content: "\f91a"; } +.bi-globe-americas-fill::before { content: "\f91b"; } +.bi-globe-asia-australia-fill::before { content: "\f91c"; } +.bi-globe-central-south-asia-fill::before { content: "\f91d"; } +.bi-globe-europe-africa-fill::before { content: "\f91e"; } diff --git a/web/vendor/bootstrap-icons/bootstrap-icons.json b/web/vendor/bootstrap-icons/bootstrap-icons.json new file mode 100644 index 0000000..9d8873b --- /dev/null +++ b/web/vendor/bootstrap-icons/bootstrap-icons.json @@ -0,0 +1,2080 @@ +{ + "123": 63103, + "alarm-fill": 61697, + "alarm": 61698, + "align-bottom": 61699, + "align-center": 61700, + "align-end": 61701, + "align-middle": 61702, + "align-start": 61703, + "align-top": 61704, + "alt": 61705, + "app-indicator": 61706, + "app": 61707, + "archive-fill": 61708, + "archive": 61709, + "arrow-90deg-down": 61710, + "arrow-90deg-left": 61711, + "arrow-90deg-right": 61712, + "arrow-90deg-up": 61713, + "arrow-bar-down": 61714, + "arrow-bar-left": 61715, + "arrow-bar-right": 61716, + "arrow-bar-up": 61717, + "arrow-clockwise": 61718, + "arrow-counterclockwise": 61719, + "arrow-down-circle-fill": 61720, + "arrow-down-circle": 61721, + "arrow-down-left-circle-fill": 61722, + "arrow-down-left-circle": 61723, + "arrow-down-left-square-fill": 61724, + "arrow-down-left-square": 61725, + "arrow-down-left": 61726, + "arrow-down-right-circle-fill": 61727, + "arrow-down-right-circle": 61728, + "arrow-down-right-square-fill": 61729, + "arrow-down-right-square": 61730, + "arrow-down-right": 61731, + "arrow-down-short": 61732, + "arrow-down-square-fill": 61733, + "arrow-down-square": 61734, + "arrow-down-up": 61735, + "arrow-down": 61736, + "arrow-left-circle-fill": 61737, + "arrow-left-circle": 61738, + "arrow-left-right": 61739, + "arrow-left-short": 61740, + "arrow-left-square-fill": 61741, + "arrow-left-square": 61742, + "arrow-left": 61743, + "arrow-repeat": 61744, + "arrow-return-left": 61745, + "arrow-return-right": 61746, + "arrow-right-circle-fill": 61747, + "arrow-right-circle": 61748, + "arrow-right-short": 61749, + "arrow-right-square-fill": 61750, + "arrow-right-square": 61751, + "arrow-right": 61752, + "arrow-up-circle-fill": 61753, + "arrow-up-circle": 61754, + "arrow-up-left-circle-fill": 61755, + "arrow-up-left-circle": 61756, + "arrow-up-left-square-fill": 61757, + "arrow-up-left-square": 61758, + "arrow-up-left": 61759, + "arrow-up-right-circle-fill": 61760, + "arrow-up-right-circle": 61761, + "arrow-up-right-square-fill": 61762, + "arrow-up-right-square": 61763, + "arrow-up-right": 61764, + "arrow-up-short": 61765, + "arrow-up-square-fill": 61766, + "arrow-up-square": 61767, + "arrow-up": 61768, + "arrows-angle-contract": 61769, + "arrows-angle-expand": 61770, + "arrows-collapse": 61771, + "arrows-expand": 61772, + "arrows-fullscreen": 61773, + "arrows-move": 61774, + "aspect-ratio-fill": 61775, + "aspect-ratio": 61776, + "asterisk": 61777, + "at": 61778, + "award-fill": 61779, + "award": 61780, + "back": 61781, + "backspace-fill": 61782, + "backspace-reverse-fill": 61783, + "backspace-reverse": 61784, + "backspace": 61785, + "badge-3d-fill": 61786, + "badge-3d": 61787, + "badge-4k-fill": 61788, + "badge-4k": 61789, + "badge-8k-fill": 61790, + "badge-8k": 61791, + "badge-ad-fill": 61792, + "badge-ad": 61793, + "badge-ar-fill": 61794, + "badge-ar": 61795, + "badge-cc-fill": 61796, + "badge-cc": 61797, + "badge-hd-fill": 61798, + "badge-hd": 61799, + "badge-tm-fill": 61800, + "badge-tm": 61801, + "badge-vo-fill": 61802, + "badge-vo": 61803, + "badge-vr-fill": 61804, + "badge-vr": 61805, + "badge-wc-fill": 61806, + "badge-wc": 61807, + "bag-check-fill": 61808, + "bag-check": 61809, + "bag-dash-fill": 61810, + "bag-dash": 61811, + "bag-fill": 61812, + "bag-plus-fill": 61813, + "bag-plus": 61814, + "bag-x-fill": 61815, + "bag-x": 61816, + "bag": 61817, + "bar-chart-fill": 61818, + "bar-chart-line-fill": 61819, + "bar-chart-line": 61820, + "bar-chart-steps": 61821, + "bar-chart": 61822, + "basket-fill": 61823, + "basket": 61824, + "basket2-fill": 61825, + "basket2": 61826, + "basket3-fill": 61827, + "basket3": 61828, + "battery-charging": 61829, + "battery-full": 61830, + "battery-half": 61831, + "battery": 61832, + "bell-fill": 61833, + "bell": 61834, + "bezier": 61835, + "bezier2": 61836, + "bicycle": 61837, + "binoculars-fill": 61838, + "binoculars": 61839, + "blockquote-left": 61840, + "blockquote-right": 61841, + "book-fill": 61842, + "book-half": 61843, + "book": 61844, + "bookmark-check-fill": 61845, + "bookmark-check": 61846, + "bookmark-dash-fill": 61847, + "bookmark-dash": 61848, + "bookmark-fill": 61849, + "bookmark-heart-fill": 61850, + "bookmark-heart": 61851, + "bookmark-plus-fill": 61852, + "bookmark-plus": 61853, + "bookmark-star-fill": 61854, + "bookmark-star": 61855, + "bookmark-x-fill": 61856, + "bookmark-x": 61857, + "bookmark": 61858, + "bookmarks-fill": 61859, + "bookmarks": 61860, + "bookshelf": 61861, + "bootstrap-fill": 61862, + "bootstrap-reboot": 61863, + "bootstrap": 61864, + "border-all": 61865, + "border-bottom": 61866, + "border-center": 61867, + "border-inner": 61868, + "border-left": 61869, + "border-middle": 61870, + "border-outer": 61871, + "border-right": 61872, + "border-style": 61873, + "border-top": 61874, + "border-width": 61875, + "border": 61876, + "bounding-box-circles": 61877, + "bounding-box": 61878, + "box-arrow-down-left": 61879, + "box-arrow-down-right": 61880, + "box-arrow-down": 61881, + "box-arrow-in-down-left": 61882, + "box-arrow-in-down-right": 61883, + "box-arrow-in-down": 61884, + "box-arrow-in-left": 61885, + "box-arrow-in-right": 61886, + "box-arrow-in-up-left": 61887, + "box-arrow-in-up-right": 61888, + "box-arrow-in-up": 61889, + "box-arrow-left": 61890, + "box-arrow-right": 61891, + "box-arrow-up-left": 61892, + "box-arrow-up-right": 61893, + "box-arrow-up": 61894, + "box-seam": 61895, + "box": 61896, + "braces": 61897, + "bricks": 61898, + "briefcase-fill": 61899, + "briefcase": 61900, + "brightness-alt-high-fill": 61901, + "brightness-alt-high": 61902, + "brightness-alt-low-fill": 61903, + "brightness-alt-low": 61904, + "brightness-high-fill": 61905, + "brightness-high": 61906, + "brightness-low-fill": 61907, + "brightness-low": 61908, + "broadcast-pin": 61909, + "broadcast": 61910, + "brush-fill": 61911, + "brush": 61912, + "bucket-fill": 61913, + "bucket": 61914, + "bug-fill": 61915, + "bug": 61916, + "building": 61917, + "bullseye": 61918, + "calculator-fill": 61919, + "calculator": 61920, + "calendar-check-fill": 61921, + "calendar-check": 61922, + "calendar-date-fill": 61923, + "calendar-date": 61924, + "calendar-day-fill": 61925, + "calendar-day": 61926, + "calendar-event-fill": 61927, + "calendar-event": 61928, + "calendar-fill": 61929, + "calendar-minus-fill": 61930, + "calendar-minus": 61931, + "calendar-month-fill": 61932, + "calendar-month": 61933, + "calendar-plus-fill": 61934, + "calendar-plus": 61935, + "calendar-range-fill": 61936, + "calendar-range": 61937, + "calendar-week-fill": 61938, + "calendar-week": 61939, + "calendar-x-fill": 61940, + "calendar-x": 61941, + "calendar": 61942, + "calendar2-check-fill": 61943, + "calendar2-check": 61944, + "calendar2-date-fill": 61945, + "calendar2-date": 61946, + "calendar2-day-fill": 61947, + "calendar2-day": 61948, + "calendar2-event-fill": 61949, + "calendar2-event": 61950, + "calendar2-fill": 61951, + "calendar2-minus-fill": 61952, + "calendar2-minus": 61953, + "calendar2-month-fill": 61954, + "calendar2-month": 61955, + "calendar2-plus-fill": 61956, + "calendar2-plus": 61957, + "calendar2-range-fill": 61958, + "calendar2-range": 61959, + "calendar2-week-fill": 61960, + "calendar2-week": 61961, + "calendar2-x-fill": 61962, + "calendar2-x": 61963, + "calendar2": 61964, + "calendar3-event-fill": 61965, + "calendar3-event": 61966, + "calendar3-fill": 61967, + "calendar3-range-fill": 61968, + "calendar3-range": 61969, + "calendar3-week-fill": 61970, + "calendar3-week": 61971, + "calendar3": 61972, + "calendar4-event": 61973, + "calendar4-range": 61974, + "calendar4-week": 61975, + "calendar4": 61976, + "camera-fill": 61977, + "camera-reels-fill": 61978, + "camera-reels": 61979, + "camera-video-fill": 61980, + "camera-video-off-fill": 61981, + "camera-video-off": 61982, + "camera-video": 61983, + "camera": 61984, + "camera2": 61985, + "capslock-fill": 61986, + "capslock": 61987, + "card-checklist": 61988, + "card-heading": 61989, + "card-image": 61990, + "card-list": 61991, + "card-text": 61992, + "caret-down-fill": 61993, + "caret-down-square-fill": 61994, + "caret-down-square": 61995, + "caret-down": 61996, + "caret-left-fill": 61997, + "caret-left-square-fill": 61998, + "caret-left-square": 61999, + "caret-left": 62000, + "caret-right-fill": 62001, + "caret-right-square-fill": 62002, + "caret-right-square": 62003, + "caret-right": 62004, + "caret-up-fill": 62005, + "caret-up-square-fill": 62006, + "caret-up-square": 62007, + "caret-up": 62008, + "cart-check-fill": 62009, + "cart-check": 62010, + "cart-dash-fill": 62011, + "cart-dash": 62012, + "cart-fill": 62013, + "cart-plus-fill": 62014, + "cart-plus": 62015, + "cart-x-fill": 62016, + "cart-x": 62017, + "cart": 62018, + "cart2": 62019, + "cart3": 62020, + "cart4": 62021, + "cash-stack": 62022, + "cash": 62023, + "cast": 62024, + "chat-dots-fill": 62025, + "chat-dots": 62026, + "chat-fill": 62027, + "chat-left-dots-fill": 62028, + "chat-left-dots": 62029, + "chat-left-fill": 62030, + "chat-left-quote-fill": 62031, + "chat-left-quote": 62032, + "chat-left-text-fill": 62033, + "chat-left-text": 62034, + "chat-left": 62035, + "chat-quote-fill": 62036, + "chat-quote": 62037, + "chat-right-dots-fill": 62038, + "chat-right-dots": 62039, + "chat-right-fill": 62040, + "chat-right-quote-fill": 62041, + "chat-right-quote": 62042, + "chat-right-text-fill": 62043, + "chat-right-text": 62044, + "chat-right": 62045, + "chat-square-dots-fill": 62046, + "chat-square-dots": 62047, + "chat-square-fill": 62048, + "chat-square-quote-fill": 62049, + "chat-square-quote": 62050, + "chat-square-text-fill": 62051, + "chat-square-text": 62052, + "chat-square": 62053, + "chat-text-fill": 62054, + "chat-text": 62055, + "chat": 62056, + "check-all": 62057, + "check-circle-fill": 62058, + "check-circle": 62059, + "check-square-fill": 62060, + "check-square": 62061, + "check": 62062, + "check2-all": 62063, + "check2-circle": 62064, + "check2-square": 62065, + "check2": 62066, + "chevron-bar-contract": 62067, + "chevron-bar-down": 62068, + "chevron-bar-expand": 62069, + "chevron-bar-left": 62070, + "chevron-bar-right": 62071, + "chevron-bar-up": 62072, + "chevron-compact-down": 62073, + "chevron-compact-left": 62074, + "chevron-compact-right": 62075, + "chevron-compact-up": 62076, + "chevron-contract": 62077, + "chevron-double-down": 62078, + "chevron-double-left": 62079, + "chevron-double-right": 62080, + "chevron-double-up": 62081, + "chevron-down": 62082, + "chevron-expand": 62083, + "chevron-left": 62084, + "chevron-right": 62085, + "chevron-up": 62086, + "circle-fill": 62087, + "circle-half": 62088, + "circle-square": 62089, + "circle": 62090, + "clipboard-check": 62091, + "clipboard-data": 62092, + "clipboard-minus": 62093, + "clipboard-plus": 62094, + "clipboard-x": 62095, + "clipboard": 62096, + "clock-fill": 62097, + "clock-history": 62098, + "clock": 62099, + "cloud-arrow-down-fill": 62100, + "cloud-arrow-down": 62101, + "cloud-arrow-up-fill": 62102, + "cloud-arrow-up": 62103, + "cloud-check-fill": 62104, + "cloud-check": 62105, + "cloud-download-fill": 62106, + "cloud-download": 62107, + "cloud-drizzle-fill": 62108, + "cloud-drizzle": 62109, + "cloud-fill": 62110, + "cloud-fog-fill": 62111, + "cloud-fog": 62112, + "cloud-fog2-fill": 62113, + "cloud-fog2": 62114, + "cloud-hail-fill": 62115, + "cloud-hail": 62116, + "cloud-haze-fill": 62118, + "cloud-haze": 62119, + "cloud-haze2-fill": 62120, + "cloud-lightning-fill": 62121, + "cloud-lightning-rain-fill": 62122, + "cloud-lightning-rain": 62123, + "cloud-lightning": 62124, + "cloud-minus-fill": 62125, + "cloud-minus": 62126, + "cloud-moon-fill": 62127, + "cloud-moon": 62128, + "cloud-plus-fill": 62129, + "cloud-plus": 62130, + "cloud-rain-fill": 62131, + "cloud-rain-heavy-fill": 62132, + "cloud-rain-heavy": 62133, + "cloud-rain": 62134, + "cloud-slash-fill": 62135, + "cloud-slash": 62136, + "cloud-sleet-fill": 62137, + "cloud-sleet": 62138, + "cloud-snow-fill": 62139, + "cloud-snow": 62140, + "cloud-sun-fill": 62141, + "cloud-sun": 62142, + "cloud-upload-fill": 62143, + "cloud-upload": 62144, + "cloud": 62145, + "clouds-fill": 62146, + "clouds": 62147, + "cloudy-fill": 62148, + "cloudy": 62149, + "code-slash": 62150, + "code-square": 62151, + "code": 62152, + "collection-fill": 62153, + "collection-play-fill": 62154, + "collection-play": 62155, + "collection": 62156, + "columns-gap": 62157, + "columns": 62158, + "command": 62159, + "compass-fill": 62160, + "compass": 62161, + "cone-striped": 62162, + "cone": 62163, + "controller": 62164, + "cpu-fill": 62165, + "cpu": 62166, + "credit-card-2-back-fill": 62167, + "credit-card-2-back": 62168, + "credit-card-2-front-fill": 62169, + "credit-card-2-front": 62170, + "credit-card-fill": 62171, + "credit-card": 62172, + "crop": 62173, + "cup-fill": 62174, + "cup-straw": 62175, + "cup": 62176, + "cursor-fill": 62177, + "cursor-text": 62178, + "cursor": 62179, + "dash-circle-dotted": 62180, + "dash-circle-fill": 62181, + "dash-circle": 62182, + "dash-square-dotted": 62183, + "dash-square-fill": 62184, + "dash-square": 62185, + "dash": 62186, + "diagram-2-fill": 62187, + "diagram-2": 62188, + "diagram-3-fill": 62189, + "diagram-3": 62190, + "diamond-fill": 62191, + "diamond-half": 62192, + "diamond": 62193, + "dice-1-fill": 62194, + "dice-1": 62195, + "dice-2-fill": 62196, + "dice-2": 62197, + "dice-3-fill": 62198, + "dice-3": 62199, + "dice-4-fill": 62200, + "dice-4": 62201, + "dice-5-fill": 62202, + "dice-5": 62203, + "dice-6-fill": 62204, + "dice-6": 62205, + "disc-fill": 62206, + "disc": 62207, + "discord": 62208, + "display-fill": 62209, + "display": 62210, + "distribute-horizontal": 62211, + "distribute-vertical": 62212, + "door-closed-fill": 62213, + "door-closed": 62214, + "door-open-fill": 62215, + "door-open": 62216, + "dot": 62217, + "download": 62218, + "droplet-fill": 62219, + "droplet-half": 62220, + "droplet": 62221, + "earbuds": 62222, + "easel-fill": 62223, + "easel": 62224, + "egg-fill": 62225, + "egg-fried": 62226, + "egg": 62227, + "eject-fill": 62228, + "eject": 62229, + "emoji-angry-fill": 62230, + "emoji-angry": 62231, + "emoji-dizzy-fill": 62232, + "emoji-dizzy": 62233, + "emoji-expressionless-fill": 62234, + "emoji-expressionless": 62235, + "emoji-frown-fill": 62236, + "emoji-frown": 62237, + "emoji-heart-eyes-fill": 62238, + "emoji-heart-eyes": 62239, + "emoji-laughing-fill": 62240, + "emoji-laughing": 62241, + "emoji-neutral-fill": 62242, + "emoji-neutral": 62243, + "emoji-smile-fill": 62244, + "emoji-smile-upside-down-fill": 62245, + "emoji-smile-upside-down": 62246, + "emoji-smile": 62247, + "emoji-sunglasses-fill": 62248, + "emoji-sunglasses": 62249, + "emoji-wink-fill": 62250, + "emoji-wink": 62251, + "envelope-fill": 62252, + "envelope-open-fill": 62253, + "envelope-open": 62254, + "envelope": 62255, + "eraser-fill": 62256, + "eraser": 62257, + "exclamation-circle-fill": 62258, + "exclamation-circle": 62259, + "exclamation-diamond-fill": 62260, + "exclamation-diamond": 62261, + "exclamation-octagon-fill": 62262, + "exclamation-octagon": 62263, + "exclamation-square-fill": 62264, + "exclamation-square": 62265, + "exclamation-triangle-fill": 62266, + "exclamation-triangle": 62267, + "exclamation": 62268, + "exclude": 62269, + "eye-fill": 62270, + "eye-slash-fill": 62271, + "eye-slash": 62272, + "eye": 62273, + "eyedropper": 62274, + "eyeglasses": 62275, + "facebook": 62276, + "file-arrow-down-fill": 62277, + "file-arrow-down": 62278, + "file-arrow-up-fill": 62279, + "file-arrow-up": 62280, + "file-bar-graph-fill": 62281, + "file-bar-graph": 62282, + "file-binary-fill": 62283, + "file-binary": 62284, + "file-break-fill": 62285, + "file-break": 62286, + "file-check-fill": 62287, + "file-check": 62288, + "file-code-fill": 62289, + "file-code": 62290, + "file-diff-fill": 62291, + "file-diff": 62292, + "file-earmark-arrow-down-fill": 62293, + "file-earmark-arrow-down": 62294, + "file-earmark-arrow-up-fill": 62295, + "file-earmark-arrow-up": 62296, + "file-earmark-bar-graph-fill": 62297, + "file-earmark-bar-graph": 62298, + "file-earmark-binary-fill": 62299, + "file-earmark-binary": 62300, + "file-earmark-break-fill": 62301, + "file-earmark-break": 62302, + "file-earmark-check-fill": 62303, + "file-earmark-check": 62304, + "file-earmark-code-fill": 62305, + "file-earmark-code": 62306, + "file-earmark-diff-fill": 62307, + "file-earmark-diff": 62308, + "file-earmark-easel-fill": 62309, + "file-earmark-easel": 62310, + "file-earmark-excel-fill": 62311, + "file-earmark-excel": 62312, + "file-earmark-fill": 62313, + "file-earmark-font-fill": 62314, + "file-earmark-font": 62315, + "file-earmark-image-fill": 62316, + "file-earmark-image": 62317, + "file-earmark-lock-fill": 62318, + "file-earmark-lock": 62319, + "file-earmark-lock2-fill": 62320, + "file-earmark-lock2": 62321, + "file-earmark-medical-fill": 62322, + "file-earmark-medical": 62323, + "file-earmark-minus-fill": 62324, + "file-earmark-minus": 62325, + "file-earmark-music-fill": 62326, + "file-earmark-music": 62327, + "file-earmark-person-fill": 62328, + "file-earmark-person": 62329, + "file-earmark-play-fill": 62330, + "file-earmark-play": 62331, + "file-earmark-plus-fill": 62332, + "file-earmark-plus": 62333, + "file-earmark-post-fill": 62334, + "file-earmark-post": 62335, + "file-earmark-ppt-fill": 62336, + "file-earmark-ppt": 62337, + "file-earmark-richtext-fill": 62338, + "file-earmark-richtext": 62339, + "file-earmark-ruled-fill": 62340, + "file-earmark-ruled": 62341, + "file-earmark-slides-fill": 62342, + "file-earmark-slides": 62343, + "file-earmark-spreadsheet-fill": 62344, + "file-earmark-spreadsheet": 62345, + "file-earmark-text-fill": 62346, + "file-earmark-text": 62347, + "file-earmark-word-fill": 62348, + "file-earmark-word": 62349, + "file-earmark-x-fill": 62350, + "file-earmark-x": 62351, + "file-earmark-zip-fill": 62352, + "file-earmark-zip": 62353, + "file-earmark": 62354, + "file-easel-fill": 62355, + "file-easel": 62356, + "file-excel-fill": 62357, + "file-excel": 62358, + "file-fill": 62359, + "file-font-fill": 62360, + "file-font": 62361, + "file-image-fill": 62362, + "file-image": 62363, + "file-lock-fill": 62364, + "file-lock": 62365, + "file-lock2-fill": 62366, + "file-lock2": 62367, + "file-medical-fill": 62368, + "file-medical": 62369, + "file-minus-fill": 62370, + "file-minus": 62371, + "file-music-fill": 62372, + "file-music": 62373, + "file-person-fill": 62374, + "file-person": 62375, + "file-play-fill": 62376, + "file-play": 62377, + "file-plus-fill": 62378, + "file-plus": 62379, + "file-post-fill": 62380, + "file-post": 62381, + "file-ppt-fill": 62382, + "file-ppt": 62383, + "file-richtext-fill": 62384, + "file-richtext": 62385, + "file-ruled-fill": 62386, + "file-ruled": 62387, + "file-slides-fill": 62388, + "file-slides": 62389, + "file-spreadsheet-fill": 62390, + "file-spreadsheet": 62391, + "file-text-fill": 62392, + "file-text": 62393, + "file-word-fill": 62394, + "file-word": 62395, + "file-x-fill": 62396, + "file-x": 62397, + "file-zip-fill": 62398, + "file-zip": 62399, + "file": 62400, + "files-alt": 62401, + "files": 62402, + "film": 62403, + "filter-circle-fill": 62404, + "filter-circle": 62405, + "filter-left": 62406, + "filter-right": 62407, + "filter-square-fill": 62408, + "filter-square": 62409, + "filter": 62410, + "flag-fill": 62411, + "flag": 62412, + "flower1": 62413, + "flower2": 62414, + "flower3": 62415, + "folder-check": 62416, + "folder-fill": 62417, + "folder-minus": 62418, + "folder-plus": 62419, + "folder-symlink-fill": 62420, + "folder-symlink": 62421, + "folder-x": 62422, + "folder": 62423, + "folder2-open": 62424, + "folder2": 62425, + "fonts": 62426, + "forward-fill": 62427, + "forward": 62428, + "front": 62429, + "fullscreen-exit": 62430, + "fullscreen": 62431, + "funnel-fill": 62432, + "funnel": 62433, + "gear-fill": 62434, + "gear-wide-connected": 62435, + "gear-wide": 62436, + "gear": 62437, + "gem": 62438, + "geo-alt-fill": 62439, + "geo-alt": 62440, + "geo-fill": 62441, + "geo": 62442, + "gift-fill": 62443, + "gift": 62444, + "github": 62445, + "globe": 62446, + "globe2": 62447, + "google": 62448, + "graph-down": 62449, + "graph-up": 62450, + "grid-1x2-fill": 62451, + "grid-1x2": 62452, + "grid-3x2-gap-fill": 62453, + "grid-3x2-gap": 62454, + "grid-3x2": 62455, + "grid-3x3-gap-fill": 62456, + "grid-3x3-gap": 62457, + "grid-3x3": 62458, + "grid-fill": 62459, + "grid": 62460, + "grip-horizontal": 62461, + "grip-vertical": 62462, + "hammer": 62463, + "hand-index-fill": 62464, + "hand-index-thumb-fill": 62465, + "hand-index-thumb": 62466, + "hand-index": 62467, + "hand-thumbs-down-fill": 62468, + "hand-thumbs-down": 62469, + "hand-thumbs-up-fill": 62470, + "hand-thumbs-up": 62471, + "handbag-fill": 62472, + "handbag": 62473, + "hash": 62474, + "hdd-fill": 62475, + "hdd-network-fill": 62476, + "hdd-network": 62477, + "hdd-rack-fill": 62478, + "hdd-rack": 62479, + "hdd-stack-fill": 62480, + "hdd-stack": 62481, + "hdd": 62482, + "headphones": 62483, + "headset": 62484, + "heart-fill": 62485, + "heart-half": 62486, + "heart": 62487, + "heptagon-fill": 62488, + "heptagon-half": 62489, + "heptagon": 62490, + "hexagon-fill": 62491, + "hexagon-half": 62492, + "hexagon": 62493, + "hourglass-bottom": 62494, + "hourglass-split": 62495, + "hourglass-top": 62496, + "hourglass": 62497, + "house-door-fill": 62498, + "house-door": 62499, + "house-fill": 62500, + "house": 62501, + "hr": 62502, + "hurricane": 62503, + "image-alt": 62504, + "image-fill": 62505, + "image": 62506, + "images": 62507, + "inbox-fill": 62508, + "inbox": 62509, + "inboxes-fill": 62510, + "inboxes": 62511, + "info-circle-fill": 62512, + "info-circle": 62513, + "info-square-fill": 62514, + "info-square": 62515, + "info": 62516, + "input-cursor-text": 62517, + "input-cursor": 62518, + "instagram": 62519, + "intersect": 62520, + "journal-album": 62521, + "journal-arrow-down": 62522, + "journal-arrow-up": 62523, + "journal-bookmark-fill": 62524, + "journal-bookmark": 62525, + "journal-check": 62526, + "journal-code": 62527, + "journal-medical": 62528, + "journal-minus": 62529, + "journal-plus": 62530, + "journal-richtext": 62531, + "journal-text": 62532, + "journal-x": 62533, + "journal": 62534, + "journals": 62535, + "joystick": 62536, + "justify-left": 62537, + "justify-right": 62538, + "justify": 62539, + "kanban-fill": 62540, + "kanban": 62541, + "key-fill": 62542, + "key": 62543, + "keyboard-fill": 62544, + "keyboard": 62545, + "ladder": 62546, + "lamp-fill": 62547, + "lamp": 62548, + "laptop-fill": 62549, + "laptop": 62550, + "layer-backward": 62551, + "layer-forward": 62552, + "layers-fill": 62553, + "layers-half": 62554, + "layers": 62555, + "layout-sidebar-inset-reverse": 62556, + "layout-sidebar-inset": 62557, + "layout-sidebar-reverse": 62558, + "layout-sidebar": 62559, + "layout-split": 62560, + "layout-text-sidebar-reverse": 62561, + "layout-text-sidebar": 62562, + "layout-text-window-reverse": 62563, + "layout-text-window": 62564, + "layout-three-columns": 62565, + "layout-wtf": 62566, + "life-preserver": 62567, + "lightbulb-fill": 62568, + "lightbulb-off-fill": 62569, + "lightbulb-off": 62570, + "lightbulb": 62571, + "lightning-charge-fill": 62572, + "lightning-charge": 62573, + "lightning-fill": 62574, + "lightning": 62575, + "link-45deg": 62576, + "link": 62577, + "linkedin": 62578, + "list-check": 62579, + "list-nested": 62580, + "list-ol": 62581, + "list-stars": 62582, + "list-task": 62583, + "list-ul": 62584, + "list": 62585, + "lock-fill": 62586, + "lock": 62587, + "mailbox": 62588, + "mailbox2": 62589, + "map-fill": 62590, + "map": 62591, + "markdown-fill": 62592, + "markdown": 62593, + "mask": 62594, + "megaphone-fill": 62595, + "megaphone": 62596, + "menu-app-fill": 62597, + "menu-app": 62598, + "menu-button-fill": 62599, + "menu-button-wide-fill": 62600, + "menu-button-wide": 62601, + "menu-button": 62602, + "menu-down": 62603, + "menu-up": 62604, + "mic-fill": 62605, + "mic-mute-fill": 62606, + "mic-mute": 62607, + "mic": 62608, + "minecart-loaded": 62609, + "minecart": 62610, + "moisture": 62611, + "moon-fill": 62612, + "moon-stars-fill": 62613, + "moon-stars": 62614, + "moon": 62615, + "mouse-fill": 62616, + "mouse": 62617, + "mouse2-fill": 62618, + "mouse2": 62619, + "mouse3-fill": 62620, + "mouse3": 62621, + "music-note-beamed": 62622, + "music-note-list": 62623, + "music-note": 62624, + "music-player-fill": 62625, + "music-player": 62626, + "newspaper": 62627, + "node-minus-fill": 62628, + "node-minus": 62629, + "node-plus-fill": 62630, + "node-plus": 62631, + "nut-fill": 62632, + "nut": 62633, + "octagon-fill": 62634, + "octagon-half": 62635, + "octagon": 62636, + "option": 62637, + "outlet": 62638, + "paint-bucket": 62639, + "palette-fill": 62640, + "palette": 62641, + "palette2": 62642, + "paperclip": 62643, + "paragraph": 62644, + "patch-check-fill": 62645, + "patch-check": 62646, + "patch-exclamation-fill": 62647, + "patch-exclamation": 62648, + "patch-minus-fill": 62649, + "patch-minus": 62650, + "patch-plus-fill": 62651, + "patch-plus": 62652, + "patch-question-fill": 62653, + "patch-question": 62654, + "pause-btn-fill": 62655, + "pause-btn": 62656, + "pause-circle-fill": 62657, + "pause-circle": 62658, + "pause-fill": 62659, + "pause": 62660, + "peace-fill": 62661, + "peace": 62662, + "pen-fill": 62663, + "pen": 62664, + "pencil-fill": 62665, + "pencil-square": 62666, + "pencil": 62667, + "pentagon-fill": 62668, + "pentagon-half": 62669, + "pentagon": 62670, + "people-fill": 62671, + "people": 62672, + "percent": 62673, + "person-badge-fill": 62674, + "person-badge": 62675, + "person-bounding-box": 62676, + "person-check-fill": 62677, + "person-check": 62678, + "person-circle": 62679, + "person-dash-fill": 62680, + "person-dash": 62681, + "person-fill": 62682, + "person-lines-fill": 62683, + "person-plus-fill": 62684, + "person-plus": 62685, + "person-square": 62686, + "person-x-fill": 62687, + "person-x": 62688, + "person": 62689, + "phone-fill": 62690, + "phone-landscape-fill": 62691, + "phone-landscape": 62692, + "phone-vibrate-fill": 62693, + "phone-vibrate": 62694, + "phone": 62695, + "pie-chart-fill": 62696, + "pie-chart": 62697, + "pin-angle-fill": 62698, + "pin-angle": 62699, + "pin-fill": 62700, + "pin": 62701, + "pip-fill": 62702, + "pip": 62703, + "play-btn-fill": 62704, + "play-btn": 62705, + "play-circle-fill": 62706, + "play-circle": 62707, + "play-fill": 62708, + "play": 62709, + "plug-fill": 62710, + "plug": 62711, + "plus-circle-dotted": 62712, + "plus-circle-fill": 62713, + "plus-circle": 62714, + "plus-square-dotted": 62715, + "plus-square-fill": 62716, + "plus-square": 62717, + "plus": 62718, + "power": 62719, + "printer-fill": 62720, + "printer": 62721, + "puzzle-fill": 62722, + "puzzle": 62723, + "question-circle-fill": 62724, + "question-circle": 62725, + "question-diamond-fill": 62726, + "question-diamond": 62727, + "question-octagon-fill": 62728, + "question-octagon": 62729, + "question-square-fill": 62730, + "question-square": 62731, + "question": 62732, + "rainbow": 62733, + "receipt-cutoff": 62734, + "receipt": 62735, + "reception-0": 62736, + "reception-1": 62737, + "reception-2": 62738, + "reception-3": 62739, + "reception-4": 62740, + "record-btn-fill": 62741, + "record-btn": 62742, + "record-circle-fill": 62743, + "record-circle": 62744, + "record-fill": 62745, + "record": 62746, + "record2-fill": 62747, + "record2": 62748, + "reply-all-fill": 62749, + "reply-all": 62750, + "reply-fill": 62751, + "reply": 62752, + "rss-fill": 62753, + "rss": 62754, + "rulers": 62755, + "save-fill": 62756, + "save": 62757, + "save2-fill": 62758, + "save2": 62759, + "scissors": 62760, + "screwdriver": 62761, + "search": 62762, + "segmented-nav": 62763, + "server": 62764, + "share-fill": 62765, + "share": 62766, + "shield-check": 62767, + "shield-exclamation": 62768, + "shield-fill-check": 62769, + "shield-fill-exclamation": 62770, + "shield-fill-minus": 62771, + "shield-fill-plus": 62772, + "shield-fill-x": 62773, + "shield-fill": 62774, + "shield-lock-fill": 62775, + "shield-lock": 62776, + "shield-minus": 62777, + "shield-plus": 62778, + "shield-shaded": 62779, + "shield-slash-fill": 62780, + "shield-slash": 62781, + "shield-x": 62782, + "shield": 62783, + "shift-fill": 62784, + "shift": 62785, + "shop-window": 62786, + "shop": 62787, + "shuffle": 62788, + "signpost-2-fill": 62789, + "signpost-2": 62790, + "signpost-fill": 62791, + "signpost-split-fill": 62792, + "signpost-split": 62793, + "signpost": 62794, + "sim-fill": 62795, + "sim": 62796, + "skip-backward-btn-fill": 62797, + "skip-backward-btn": 62798, + "skip-backward-circle-fill": 62799, + "skip-backward-circle": 62800, + "skip-backward-fill": 62801, + "skip-backward": 62802, + "skip-end-btn-fill": 62803, + "skip-end-btn": 62804, + "skip-end-circle-fill": 62805, + "skip-end-circle": 62806, + "skip-end-fill": 62807, + "skip-end": 62808, + "skip-forward-btn-fill": 62809, + "skip-forward-btn": 62810, + "skip-forward-circle-fill": 62811, + "skip-forward-circle": 62812, + "skip-forward-fill": 62813, + "skip-forward": 62814, + "skip-start-btn-fill": 62815, + "skip-start-btn": 62816, + "skip-start-circle-fill": 62817, + "skip-start-circle": 62818, + "skip-start-fill": 62819, + "skip-start": 62820, + "slack": 62821, + "slash-circle-fill": 62822, + "slash-circle": 62823, + "slash-square-fill": 62824, + "slash-square": 62825, + "slash": 62826, + "sliders": 62827, + "smartwatch": 62828, + "snow": 62829, + "snow2": 62830, + "snow3": 62831, + "sort-alpha-down-alt": 62832, + "sort-alpha-down": 62833, + "sort-alpha-up-alt": 62834, + "sort-alpha-up": 62835, + "sort-down-alt": 62836, + "sort-down": 62837, + "sort-numeric-down-alt": 62838, + "sort-numeric-down": 62839, + "sort-numeric-up-alt": 62840, + "sort-numeric-up": 62841, + "sort-up-alt": 62842, + "sort-up": 62843, + "soundwave": 62844, + "speaker-fill": 62845, + "speaker": 62846, + "speedometer": 62847, + "speedometer2": 62848, + "spellcheck": 62849, + "square-fill": 62850, + "square-half": 62851, + "square": 62852, + "stack": 62853, + "star-fill": 62854, + "star-half": 62855, + "star": 62856, + "stars": 62857, + "stickies-fill": 62858, + "stickies": 62859, + "sticky-fill": 62860, + "sticky": 62861, + "stop-btn-fill": 62862, + "stop-btn": 62863, + "stop-circle-fill": 62864, + "stop-circle": 62865, + "stop-fill": 62866, + "stop": 62867, + "stoplights-fill": 62868, + "stoplights": 62869, + "stopwatch-fill": 62870, + "stopwatch": 62871, + "subtract": 62872, + "suit-club-fill": 62873, + "suit-club": 62874, + "suit-diamond-fill": 62875, + "suit-diamond": 62876, + "suit-heart-fill": 62877, + "suit-heart": 62878, + "suit-spade-fill": 62879, + "suit-spade": 62880, + "sun-fill": 62881, + "sun": 62882, + "sunglasses": 62883, + "sunrise-fill": 62884, + "sunrise": 62885, + "sunset-fill": 62886, + "sunset": 62887, + "symmetry-horizontal": 62888, + "symmetry-vertical": 62889, + "table": 62890, + "tablet-fill": 62891, + "tablet-landscape-fill": 62892, + "tablet-landscape": 62893, + "tablet": 62894, + "tag-fill": 62895, + "tag": 62896, + "tags-fill": 62897, + "tags": 62898, + "telegram": 62899, + "telephone-fill": 62900, + "telephone-forward-fill": 62901, + "telephone-forward": 62902, + "telephone-inbound-fill": 62903, + "telephone-inbound": 62904, + "telephone-minus-fill": 62905, + "telephone-minus": 62906, + "telephone-outbound-fill": 62907, + "telephone-outbound": 62908, + "telephone-plus-fill": 62909, + "telephone-plus": 62910, + "telephone-x-fill": 62911, + "telephone-x": 62912, + "telephone": 62913, + "terminal-fill": 62914, + "terminal": 62915, + "text-center": 62916, + "text-indent-left": 62917, + "text-indent-right": 62918, + "text-left": 62919, + "text-paragraph": 62920, + "text-right": 62921, + "textarea-resize": 62922, + "textarea-t": 62923, + "textarea": 62924, + "thermometer-half": 62925, + "thermometer-high": 62926, + "thermometer-low": 62927, + "thermometer-snow": 62928, + "thermometer-sun": 62929, + "thermometer": 62930, + "three-dots-vertical": 62931, + "three-dots": 62932, + "toggle-off": 62933, + "toggle-on": 62934, + "toggle2-off": 62935, + "toggle2-on": 62936, + "toggles": 62937, + "toggles2": 62938, + "tools": 62939, + "tornado": 62940, + "trash-fill": 62941, + "trash": 62942, + "trash2-fill": 62943, + "trash2": 62944, + "tree-fill": 62945, + "tree": 62946, + "triangle-fill": 62947, + "triangle-half": 62948, + "triangle": 62949, + "trophy-fill": 62950, + "trophy": 62951, + "tropical-storm": 62952, + "truck-flatbed": 62953, + "truck": 62954, + "tsunami": 62955, + "tv-fill": 62956, + "tv": 62957, + "twitch": 62958, + "twitter": 62959, + "type-bold": 62960, + "type-h1": 62961, + "type-h2": 62962, + "type-h3": 62963, + "type-italic": 62964, + "type-strikethrough": 62965, + "type-underline": 62966, + "type": 62967, + "ui-checks-grid": 62968, + "ui-checks": 62969, + "ui-radios-grid": 62970, + "ui-radios": 62971, + "umbrella-fill": 62972, + "umbrella": 62973, + "union": 62974, + "unlock-fill": 62975, + "unlock": 62976, + "upc-scan": 62977, + "upc": 62978, + "upload": 62979, + "vector-pen": 62980, + "view-list": 62981, + "view-stacked": 62982, + "vinyl-fill": 62983, + "vinyl": 62984, + "voicemail": 62985, + "volume-down-fill": 62986, + "volume-down": 62987, + "volume-mute-fill": 62988, + "volume-mute": 62989, + "volume-off-fill": 62990, + "volume-off": 62991, + "volume-up-fill": 62992, + "volume-up": 62993, + "vr": 62994, + "wallet-fill": 62995, + "wallet": 62996, + "wallet2": 62997, + "watch": 62998, + "water": 62999, + "whatsapp": 63000, + "wifi-1": 63001, + "wifi-2": 63002, + "wifi-off": 63003, + "wifi": 63004, + "wind": 63005, + "window-dock": 63006, + "window-sidebar": 63007, + "window": 63008, + "wrench": 63009, + "x-circle-fill": 63010, + "x-circle": 63011, + "x-diamond-fill": 63012, + "x-diamond": 63013, + "x-octagon-fill": 63014, + "x-octagon": 63015, + "x-square-fill": 63016, + "x-square": 63017, + "x": 63018, + "youtube": 63019, + "zoom-in": 63020, + "zoom-out": 63021, + "bank": 63022, + "bank2": 63023, + "bell-slash-fill": 63024, + "bell-slash": 63025, + "cash-coin": 63026, + "check-lg": 63027, + "coin": 63028, + "currency-bitcoin": 63029, + "currency-dollar": 63030, + "currency-euro": 63031, + "currency-exchange": 63032, + "currency-pound": 63033, + "currency-yen": 63034, + "dash-lg": 63035, + "exclamation-lg": 63036, + "file-earmark-pdf-fill": 63037, + "file-earmark-pdf": 63038, + "file-pdf-fill": 63039, + "file-pdf": 63040, + "gender-ambiguous": 63041, + "gender-female": 63042, + "gender-male": 63043, + "gender-trans": 63044, + "headset-vr": 63045, + "info-lg": 63046, + "mastodon": 63047, + "messenger": 63048, + "piggy-bank-fill": 63049, + "piggy-bank": 63050, + "pin-map-fill": 63051, + "pin-map": 63052, + "plus-lg": 63053, + "question-lg": 63054, + "recycle": 63055, + "reddit": 63056, + "safe-fill": 63057, + "safe2-fill": 63058, + "safe2": 63059, + "sd-card-fill": 63060, + "sd-card": 63061, + "skype": 63062, + "slash-lg": 63063, + "translate": 63064, + "x-lg": 63065, + "safe": 63066, + "apple": 63067, + "microsoft": 63069, + "windows": 63070, + "behance": 63068, + "dribbble": 63071, + "line": 63072, + "medium": 63073, + "paypal": 63074, + "pinterest": 63075, + "signal": 63076, + "snapchat": 63077, + "spotify": 63078, + "stack-overflow": 63079, + "strava": 63080, + "wordpress": 63081, + "vimeo": 63082, + "activity": 63083, + "easel2-fill": 63084, + "easel2": 63085, + "easel3-fill": 63086, + "easel3": 63087, + "fan": 63088, + "fingerprint": 63089, + "graph-down-arrow": 63090, + "graph-up-arrow": 63091, + "hypnotize": 63092, + "magic": 63093, + "person-rolodex": 63094, + "person-video": 63095, + "person-video2": 63096, + "person-video3": 63097, + "person-workspace": 63098, + "radioactive": 63099, + "webcam-fill": 63100, + "webcam": 63101, + "yin-yang": 63102, + "bandaid-fill": 63104, + "bandaid": 63105, + "bluetooth": 63106, + "body-text": 63107, + "boombox": 63108, + "boxes": 63109, + "dpad-fill": 63110, + "dpad": 63111, + "ear-fill": 63112, + "ear": 63113, + "envelope-check-fill": 63115, + "envelope-check": 63116, + "envelope-dash-fill": 63118, + "envelope-dash": 63119, + "envelope-exclamation-fill": 63121, + "envelope-exclamation": 63122, + "envelope-plus-fill": 63123, + "envelope-plus": 63124, + "envelope-slash-fill": 63126, + "envelope-slash": 63127, + "envelope-x-fill": 63129, + "envelope-x": 63130, + "explicit-fill": 63131, + "explicit": 63132, + "git": 63133, + "infinity": 63134, + "list-columns-reverse": 63135, + "list-columns": 63136, + "meta": 63137, + "nintendo-switch": 63140, + "pc-display-horizontal": 63141, + "pc-display": 63142, + "pc-horizontal": 63143, + "pc": 63144, + "playstation": 63145, + "plus-slash-minus": 63146, + "projector-fill": 63147, + "projector": 63148, + "qr-code-scan": 63149, + "qr-code": 63150, + "quora": 63151, + "quote": 63152, + "robot": 63153, + "send-check-fill": 63154, + "send-check": 63155, + "send-dash-fill": 63156, + "send-dash": 63157, + "send-exclamation-fill": 63159, + "send-exclamation": 63160, + "send-fill": 63161, + "send-plus-fill": 63162, + "send-plus": 63163, + "send-slash-fill": 63164, + "send-slash": 63165, + "send-x-fill": 63166, + "send-x": 63167, + "send": 63168, + "steam": 63169, + "terminal-dash": 63171, + "terminal-plus": 63172, + "terminal-split": 63173, + "ticket-detailed-fill": 63174, + "ticket-detailed": 63175, + "ticket-fill": 63176, + "ticket-perforated-fill": 63177, + "ticket-perforated": 63178, + "ticket": 63179, + "tiktok": 63180, + "window-dash": 63181, + "window-desktop": 63182, + "window-fullscreen": 63183, + "window-plus": 63184, + "window-split": 63185, + "window-stack": 63186, + "window-x": 63187, + "xbox": 63188, + "ethernet": 63189, + "hdmi-fill": 63190, + "hdmi": 63191, + "usb-c-fill": 63192, + "usb-c": 63193, + "usb-fill": 63194, + "usb-plug-fill": 63195, + "usb-plug": 63196, + "usb-symbol": 63197, + "usb": 63198, + "boombox-fill": 63199, + "displayport": 63201, + "gpu-card": 63202, + "memory": 63203, + "modem-fill": 63204, + "modem": 63205, + "motherboard-fill": 63206, + "motherboard": 63207, + "optical-audio-fill": 63208, + "optical-audio": 63209, + "pci-card": 63210, + "router-fill": 63211, + "router": 63212, + "thunderbolt-fill": 63215, + "thunderbolt": 63216, + "usb-drive-fill": 63217, + "usb-drive": 63218, + "usb-micro-fill": 63219, + "usb-micro": 63220, + "usb-mini-fill": 63221, + "usb-mini": 63222, + "cloud-haze2": 63223, + "device-hdd-fill": 63224, + "device-hdd": 63225, + "device-ssd-fill": 63226, + "device-ssd": 63227, + "displayport-fill": 63228, + "mortarboard-fill": 63229, + "mortarboard": 63230, + "terminal-x": 63231, + "arrow-through-heart-fill": 63232, + "arrow-through-heart": 63233, + "badge-sd-fill": 63234, + "badge-sd": 63235, + "bag-heart-fill": 63236, + "bag-heart": 63237, + "balloon-fill": 63238, + "balloon-heart-fill": 63239, + "balloon-heart": 63240, + "balloon": 63241, + "box2-fill": 63242, + "box2-heart-fill": 63243, + "box2-heart": 63244, + "box2": 63245, + "braces-asterisk": 63246, + "calendar-heart-fill": 63247, + "calendar-heart": 63248, + "calendar2-heart-fill": 63249, + "calendar2-heart": 63250, + "chat-heart-fill": 63251, + "chat-heart": 63252, + "chat-left-heart-fill": 63253, + "chat-left-heart": 63254, + "chat-right-heart-fill": 63255, + "chat-right-heart": 63256, + "chat-square-heart-fill": 63257, + "chat-square-heart": 63258, + "clipboard-check-fill": 63259, + "clipboard-data-fill": 63260, + "clipboard-fill": 63261, + "clipboard-heart-fill": 63262, + "clipboard-heart": 63263, + "clipboard-minus-fill": 63264, + "clipboard-plus-fill": 63265, + "clipboard-pulse": 63266, + "clipboard-x-fill": 63267, + "clipboard2-check-fill": 63268, + "clipboard2-check": 63269, + "clipboard2-data-fill": 63270, + "clipboard2-data": 63271, + "clipboard2-fill": 63272, + "clipboard2-heart-fill": 63273, + "clipboard2-heart": 63274, + "clipboard2-minus-fill": 63275, + "clipboard2-minus": 63276, + "clipboard2-plus-fill": 63277, + "clipboard2-plus": 63278, + "clipboard2-pulse-fill": 63279, + "clipboard2-pulse": 63280, + "clipboard2-x-fill": 63281, + "clipboard2-x": 63282, + "clipboard2": 63283, + "emoji-kiss-fill": 63284, + "emoji-kiss": 63285, + "envelope-heart-fill": 63286, + "envelope-heart": 63287, + "envelope-open-heart-fill": 63288, + "envelope-open-heart": 63289, + "envelope-paper-fill": 63290, + "envelope-paper-heart-fill": 63291, + "envelope-paper-heart": 63292, + "envelope-paper": 63293, + "filetype-aac": 63294, + "filetype-ai": 63295, + "filetype-bmp": 63296, + "filetype-cs": 63297, + "filetype-css": 63298, + "filetype-csv": 63299, + "filetype-doc": 63300, + "filetype-docx": 63301, + "filetype-exe": 63302, + "filetype-gif": 63303, + "filetype-heic": 63304, + "filetype-html": 63305, + "filetype-java": 63306, + "filetype-jpg": 63307, + "filetype-js": 63308, + "filetype-jsx": 63309, + "filetype-key": 63310, + "filetype-m4p": 63311, + "filetype-md": 63312, + "filetype-mdx": 63313, + "filetype-mov": 63314, + "filetype-mp3": 63315, + "filetype-mp4": 63316, + "filetype-otf": 63317, + "filetype-pdf": 63318, + "filetype-php": 63319, + "filetype-png": 63320, + "filetype-ppt": 63322, + "filetype-psd": 63323, + "filetype-py": 63324, + "filetype-raw": 63325, + "filetype-rb": 63326, + "filetype-sass": 63327, + "filetype-scss": 63328, + "filetype-sh": 63329, + "filetype-svg": 63330, + "filetype-tiff": 63331, + "filetype-tsx": 63332, + "filetype-ttf": 63333, + "filetype-txt": 63334, + "filetype-wav": 63335, + "filetype-woff": 63336, + "filetype-xls": 63338, + "filetype-xml": 63339, + "filetype-yml": 63340, + "heart-arrow": 63341, + "heart-pulse-fill": 63342, + "heart-pulse": 63343, + "heartbreak-fill": 63344, + "heartbreak": 63345, + "hearts": 63346, + "hospital-fill": 63347, + "hospital": 63348, + "house-heart-fill": 63349, + "house-heart": 63350, + "incognito": 63351, + "magnet-fill": 63352, + "magnet": 63353, + "person-heart": 63354, + "person-hearts": 63355, + "phone-flip": 63356, + "plugin": 63357, + "postage-fill": 63358, + "postage-heart-fill": 63359, + "postage-heart": 63360, + "postage": 63361, + "postcard-fill": 63362, + "postcard-heart-fill": 63363, + "postcard-heart": 63364, + "postcard": 63365, + "search-heart-fill": 63366, + "search-heart": 63367, + "sliders2-vertical": 63368, + "sliders2": 63369, + "trash3-fill": 63370, + "trash3": 63371, + "valentine": 63372, + "valentine2": 63373, + "wrench-adjustable-circle-fill": 63374, + "wrench-adjustable-circle": 63375, + "wrench-adjustable": 63376, + "filetype-json": 63377, + "filetype-pptx": 63378, + "filetype-xlsx": 63379, + "1-circle-fill": 63382, + "1-circle": 63383, + "1-square-fill": 63384, + "1-square": 63385, + "2-circle-fill": 63388, + "2-circle": 63389, + "2-square-fill": 63390, + "2-square": 63391, + "3-circle-fill": 63394, + "3-circle": 63395, + "3-square-fill": 63396, + "3-square": 63397, + "4-circle-fill": 63400, + "4-circle": 63401, + "4-square-fill": 63402, + "4-square": 63403, + "5-circle-fill": 63406, + "5-circle": 63407, + "5-square-fill": 63408, + "5-square": 63409, + "6-circle-fill": 63412, + "6-circle": 63413, + "6-square-fill": 63414, + "6-square": 63415, + "7-circle-fill": 63418, + "7-circle": 63419, + "7-square-fill": 63420, + "7-square": 63421, + "8-circle-fill": 63424, + "8-circle": 63425, + "8-square-fill": 63426, + "8-square": 63427, + "9-circle-fill": 63430, + "9-circle": 63431, + "9-square-fill": 63432, + "9-square": 63433, + "airplane-engines-fill": 63434, + "airplane-engines": 63435, + "airplane-fill": 63436, + "airplane": 63437, + "alexa": 63438, + "alipay": 63439, + "android": 63440, + "android2": 63441, + "box-fill": 63442, + "box-seam-fill": 63443, + "browser-chrome": 63444, + "browser-edge": 63445, + "browser-firefox": 63446, + "browser-safari": 63447, + "c-circle-fill": 63450, + "c-circle": 63451, + "c-square-fill": 63452, + "c-square": 63453, + "capsule-pill": 63454, + "capsule": 63455, + "car-front-fill": 63456, + "car-front": 63457, + "cassette-fill": 63458, + "cassette": 63459, + "cc-circle-fill": 63462, + "cc-circle": 63463, + "cc-square-fill": 63464, + "cc-square": 63465, + "cup-hot-fill": 63466, + "cup-hot": 63467, + "currency-rupee": 63468, + "dropbox": 63469, + "escape": 63470, + "fast-forward-btn-fill": 63471, + "fast-forward-btn": 63472, + "fast-forward-circle-fill": 63473, + "fast-forward-circle": 63474, + "fast-forward-fill": 63475, + "fast-forward": 63476, + "filetype-sql": 63477, + "fire": 63478, + "google-play": 63479, + "h-circle-fill": 63482, + "h-circle": 63483, + "h-square-fill": 63484, + "h-square": 63485, + "indent": 63486, + "lungs-fill": 63487, + "lungs": 63488, + "microsoft-teams": 63489, + "p-circle-fill": 63492, + "p-circle": 63493, + "p-square-fill": 63494, + "p-square": 63495, + "pass-fill": 63496, + "pass": 63497, + "prescription": 63498, + "prescription2": 63499, + "r-circle-fill": 63502, + "r-circle": 63503, + "r-square-fill": 63504, + "r-square": 63505, + "repeat-1": 63506, + "repeat": 63507, + "rewind-btn-fill": 63508, + "rewind-btn": 63509, + "rewind-circle-fill": 63510, + "rewind-circle": 63511, + "rewind-fill": 63512, + "rewind": 63513, + "train-freight-front-fill": 63514, + "train-freight-front": 63515, + "train-front-fill": 63516, + "train-front": 63517, + "train-lightrail-front-fill": 63518, + "train-lightrail-front": 63519, + "truck-front-fill": 63520, + "truck-front": 63521, + "ubuntu": 63522, + "unindent": 63523, + "unity": 63524, + "universal-access-circle": 63525, + "universal-access": 63526, + "virus": 63527, + "virus2": 63528, + "wechat": 63529, + "yelp": 63530, + "sign-stop-fill": 63531, + "sign-stop-lights-fill": 63532, + "sign-stop-lights": 63533, + "sign-stop": 63534, + "sign-turn-left-fill": 63535, + "sign-turn-left": 63536, + "sign-turn-right-fill": 63537, + "sign-turn-right": 63538, + "sign-turn-slight-left-fill": 63539, + "sign-turn-slight-left": 63540, + "sign-turn-slight-right-fill": 63541, + "sign-turn-slight-right": 63542, + "sign-yield-fill": 63543, + "sign-yield": 63544, + "ev-station-fill": 63545, + "ev-station": 63546, + "fuel-pump-diesel-fill": 63547, + "fuel-pump-diesel": 63548, + "fuel-pump-fill": 63549, + "fuel-pump": 63550, + "0-circle-fill": 63551, + "0-circle": 63552, + "0-square-fill": 63553, + "0-square": 63554, + "rocket-fill": 63555, + "rocket-takeoff-fill": 63556, + "rocket-takeoff": 63557, + "rocket": 63558, + "stripe": 63559, + "subscript": 63560, + "superscript": 63561, + "trello": 63562, + "envelope-at-fill": 63563, + "envelope-at": 63564, + "regex": 63565, + "text-wrap": 63566, + "sign-dead-end-fill": 63567, + "sign-dead-end": 63568, + "sign-do-not-enter-fill": 63569, + "sign-do-not-enter": 63570, + "sign-intersection-fill": 63571, + "sign-intersection-side-fill": 63572, + "sign-intersection-side": 63573, + "sign-intersection-t-fill": 63574, + "sign-intersection-t": 63575, + "sign-intersection-y-fill": 63576, + "sign-intersection-y": 63577, + "sign-intersection": 63578, + "sign-merge-left-fill": 63579, + "sign-merge-left": 63580, + "sign-merge-right-fill": 63581, + "sign-merge-right": 63582, + "sign-no-left-turn-fill": 63583, + "sign-no-left-turn": 63584, + "sign-no-parking-fill": 63585, + "sign-no-parking": 63586, + "sign-no-right-turn-fill": 63587, + "sign-no-right-turn": 63588, + "sign-railroad-fill": 63589, + "sign-railroad": 63590, + "building-add": 63591, + "building-check": 63592, + "building-dash": 63593, + "building-down": 63594, + "building-exclamation": 63595, + "building-fill-add": 63596, + "building-fill-check": 63597, + "building-fill-dash": 63598, + "building-fill-down": 63599, + "building-fill-exclamation": 63600, + "building-fill-gear": 63601, + "building-fill-lock": 63602, + "building-fill-slash": 63603, + "building-fill-up": 63604, + "building-fill-x": 63605, + "building-fill": 63606, + "building-gear": 63607, + "building-lock": 63608, + "building-slash": 63609, + "building-up": 63610, + "building-x": 63611, + "buildings-fill": 63612, + "buildings": 63613, + "bus-front-fill": 63614, + "bus-front": 63615, + "ev-front-fill": 63616, + "ev-front": 63617, + "globe-americas": 63618, + "globe-asia-australia": 63619, + "globe-central-south-asia": 63620, + "globe-europe-africa": 63621, + "house-add-fill": 63622, + "house-add": 63623, + "house-check-fill": 63624, + "house-check": 63625, + "house-dash-fill": 63626, + "house-dash": 63627, + "house-down-fill": 63628, + "house-down": 63629, + "house-exclamation-fill": 63630, + "house-exclamation": 63631, + "house-gear-fill": 63632, + "house-gear": 63633, + "house-lock-fill": 63634, + "house-lock": 63635, + "house-slash-fill": 63636, + "house-slash": 63637, + "house-up-fill": 63638, + "house-up": 63639, + "house-x-fill": 63640, + "house-x": 63641, + "person-add": 63642, + "person-down": 63643, + "person-exclamation": 63644, + "person-fill-add": 63645, + "person-fill-check": 63646, + "person-fill-dash": 63647, + "person-fill-down": 63648, + "person-fill-exclamation": 63649, + "person-fill-gear": 63650, + "person-fill-lock": 63651, + "person-fill-slash": 63652, + "person-fill-up": 63653, + "person-fill-x": 63654, + "person-gear": 63655, + "person-lock": 63656, + "person-slash": 63657, + "person-up": 63658, + "scooter": 63659, + "taxi-front-fill": 63660, + "taxi-front": 63661, + "amd": 63662, + "database-add": 63663, + "database-check": 63664, + "database-dash": 63665, + "database-down": 63666, + "database-exclamation": 63667, + "database-fill-add": 63668, + "database-fill-check": 63669, + "database-fill-dash": 63670, + "database-fill-down": 63671, + "database-fill-exclamation": 63672, + "database-fill-gear": 63673, + "database-fill-lock": 63674, + "database-fill-slash": 63675, + "database-fill-up": 63676, + "database-fill-x": 63677, + "database-fill": 63678, + "database-gear": 63679, + "database-lock": 63680, + "database-slash": 63681, + "database-up": 63682, + "database-x": 63683, + "database": 63684, + "houses-fill": 63685, + "houses": 63686, + "nvidia": 63687, + "person-vcard-fill": 63688, + "person-vcard": 63689, + "sina-weibo": 63690, + "tencent-qq": 63691, + "wikipedia": 63692, + "alphabet-uppercase": 62117, + "alphabet": 63114, + "amazon": 63117, + "arrows-collapse-vertical": 63120, + "arrows-expand-vertical": 63125, + "arrows-vertical": 63128, + "arrows": 63138, + "ban-fill": 63139, + "ban": 63158, + "bing": 63170, + "cake": 63200, + "cake2": 63213, + "cookie": 63214, + "copy": 63321, + "crosshair": 63337, + "crosshair2": 63380, + "emoji-astonished-fill": 63381, + "emoji-astonished": 63386, + "emoji-grimace-fill": 63387, + "emoji-grimace": 63392, + "emoji-grin-fill": 63393, + "emoji-grin": 63398, + "emoji-surprise-fill": 63399, + "emoji-surprise": 63404, + "emoji-tear-fill": 63405, + "emoji-tear": 63410, + "envelope-arrow-down-fill": 63411, + "envelope-arrow-down": 63416, + "envelope-arrow-up-fill": 63417, + "envelope-arrow-up": 63422, + "feather": 63423, + "feather2": 63428, + "floppy-fill": 63429, + "floppy": 63448, + "floppy2-fill": 63449, + "floppy2": 63460, + "gitlab": 63461, + "highlighter": 63480, + "marker-tip": 63490, + "nvme-fill": 63491, + "nvme": 63500, + "opencollective": 63501, + "pci-card-network": 63693, + "pci-card-sound": 63694, + "radar": 63695, + "send-arrow-down-fill": 63696, + "send-arrow-down": 63697, + "send-arrow-up-fill": 63698, + "send-arrow-up": 63699, + "sim-slash-fill": 63700, + "sim-slash": 63701, + "sourceforge": 63702, + "substack": 63703, + "threads-fill": 63704, + "threads": 63705, + "transparency": 63706, + "twitter-x": 63707, + "type-h4": 63708, + "type-h5": 63709, + "type-h6": 63710, + "backpack-fill": 63711, + "backpack": 63712, + "backpack2-fill": 63713, + "backpack2": 63714, + "backpack3-fill": 63715, + "backpack3": 63716, + "backpack4-fill": 63717, + "backpack4": 63718, + "brilliance": 63719, + "cake-fill": 63720, + "cake2-fill": 63721, + "duffle-fill": 63722, + "duffle": 63723, + "exposure": 63724, + "gender-neuter": 63725, + "highlights": 63726, + "luggage-fill": 63727, + "luggage": 63728, + "mailbox-flag": 63729, + "mailbox2-flag": 63730, + "noise-reduction": 63731, + "passport-fill": 63732, + "passport": 63733, + "person-arms-up": 63734, + "person-raised-hand": 63735, + "person-standing-dress": 63736, + "person-standing": 63737, + "person-walking": 63738, + "person-wheelchair": 63739, + "shadows": 63740, + "suitcase-fill": 63741, + "suitcase-lg-fill": 63742, + "suitcase-lg": 63743, + "suitcase": 63744, + "suitcase2-fill": 63745, + "suitcase2": 63746, + "vignette": 63747, + "bluesky": 63481, + "tux": 63748, + "beaker-fill": 63749, + "beaker": 63750, + "flask-fill": 63751, + "flask-florence-fill": 63752, + "flask-florence": 63753, + "flask": 63754, + "leaf-fill": 63755, + "leaf": 63756, + "measuring-cup-fill": 63757, + "measuring-cup": 63758, + "unlock2-fill": 63759, + "unlock2": 63760, + "battery-low": 63761, + "anthropic": 63762, + "apple-music": 63763, + "claude": 63764, + "openai": 63765, + "perplexity": 63766, + "css": 63767, + "javascript": 63768, + "typescript": 63769, + "fork-knife": 63770, + "globe-americas-fill": 63771, + "globe-asia-australia-fill": 63772, + "globe-central-south-asia-fill": 63773, + "globe-europe-africa-fill": 63774 +} \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bootstrap-icons.min.css b/web/vendor/bootstrap-icons/bootstrap-icons.min.css new file mode 100644 index 0000000..706a5c8 --- /dev/null +++ b/web/vendor/bootstrap-icons/bootstrap-icons.min.css @@ -0,0 +1,5 @@ +/*! + * Bootstrap Icons v1.13.1 (https://icons.getbootstrap.com/) + * Copyright 2019-2024 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/icons/blob/main/LICENSE) + */@font-face{font-display:block;font-family:bootstrap-icons;src:url("fonts/bootstrap-icons.woff2?e34853135f9e39acf64315236852cd5a") format("woff2"),url("fonts/bootstrap-icons.woff?e34853135f9e39acf64315236852cd5a") format("woff")}.bi::before,[class*=" bi-"]::before,[class^=bi-]::before{display:inline-block;font-family:bootstrap-icons!important;font-style:normal;font-weight:400!important;font-variant:normal;text-transform:none;line-height:1;vertical-align:-.125em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.bi-123::before{content:"\f67f"}.bi-alarm-fill::before{content:"\f101"}.bi-alarm::before{content:"\f102"}.bi-align-bottom::before{content:"\f103"}.bi-align-center::before{content:"\f104"}.bi-align-end::before{content:"\f105"}.bi-align-middle::before{content:"\f106"}.bi-align-start::before{content:"\f107"}.bi-align-top::before{content:"\f108"}.bi-alt::before{content:"\f109"}.bi-app-indicator::before{content:"\f10a"}.bi-app::before{content:"\f10b"}.bi-archive-fill::before{content:"\f10c"}.bi-archive::before{content:"\f10d"}.bi-arrow-90deg-down::before{content:"\f10e"}.bi-arrow-90deg-left::before{content:"\f10f"}.bi-arrow-90deg-right::before{content:"\f110"}.bi-arrow-90deg-up::before{content:"\f111"}.bi-arrow-bar-down::before{content:"\f112"}.bi-arrow-bar-left::before{content:"\f113"}.bi-arrow-bar-right::before{content:"\f114"}.bi-arrow-bar-up::before{content:"\f115"}.bi-arrow-clockwise::before{content:"\f116"}.bi-arrow-counterclockwise::before{content:"\f117"}.bi-arrow-down-circle-fill::before{content:"\f118"}.bi-arrow-down-circle::before{content:"\f119"}.bi-arrow-down-left-circle-fill::before{content:"\f11a"}.bi-arrow-down-left-circle::before{content:"\f11b"}.bi-arrow-down-left-square-fill::before{content:"\f11c"}.bi-arrow-down-left-square::before{content:"\f11d"}.bi-arrow-down-left::before{content:"\f11e"}.bi-arrow-down-right-circle-fill::before{content:"\f11f"}.bi-arrow-down-right-circle::before{content:"\f120"}.bi-arrow-down-right-square-fill::before{content:"\f121"}.bi-arrow-down-right-square::before{content:"\f122"}.bi-arrow-down-right::before{content:"\f123"}.bi-arrow-down-short::before{content:"\f124"}.bi-arrow-down-square-fill::before{content:"\f125"}.bi-arrow-down-square::before{content:"\f126"}.bi-arrow-down-up::before{content:"\f127"}.bi-arrow-down::before{content:"\f128"}.bi-arrow-left-circle-fill::before{content:"\f129"}.bi-arrow-left-circle::before{content:"\f12a"}.bi-arrow-left-right::before{content:"\f12b"}.bi-arrow-left-short::before{content:"\f12c"}.bi-arrow-left-square-fill::before{content:"\f12d"}.bi-arrow-left-square::before{content:"\f12e"}.bi-arrow-left::before{content:"\f12f"}.bi-arrow-repeat::before{content:"\f130"}.bi-arrow-return-left::before{content:"\f131"}.bi-arrow-return-right::before{content:"\f132"}.bi-arrow-right-circle-fill::before{content:"\f133"}.bi-arrow-right-circle::before{content:"\f134"}.bi-arrow-right-short::before{content:"\f135"}.bi-arrow-right-square-fill::before{content:"\f136"}.bi-arrow-right-square::before{content:"\f137"}.bi-arrow-right::before{content:"\f138"}.bi-arrow-up-circle-fill::before{content:"\f139"}.bi-arrow-up-circle::before{content:"\f13a"}.bi-arrow-up-left-circle-fill::before{content:"\f13b"}.bi-arrow-up-left-circle::before{content:"\f13c"}.bi-arrow-up-left-square-fill::before{content:"\f13d"}.bi-arrow-up-left-square::before{content:"\f13e"}.bi-arrow-up-left::before{content:"\f13f"}.bi-arrow-up-right-circle-fill::before{content:"\f140"}.bi-arrow-up-right-circle::before{content:"\f141"}.bi-arrow-up-right-square-fill::before{content:"\f142"}.bi-arrow-up-right-square::before{content:"\f143"}.bi-arrow-up-right::before{content:"\f144"}.bi-arrow-up-short::before{content:"\f145"}.bi-arrow-up-square-fill::before{content:"\f146"}.bi-arrow-up-square::before{content:"\f147"}.bi-arrow-up::before{content:"\f148"}.bi-arrows-angle-contract::before{content:"\f149"}.bi-arrows-angle-expand::before{content:"\f14a"}.bi-arrows-collapse::before{content:"\f14b"}.bi-arrows-expand::before{content:"\f14c"}.bi-arrows-fullscreen::before{content:"\f14d"}.bi-arrows-move::before{content:"\f14e"}.bi-aspect-ratio-fill::before{content:"\f14f"}.bi-aspect-ratio::before{content:"\f150"}.bi-asterisk::before{content:"\f151"}.bi-at::before{content:"\f152"}.bi-award-fill::before{content:"\f153"}.bi-award::before{content:"\f154"}.bi-back::before{content:"\f155"}.bi-backspace-fill::before{content:"\f156"}.bi-backspace-reverse-fill::before{content:"\f157"}.bi-backspace-reverse::before{content:"\f158"}.bi-backspace::before{content:"\f159"}.bi-badge-3d-fill::before{content:"\f15a"}.bi-badge-3d::before{content:"\f15b"}.bi-badge-4k-fill::before{content:"\f15c"}.bi-badge-4k::before{content:"\f15d"}.bi-badge-8k-fill::before{content:"\f15e"}.bi-badge-8k::before{content:"\f15f"}.bi-badge-ad-fill::before{content:"\f160"}.bi-badge-ad::before{content:"\f161"}.bi-badge-ar-fill::before{content:"\f162"}.bi-badge-ar::before{content:"\f163"}.bi-badge-cc-fill::before{content:"\f164"}.bi-badge-cc::before{content:"\f165"}.bi-badge-hd-fill::before{content:"\f166"}.bi-badge-hd::before{content:"\f167"}.bi-badge-tm-fill::before{content:"\f168"}.bi-badge-tm::before{content:"\f169"}.bi-badge-vo-fill::before{content:"\f16a"}.bi-badge-vo::before{content:"\f16b"}.bi-badge-vr-fill::before{content:"\f16c"}.bi-badge-vr::before{content:"\f16d"}.bi-badge-wc-fill::before{content:"\f16e"}.bi-badge-wc::before{content:"\f16f"}.bi-bag-check-fill::before{content:"\f170"}.bi-bag-check::before{content:"\f171"}.bi-bag-dash-fill::before{content:"\f172"}.bi-bag-dash::before{content:"\f173"}.bi-bag-fill::before{content:"\f174"}.bi-bag-plus-fill::before{content:"\f175"}.bi-bag-plus::before{content:"\f176"}.bi-bag-x-fill::before{content:"\f177"}.bi-bag-x::before{content:"\f178"}.bi-bag::before{content:"\f179"}.bi-bar-chart-fill::before{content:"\f17a"}.bi-bar-chart-line-fill::before{content:"\f17b"}.bi-bar-chart-line::before{content:"\f17c"}.bi-bar-chart-steps::before{content:"\f17d"}.bi-bar-chart::before{content:"\f17e"}.bi-basket-fill::before{content:"\f17f"}.bi-basket::before{content:"\f180"}.bi-basket2-fill::before{content:"\f181"}.bi-basket2::before{content:"\f182"}.bi-basket3-fill::before{content:"\f183"}.bi-basket3::before{content:"\f184"}.bi-battery-charging::before{content:"\f185"}.bi-battery-full::before{content:"\f186"}.bi-battery-half::before{content:"\f187"}.bi-battery::before{content:"\f188"}.bi-bell-fill::before{content:"\f189"}.bi-bell::before{content:"\f18a"}.bi-bezier::before{content:"\f18b"}.bi-bezier2::before{content:"\f18c"}.bi-bicycle::before{content:"\f18d"}.bi-binoculars-fill::before{content:"\f18e"}.bi-binoculars::before{content:"\f18f"}.bi-blockquote-left::before{content:"\f190"}.bi-blockquote-right::before{content:"\f191"}.bi-book-fill::before{content:"\f192"}.bi-book-half::before{content:"\f193"}.bi-book::before{content:"\f194"}.bi-bookmark-check-fill::before{content:"\f195"}.bi-bookmark-check::before{content:"\f196"}.bi-bookmark-dash-fill::before{content:"\f197"}.bi-bookmark-dash::before{content:"\f198"}.bi-bookmark-fill::before{content:"\f199"}.bi-bookmark-heart-fill::before{content:"\f19a"}.bi-bookmark-heart::before{content:"\f19b"}.bi-bookmark-plus-fill::before{content:"\f19c"}.bi-bookmark-plus::before{content:"\f19d"}.bi-bookmark-star-fill::before{content:"\f19e"}.bi-bookmark-star::before{content:"\f19f"}.bi-bookmark-x-fill::before{content:"\f1a0"}.bi-bookmark-x::before{content:"\f1a1"}.bi-bookmark::before{content:"\f1a2"}.bi-bookmarks-fill::before{content:"\f1a3"}.bi-bookmarks::before{content:"\f1a4"}.bi-bookshelf::before{content:"\f1a5"}.bi-bootstrap-fill::before{content:"\f1a6"}.bi-bootstrap-reboot::before{content:"\f1a7"}.bi-bootstrap::before{content:"\f1a8"}.bi-border-all::before{content:"\f1a9"}.bi-border-bottom::before{content:"\f1aa"}.bi-border-center::before{content:"\f1ab"}.bi-border-inner::before{content:"\f1ac"}.bi-border-left::before{content:"\f1ad"}.bi-border-middle::before{content:"\f1ae"}.bi-border-outer::before{content:"\f1af"}.bi-border-right::before{content:"\f1b0"}.bi-border-style::before{content:"\f1b1"}.bi-border-top::before{content:"\f1b2"}.bi-border-width::before{content:"\f1b3"}.bi-border::before{content:"\f1b4"}.bi-bounding-box-circles::before{content:"\f1b5"}.bi-bounding-box::before{content:"\f1b6"}.bi-box-arrow-down-left::before{content:"\f1b7"}.bi-box-arrow-down-right::before{content:"\f1b8"}.bi-box-arrow-down::before{content:"\f1b9"}.bi-box-arrow-in-down-left::before{content:"\f1ba"}.bi-box-arrow-in-down-right::before{content:"\f1bb"}.bi-box-arrow-in-down::before{content:"\f1bc"}.bi-box-arrow-in-left::before{content:"\f1bd"}.bi-box-arrow-in-right::before{content:"\f1be"}.bi-box-arrow-in-up-left::before{content:"\f1bf"}.bi-box-arrow-in-up-right::before{content:"\f1c0"}.bi-box-arrow-in-up::before{content:"\f1c1"}.bi-box-arrow-left::before{content:"\f1c2"}.bi-box-arrow-right::before{content:"\f1c3"}.bi-box-arrow-up-left::before{content:"\f1c4"}.bi-box-arrow-up-right::before{content:"\f1c5"}.bi-box-arrow-up::before{content:"\f1c6"}.bi-box-seam::before{content:"\f1c7"}.bi-box::before{content:"\f1c8"}.bi-braces::before{content:"\f1c9"}.bi-bricks::before{content:"\f1ca"}.bi-briefcase-fill::before{content:"\f1cb"}.bi-briefcase::before{content:"\f1cc"}.bi-brightness-alt-high-fill::before{content:"\f1cd"}.bi-brightness-alt-high::before{content:"\f1ce"}.bi-brightness-alt-low-fill::before{content:"\f1cf"}.bi-brightness-alt-low::before{content:"\f1d0"}.bi-brightness-high-fill::before{content:"\f1d1"}.bi-brightness-high::before{content:"\f1d2"}.bi-brightness-low-fill::before{content:"\f1d3"}.bi-brightness-low::before{content:"\f1d4"}.bi-broadcast-pin::before{content:"\f1d5"}.bi-broadcast::before{content:"\f1d6"}.bi-brush-fill::before{content:"\f1d7"}.bi-brush::before{content:"\f1d8"}.bi-bucket-fill::before{content:"\f1d9"}.bi-bucket::before{content:"\f1da"}.bi-bug-fill::before{content:"\f1db"}.bi-bug::before{content:"\f1dc"}.bi-building::before{content:"\f1dd"}.bi-bullseye::before{content:"\f1de"}.bi-calculator-fill::before{content:"\f1df"}.bi-calculator::before{content:"\f1e0"}.bi-calendar-check-fill::before{content:"\f1e1"}.bi-calendar-check::before{content:"\f1e2"}.bi-calendar-date-fill::before{content:"\f1e3"}.bi-calendar-date::before{content:"\f1e4"}.bi-calendar-day-fill::before{content:"\f1e5"}.bi-calendar-day::before{content:"\f1e6"}.bi-calendar-event-fill::before{content:"\f1e7"}.bi-calendar-event::before{content:"\f1e8"}.bi-calendar-fill::before{content:"\f1e9"}.bi-calendar-minus-fill::before{content:"\f1ea"}.bi-calendar-minus::before{content:"\f1eb"}.bi-calendar-month-fill::before{content:"\f1ec"}.bi-calendar-month::before{content:"\f1ed"}.bi-calendar-plus-fill::before{content:"\f1ee"}.bi-calendar-plus::before{content:"\f1ef"}.bi-calendar-range-fill::before{content:"\f1f0"}.bi-calendar-range::before{content:"\f1f1"}.bi-calendar-week-fill::before{content:"\f1f2"}.bi-calendar-week::before{content:"\f1f3"}.bi-calendar-x-fill::before{content:"\f1f4"}.bi-calendar-x::before{content:"\f1f5"}.bi-calendar::before{content:"\f1f6"}.bi-calendar2-check-fill::before{content:"\f1f7"}.bi-calendar2-check::before{content:"\f1f8"}.bi-calendar2-date-fill::before{content:"\f1f9"}.bi-calendar2-date::before{content:"\f1fa"}.bi-calendar2-day-fill::before{content:"\f1fb"}.bi-calendar2-day::before{content:"\f1fc"}.bi-calendar2-event-fill::before{content:"\f1fd"}.bi-calendar2-event::before{content:"\f1fe"}.bi-calendar2-fill::before{content:"\f1ff"}.bi-calendar2-minus-fill::before{content:"\f200"}.bi-calendar2-minus::before{content:"\f201"}.bi-calendar2-month-fill::before{content:"\f202"}.bi-calendar2-month::before{content:"\f203"}.bi-calendar2-plus-fill::before{content:"\f204"}.bi-calendar2-plus::before{content:"\f205"}.bi-calendar2-range-fill::before{content:"\f206"}.bi-calendar2-range::before{content:"\f207"}.bi-calendar2-week-fill::before{content:"\f208"}.bi-calendar2-week::before{content:"\f209"}.bi-calendar2-x-fill::before{content:"\f20a"}.bi-calendar2-x::before{content:"\f20b"}.bi-calendar2::before{content:"\f20c"}.bi-calendar3-event-fill::before{content:"\f20d"}.bi-calendar3-event::before{content:"\f20e"}.bi-calendar3-fill::before{content:"\f20f"}.bi-calendar3-range-fill::before{content:"\f210"}.bi-calendar3-range::before{content:"\f211"}.bi-calendar3-week-fill::before{content:"\f212"}.bi-calendar3-week::before{content:"\f213"}.bi-calendar3::before{content:"\f214"}.bi-calendar4-event::before{content:"\f215"}.bi-calendar4-range::before{content:"\f216"}.bi-calendar4-week::before{content:"\f217"}.bi-calendar4::before{content:"\f218"}.bi-camera-fill::before{content:"\f219"}.bi-camera-reels-fill::before{content:"\f21a"}.bi-camera-reels::before{content:"\f21b"}.bi-camera-video-fill::before{content:"\f21c"}.bi-camera-video-off-fill::before{content:"\f21d"}.bi-camera-video-off::before{content:"\f21e"}.bi-camera-video::before{content:"\f21f"}.bi-camera::before{content:"\f220"}.bi-camera2::before{content:"\f221"}.bi-capslock-fill::before{content:"\f222"}.bi-capslock::before{content:"\f223"}.bi-card-checklist::before{content:"\f224"}.bi-card-heading::before{content:"\f225"}.bi-card-image::before{content:"\f226"}.bi-card-list::before{content:"\f227"}.bi-card-text::before{content:"\f228"}.bi-caret-down-fill::before{content:"\f229"}.bi-caret-down-square-fill::before{content:"\f22a"}.bi-caret-down-square::before{content:"\f22b"}.bi-caret-down::before{content:"\f22c"}.bi-caret-left-fill::before{content:"\f22d"}.bi-caret-left-square-fill::before{content:"\f22e"}.bi-caret-left-square::before{content:"\f22f"}.bi-caret-left::before{content:"\f230"}.bi-caret-right-fill::before{content:"\f231"}.bi-caret-right-square-fill::before{content:"\f232"}.bi-caret-right-square::before{content:"\f233"}.bi-caret-right::before{content:"\f234"}.bi-caret-up-fill::before{content:"\f235"}.bi-caret-up-square-fill::before{content:"\f236"}.bi-caret-up-square::before{content:"\f237"}.bi-caret-up::before{content:"\f238"}.bi-cart-check-fill::before{content:"\f239"}.bi-cart-check::before{content:"\f23a"}.bi-cart-dash-fill::before{content:"\f23b"}.bi-cart-dash::before{content:"\f23c"}.bi-cart-fill::before{content:"\f23d"}.bi-cart-plus-fill::before{content:"\f23e"}.bi-cart-plus::before{content:"\f23f"}.bi-cart-x-fill::before{content:"\f240"}.bi-cart-x::before{content:"\f241"}.bi-cart::before{content:"\f242"}.bi-cart2::before{content:"\f243"}.bi-cart3::before{content:"\f244"}.bi-cart4::before{content:"\f245"}.bi-cash-stack::before{content:"\f246"}.bi-cash::before{content:"\f247"}.bi-cast::before{content:"\f248"}.bi-chat-dots-fill::before{content:"\f249"}.bi-chat-dots::before{content:"\f24a"}.bi-chat-fill::before{content:"\f24b"}.bi-chat-left-dots-fill::before{content:"\f24c"}.bi-chat-left-dots::before{content:"\f24d"}.bi-chat-left-fill::before{content:"\f24e"}.bi-chat-left-quote-fill::before{content:"\f24f"}.bi-chat-left-quote::before{content:"\f250"}.bi-chat-left-text-fill::before{content:"\f251"}.bi-chat-left-text::before{content:"\f252"}.bi-chat-left::before{content:"\f253"}.bi-chat-quote-fill::before{content:"\f254"}.bi-chat-quote::before{content:"\f255"}.bi-chat-right-dots-fill::before{content:"\f256"}.bi-chat-right-dots::before{content:"\f257"}.bi-chat-right-fill::before{content:"\f258"}.bi-chat-right-quote-fill::before{content:"\f259"}.bi-chat-right-quote::before{content:"\f25a"}.bi-chat-right-text-fill::before{content:"\f25b"}.bi-chat-right-text::before{content:"\f25c"}.bi-chat-right::before{content:"\f25d"}.bi-chat-square-dots-fill::before{content:"\f25e"}.bi-chat-square-dots::before{content:"\f25f"}.bi-chat-square-fill::before{content:"\f260"}.bi-chat-square-quote-fill::before{content:"\f261"}.bi-chat-square-quote::before{content:"\f262"}.bi-chat-square-text-fill::before{content:"\f263"}.bi-chat-square-text::before{content:"\f264"}.bi-chat-square::before{content:"\f265"}.bi-chat-text-fill::before{content:"\f266"}.bi-chat-text::before{content:"\f267"}.bi-chat::before{content:"\f268"}.bi-check-all::before{content:"\f269"}.bi-check-circle-fill::before{content:"\f26a"}.bi-check-circle::before{content:"\f26b"}.bi-check-square-fill::before{content:"\f26c"}.bi-check-square::before{content:"\f26d"}.bi-check::before{content:"\f26e"}.bi-check2-all::before{content:"\f26f"}.bi-check2-circle::before{content:"\f270"}.bi-check2-square::before{content:"\f271"}.bi-check2::before{content:"\f272"}.bi-chevron-bar-contract::before{content:"\f273"}.bi-chevron-bar-down::before{content:"\f274"}.bi-chevron-bar-expand::before{content:"\f275"}.bi-chevron-bar-left::before{content:"\f276"}.bi-chevron-bar-right::before{content:"\f277"}.bi-chevron-bar-up::before{content:"\f278"}.bi-chevron-compact-down::before{content:"\f279"}.bi-chevron-compact-left::before{content:"\f27a"}.bi-chevron-compact-right::before{content:"\f27b"}.bi-chevron-compact-up::before{content:"\f27c"}.bi-chevron-contract::before{content:"\f27d"}.bi-chevron-double-down::before{content:"\f27e"}.bi-chevron-double-left::before{content:"\f27f"}.bi-chevron-double-right::before{content:"\f280"}.bi-chevron-double-up::before{content:"\f281"}.bi-chevron-down::before{content:"\f282"}.bi-chevron-expand::before{content:"\f283"}.bi-chevron-left::before{content:"\f284"}.bi-chevron-right::before{content:"\f285"}.bi-chevron-up::before{content:"\f286"}.bi-circle-fill::before{content:"\f287"}.bi-circle-half::before{content:"\f288"}.bi-circle-square::before{content:"\f289"}.bi-circle::before{content:"\f28a"}.bi-clipboard-check::before{content:"\f28b"}.bi-clipboard-data::before{content:"\f28c"}.bi-clipboard-minus::before{content:"\f28d"}.bi-clipboard-plus::before{content:"\f28e"}.bi-clipboard-x::before{content:"\f28f"}.bi-clipboard::before{content:"\f290"}.bi-clock-fill::before{content:"\f291"}.bi-clock-history::before{content:"\f292"}.bi-clock::before{content:"\f293"}.bi-cloud-arrow-down-fill::before{content:"\f294"}.bi-cloud-arrow-down::before{content:"\f295"}.bi-cloud-arrow-up-fill::before{content:"\f296"}.bi-cloud-arrow-up::before{content:"\f297"}.bi-cloud-check-fill::before{content:"\f298"}.bi-cloud-check::before{content:"\f299"}.bi-cloud-download-fill::before{content:"\f29a"}.bi-cloud-download::before{content:"\f29b"}.bi-cloud-drizzle-fill::before{content:"\f29c"}.bi-cloud-drizzle::before{content:"\f29d"}.bi-cloud-fill::before{content:"\f29e"}.bi-cloud-fog-fill::before{content:"\f29f"}.bi-cloud-fog::before{content:"\f2a0"}.bi-cloud-fog2-fill::before{content:"\f2a1"}.bi-cloud-fog2::before{content:"\f2a2"}.bi-cloud-hail-fill::before{content:"\f2a3"}.bi-cloud-hail::before{content:"\f2a4"}.bi-cloud-haze-fill::before{content:"\f2a6"}.bi-cloud-haze::before{content:"\f2a7"}.bi-cloud-haze2-fill::before{content:"\f2a8"}.bi-cloud-lightning-fill::before{content:"\f2a9"}.bi-cloud-lightning-rain-fill::before{content:"\f2aa"}.bi-cloud-lightning-rain::before{content:"\f2ab"}.bi-cloud-lightning::before{content:"\f2ac"}.bi-cloud-minus-fill::before{content:"\f2ad"}.bi-cloud-minus::before{content:"\f2ae"}.bi-cloud-moon-fill::before{content:"\f2af"}.bi-cloud-moon::before{content:"\f2b0"}.bi-cloud-plus-fill::before{content:"\f2b1"}.bi-cloud-plus::before{content:"\f2b2"}.bi-cloud-rain-fill::before{content:"\f2b3"}.bi-cloud-rain-heavy-fill::before{content:"\f2b4"}.bi-cloud-rain-heavy::before{content:"\f2b5"}.bi-cloud-rain::before{content:"\f2b6"}.bi-cloud-slash-fill::before{content:"\f2b7"}.bi-cloud-slash::before{content:"\f2b8"}.bi-cloud-sleet-fill::before{content:"\f2b9"}.bi-cloud-sleet::before{content:"\f2ba"}.bi-cloud-snow-fill::before{content:"\f2bb"}.bi-cloud-snow::before{content:"\f2bc"}.bi-cloud-sun-fill::before{content:"\f2bd"}.bi-cloud-sun::before{content:"\f2be"}.bi-cloud-upload-fill::before{content:"\f2bf"}.bi-cloud-upload::before{content:"\f2c0"}.bi-cloud::before{content:"\f2c1"}.bi-clouds-fill::before{content:"\f2c2"}.bi-clouds::before{content:"\f2c3"}.bi-cloudy-fill::before{content:"\f2c4"}.bi-cloudy::before{content:"\f2c5"}.bi-code-slash::before{content:"\f2c6"}.bi-code-square::before{content:"\f2c7"}.bi-code::before{content:"\f2c8"}.bi-collection-fill::before{content:"\f2c9"}.bi-collection-play-fill::before{content:"\f2ca"}.bi-collection-play::before{content:"\f2cb"}.bi-collection::before{content:"\f2cc"}.bi-columns-gap::before{content:"\f2cd"}.bi-columns::before{content:"\f2ce"}.bi-command::before{content:"\f2cf"}.bi-compass-fill::before{content:"\f2d0"}.bi-compass::before{content:"\f2d1"}.bi-cone-striped::before{content:"\f2d2"}.bi-cone::before{content:"\f2d3"}.bi-controller::before{content:"\f2d4"}.bi-cpu-fill::before{content:"\f2d5"}.bi-cpu::before{content:"\f2d6"}.bi-credit-card-2-back-fill::before{content:"\f2d7"}.bi-credit-card-2-back::before{content:"\f2d8"}.bi-credit-card-2-front-fill::before{content:"\f2d9"}.bi-credit-card-2-front::before{content:"\f2da"}.bi-credit-card-fill::before{content:"\f2db"}.bi-credit-card::before{content:"\f2dc"}.bi-crop::before{content:"\f2dd"}.bi-cup-fill::before{content:"\f2de"}.bi-cup-straw::before{content:"\f2df"}.bi-cup::before{content:"\f2e0"}.bi-cursor-fill::before{content:"\f2e1"}.bi-cursor-text::before{content:"\f2e2"}.bi-cursor::before{content:"\f2e3"}.bi-dash-circle-dotted::before{content:"\f2e4"}.bi-dash-circle-fill::before{content:"\f2e5"}.bi-dash-circle::before{content:"\f2e6"}.bi-dash-square-dotted::before{content:"\f2e7"}.bi-dash-square-fill::before{content:"\f2e8"}.bi-dash-square::before{content:"\f2e9"}.bi-dash::before{content:"\f2ea"}.bi-diagram-2-fill::before{content:"\f2eb"}.bi-diagram-2::before{content:"\f2ec"}.bi-diagram-3-fill::before{content:"\f2ed"}.bi-diagram-3::before{content:"\f2ee"}.bi-diamond-fill::before{content:"\f2ef"}.bi-diamond-half::before{content:"\f2f0"}.bi-diamond::before{content:"\f2f1"}.bi-dice-1-fill::before{content:"\f2f2"}.bi-dice-1::before{content:"\f2f3"}.bi-dice-2-fill::before{content:"\f2f4"}.bi-dice-2::before{content:"\f2f5"}.bi-dice-3-fill::before{content:"\f2f6"}.bi-dice-3::before{content:"\f2f7"}.bi-dice-4-fill::before{content:"\f2f8"}.bi-dice-4::before{content:"\f2f9"}.bi-dice-5-fill::before{content:"\f2fa"}.bi-dice-5::before{content:"\f2fb"}.bi-dice-6-fill::before{content:"\f2fc"}.bi-dice-6::before{content:"\f2fd"}.bi-disc-fill::before{content:"\f2fe"}.bi-disc::before{content:"\f2ff"}.bi-discord::before{content:"\f300"}.bi-display-fill::before{content:"\f301"}.bi-display::before{content:"\f302"}.bi-distribute-horizontal::before{content:"\f303"}.bi-distribute-vertical::before{content:"\f304"}.bi-door-closed-fill::before{content:"\f305"}.bi-door-closed::before{content:"\f306"}.bi-door-open-fill::before{content:"\f307"}.bi-door-open::before{content:"\f308"}.bi-dot::before{content:"\f309"}.bi-download::before{content:"\f30a"}.bi-droplet-fill::before{content:"\f30b"}.bi-droplet-half::before{content:"\f30c"}.bi-droplet::before{content:"\f30d"}.bi-earbuds::before{content:"\f30e"}.bi-easel-fill::before{content:"\f30f"}.bi-easel::before{content:"\f310"}.bi-egg-fill::before{content:"\f311"}.bi-egg-fried::before{content:"\f312"}.bi-egg::before{content:"\f313"}.bi-eject-fill::before{content:"\f314"}.bi-eject::before{content:"\f315"}.bi-emoji-angry-fill::before{content:"\f316"}.bi-emoji-angry::before{content:"\f317"}.bi-emoji-dizzy-fill::before{content:"\f318"}.bi-emoji-dizzy::before{content:"\f319"}.bi-emoji-expressionless-fill::before{content:"\f31a"}.bi-emoji-expressionless::before{content:"\f31b"}.bi-emoji-frown-fill::before{content:"\f31c"}.bi-emoji-frown::before{content:"\f31d"}.bi-emoji-heart-eyes-fill::before{content:"\f31e"}.bi-emoji-heart-eyes::before{content:"\f31f"}.bi-emoji-laughing-fill::before{content:"\f320"}.bi-emoji-laughing::before{content:"\f321"}.bi-emoji-neutral-fill::before{content:"\f322"}.bi-emoji-neutral::before{content:"\f323"}.bi-emoji-smile-fill::before{content:"\f324"}.bi-emoji-smile-upside-down-fill::before{content:"\f325"}.bi-emoji-smile-upside-down::before{content:"\f326"}.bi-emoji-smile::before{content:"\f327"}.bi-emoji-sunglasses-fill::before{content:"\f328"}.bi-emoji-sunglasses::before{content:"\f329"}.bi-emoji-wink-fill::before{content:"\f32a"}.bi-emoji-wink::before{content:"\f32b"}.bi-envelope-fill::before{content:"\f32c"}.bi-envelope-open-fill::before{content:"\f32d"}.bi-envelope-open::before{content:"\f32e"}.bi-envelope::before{content:"\f32f"}.bi-eraser-fill::before{content:"\f330"}.bi-eraser::before{content:"\f331"}.bi-exclamation-circle-fill::before{content:"\f332"}.bi-exclamation-circle::before{content:"\f333"}.bi-exclamation-diamond-fill::before{content:"\f334"}.bi-exclamation-diamond::before{content:"\f335"}.bi-exclamation-octagon-fill::before{content:"\f336"}.bi-exclamation-octagon::before{content:"\f337"}.bi-exclamation-square-fill::before{content:"\f338"}.bi-exclamation-square::before{content:"\f339"}.bi-exclamation-triangle-fill::before{content:"\f33a"}.bi-exclamation-triangle::before{content:"\f33b"}.bi-exclamation::before{content:"\f33c"}.bi-exclude::before{content:"\f33d"}.bi-eye-fill::before{content:"\f33e"}.bi-eye-slash-fill::before{content:"\f33f"}.bi-eye-slash::before{content:"\f340"}.bi-eye::before{content:"\f341"}.bi-eyedropper::before{content:"\f342"}.bi-eyeglasses::before{content:"\f343"}.bi-facebook::before{content:"\f344"}.bi-file-arrow-down-fill::before{content:"\f345"}.bi-file-arrow-down::before{content:"\f346"}.bi-file-arrow-up-fill::before{content:"\f347"}.bi-file-arrow-up::before{content:"\f348"}.bi-file-bar-graph-fill::before{content:"\f349"}.bi-file-bar-graph::before{content:"\f34a"}.bi-file-binary-fill::before{content:"\f34b"}.bi-file-binary::before{content:"\f34c"}.bi-file-break-fill::before{content:"\f34d"}.bi-file-break::before{content:"\f34e"}.bi-file-check-fill::before{content:"\f34f"}.bi-file-check::before{content:"\f350"}.bi-file-code-fill::before{content:"\f351"}.bi-file-code::before{content:"\f352"}.bi-file-diff-fill::before{content:"\f353"}.bi-file-diff::before{content:"\f354"}.bi-file-earmark-arrow-down-fill::before{content:"\f355"}.bi-file-earmark-arrow-down::before{content:"\f356"}.bi-file-earmark-arrow-up-fill::before{content:"\f357"}.bi-file-earmark-arrow-up::before{content:"\f358"}.bi-file-earmark-bar-graph-fill::before{content:"\f359"}.bi-file-earmark-bar-graph::before{content:"\f35a"}.bi-file-earmark-binary-fill::before{content:"\f35b"}.bi-file-earmark-binary::before{content:"\f35c"}.bi-file-earmark-break-fill::before{content:"\f35d"}.bi-file-earmark-break::before{content:"\f35e"}.bi-file-earmark-check-fill::before{content:"\f35f"}.bi-file-earmark-check::before{content:"\f360"}.bi-file-earmark-code-fill::before{content:"\f361"}.bi-file-earmark-code::before{content:"\f362"}.bi-file-earmark-diff-fill::before{content:"\f363"}.bi-file-earmark-diff::before{content:"\f364"}.bi-file-earmark-easel-fill::before{content:"\f365"}.bi-file-earmark-easel::before{content:"\f366"}.bi-file-earmark-excel-fill::before{content:"\f367"}.bi-file-earmark-excel::before{content:"\f368"}.bi-file-earmark-fill::before{content:"\f369"}.bi-file-earmark-font-fill::before{content:"\f36a"}.bi-file-earmark-font::before{content:"\f36b"}.bi-file-earmark-image-fill::before{content:"\f36c"}.bi-file-earmark-image::before{content:"\f36d"}.bi-file-earmark-lock-fill::before{content:"\f36e"}.bi-file-earmark-lock::before{content:"\f36f"}.bi-file-earmark-lock2-fill::before{content:"\f370"}.bi-file-earmark-lock2::before{content:"\f371"}.bi-file-earmark-medical-fill::before{content:"\f372"}.bi-file-earmark-medical::before{content:"\f373"}.bi-file-earmark-minus-fill::before{content:"\f374"}.bi-file-earmark-minus::before{content:"\f375"}.bi-file-earmark-music-fill::before{content:"\f376"}.bi-file-earmark-music::before{content:"\f377"}.bi-file-earmark-person-fill::before{content:"\f378"}.bi-file-earmark-person::before{content:"\f379"}.bi-file-earmark-play-fill::before{content:"\f37a"}.bi-file-earmark-play::before{content:"\f37b"}.bi-file-earmark-plus-fill::before{content:"\f37c"}.bi-file-earmark-plus::before{content:"\f37d"}.bi-file-earmark-post-fill::before{content:"\f37e"}.bi-file-earmark-post::before{content:"\f37f"}.bi-file-earmark-ppt-fill::before{content:"\f380"}.bi-file-earmark-ppt::before{content:"\f381"}.bi-file-earmark-richtext-fill::before{content:"\f382"}.bi-file-earmark-richtext::before{content:"\f383"}.bi-file-earmark-ruled-fill::before{content:"\f384"}.bi-file-earmark-ruled::before{content:"\f385"}.bi-file-earmark-slides-fill::before{content:"\f386"}.bi-file-earmark-slides::before{content:"\f387"}.bi-file-earmark-spreadsheet-fill::before{content:"\f388"}.bi-file-earmark-spreadsheet::before{content:"\f389"}.bi-file-earmark-text-fill::before{content:"\f38a"}.bi-file-earmark-text::before{content:"\f38b"}.bi-file-earmark-word-fill::before{content:"\f38c"}.bi-file-earmark-word::before{content:"\f38d"}.bi-file-earmark-x-fill::before{content:"\f38e"}.bi-file-earmark-x::before{content:"\f38f"}.bi-file-earmark-zip-fill::before{content:"\f390"}.bi-file-earmark-zip::before{content:"\f391"}.bi-file-earmark::before{content:"\f392"}.bi-file-easel-fill::before{content:"\f393"}.bi-file-easel::before{content:"\f394"}.bi-file-excel-fill::before{content:"\f395"}.bi-file-excel::before{content:"\f396"}.bi-file-fill::before{content:"\f397"}.bi-file-font-fill::before{content:"\f398"}.bi-file-font::before{content:"\f399"}.bi-file-image-fill::before{content:"\f39a"}.bi-file-image::before{content:"\f39b"}.bi-file-lock-fill::before{content:"\f39c"}.bi-file-lock::before{content:"\f39d"}.bi-file-lock2-fill::before{content:"\f39e"}.bi-file-lock2::before{content:"\f39f"}.bi-file-medical-fill::before{content:"\f3a0"}.bi-file-medical::before{content:"\f3a1"}.bi-file-minus-fill::before{content:"\f3a2"}.bi-file-minus::before{content:"\f3a3"}.bi-file-music-fill::before{content:"\f3a4"}.bi-file-music::before{content:"\f3a5"}.bi-file-person-fill::before{content:"\f3a6"}.bi-file-person::before{content:"\f3a7"}.bi-file-play-fill::before{content:"\f3a8"}.bi-file-play::before{content:"\f3a9"}.bi-file-plus-fill::before{content:"\f3aa"}.bi-file-plus::before{content:"\f3ab"}.bi-file-post-fill::before{content:"\f3ac"}.bi-file-post::before{content:"\f3ad"}.bi-file-ppt-fill::before{content:"\f3ae"}.bi-file-ppt::before{content:"\f3af"}.bi-file-richtext-fill::before{content:"\f3b0"}.bi-file-richtext::before{content:"\f3b1"}.bi-file-ruled-fill::before{content:"\f3b2"}.bi-file-ruled::before{content:"\f3b3"}.bi-file-slides-fill::before{content:"\f3b4"}.bi-file-slides::before{content:"\f3b5"}.bi-file-spreadsheet-fill::before{content:"\f3b6"}.bi-file-spreadsheet::before{content:"\f3b7"}.bi-file-text-fill::before{content:"\f3b8"}.bi-file-text::before{content:"\f3b9"}.bi-file-word-fill::before{content:"\f3ba"}.bi-file-word::before{content:"\f3bb"}.bi-file-x-fill::before{content:"\f3bc"}.bi-file-x::before{content:"\f3bd"}.bi-file-zip-fill::before{content:"\f3be"}.bi-file-zip::before{content:"\f3bf"}.bi-file::before{content:"\f3c0"}.bi-files-alt::before{content:"\f3c1"}.bi-files::before{content:"\f3c2"}.bi-film::before{content:"\f3c3"}.bi-filter-circle-fill::before{content:"\f3c4"}.bi-filter-circle::before{content:"\f3c5"}.bi-filter-left::before{content:"\f3c6"}.bi-filter-right::before{content:"\f3c7"}.bi-filter-square-fill::before{content:"\f3c8"}.bi-filter-square::before{content:"\f3c9"}.bi-filter::before{content:"\f3ca"}.bi-flag-fill::before{content:"\f3cb"}.bi-flag::before{content:"\f3cc"}.bi-flower1::before{content:"\f3cd"}.bi-flower2::before{content:"\f3ce"}.bi-flower3::before{content:"\f3cf"}.bi-folder-check::before{content:"\f3d0"}.bi-folder-fill::before{content:"\f3d1"}.bi-folder-minus::before{content:"\f3d2"}.bi-folder-plus::before{content:"\f3d3"}.bi-folder-symlink-fill::before{content:"\f3d4"}.bi-folder-symlink::before{content:"\f3d5"}.bi-folder-x::before{content:"\f3d6"}.bi-folder::before{content:"\f3d7"}.bi-folder2-open::before{content:"\f3d8"}.bi-folder2::before{content:"\f3d9"}.bi-fonts::before{content:"\f3da"}.bi-forward-fill::before{content:"\f3db"}.bi-forward::before{content:"\f3dc"}.bi-front::before{content:"\f3dd"}.bi-fullscreen-exit::before{content:"\f3de"}.bi-fullscreen::before{content:"\f3df"}.bi-funnel-fill::before{content:"\f3e0"}.bi-funnel::before{content:"\f3e1"}.bi-gear-fill::before{content:"\f3e2"}.bi-gear-wide-connected::before{content:"\f3e3"}.bi-gear-wide::before{content:"\f3e4"}.bi-gear::before{content:"\f3e5"}.bi-gem::before{content:"\f3e6"}.bi-geo-alt-fill::before{content:"\f3e7"}.bi-geo-alt::before{content:"\f3e8"}.bi-geo-fill::before{content:"\f3e9"}.bi-geo::before{content:"\f3ea"}.bi-gift-fill::before{content:"\f3eb"}.bi-gift::before{content:"\f3ec"}.bi-github::before{content:"\f3ed"}.bi-globe::before{content:"\f3ee"}.bi-globe2::before{content:"\f3ef"}.bi-google::before{content:"\f3f0"}.bi-graph-down::before{content:"\f3f1"}.bi-graph-up::before{content:"\f3f2"}.bi-grid-1x2-fill::before{content:"\f3f3"}.bi-grid-1x2::before{content:"\f3f4"}.bi-grid-3x2-gap-fill::before{content:"\f3f5"}.bi-grid-3x2-gap::before{content:"\f3f6"}.bi-grid-3x2::before{content:"\f3f7"}.bi-grid-3x3-gap-fill::before{content:"\f3f8"}.bi-grid-3x3-gap::before{content:"\f3f9"}.bi-grid-3x3::before{content:"\f3fa"}.bi-grid-fill::before{content:"\f3fb"}.bi-grid::before{content:"\f3fc"}.bi-grip-horizontal::before{content:"\f3fd"}.bi-grip-vertical::before{content:"\f3fe"}.bi-hammer::before{content:"\f3ff"}.bi-hand-index-fill::before{content:"\f400"}.bi-hand-index-thumb-fill::before{content:"\f401"}.bi-hand-index-thumb::before{content:"\f402"}.bi-hand-index::before{content:"\f403"}.bi-hand-thumbs-down-fill::before{content:"\f404"}.bi-hand-thumbs-down::before{content:"\f405"}.bi-hand-thumbs-up-fill::before{content:"\f406"}.bi-hand-thumbs-up::before{content:"\f407"}.bi-handbag-fill::before{content:"\f408"}.bi-handbag::before{content:"\f409"}.bi-hash::before{content:"\f40a"}.bi-hdd-fill::before{content:"\f40b"}.bi-hdd-network-fill::before{content:"\f40c"}.bi-hdd-network::before{content:"\f40d"}.bi-hdd-rack-fill::before{content:"\f40e"}.bi-hdd-rack::before{content:"\f40f"}.bi-hdd-stack-fill::before{content:"\f410"}.bi-hdd-stack::before{content:"\f411"}.bi-hdd::before{content:"\f412"}.bi-headphones::before{content:"\f413"}.bi-headset::before{content:"\f414"}.bi-heart-fill::before{content:"\f415"}.bi-heart-half::before{content:"\f416"}.bi-heart::before{content:"\f417"}.bi-heptagon-fill::before{content:"\f418"}.bi-heptagon-half::before{content:"\f419"}.bi-heptagon::before{content:"\f41a"}.bi-hexagon-fill::before{content:"\f41b"}.bi-hexagon-half::before{content:"\f41c"}.bi-hexagon::before{content:"\f41d"}.bi-hourglass-bottom::before{content:"\f41e"}.bi-hourglass-split::before{content:"\f41f"}.bi-hourglass-top::before{content:"\f420"}.bi-hourglass::before{content:"\f421"}.bi-house-door-fill::before{content:"\f422"}.bi-house-door::before{content:"\f423"}.bi-house-fill::before{content:"\f424"}.bi-house::before{content:"\f425"}.bi-hr::before{content:"\f426"}.bi-hurricane::before{content:"\f427"}.bi-image-alt::before{content:"\f428"}.bi-image-fill::before{content:"\f429"}.bi-image::before{content:"\f42a"}.bi-images::before{content:"\f42b"}.bi-inbox-fill::before{content:"\f42c"}.bi-inbox::before{content:"\f42d"}.bi-inboxes-fill::before{content:"\f42e"}.bi-inboxes::before{content:"\f42f"}.bi-info-circle-fill::before{content:"\f430"}.bi-info-circle::before{content:"\f431"}.bi-info-square-fill::before{content:"\f432"}.bi-info-square::before{content:"\f433"}.bi-info::before{content:"\f434"}.bi-input-cursor-text::before{content:"\f435"}.bi-input-cursor::before{content:"\f436"}.bi-instagram::before{content:"\f437"}.bi-intersect::before{content:"\f438"}.bi-journal-album::before{content:"\f439"}.bi-journal-arrow-down::before{content:"\f43a"}.bi-journal-arrow-up::before{content:"\f43b"}.bi-journal-bookmark-fill::before{content:"\f43c"}.bi-journal-bookmark::before{content:"\f43d"}.bi-journal-check::before{content:"\f43e"}.bi-journal-code::before{content:"\f43f"}.bi-journal-medical::before{content:"\f440"}.bi-journal-minus::before{content:"\f441"}.bi-journal-plus::before{content:"\f442"}.bi-journal-richtext::before{content:"\f443"}.bi-journal-text::before{content:"\f444"}.bi-journal-x::before{content:"\f445"}.bi-journal::before{content:"\f446"}.bi-journals::before{content:"\f447"}.bi-joystick::before{content:"\f448"}.bi-justify-left::before{content:"\f449"}.bi-justify-right::before{content:"\f44a"}.bi-justify::before{content:"\f44b"}.bi-kanban-fill::before{content:"\f44c"}.bi-kanban::before{content:"\f44d"}.bi-key-fill::before{content:"\f44e"}.bi-key::before{content:"\f44f"}.bi-keyboard-fill::before{content:"\f450"}.bi-keyboard::before{content:"\f451"}.bi-ladder::before{content:"\f452"}.bi-lamp-fill::before{content:"\f453"}.bi-lamp::before{content:"\f454"}.bi-laptop-fill::before{content:"\f455"}.bi-laptop::before{content:"\f456"}.bi-layer-backward::before{content:"\f457"}.bi-layer-forward::before{content:"\f458"}.bi-layers-fill::before{content:"\f459"}.bi-layers-half::before{content:"\f45a"}.bi-layers::before{content:"\f45b"}.bi-layout-sidebar-inset-reverse::before{content:"\f45c"}.bi-layout-sidebar-inset::before{content:"\f45d"}.bi-layout-sidebar-reverse::before{content:"\f45e"}.bi-layout-sidebar::before{content:"\f45f"}.bi-layout-split::before{content:"\f460"}.bi-layout-text-sidebar-reverse::before{content:"\f461"}.bi-layout-text-sidebar::before{content:"\f462"}.bi-layout-text-window-reverse::before{content:"\f463"}.bi-layout-text-window::before{content:"\f464"}.bi-layout-three-columns::before{content:"\f465"}.bi-layout-wtf::before{content:"\f466"}.bi-life-preserver::before{content:"\f467"}.bi-lightbulb-fill::before{content:"\f468"}.bi-lightbulb-off-fill::before{content:"\f469"}.bi-lightbulb-off::before{content:"\f46a"}.bi-lightbulb::before{content:"\f46b"}.bi-lightning-charge-fill::before{content:"\f46c"}.bi-lightning-charge::before{content:"\f46d"}.bi-lightning-fill::before{content:"\f46e"}.bi-lightning::before{content:"\f46f"}.bi-link-45deg::before{content:"\f470"}.bi-link::before{content:"\f471"}.bi-linkedin::before{content:"\f472"}.bi-list-check::before{content:"\f473"}.bi-list-nested::before{content:"\f474"}.bi-list-ol::before{content:"\f475"}.bi-list-stars::before{content:"\f476"}.bi-list-task::before{content:"\f477"}.bi-list-ul::before{content:"\f478"}.bi-list::before{content:"\f479"}.bi-lock-fill::before{content:"\f47a"}.bi-lock::before{content:"\f47b"}.bi-mailbox::before{content:"\f47c"}.bi-mailbox2::before{content:"\f47d"}.bi-map-fill::before{content:"\f47e"}.bi-map::before{content:"\f47f"}.bi-markdown-fill::before{content:"\f480"}.bi-markdown::before{content:"\f481"}.bi-mask::before{content:"\f482"}.bi-megaphone-fill::before{content:"\f483"}.bi-megaphone::before{content:"\f484"}.bi-menu-app-fill::before{content:"\f485"}.bi-menu-app::before{content:"\f486"}.bi-menu-button-fill::before{content:"\f487"}.bi-menu-button-wide-fill::before{content:"\f488"}.bi-menu-button-wide::before{content:"\f489"}.bi-menu-button::before{content:"\f48a"}.bi-menu-down::before{content:"\f48b"}.bi-menu-up::before{content:"\f48c"}.bi-mic-fill::before{content:"\f48d"}.bi-mic-mute-fill::before{content:"\f48e"}.bi-mic-mute::before{content:"\f48f"}.bi-mic::before{content:"\f490"}.bi-minecart-loaded::before{content:"\f491"}.bi-minecart::before{content:"\f492"}.bi-moisture::before{content:"\f493"}.bi-moon-fill::before{content:"\f494"}.bi-moon-stars-fill::before{content:"\f495"}.bi-moon-stars::before{content:"\f496"}.bi-moon::before{content:"\f497"}.bi-mouse-fill::before{content:"\f498"}.bi-mouse::before{content:"\f499"}.bi-mouse2-fill::before{content:"\f49a"}.bi-mouse2::before{content:"\f49b"}.bi-mouse3-fill::before{content:"\f49c"}.bi-mouse3::before{content:"\f49d"}.bi-music-note-beamed::before{content:"\f49e"}.bi-music-note-list::before{content:"\f49f"}.bi-music-note::before{content:"\f4a0"}.bi-music-player-fill::before{content:"\f4a1"}.bi-music-player::before{content:"\f4a2"}.bi-newspaper::before{content:"\f4a3"}.bi-node-minus-fill::before{content:"\f4a4"}.bi-node-minus::before{content:"\f4a5"}.bi-node-plus-fill::before{content:"\f4a6"}.bi-node-plus::before{content:"\f4a7"}.bi-nut-fill::before{content:"\f4a8"}.bi-nut::before{content:"\f4a9"}.bi-octagon-fill::before{content:"\f4aa"}.bi-octagon-half::before{content:"\f4ab"}.bi-octagon::before{content:"\f4ac"}.bi-option::before{content:"\f4ad"}.bi-outlet::before{content:"\f4ae"}.bi-paint-bucket::before{content:"\f4af"}.bi-palette-fill::before{content:"\f4b0"}.bi-palette::before{content:"\f4b1"}.bi-palette2::before{content:"\f4b2"}.bi-paperclip::before{content:"\f4b3"}.bi-paragraph::before{content:"\f4b4"}.bi-patch-check-fill::before{content:"\f4b5"}.bi-patch-check::before{content:"\f4b6"}.bi-patch-exclamation-fill::before{content:"\f4b7"}.bi-patch-exclamation::before{content:"\f4b8"}.bi-patch-minus-fill::before{content:"\f4b9"}.bi-patch-minus::before{content:"\f4ba"}.bi-patch-plus-fill::before{content:"\f4bb"}.bi-patch-plus::before{content:"\f4bc"}.bi-patch-question-fill::before{content:"\f4bd"}.bi-patch-question::before{content:"\f4be"}.bi-pause-btn-fill::before{content:"\f4bf"}.bi-pause-btn::before{content:"\f4c0"}.bi-pause-circle-fill::before{content:"\f4c1"}.bi-pause-circle::before{content:"\f4c2"}.bi-pause-fill::before{content:"\f4c3"}.bi-pause::before{content:"\f4c4"}.bi-peace-fill::before{content:"\f4c5"}.bi-peace::before{content:"\f4c6"}.bi-pen-fill::before{content:"\f4c7"}.bi-pen::before{content:"\f4c8"}.bi-pencil-fill::before{content:"\f4c9"}.bi-pencil-square::before{content:"\f4ca"}.bi-pencil::before{content:"\f4cb"}.bi-pentagon-fill::before{content:"\f4cc"}.bi-pentagon-half::before{content:"\f4cd"}.bi-pentagon::before{content:"\f4ce"}.bi-people-fill::before{content:"\f4cf"}.bi-people::before{content:"\f4d0"}.bi-percent::before{content:"\f4d1"}.bi-person-badge-fill::before{content:"\f4d2"}.bi-person-badge::before{content:"\f4d3"}.bi-person-bounding-box::before{content:"\f4d4"}.bi-person-check-fill::before{content:"\f4d5"}.bi-person-check::before{content:"\f4d6"}.bi-person-circle::before{content:"\f4d7"}.bi-person-dash-fill::before{content:"\f4d8"}.bi-person-dash::before{content:"\f4d9"}.bi-person-fill::before{content:"\f4da"}.bi-person-lines-fill::before{content:"\f4db"}.bi-person-plus-fill::before{content:"\f4dc"}.bi-person-plus::before{content:"\f4dd"}.bi-person-square::before{content:"\f4de"}.bi-person-x-fill::before{content:"\f4df"}.bi-person-x::before{content:"\f4e0"}.bi-person::before{content:"\f4e1"}.bi-phone-fill::before{content:"\f4e2"}.bi-phone-landscape-fill::before{content:"\f4e3"}.bi-phone-landscape::before{content:"\f4e4"}.bi-phone-vibrate-fill::before{content:"\f4e5"}.bi-phone-vibrate::before{content:"\f4e6"}.bi-phone::before{content:"\f4e7"}.bi-pie-chart-fill::before{content:"\f4e8"}.bi-pie-chart::before{content:"\f4e9"}.bi-pin-angle-fill::before{content:"\f4ea"}.bi-pin-angle::before{content:"\f4eb"}.bi-pin-fill::before{content:"\f4ec"}.bi-pin::before{content:"\f4ed"}.bi-pip-fill::before{content:"\f4ee"}.bi-pip::before{content:"\f4ef"}.bi-play-btn-fill::before{content:"\f4f0"}.bi-play-btn::before{content:"\f4f1"}.bi-play-circle-fill::before{content:"\f4f2"}.bi-play-circle::before{content:"\f4f3"}.bi-play-fill::before{content:"\f4f4"}.bi-play::before{content:"\f4f5"}.bi-plug-fill::before{content:"\f4f6"}.bi-plug::before{content:"\f4f7"}.bi-plus-circle-dotted::before{content:"\f4f8"}.bi-plus-circle-fill::before{content:"\f4f9"}.bi-plus-circle::before{content:"\f4fa"}.bi-plus-square-dotted::before{content:"\f4fb"}.bi-plus-square-fill::before{content:"\f4fc"}.bi-plus-square::before{content:"\f4fd"}.bi-plus::before{content:"\f4fe"}.bi-power::before{content:"\f4ff"}.bi-printer-fill::before{content:"\f500"}.bi-printer::before{content:"\f501"}.bi-puzzle-fill::before{content:"\f502"}.bi-puzzle::before{content:"\f503"}.bi-question-circle-fill::before{content:"\f504"}.bi-question-circle::before{content:"\f505"}.bi-question-diamond-fill::before{content:"\f506"}.bi-question-diamond::before{content:"\f507"}.bi-question-octagon-fill::before{content:"\f508"}.bi-question-octagon::before{content:"\f509"}.bi-question-square-fill::before{content:"\f50a"}.bi-question-square::before{content:"\f50b"}.bi-question::before{content:"\f50c"}.bi-rainbow::before{content:"\f50d"}.bi-receipt-cutoff::before{content:"\f50e"}.bi-receipt::before{content:"\f50f"}.bi-reception-0::before{content:"\f510"}.bi-reception-1::before{content:"\f511"}.bi-reception-2::before{content:"\f512"}.bi-reception-3::before{content:"\f513"}.bi-reception-4::before{content:"\f514"}.bi-record-btn-fill::before{content:"\f515"}.bi-record-btn::before{content:"\f516"}.bi-record-circle-fill::before{content:"\f517"}.bi-record-circle::before{content:"\f518"}.bi-record-fill::before{content:"\f519"}.bi-record::before{content:"\f51a"}.bi-record2-fill::before{content:"\f51b"}.bi-record2::before{content:"\f51c"}.bi-reply-all-fill::before{content:"\f51d"}.bi-reply-all::before{content:"\f51e"}.bi-reply-fill::before{content:"\f51f"}.bi-reply::before{content:"\f520"}.bi-rss-fill::before{content:"\f521"}.bi-rss::before{content:"\f522"}.bi-rulers::before{content:"\f523"}.bi-save-fill::before{content:"\f524"}.bi-save::before{content:"\f525"}.bi-save2-fill::before{content:"\f526"}.bi-save2::before{content:"\f527"}.bi-scissors::before{content:"\f528"}.bi-screwdriver::before{content:"\f529"}.bi-search::before{content:"\f52a"}.bi-segmented-nav::before{content:"\f52b"}.bi-server::before{content:"\f52c"}.bi-share-fill::before{content:"\f52d"}.bi-share::before{content:"\f52e"}.bi-shield-check::before{content:"\f52f"}.bi-shield-exclamation::before{content:"\f530"}.bi-shield-fill-check::before{content:"\f531"}.bi-shield-fill-exclamation::before{content:"\f532"}.bi-shield-fill-minus::before{content:"\f533"}.bi-shield-fill-plus::before{content:"\f534"}.bi-shield-fill-x::before{content:"\f535"}.bi-shield-fill::before{content:"\f536"}.bi-shield-lock-fill::before{content:"\f537"}.bi-shield-lock::before{content:"\f538"}.bi-shield-minus::before{content:"\f539"}.bi-shield-plus::before{content:"\f53a"}.bi-shield-shaded::before{content:"\f53b"}.bi-shield-slash-fill::before{content:"\f53c"}.bi-shield-slash::before{content:"\f53d"}.bi-shield-x::before{content:"\f53e"}.bi-shield::before{content:"\f53f"}.bi-shift-fill::before{content:"\f540"}.bi-shift::before{content:"\f541"}.bi-shop-window::before{content:"\f542"}.bi-shop::before{content:"\f543"}.bi-shuffle::before{content:"\f544"}.bi-signpost-2-fill::before{content:"\f545"}.bi-signpost-2::before{content:"\f546"}.bi-signpost-fill::before{content:"\f547"}.bi-signpost-split-fill::before{content:"\f548"}.bi-signpost-split::before{content:"\f549"}.bi-signpost::before{content:"\f54a"}.bi-sim-fill::before{content:"\f54b"}.bi-sim::before{content:"\f54c"}.bi-skip-backward-btn-fill::before{content:"\f54d"}.bi-skip-backward-btn::before{content:"\f54e"}.bi-skip-backward-circle-fill::before{content:"\f54f"}.bi-skip-backward-circle::before{content:"\f550"}.bi-skip-backward-fill::before{content:"\f551"}.bi-skip-backward::before{content:"\f552"}.bi-skip-end-btn-fill::before{content:"\f553"}.bi-skip-end-btn::before{content:"\f554"}.bi-skip-end-circle-fill::before{content:"\f555"}.bi-skip-end-circle::before{content:"\f556"}.bi-skip-end-fill::before{content:"\f557"}.bi-skip-end::before{content:"\f558"}.bi-skip-forward-btn-fill::before{content:"\f559"}.bi-skip-forward-btn::before{content:"\f55a"}.bi-skip-forward-circle-fill::before{content:"\f55b"}.bi-skip-forward-circle::before{content:"\f55c"}.bi-skip-forward-fill::before{content:"\f55d"}.bi-skip-forward::before{content:"\f55e"}.bi-skip-start-btn-fill::before{content:"\f55f"}.bi-skip-start-btn::before{content:"\f560"}.bi-skip-start-circle-fill::before{content:"\f561"}.bi-skip-start-circle::before{content:"\f562"}.bi-skip-start-fill::before{content:"\f563"}.bi-skip-start::before{content:"\f564"}.bi-slack::before{content:"\f565"}.bi-slash-circle-fill::before{content:"\f566"}.bi-slash-circle::before{content:"\f567"}.bi-slash-square-fill::before{content:"\f568"}.bi-slash-square::before{content:"\f569"}.bi-slash::before{content:"\f56a"}.bi-sliders::before{content:"\f56b"}.bi-smartwatch::before{content:"\f56c"}.bi-snow::before{content:"\f56d"}.bi-snow2::before{content:"\f56e"}.bi-snow3::before{content:"\f56f"}.bi-sort-alpha-down-alt::before{content:"\f570"}.bi-sort-alpha-down::before{content:"\f571"}.bi-sort-alpha-up-alt::before{content:"\f572"}.bi-sort-alpha-up::before{content:"\f573"}.bi-sort-down-alt::before{content:"\f574"}.bi-sort-down::before{content:"\f575"}.bi-sort-numeric-down-alt::before{content:"\f576"}.bi-sort-numeric-down::before{content:"\f577"}.bi-sort-numeric-up-alt::before{content:"\f578"}.bi-sort-numeric-up::before{content:"\f579"}.bi-sort-up-alt::before{content:"\f57a"}.bi-sort-up::before{content:"\f57b"}.bi-soundwave::before{content:"\f57c"}.bi-speaker-fill::before{content:"\f57d"}.bi-speaker::before{content:"\f57e"}.bi-speedometer::before{content:"\f57f"}.bi-speedometer2::before{content:"\f580"}.bi-spellcheck::before{content:"\f581"}.bi-square-fill::before{content:"\f582"}.bi-square-half::before{content:"\f583"}.bi-square::before{content:"\f584"}.bi-stack::before{content:"\f585"}.bi-star-fill::before{content:"\f586"}.bi-star-half::before{content:"\f587"}.bi-star::before{content:"\f588"}.bi-stars::before{content:"\f589"}.bi-stickies-fill::before{content:"\f58a"}.bi-stickies::before{content:"\f58b"}.bi-sticky-fill::before{content:"\f58c"}.bi-sticky::before{content:"\f58d"}.bi-stop-btn-fill::before{content:"\f58e"}.bi-stop-btn::before{content:"\f58f"}.bi-stop-circle-fill::before{content:"\f590"}.bi-stop-circle::before{content:"\f591"}.bi-stop-fill::before{content:"\f592"}.bi-stop::before{content:"\f593"}.bi-stoplights-fill::before{content:"\f594"}.bi-stoplights::before{content:"\f595"}.bi-stopwatch-fill::before{content:"\f596"}.bi-stopwatch::before{content:"\f597"}.bi-subtract::before{content:"\f598"}.bi-suit-club-fill::before{content:"\f599"}.bi-suit-club::before{content:"\f59a"}.bi-suit-diamond-fill::before{content:"\f59b"}.bi-suit-diamond::before{content:"\f59c"}.bi-suit-heart-fill::before{content:"\f59d"}.bi-suit-heart::before{content:"\f59e"}.bi-suit-spade-fill::before{content:"\f59f"}.bi-suit-spade::before{content:"\f5a0"}.bi-sun-fill::before{content:"\f5a1"}.bi-sun::before{content:"\f5a2"}.bi-sunglasses::before{content:"\f5a3"}.bi-sunrise-fill::before{content:"\f5a4"}.bi-sunrise::before{content:"\f5a5"}.bi-sunset-fill::before{content:"\f5a6"}.bi-sunset::before{content:"\f5a7"}.bi-symmetry-horizontal::before{content:"\f5a8"}.bi-symmetry-vertical::before{content:"\f5a9"}.bi-table::before{content:"\f5aa"}.bi-tablet-fill::before{content:"\f5ab"}.bi-tablet-landscape-fill::before{content:"\f5ac"}.bi-tablet-landscape::before{content:"\f5ad"}.bi-tablet::before{content:"\f5ae"}.bi-tag-fill::before{content:"\f5af"}.bi-tag::before{content:"\f5b0"}.bi-tags-fill::before{content:"\f5b1"}.bi-tags::before{content:"\f5b2"}.bi-telegram::before{content:"\f5b3"}.bi-telephone-fill::before{content:"\f5b4"}.bi-telephone-forward-fill::before{content:"\f5b5"}.bi-telephone-forward::before{content:"\f5b6"}.bi-telephone-inbound-fill::before{content:"\f5b7"}.bi-telephone-inbound::before{content:"\f5b8"}.bi-telephone-minus-fill::before{content:"\f5b9"}.bi-telephone-minus::before{content:"\f5ba"}.bi-telephone-outbound-fill::before{content:"\f5bb"}.bi-telephone-outbound::before{content:"\f5bc"}.bi-telephone-plus-fill::before{content:"\f5bd"}.bi-telephone-plus::before{content:"\f5be"}.bi-telephone-x-fill::before{content:"\f5bf"}.bi-telephone-x::before{content:"\f5c0"}.bi-telephone::before{content:"\f5c1"}.bi-terminal-fill::before{content:"\f5c2"}.bi-terminal::before{content:"\f5c3"}.bi-text-center::before{content:"\f5c4"}.bi-text-indent-left::before{content:"\f5c5"}.bi-text-indent-right::before{content:"\f5c6"}.bi-text-left::before{content:"\f5c7"}.bi-text-paragraph::before{content:"\f5c8"}.bi-text-right::before{content:"\f5c9"}.bi-textarea-resize::before{content:"\f5ca"}.bi-textarea-t::before{content:"\f5cb"}.bi-textarea::before{content:"\f5cc"}.bi-thermometer-half::before{content:"\f5cd"}.bi-thermometer-high::before{content:"\f5ce"}.bi-thermometer-low::before{content:"\f5cf"}.bi-thermometer-snow::before{content:"\f5d0"}.bi-thermometer-sun::before{content:"\f5d1"}.bi-thermometer::before{content:"\f5d2"}.bi-three-dots-vertical::before{content:"\f5d3"}.bi-three-dots::before{content:"\f5d4"}.bi-toggle-off::before{content:"\f5d5"}.bi-toggle-on::before{content:"\f5d6"}.bi-toggle2-off::before{content:"\f5d7"}.bi-toggle2-on::before{content:"\f5d8"}.bi-toggles::before{content:"\f5d9"}.bi-toggles2::before{content:"\f5da"}.bi-tools::before{content:"\f5db"}.bi-tornado::before{content:"\f5dc"}.bi-trash-fill::before{content:"\f5dd"}.bi-trash::before{content:"\f5de"}.bi-trash2-fill::before{content:"\f5df"}.bi-trash2::before{content:"\f5e0"}.bi-tree-fill::before{content:"\f5e1"}.bi-tree::before{content:"\f5e2"}.bi-triangle-fill::before{content:"\f5e3"}.bi-triangle-half::before{content:"\f5e4"}.bi-triangle::before{content:"\f5e5"}.bi-trophy-fill::before{content:"\f5e6"}.bi-trophy::before{content:"\f5e7"}.bi-tropical-storm::before{content:"\f5e8"}.bi-truck-flatbed::before{content:"\f5e9"}.bi-truck::before{content:"\f5ea"}.bi-tsunami::before{content:"\f5eb"}.bi-tv-fill::before{content:"\f5ec"}.bi-tv::before{content:"\f5ed"}.bi-twitch::before{content:"\f5ee"}.bi-twitter::before{content:"\f5ef"}.bi-type-bold::before{content:"\f5f0"}.bi-type-h1::before{content:"\f5f1"}.bi-type-h2::before{content:"\f5f2"}.bi-type-h3::before{content:"\f5f3"}.bi-type-italic::before{content:"\f5f4"}.bi-type-strikethrough::before{content:"\f5f5"}.bi-type-underline::before{content:"\f5f6"}.bi-type::before{content:"\f5f7"}.bi-ui-checks-grid::before{content:"\f5f8"}.bi-ui-checks::before{content:"\f5f9"}.bi-ui-radios-grid::before{content:"\f5fa"}.bi-ui-radios::before{content:"\f5fb"}.bi-umbrella-fill::before{content:"\f5fc"}.bi-umbrella::before{content:"\f5fd"}.bi-union::before{content:"\f5fe"}.bi-unlock-fill::before{content:"\f5ff"}.bi-unlock::before{content:"\f600"}.bi-upc-scan::before{content:"\f601"}.bi-upc::before{content:"\f602"}.bi-upload::before{content:"\f603"}.bi-vector-pen::before{content:"\f604"}.bi-view-list::before{content:"\f605"}.bi-view-stacked::before{content:"\f606"}.bi-vinyl-fill::before{content:"\f607"}.bi-vinyl::before{content:"\f608"}.bi-voicemail::before{content:"\f609"}.bi-volume-down-fill::before{content:"\f60a"}.bi-volume-down::before{content:"\f60b"}.bi-volume-mute-fill::before{content:"\f60c"}.bi-volume-mute::before{content:"\f60d"}.bi-volume-off-fill::before{content:"\f60e"}.bi-volume-off::before{content:"\f60f"}.bi-volume-up-fill::before{content:"\f610"}.bi-volume-up::before{content:"\f611"}.bi-vr::before{content:"\f612"}.bi-wallet-fill::before{content:"\f613"}.bi-wallet::before{content:"\f614"}.bi-wallet2::before{content:"\f615"}.bi-watch::before{content:"\f616"}.bi-water::before{content:"\f617"}.bi-whatsapp::before{content:"\f618"}.bi-wifi-1::before{content:"\f619"}.bi-wifi-2::before{content:"\f61a"}.bi-wifi-off::before{content:"\f61b"}.bi-wifi::before{content:"\f61c"}.bi-wind::before{content:"\f61d"}.bi-window-dock::before{content:"\f61e"}.bi-window-sidebar::before{content:"\f61f"}.bi-window::before{content:"\f620"}.bi-wrench::before{content:"\f621"}.bi-x-circle-fill::before{content:"\f622"}.bi-x-circle::before{content:"\f623"}.bi-x-diamond-fill::before{content:"\f624"}.bi-x-diamond::before{content:"\f625"}.bi-x-octagon-fill::before{content:"\f626"}.bi-x-octagon::before{content:"\f627"}.bi-x-square-fill::before{content:"\f628"}.bi-x-square::before{content:"\f629"}.bi-x::before{content:"\f62a"}.bi-youtube::before{content:"\f62b"}.bi-zoom-in::before{content:"\f62c"}.bi-zoom-out::before{content:"\f62d"}.bi-bank::before{content:"\f62e"}.bi-bank2::before{content:"\f62f"}.bi-bell-slash-fill::before{content:"\f630"}.bi-bell-slash::before{content:"\f631"}.bi-cash-coin::before{content:"\f632"}.bi-check-lg::before{content:"\f633"}.bi-coin::before{content:"\f634"}.bi-currency-bitcoin::before{content:"\f635"}.bi-currency-dollar::before{content:"\f636"}.bi-currency-euro::before{content:"\f637"}.bi-currency-exchange::before{content:"\f638"}.bi-currency-pound::before{content:"\f639"}.bi-currency-yen::before{content:"\f63a"}.bi-dash-lg::before{content:"\f63b"}.bi-exclamation-lg::before{content:"\f63c"}.bi-file-earmark-pdf-fill::before{content:"\f63d"}.bi-file-earmark-pdf::before{content:"\f63e"}.bi-file-pdf-fill::before{content:"\f63f"}.bi-file-pdf::before{content:"\f640"}.bi-gender-ambiguous::before{content:"\f641"}.bi-gender-female::before{content:"\f642"}.bi-gender-male::before{content:"\f643"}.bi-gender-trans::before{content:"\f644"}.bi-headset-vr::before{content:"\f645"}.bi-info-lg::before{content:"\f646"}.bi-mastodon::before{content:"\f647"}.bi-messenger::before{content:"\f648"}.bi-piggy-bank-fill::before{content:"\f649"}.bi-piggy-bank::before{content:"\f64a"}.bi-pin-map-fill::before{content:"\f64b"}.bi-pin-map::before{content:"\f64c"}.bi-plus-lg::before{content:"\f64d"}.bi-question-lg::before{content:"\f64e"}.bi-recycle::before{content:"\f64f"}.bi-reddit::before{content:"\f650"}.bi-safe-fill::before{content:"\f651"}.bi-safe2-fill::before{content:"\f652"}.bi-safe2::before{content:"\f653"}.bi-sd-card-fill::before{content:"\f654"}.bi-sd-card::before{content:"\f655"}.bi-skype::before{content:"\f656"}.bi-slash-lg::before{content:"\f657"}.bi-translate::before{content:"\f658"}.bi-x-lg::before{content:"\f659"}.bi-safe::before{content:"\f65a"}.bi-apple::before{content:"\f65b"}.bi-microsoft::before{content:"\f65d"}.bi-windows::before{content:"\f65e"}.bi-behance::before{content:"\f65c"}.bi-dribbble::before{content:"\f65f"}.bi-line::before{content:"\f660"}.bi-medium::before{content:"\f661"}.bi-paypal::before{content:"\f662"}.bi-pinterest::before{content:"\f663"}.bi-signal::before{content:"\f664"}.bi-snapchat::before{content:"\f665"}.bi-spotify::before{content:"\f666"}.bi-stack-overflow::before{content:"\f667"}.bi-strava::before{content:"\f668"}.bi-wordpress::before{content:"\f669"}.bi-vimeo::before{content:"\f66a"}.bi-activity::before{content:"\f66b"}.bi-easel2-fill::before{content:"\f66c"}.bi-easel2::before{content:"\f66d"}.bi-easel3-fill::before{content:"\f66e"}.bi-easel3::before{content:"\f66f"}.bi-fan::before{content:"\f670"}.bi-fingerprint::before{content:"\f671"}.bi-graph-down-arrow::before{content:"\f672"}.bi-graph-up-arrow::before{content:"\f673"}.bi-hypnotize::before{content:"\f674"}.bi-magic::before{content:"\f675"}.bi-person-rolodex::before{content:"\f676"}.bi-person-video::before{content:"\f677"}.bi-person-video2::before{content:"\f678"}.bi-person-video3::before{content:"\f679"}.bi-person-workspace::before{content:"\f67a"}.bi-radioactive::before{content:"\f67b"}.bi-webcam-fill::before{content:"\f67c"}.bi-webcam::before{content:"\f67d"}.bi-yin-yang::before{content:"\f67e"}.bi-bandaid-fill::before{content:"\f680"}.bi-bandaid::before{content:"\f681"}.bi-bluetooth::before{content:"\f682"}.bi-body-text::before{content:"\f683"}.bi-boombox::before{content:"\f684"}.bi-boxes::before{content:"\f685"}.bi-dpad-fill::before{content:"\f686"}.bi-dpad::before{content:"\f687"}.bi-ear-fill::before{content:"\f688"}.bi-ear::before{content:"\f689"}.bi-envelope-check-fill::before{content:"\f68b"}.bi-envelope-check::before{content:"\f68c"}.bi-envelope-dash-fill::before{content:"\f68e"}.bi-envelope-dash::before{content:"\f68f"}.bi-envelope-exclamation-fill::before{content:"\f691"}.bi-envelope-exclamation::before{content:"\f692"}.bi-envelope-plus-fill::before{content:"\f693"}.bi-envelope-plus::before{content:"\f694"}.bi-envelope-slash-fill::before{content:"\f696"}.bi-envelope-slash::before{content:"\f697"}.bi-envelope-x-fill::before{content:"\f699"}.bi-envelope-x::before{content:"\f69a"}.bi-explicit-fill::before{content:"\f69b"}.bi-explicit::before{content:"\f69c"}.bi-git::before{content:"\f69d"}.bi-infinity::before{content:"\f69e"}.bi-list-columns-reverse::before{content:"\f69f"}.bi-list-columns::before{content:"\f6a0"}.bi-meta::before{content:"\f6a1"}.bi-nintendo-switch::before{content:"\f6a4"}.bi-pc-display-horizontal::before{content:"\f6a5"}.bi-pc-display::before{content:"\f6a6"}.bi-pc-horizontal::before{content:"\f6a7"}.bi-pc::before{content:"\f6a8"}.bi-playstation::before{content:"\f6a9"}.bi-plus-slash-minus::before{content:"\f6aa"}.bi-projector-fill::before{content:"\f6ab"}.bi-projector::before{content:"\f6ac"}.bi-qr-code-scan::before{content:"\f6ad"}.bi-qr-code::before{content:"\f6ae"}.bi-quora::before{content:"\f6af"}.bi-quote::before{content:"\f6b0"}.bi-robot::before{content:"\f6b1"}.bi-send-check-fill::before{content:"\f6b2"}.bi-send-check::before{content:"\f6b3"}.bi-send-dash-fill::before{content:"\f6b4"}.bi-send-dash::before{content:"\f6b5"}.bi-send-exclamation-fill::before{content:"\f6b7"}.bi-send-exclamation::before{content:"\f6b8"}.bi-send-fill::before{content:"\f6b9"}.bi-send-plus-fill::before{content:"\f6ba"}.bi-send-plus::before{content:"\f6bb"}.bi-send-slash-fill::before{content:"\f6bc"}.bi-send-slash::before{content:"\f6bd"}.bi-send-x-fill::before{content:"\f6be"}.bi-send-x::before{content:"\f6bf"}.bi-send::before{content:"\f6c0"}.bi-steam::before{content:"\f6c1"}.bi-terminal-dash::before{content:"\f6c3"}.bi-terminal-plus::before{content:"\f6c4"}.bi-terminal-split::before{content:"\f6c5"}.bi-ticket-detailed-fill::before{content:"\f6c6"}.bi-ticket-detailed::before{content:"\f6c7"}.bi-ticket-fill::before{content:"\f6c8"}.bi-ticket-perforated-fill::before{content:"\f6c9"}.bi-ticket-perforated::before{content:"\f6ca"}.bi-ticket::before{content:"\f6cb"}.bi-tiktok::before{content:"\f6cc"}.bi-window-dash::before{content:"\f6cd"}.bi-window-desktop::before{content:"\f6ce"}.bi-window-fullscreen::before{content:"\f6cf"}.bi-window-plus::before{content:"\f6d0"}.bi-window-split::before{content:"\f6d1"}.bi-window-stack::before{content:"\f6d2"}.bi-window-x::before{content:"\f6d3"}.bi-xbox::before{content:"\f6d4"}.bi-ethernet::before{content:"\f6d5"}.bi-hdmi-fill::before{content:"\f6d6"}.bi-hdmi::before{content:"\f6d7"}.bi-usb-c-fill::before{content:"\f6d8"}.bi-usb-c::before{content:"\f6d9"}.bi-usb-fill::before{content:"\f6da"}.bi-usb-plug-fill::before{content:"\f6db"}.bi-usb-plug::before{content:"\f6dc"}.bi-usb-symbol::before{content:"\f6dd"}.bi-usb::before{content:"\f6de"}.bi-boombox-fill::before{content:"\f6df"}.bi-displayport::before{content:"\f6e1"}.bi-gpu-card::before{content:"\f6e2"}.bi-memory::before{content:"\f6e3"}.bi-modem-fill::before{content:"\f6e4"}.bi-modem::before{content:"\f6e5"}.bi-motherboard-fill::before{content:"\f6e6"}.bi-motherboard::before{content:"\f6e7"}.bi-optical-audio-fill::before{content:"\f6e8"}.bi-optical-audio::before{content:"\f6e9"}.bi-pci-card::before{content:"\f6ea"}.bi-router-fill::before{content:"\f6eb"}.bi-router::before{content:"\f6ec"}.bi-thunderbolt-fill::before{content:"\f6ef"}.bi-thunderbolt::before{content:"\f6f0"}.bi-usb-drive-fill::before{content:"\f6f1"}.bi-usb-drive::before{content:"\f6f2"}.bi-usb-micro-fill::before{content:"\f6f3"}.bi-usb-micro::before{content:"\f6f4"}.bi-usb-mini-fill::before{content:"\f6f5"}.bi-usb-mini::before{content:"\f6f6"}.bi-cloud-haze2::before{content:"\f6f7"}.bi-device-hdd-fill::before{content:"\f6f8"}.bi-device-hdd::before{content:"\f6f9"}.bi-device-ssd-fill::before{content:"\f6fa"}.bi-device-ssd::before{content:"\f6fb"}.bi-displayport-fill::before{content:"\f6fc"}.bi-mortarboard-fill::before{content:"\f6fd"}.bi-mortarboard::before{content:"\f6fe"}.bi-terminal-x::before{content:"\f6ff"}.bi-arrow-through-heart-fill::before{content:"\f700"}.bi-arrow-through-heart::before{content:"\f701"}.bi-badge-sd-fill::before{content:"\f702"}.bi-badge-sd::before{content:"\f703"}.bi-bag-heart-fill::before{content:"\f704"}.bi-bag-heart::before{content:"\f705"}.bi-balloon-fill::before{content:"\f706"}.bi-balloon-heart-fill::before{content:"\f707"}.bi-balloon-heart::before{content:"\f708"}.bi-balloon::before{content:"\f709"}.bi-box2-fill::before{content:"\f70a"}.bi-box2-heart-fill::before{content:"\f70b"}.bi-box2-heart::before{content:"\f70c"}.bi-box2::before{content:"\f70d"}.bi-braces-asterisk::before{content:"\f70e"}.bi-calendar-heart-fill::before{content:"\f70f"}.bi-calendar-heart::before{content:"\f710"}.bi-calendar2-heart-fill::before{content:"\f711"}.bi-calendar2-heart::before{content:"\f712"}.bi-chat-heart-fill::before{content:"\f713"}.bi-chat-heart::before{content:"\f714"}.bi-chat-left-heart-fill::before{content:"\f715"}.bi-chat-left-heart::before{content:"\f716"}.bi-chat-right-heart-fill::before{content:"\f717"}.bi-chat-right-heart::before{content:"\f718"}.bi-chat-square-heart-fill::before{content:"\f719"}.bi-chat-square-heart::before{content:"\f71a"}.bi-clipboard-check-fill::before{content:"\f71b"}.bi-clipboard-data-fill::before{content:"\f71c"}.bi-clipboard-fill::before{content:"\f71d"}.bi-clipboard-heart-fill::before{content:"\f71e"}.bi-clipboard-heart::before{content:"\f71f"}.bi-clipboard-minus-fill::before{content:"\f720"}.bi-clipboard-plus-fill::before{content:"\f721"}.bi-clipboard-pulse::before{content:"\f722"}.bi-clipboard-x-fill::before{content:"\f723"}.bi-clipboard2-check-fill::before{content:"\f724"}.bi-clipboard2-check::before{content:"\f725"}.bi-clipboard2-data-fill::before{content:"\f726"}.bi-clipboard2-data::before{content:"\f727"}.bi-clipboard2-fill::before{content:"\f728"}.bi-clipboard2-heart-fill::before{content:"\f729"}.bi-clipboard2-heart::before{content:"\f72a"}.bi-clipboard2-minus-fill::before{content:"\f72b"}.bi-clipboard2-minus::before{content:"\f72c"}.bi-clipboard2-plus-fill::before{content:"\f72d"}.bi-clipboard2-plus::before{content:"\f72e"}.bi-clipboard2-pulse-fill::before{content:"\f72f"}.bi-clipboard2-pulse::before{content:"\f730"}.bi-clipboard2-x-fill::before{content:"\f731"}.bi-clipboard2-x::before{content:"\f732"}.bi-clipboard2::before{content:"\f733"}.bi-emoji-kiss-fill::before{content:"\f734"}.bi-emoji-kiss::before{content:"\f735"}.bi-envelope-heart-fill::before{content:"\f736"}.bi-envelope-heart::before{content:"\f737"}.bi-envelope-open-heart-fill::before{content:"\f738"}.bi-envelope-open-heart::before{content:"\f739"}.bi-envelope-paper-fill::before{content:"\f73a"}.bi-envelope-paper-heart-fill::before{content:"\f73b"}.bi-envelope-paper-heart::before{content:"\f73c"}.bi-envelope-paper::before{content:"\f73d"}.bi-filetype-aac::before{content:"\f73e"}.bi-filetype-ai::before{content:"\f73f"}.bi-filetype-bmp::before{content:"\f740"}.bi-filetype-cs::before{content:"\f741"}.bi-filetype-css::before{content:"\f742"}.bi-filetype-csv::before{content:"\f743"}.bi-filetype-doc::before{content:"\f744"}.bi-filetype-docx::before{content:"\f745"}.bi-filetype-exe::before{content:"\f746"}.bi-filetype-gif::before{content:"\f747"}.bi-filetype-heic::before{content:"\f748"}.bi-filetype-html::before{content:"\f749"}.bi-filetype-java::before{content:"\f74a"}.bi-filetype-jpg::before{content:"\f74b"}.bi-filetype-js::before{content:"\f74c"}.bi-filetype-jsx::before{content:"\f74d"}.bi-filetype-key::before{content:"\f74e"}.bi-filetype-m4p::before{content:"\f74f"}.bi-filetype-md::before{content:"\f750"}.bi-filetype-mdx::before{content:"\f751"}.bi-filetype-mov::before{content:"\f752"}.bi-filetype-mp3::before{content:"\f753"}.bi-filetype-mp4::before{content:"\f754"}.bi-filetype-otf::before{content:"\f755"}.bi-filetype-pdf::before{content:"\f756"}.bi-filetype-php::before{content:"\f757"}.bi-filetype-png::before{content:"\f758"}.bi-filetype-ppt::before{content:"\f75a"}.bi-filetype-psd::before{content:"\f75b"}.bi-filetype-py::before{content:"\f75c"}.bi-filetype-raw::before{content:"\f75d"}.bi-filetype-rb::before{content:"\f75e"}.bi-filetype-sass::before{content:"\f75f"}.bi-filetype-scss::before{content:"\f760"}.bi-filetype-sh::before{content:"\f761"}.bi-filetype-svg::before{content:"\f762"}.bi-filetype-tiff::before{content:"\f763"}.bi-filetype-tsx::before{content:"\f764"}.bi-filetype-ttf::before{content:"\f765"}.bi-filetype-txt::before{content:"\f766"}.bi-filetype-wav::before{content:"\f767"}.bi-filetype-woff::before{content:"\f768"}.bi-filetype-xls::before{content:"\f76a"}.bi-filetype-xml::before{content:"\f76b"}.bi-filetype-yml::before{content:"\f76c"}.bi-heart-arrow::before{content:"\f76d"}.bi-heart-pulse-fill::before{content:"\f76e"}.bi-heart-pulse::before{content:"\f76f"}.bi-heartbreak-fill::before{content:"\f770"}.bi-heartbreak::before{content:"\f771"}.bi-hearts::before{content:"\f772"}.bi-hospital-fill::before{content:"\f773"}.bi-hospital::before{content:"\f774"}.bi-house-heart-fill::before{content:"\f775"}.bi-house-heart::before{content:"\f776"}.bi-incognito::before{content:"\f777"}.bi-magnet-fill::before{content:"\f778"}.bi-magnet::before{content:"\f779"}.bi-person-heart::before{content:"\f77a"}.bi-person-hearts::before{content:"\f77b"}.bi-phone-flip::before{content:"\f77c"}.bi-plugin::before{content:"\f77d"}.bi-postage-fill::before{content:"\f77e"}.bi-postage-heart-fill::before{content:"\f77f"}.bi-postage-heart::before{content:"\f780"}.bi-postage::before{content:"\f781"}.bi-postcard-fill::before{content:"\f782"}.bi-postcard-heart-fill::before{content:"\f783"}.bi-postcard-heart::before{content:"\f784"}.bi-postcard::before{content:"\f785"}.bi-search-heart-fill::before{content:"\f786"}.bi-search-heart::before{content:"\f787"}.bi-sliders2-vertical::before{content:"\f788"}.bi-sliders2::before{content:"\f789"}.bi-trash3-fill::before{content:"\f78a"}.bi-trash3::before{content:"\f78b"}.bi-valentine::before{content:"\f78c"}.bi-valentine2::before{content:"\f78d"}.bi-wrench-adjustable-circle-fill::before{content:"\f78e"}.bi-wrench-adjustable-circle::before{content:"\f78f"}.bi-wrench-adjustable::before{content:"\f790"}.bi-filetype-json::before{content:"\f791"}.bi-filetype-pptx::before{content:"\f792"}.bi-filetype-xlsx::before{content:"\f793"}.bi-1-circle-fill::before{content:"\f796"}.bi-1-circle::before{content:"\f797"}.bi-1-square-fill::before{content:"\f798"}.bi-1-square::before{content:"\f799"}.bi-2-circle-fill::before{content:"\f79c"}.bi-2-circle::before{content:"\f79d"}.bi-2-square-fill::before{content:"\f79e"}.bi-2-square::before{content:"\f79f"}.bi-3-circle-fill::before{content:"\f7a2"}.bi-3-circle::before{content:"\f7a3"}.bi-3-square-fill::before{content:"\f7a4"}.bi-3-square::before{content:"\f7a5"}.bi-4-circle-fill::before{content:"\f7a8"}.bi-4-circle::before{content:"\f7a9"}.bi-4-square-fill::before{content:"\f7aa"}.bi-4-square::before{content:"\f7ab"}.bi-5-circle-fill::before{content:"\f7ae"}.bi-5-circle::before{content:"\f7af"}.bi-5-square-fill::before{content:"\f7b0"}.bi-5-square::before{content:"\f7b1"}.bi-6-circle-fill::before{content:"\f7b4"}.bi-6-circle::before{content:"\f7b5"}.bi-6-square-fill::before{content:"\f7b6"}.bi-6-square::before{content:"\f7b7"}.bi-7-circle-fill::before{content:"\f7ba"}.bi-7-circle::before{content:"\f7bb"}.bi-7-square-fill::before{content:"\f7bc"}.bi-7-square::before{content:"\f7bd"}.bi-8-circle-fill::before{content:"\f7c0"}.bi-8-circle::before{content:"\f7c1"}.bi-8-square-fill::before{content:"\f7c2"}.bi-8-square::before{content:"\f7c3"}.bi-9-circle-fill::before{content:"\f7c6"}.bi-9-circle::before{content:"\f7c7"}.bi-9-square-fill::before{content:"\f7c8"}.bi-9-square::before{content:"\f7c9"}.bi-airplane-engines-fill::before{content:"\f7ca"}.bi-airplane-engines::before{content:"\f7cb"}.bi-airplane-fill::before{content:"\f7cc"}.bi-airplane::before{content:"\f7cd"}.bi-alexa::before{content:"\f7ce"}.bi-alipay::before{content:"\f7cf"}.bi-android::before{content:"\f7d0"}.bi-android2::before{content:"\f7d1"}.bi-box-fill::before{content:"\f7d2"}.bi-box-seam-fill::before{content:"\f7d3"}.bi-browser-chrome::before{content:"\f7d4"}.bi-browser-edge::before{content:"\f7d5"}.bi-browser-firefox::before{content:"\f7d6"}.bi-browser-safari::before{content:"\f7d7"}.bi-c-circle-fill::before{content:"\f7da"}.bi-c-circle::before{content:"\f7db"}.bi-c-square-fill::before{content:"\f7dc"}.bi-c-square::before{content:"\f7dd"}.bi-capsule-pill::before{content:"\f7de"}.bi-capsule::before{content:"\f7df"}.bi-car-front-fill::before{content:"\f7e0"}.bi-car-front::before{content:"\f7e1"}.bi-cassette-fill::before{content:"\f7e2"}.bi-cassette::before{content:"\f7e3"}.bi-cc-circle-fill::before{content:"\f7e6"}.bi-cc-circle::before{content:"\f7e7"}.bi-cc-square-fill::before{content:"\f7e8"}.bi-cc-square::before{content:"\f7e9"}.bi-cup-hot-fill::before{content:"\f7ea"}.bi-cup-hot::before{content:"\f7eb"}.bi-currency-rupee::before{content:"\f7ec"}.bi-dropbox::before{content:"\f7ed"}.bi-escape::before{content:"\f7ee"}.bi-fast-forward-btn-fill::before{content:"\f7ef"}.bi-fast-forward-btn::before{content:"\f7f0"}.bi-fast-forward-circle-fill::before{content:"\f7f1"}.bi-fast-forward-circle::before{content:"\f7f2"}.bi-fast-forward-fill::before{content:"\f7f3"}.bi-fast-forward::before{content:"\f7f4"}.bi-filetype-sql::before{content:"\f7f5"}.bi-fire::before{content:"\f7f6"}.bi-google-play::before{content:"\f7f7"}.bi-h-circle-fill::before{content:"\f7fa"}.bi-h-circle::before{content:"\f7fb"}.bi-h-square-fill::before{content:"\f7fc"}.bi-h-square::before{content:"\f7fd"}.bi-indent::before{content:"\f7fe"}.bi-lungs-fill::before{content:"\f7ff"}.bi-lungs::before{content:"\f800"}.bi-microsoft-teams::before{content:"\f801"}.bi-p-circle-fill::before{content:"\f804"}.bi-p-circle::before{content:"\f805"}.bi-p-square-fill::before{content:"\f806"}.bi-p-square::before{content:"\f807"}.bi-pass-fill::before{content:"\f808"}.bi-pass::before{content:"\f809"}.bi-prescription::before{content:"\f80a"}.bi-prescription2::before{content:"\f80b"}.bi-r-circle-fill::before{content:"\f80e"}.bi-r-circle::before{content:"\f80f"}.bi-r-square-fill::before{content:"\f810"}.bi-r-square::before{content:"\f811"}.bi-repeat-1::before{content:"\f812"}.bi-repeat::before{content:"\f813"}.bi-rewind-btn-fill::before{content:"\f814"}.bi-rewind-btn::before{content:"\f815"}.bi-rewind-circle-fill::before{content:"\f816"}.bi-rewind-circle::before{content:"\f817"}.bi-rewind-fill::before{content:"\f818"}.bi-rewind::before{content:"\f819"}.bi-train-freight-front-fill::before{content:"\f81a"}.bi-train-freight-front::before{content:"\f81b"}.bi-train-front-fill::before{content:"\f81c"}.bi-train-front::before{content:"\f81d"}.bi-train-lightrail-front-fill::before{content:"\f81e"}.bi-train-lightrail-front::before{content:"\f81f"}.bi-truck-front-fill::before{content:"\f820"}.bi-truck-front::before{content:"\f821"}.bi-ubuntu::before{content:"\f822"}.bi-unindent::before{content:"\f823"}.bi-unity::before{content:"\f824"}.bi-universal-access-circle::before{content:"\f825"}.bi-universal-access::before{content:"\f826"}.bi-virus::before{content:"\f827"}.bi-virus2::before{content:"\f828"}.bi-wechat::before{content:"\f829"}.bi-yelp::before{content:"\f82a"}.bi-sign-stop-fill::before{content:"\f82b"}.bi-sign-stop-lights-fill::before{content:"\f82c"}.bi-sign-stop-lights::before{content:"\f82d"}.bi-sign-stop::before{content:"\f82e"}.bi-sign-turn-left-fill::before{content:"\f82f"}.bi-sign-turn-left::before{content:"\f830"}.bi-sign-turn-right-fill::before{content:"\f831"}.bi-sign-turn-right::before{content:"\f832"}.bi-sign-turn-slight-left-fill::before{content:"\f833"}.bi-sign-turn-slight-left::before{content:"\f834"}.bi-sign-turn-slight-right-fill::before{content:"\f835"}.bi-sign-turn-slight-right::before{content:"\f836"}.bi-sign-yield-fill::before{content:"\f837"}.bi-sign-yield::before{content:"\f838"}.bi-ev-station-fill::before{content:"\f839"}.bi-ev-station::before{content:"\f83a"}.bi-fuel-pump-diesel-fill::before{content:"\f83b"}.bi-fuel-pump-diesel::before{content:"\f83c"}.bi-fuel-pump-fill::before{content:"\f83d"}.bi-fuel-pump::before{content:"\f83e"}.bi-0-circle-fill::before{content:"\f83f"}.bi-0-circle::before{content:"\f840"}.bi-0-square-fill::before{content:"\f841"}.bi-0-square::before{content:"\f842"}.bi-rocket-fill::before{content:"\f843"}.bi-rocket-takeoff-fill::before{content:"\f844"}.bi-rocket-takeoff::before{content:"\f845"}.bi-rocket::before{content:"\f846"}.bi-stripe::before{content:"\f847"}.bi-subscript::before{content:"\f848"}.bi-superscript::before{content:"\f849"}.bi-trello::before{content:"\f84a"}.bi-envelope-at-fill::before{content:"\f84b"}.bi-envelope-at::before{content:"\f84c"}.bi-regex::before{content:"\f84d"}.bi-text-wrap::before{content:"\f84e"}.bi-sign-dead-end-fill::before{content:"\f84f"}.bi-sign-dead-end::before{content:"\f850"}.bi-sign-do-not-enter-fill::before{content:"\f851"}.bi-sign-do-not-enter::before{content:"\f852"}.bi-sign-intersection-fill::before{content:"\f853"}.bi-sign-intersection-side-fill::before{content:"\f854"}.bi-sign-intersection-side::before{content:"\f855"}.bi-sign-intersection-t-fill::before{content:"\f856"}.bi-sign-intersection-t::before{content:"\f857"}.bi-sign-intersection-y-fill::before{content:"\f858"}.bi-sign-intersection-y::before{content:"\f859"}.bi-sign-intersection::before{content:"\f85a"}.bi-sign-merge-left-fill::before{content:"\f85b"}.bi-sign-merge-left::before{content:"\f85c"}.bi-sign-merge-right-fill::before{content:"\f85d"}.bi-sign-merge-right::before{content:"\f85e"}.bi-sign-no-left-turn-fill::before{content:"\f85f"}.bi-sign-no-left-turn::before{content:"\f860"}.bi-sign-no-parking-fill::before{content:"\f861"}.bi-sign-no-parking::before{content:"\f862"}.bi-sign-no-right-turn-fill::before{content:"\f863"}.bi-sign-no-right-turn::before{content:"\f864"}.bi-sign-railroad-fill::before{content:"\f865"}.bi-sign-railroad::before{content:"\f866"}.bi-building-add::before{content:"\f867"}.bi-building-check::before{content:"\f868"}.bi-building-dash::before{content:"\f869"}.bi-building-down::before{content:"\f86a"}.bi-building-exclamation::before{content:"\f86b"}.bi-building-fill-add::before{content:"\f86c"}.bi-building-fill-check::before{content:"\f86d"}.bi-building-fill-dash::before{content:"\f86e"}.bi-building-fill-down::before{content:"\f86f"}.bi-building-fill-exclamation::before{content:"\f870"}.bi-building-fill-gear::before{content:"\f871"}.bi-building-fill-lock::before{content:"\f872"}.bi-building-fill-slash::before{content:"\f873"}.bi-building-fill-up::before{content:"\f874"}.bi-building-fill-x::before{content:"\f875"}.bi-building-fill::before{content:"\f876"}.bi-building-gear::before{content:"\f877"}.bi-building-lock::before{content:"\f878"}.bi-building-slash::before{content:"\f879"}.bi-building-up::before{content:"\f87a"}.bi-building-x::before{content:"\f87b"}.bi-buildings-fill::before{content:"\f87c"}.bi-buildings::before{content:"\f87d"}.bi-bus-front-fill::before{content:"\f87e"}.bi-bus-front::before{content:"\f87f"}.bi-ev-front-fill::before{content:"\f880"}.bi-ev-front::before{content:"\f881"}.bi-globe-americas::before{content:"\f882"}.bi-globe-asia-australia::before{content:"\f883"}.bi-globe-central-south-asia::before{content:"\f884"}.bi-globe-europe-africa::before{content:"\f885"}.bi-house-add-fill::before{content:"\f886"}.bi-house-add::before{content:"\f887"}.bi-house-check-fill::before{content:"\f888"}.bi-house-check::before{content:"\f889"}.bi-house-dash-fill::before{content:"\f88a"}.bi-house-dash::before{content:"\f88b"}.bi-house-down-fill::before{content:"\f88c"}.bi-house-down::before{content:"\f88d"}.bi-house-exclamation-fill::before{content:"\f88e"}.bi-house-exclamation::before{content:"\f88f"}.bi-house-gear-fill::before{content:"\f890"}.bi-house-gear::before{content:"\f891"}.bi-house-lock-fill::before{content:"\f892"}.bi-house-lock::before{content:"\f893"}.bi-house-slash-fill::before{content:"\f894"}.bi-house-slash::before{content:"\f895"}.bi-house-up-fill::before{content:"\f896"}.bi-house-up::before{content:"\f897"}.bi-house-x-fill::before{content:"\f898"}.bi-house-x::before{content:"\f899"}.bi-person-add::before{content:"\f89a"}.bi-person-down::before{content:"\f89b"}.bi-person-exclamation::before{content:"\f89c"}.bi-person-fill-add::before{content:"\f89d"}.bi-person-fill-check::before{content:"\f89e"}.bi-person-fill-dash::before{content:"\f89f"}.bi-person-fill-down::before{content:"\f8a0"}.bi-person-fill-exclamation::before{content:"\f8a1"}.bi-person-fill-gear::before{content:"\f8a2"}.bi-person-fill-lock::before{content:"\f8a3"}.bi-person-fill-slash::before{content:"\f8a4"}.bi-person-fill-up::before{content:"\f8a5"}.bi-person-fill-x::before{content:"\f8a6"}.bi-person-gear::before{content:"\f8a7"}.bi-person-lock::before{content:"\f8a8"}.bi-person-slash::before{content:"\f8a9"}.bi-person-up::before{content:"\f8aa"}.bi-scooter::before{content:"\f8ab"}.bi-taxi-front-fill::before{content:"\f8ac"}.bi-taxi-front::before{content:"\f8ad"}.bi-amd::before{content:"\f8ae"}.bi-database-add::before{content:"\f8af"}.bi-database-check::before{content:"\f8b0"}.bi-database-dash::before{content:"\f8b1"}.bi-database-down::before{content:"\f8b2"}.bi-database-exclamation::before{content:"\f8b3"}.bi-database-fill-add::before{content:"\f8b4"}.bi-database-fill-check::before{content:"\f8b5"}.bi-database-fill-dash::before{content:"\f8b6"}.bi-database-fill-down::before{content:"\f8b7"}.bi-database-fill-exclamation::before{content:"\f8b8"}.bi-database-fill-gear::before{content:"\f8b9"}.bi-database-fill-lock::before{content:"\f8ba"}.bi-database-fill-slash::before{content:"\f8bb"}.bi-database-fill-up::before{content:"\f8bc"}.bi-database-fill-x::before{content:"\f8bd"}.bi-database-fill::before{content:"\f8be"}.bi-database-gear::before{content:"\f8bf"}.bi-database-lock::before{content:"\f8c0"}.bi-database-slash::before{content:"\f8c1"}.bi-database-up::before{content:"\f8c2"}.bi-database-x::before{content:"\f8c3"}.bi-database::before{content:"\f8c4"}.bi-houses-fill::before{content:"\f8c5"}.bi-houses::before{content:"\f8c6"}.bi-nvidia::before{content:"\f8c7"}.bi-person-vcard-fill::before{content:"\f8c8"}.bi-person-vcard::before{content:"\f8c9"}.bi-sina-weibo::before{content:"\f8ca"}.bi-tencent-qq::before{content:"\f8cb"}.bi-wikipedia::before{content:"\f8cc"}.bi-alphabet-uppercase::before{content:"\f2a5"}.bi-alphabet::before{content:"\f68a"}.bi-amazon::before{content:"\f68d"}.bi-arrows-collapse-vertical::before{content:"\f690"}.bi-arrows-expand-vertical::before{content:"\f695"}.bi-arrows-vertical::before{content:"\f698"}.bi-arrows::before{content:"\f6a2"}.bi-ban-fill::before{content:"\f6a3"}.bi-ban::before{content:"\f6b6"}.bi-bing::before{content:"\f6c2"}.bi-cake::before{content:"\f6e0"}.bi-cake2::before{content:"\f6ed"}.bi-cookie::before{content:"\f6ee"}.bi-copy::before{content:"\f759"}.bi-crosshair::before{content:"\f769"}.bi-crosshair2::before{content:"\f794"}.bi-emoji-astonished-fill::before{content:"\f795"}.bi-emoji-astonished::before{content:"\f79a"}.bi-emoji-grimace-fill::before{content:"\f79b"}.bi-emoji-grimace::before{content:"\f7a0"}.bi-emoji-grin-fill::before{content:"\f7a1"}.bi-emoji-grin::before{content:"\f7a6"}.bi-emoji-surprise-fill::before{content:"\f7a7"}.bi-emoji-surprise::before{content:"\f7ac"}.bi-emoji-tear-fill::before{content:"\f7ad"}.bi-emoji-tear::before{content:"\f7b2"}.bi-envelope-arrow-down-fill::before{content:"\f7b3"}.bi-envelope-arrow-down::before{content:"\f7b8"}.bi-envelope-arrow-up-fill::before{content:"\f7b9"}.bi-envelope-arrow-up::before{content:"\f7be"}.bi-feather::before{content:"\f7bf"}.bi-feather2::before{content:"\f7c4"}.bi-floppy-fill::before{content:"\f7c5"}.bi-floppy::before{content:"\f7d8"}.bi-floppy2-fill::before{content:"\f7d9"}.bi-floppy2::before{content:"\f7e4"}.bi-gitlab::before{content:"\f7e5"}.bi-highlighter::before{content:"\f7f8"}.bi-marker-tip::before{content:"\f802"}.bi-nvme-fill::before{content:"\f803"}.bi-nvme::before{content:"\f80c"}.bi-opencollective::before{content:"\f80d"}.bi-pci-card-network::before{content:"\f8cd"}.bi-pci-card-sound::before{content:"\f8ce"}.bi-radar::before{content:"\f8cf"}.bi-send-arrow-down-fill::before{content:"\f8d0"}.bi-send-arrow-down::before{content:"\f8d1"}.bi-send-arrow-up-fill::before{content:"\f8d2"}.bi-send-arrow-up::before{content:"\f8d3"}.bi-sim-slash-fill::before{content:"\f8d4"}.bi-sim-slash::before{content:"\f8d5"}.bi-sourceforge::before{content:"\f8d6"}.bi-substack::before{content:"\f8d7"}.bi-threads-fill::before{content:"\f8d8"}.bi-threads::before{content:"\f8d9"}.bi-transparency::before{content:"\f8da"}.bi-twitter-x::before{content:"\f8db"}.bi-type-h4::before{content:"\f8dc"}.bi-type-h5::before{content:"\f8dd"}.bi-type-h6::before{content:"\f8de"}.bi-backpack-fill::before{content:"\f8df"}.bi-backpack::before{content:"\f8e0"}.bi-backpack2-fill::before{content:"\f8e1"}.bi-backpack2::before{content:"\f8e2"}.bi-backpack3-fill::before{content:"\f8e3"}.bi-backpack3::before{content:"\f8e4"}.bi-backpack4-fill::before{content:"\f8e5"}.bi-backpack4::before{content:"\f8e6"}.bi-brilliance::before{content:"\f8e7"}.bi-cake-fill::before{content:"\f8e8"}.bi-cake2-fill::before{content:"\f8e9"}.bi-duffle-fill::before{content:"\f8ea"}.bi-duffle::before{content:"\f8eb"}.bi-exposure::before{content:"\f8ec"}.bi-gender-neuter::before{content:"\f8ed"}.bi-highlights::before{content:"\f8ee"}.bi-luggage-fill::before{content:"\f8ef"}.bi-luggage::before{content:"\f8f0"}.bi-mailbox-flag::before{content:"\f8f1"}.bi-mailbox2-flag::before{content:"\f8f2"}.bi-noise-reduction::before{content:"\f8f3"}.bi-passport-fill::before{content:"\f8f4"}.bi-passport::before{content:"\f8f5"}.bi-person-arms-up::before{content:"\f8f6"}.bi-person-raised-hand::before{content:"\f8f7"}.bi-person-standing-dress::before{content:"\f8f8"}.bi-person-standing::before{content:"\f8f9"}.bi-person-walking::before{content:"\f8fa"}.bi-person-wheelchair::before{content:"\f8fb"}.bi-shadows::before{content:"\f8fc"}.bi-suitcase-fill::before{content:"\f8fd"}.bi-suitcase-lg-fill::before{content:"\f8fe"}.bi-suitcase-lg::before{content:"\f8ff"}.bi-suitcase::before{content:"\f900"}.bi-suitcase2-fill::before{content:"\f901"}.bi-suitcase2::before{content:"\f902"}.bi-vignette::before{content:"\f903"}.bi-bluesky::before{content:"\f7f9"}.bi-tux::before{content:"\f904"}.bi-beaker-fill::before{content:"\f905"}.bi-beaker::before{content:"\f906"}.bi-flask-fill::before{content:"\f907"}.bi-flask-florence-fill::before{content:"\f908"}.bi-flask-florence::before{content:"\f909"}.bi-flask::before{content:"\f90a"}.bi-leaf-fill::before{content:"\f90b"}.bi-leaf::before{content:"\f90c"}.bi-measuring-cup-fill::before{content:"\f90d"}.bi-measuring-cup::before{content:"\f90e"}.bi-unlock2-fill::before{content:"\f90f"}.bi-unlock2::before{content:"\f910"}.bi-battery-low::before{content:"\f911"}.bi-anthropic::before{content:"\f912"}.bi-apple-music::before{content:"\f913"}.bi-claude::before{content:"\f914"}.bi-openai::before{content:"\f915"}.bi-perplexity::before{content:"\f916"}.bi-css::before{content:"\f917"}.bi-javascript::before{content:"\f918"}.bi-typescript::before{content:"\f919"}.bi-fork-knife::before{content:"\f91a"}.bi-globe-americas-fill::before{content:"\f91b"}.bi-globe-asia-australia-fill::before{content:"\f91c"}.bi-globe-central-south-asia-fill::before{content:"\f91d"}.bi-globe-europe-africa-fill::before{content:"\f91e"} \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bootstrap-icons.scss b/web/vendor/bootstrap-icons/bootstrap-icons.scss new file mode 100644 index 0000000..19735c4 --- /dev/null +++ b/web/vendor/bootstrap-icons/bootstrap-icons.scss @@ -0,0 +1,2118 @@ +/*! + * Bootstrap Icons v1.13.1 (https://icons.getbootstrap.com/) + * Copyright 2019-2024 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/icons/blob/main/LICENSE) + */ + +$bootstrap-icons-font: "bootstrap-icons" !default; +$bootstrap-icons-font-dir: "./fonts" !default; +$bootstrap-icons-font-file: "#{$bootstrap-icons-font-dir}/#{$bootstrap-icons-font}" !default; +$bootstrap-icons-font-hash: "24e3eb84d0bcaf83d77f904c78ac1f47" !default; +$bootstrap-icons-font-src: url("#{$bootstrap-icons-font-file}.woff2?#{$bootstrap-icons-font-hash}") format("woff2"), + url("#{$bootstrap-icons-font-file}.woff?#{$bootstrap-icons-font-hash}") format("woff") !default; + +@font-face { + font-display: block; + font-family: $bootstrap-icons-font; + src: $bootstrap-icons-font-src; +} + +.bi::before, +[class^="bi-"]::before, +[class*=" bi-"]::before { + display: inline-block; + font-family: $bootstrap-icons-font !important; + font-style: normal; + font-weight: normal !important; + font-variant: normal; + text-transform: none; + line-height: 1; + vertical-align: -.125em; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +$bootstrap-icons-map: ( + "123": "\f67f", + "alarm-fill": "\f101", + "alarm": "\f102", + "align-bottom": "\f103", + "align-center": "\f104", + "align-end": "\f105", + "align-middle": "\f106", + "align-start": "\f107", + "align-top": "\f108", + "alt": "\f109", + "app-indicator": "\f10a", + "app": "\f10b", + "archive-fill": "\f10c", + "archive": "\f10d", + "arrow-90deg-down": "\f10e", + "arrow-90deg-left": "\f10f", + "arrow-90deg-right": "\f110", + "arrow-90deg-up": "\f111", + "arrow-bar-down": "\f112", + "arrow-bar-left": "\f113", + "arrow-bar-right": "\f114", + "arrow-bar-up": "\f115", + "arrow-clockwise": "\f116", + "arrow-counterclockwise": "\f117", + "arrow-down-circle-fill": "\f118", + "arrow-down-circle": "\f119", + "arrow-down-left-circle-fill": "\f11a", + "arrow-down-left-circle": "\f11b", + "arrow-down-left-square-fill": "\f11c", + "arrow-down-left-square": "\f11d", + "arrow-down-left": "\f11e", + "arrow-down-right-circle-fill": "\f11f", + "arrow-down-right-circle": "\f120", + "arrow-down-right-square-fill": "\f121", + "arrow-down-right-square": "\f122", + "arrow-down-right": "\f123", + "arrow-down-short": "\f124", + "arrow-down-square-fill": "\f125", + "arrow-down-square": "\f126", + "arrow-down-up": "\f127", + "arrow-down": "\f128", + "arrow-left-circle-fill": "\f129", + "arrow-left-circle": "\f12a", + "arrow-left-right": "\f12b", + "arrow-left-short": "\f12c", + "arrow-left-square-fill": "\f12d", + "arrow-left-square": "\f12e", + "arrow-left": "\f12f", + "arrow-repeat": "\f130", + "arrow-return-left": "\f131", + "arrow-return-right": "\f132", + "arrow-right-circle-fill": "\f133", + "arrow-right-circle": "\f134", + "arrow-right-short": "\f135", + "arrow-right-square-fill": "\f136", + "arrow-right-square": "\f137", + "arrow-right": "\f138", + "arrow-up-circle-fill": "\f139", + "arrow-up-circle": "\f13a", + "arrow-up-left-circle-fill": "\f13b", + "arrow-up-left-circle": "\f13c", + "arrow-up-left-square-fill": "\f13d", + "arrow-up-left-square": "\f13e", + "arrow-up-left": "\f13f", + "arrow-up-right-circle-fill": "\f140", + "arrow-up-right-circle": "\f141", + "arrow-up-right-square-fill": "\f142", + "arrow-up-right-square": "\f143", + "arrow-up-right": "\f144", + "arrow-up-short": "\f145", + "arrow-up-square-fill": "\f146", + "arrow-up-square": "\f147", + "arrow-up": "\f148", + "arrows-angle-contract": "\f149", + "arrows-angle-expand": "\f14a", + "arrows-collapse": "\f14b", + "arrows-expand": "\f14c", + "arrows-fullscreen": "\f14d", + "arrows-move": "\f14e", + "aspect-ratio-fill": "\f14f", + "aspect-ratio": "\f150", + "asterisk": "\f151", + "at": "\f152", + "award-fill": "\f153", + "award": "\f154", + "back": "\f155", + "backspace-fill": "\f156", + "backspace-reverse-fill": "\f157", + "backspace-reverse": "\f158", + "backspace": "\f159", + "badge-3d-fill": "\f15a", + "badge-3d": "\f15b", + "badge-4k-fill": "\f15c", + "badge-4k": "\f15d", + "badge-8k-fill": "\f15e", + "badge-8k": "\f15f", + "badge-ad-fill": "\f160", + "badge-ad": "\f161", + "badge-ar-fill": "\f162", + "badge-ar": "\f163", + "badge-cc-fill": "\f164", + "badge-cc": "\f165", + "badge-hd-fill": "\f166", + "badge-hd": "\f167", + "badge-tm-fill": "\f168", + "badge-tm": "\f169", + "badge-vo-fill": "\f16a", + "badge-vo": "\f16b", + "badge-vr-fill": "\f16c", + "badge-vr": "\f16d", + "badge-wc-fill": "\f16e", + "badge-wc": "\f16f", + "bag-check-fill": "\f170", + "bag-check": "\f171", + "bag-dash-fill": "\f172", + "bag-dash": "\f173", + "bag-fill": "\f174", + "bag-plus-fill": "\f175", + "bag-plus": "\f176", + "bag-x-fill": "\f177", + "bag-x": "\f178", + "bag": "\f179", + "bar-chart-fill": "\f17a", + "bar-chart-line-fill": "\f17b", + "bar-chart-line": "\f17c", + "bar-chart-steps": "\f17d", + "bar-chart": "\f17e", + "basket-fill": "\f17f", + "basket": "\f180", + "basket2-fill": "\f181", + "basket2": "\f182", + "basket3-fill": "\f183", + "basket3": "\f184", + "battery-charging": "\f185", + "battery-full": "\f186", + "battery-half": "\f187", + "battery": "\f188", + "bell-fill": "\f189", + "bell": "\f18a", + "bezier": "\f18b", + "bezier2": "\f18c", + "bicycle": "\f18d", + "binoculars-fill": "\f18e", + "binoculars": "\f18f", + "blockquote-left": "\f190", + "blockquote-right": "\f191", + "book-fill": "\f192", + "book-half": "\f193", + "book": "\f194", + "bookmark-check-fill": "\f195", + "bookmark-check": "\f196", + "bookmark-dash-fill": "\f197", + "bookmark-dash": "\f198", + "bookmark-fill": "\f199", + "bookmark-heart-fill": "\f19a", + "bookmark-heart": "\f19b", + "bookmark-plus-fill": "\f19c", + "bookmark-plus": "\f19d", + "bookmark-star-fill": "\f19e", + "bookmark-star": "\f19f", + "bookmark-x-fill": "\f1a0", + "bookmark-x": "\f1a1", + "bookmark": "\f1a2", + "bookmarks-fill": "\f1a3", + "bookmarks": "\f1a4", + "bookshelf": "\f1a5", + "bootstrap-fill": "\f1a6", + "bootstrap-reboot": "\f1a7", + "bootstrap": "\f1a8", + "border-all": "\f1a9", + "border-bottom": "\f1aa", + "border-center": "\f1ab", + "border-inner": "\f1ac", + "border-left": "\f1ad", + "border-middle": "\f1ae", + "border-outer": "\f1af", + "border-right": "\f1b0", + "border-style": "\f1b1", + "border-top": "\f1b2", + "border-width": "\f1b3", + "border": "\f1b4", + "bounding-box-circles": "\f1b5", + "bounding-box": "\f1b6", + "box-arrow-down-left": "\f1b7", + "box-arrow-down-right": "\f1b8", + "box-arrow-down": "\f1b9", + "box-arrow-in-down-left": "\f1ba", + "box-arrow-in-down-right": "\f1bb", + "box-arrow-in-down": "\f1bc", + "box-arrow-in-left": "\f1bd", + "box-arrow-in-right": "\f1be", + "box-arrow-in-up-left": "\f1bf", + "box-arrow-in-up-right": "\f1c0", + "box-arrow-in-up": "\f1c1", + "box-arrow-left": "\f1c2", + "box-arrow-right": "\f1c3", + "box-arrow-up-left": "\f1c4", + "box-arrow-up-right": "\f1c5", + "box-arrow-up": "\f1c6", + "box-seam": "\f1c7", + "box": "\f1c8", + "braces": "\f1c9", + "bricks": "\f1ca", + "briefcase-fill": "\f1cb", + "briefcase": "\f1cc", + "brightness-alt-high-fill": "\f1cd", + "brightness-alt-high": "\f1ce", + "brightness-alt-low-fill": "\f1cf", + "brightness-alt-low": "\f1d0", + "brightness-high-fill": "\f1d1", + "brightness-high": "\f1d2", + "brightness-low-fill": "\f1d3", + "brightness-low": "\f1d4", + "broadcast-pin": "\f1d5", + "broadcast": "\f1d6", + "brush-fill": "\f1d7", + "brush": "\f1d8", + "bucket-fill": "\f1d9", + "bucket": "\f1da", + "bug-fill": "\f1db", + "bug": "\f1dc", + "building": "\f1dd", + "bullseye": "\f1de", + "calculator-fill": "\f1df", + "calculator": "\f1e0", + "calendar-check-fill": "\f1e1", + "calendar-check": "\f1e2", + "calendar-date-fill": "\f1e3", + "calendar-date": "\f1e4", + "calendar-day-fill": "\f1e5", + "calendar-day": "\f1e6", + "calendar-event-fill": "\f1e7", + "calendar-event": "\f1e8", + "calendar-fill": "\f1e9", + "calendar-minus-fill": "\f1ea", + "calendar-minus": "\f1eb", + "calendar-month-fill": "\f1ec", + "calendar-month": "\f1ed", + "calendar-plus-fill": "\f1ee", + "calendar-plus": "\f1ef", + "calendar-range-fill": "\f1f0", + "calendar-range": "\f1f1", + "calendar-week-fill": "\f1f2", + "calendar-week": "\f1f3", + "calendar-x-fill": "\f1f4", + "calendar-x": "\f1f5", + "calendar": "\f1f6", + "calendar2-check-fill": "\f1f7", + "calendar2-check": "\f1f8", + "calendar2-date-fill": "\f1f9", + "calendar2-date": "\f1fa", + "calendar2-day-fill": "\f1fb", + "calendar2-day": "\f1fc", + "calendar2-event-fill": "\f1fd", + "calendar2-event": "\f1fe", + "calendar2-fill": "\f1ff", + "calendar2-minus-fill": "\f200", + "calendar2-minus": "\f201", + "calendar2-month-fill": "\f202", + "calendar2-month": "\f203", + "calendar2-plus-fill": "\f204", + "calendar2-plus": "\f205", + "calendar2-range-fill": "\f206", + "calendar2-range": "\f207", + "calendar2-week-fill": "\f208", + "calendar2-week": "\f209", + "calendar2-x-fill": "\f20a", + "calendar2-x": "\f20b", + "calendar2": "\f20c", + "calendar3-event-fill": "\f20d", + "calendar3-event": "\f20e", + "calendar3-fill": "\f20f", + "calendar3-range-fill": "\f210", + "calendar3-range": "\f211", + "calendar3-week-fill": "\f212", + "calendar3-week": "\f213", + "calendar3": "\f214", + "calendar4-event": "\f215", + "calendar4-range": "\f216", + "calendar4-week": "\f217", + "calendar4": "\f218", + "camera-fill": "\f219", + "camera-reels-fill": "\f21a", + "camera-reels": "\f21b", + "camera-video-fill": "\f21c", + "camera-video-off-fill": "\f21d", + "camera-video-off": "\f21e", + "camera-video": "\f21f", + "camera": "\f220", + "camera2": "\f221", + "capslock-fill": "\f222", + "capslock": "\f223", + "card-checklist": "\f224", + "card-heading": "\f225", + "card-image": "\f226", + "card-list": "\f227", + "card-text": "\f228", + "caret-down-fill": "\f229", + "caret-down-square-fill": "\f22a", + "caret-down-square": "\f22b", + "caret-down": "\f22c", + "caret-left-fill": "\f22d", + "caret-left-square-fill": "\f22e", + "caret-left-square": "\f22f", + "caret-left": "\f230", + "caret-right-fill": "\f231", + "caret-right-square-fill": "\f232", + "caret-right-square": "\f233", + "caret-right": "\f234", + "caret-up-fill": "\f235", + "caret-up-square-fill": "\f236", + "caret-up-square": "\f237", + "caret-up": "\f238", + "cart-check-fill": "\f239", + "cart-check": "\f23a", + "cart-dash-fill": "\f23b", + "cart-dash": "\f23c", + "cart-fill": "\f23d", + "cart-plus-fill": "\f23e", + "cart-plus": "\f23f", + "cart-x-fill": "\f240", + "cart-x": "\f241", + "cart": "\f242", + "cart2": "\f243", + "cart3": "\f244", + "cart4": "\f245", + "cash-stack": "\f246", + "cash": "\f247", + "cast": "\f248", + "chat-dots-fill": "\f249", + "chat-dots": "\f24a", + "chat-fill": "\f24b", + "chat-left-dots-fill": "\f24c", + "chat-left-dots": "\f24d", + "chat-left-fill": "\f24e", + "chat-left-quote-fill": "\f24f", + "chat-left-quote": "\f250", + "chat-left-text-fill": "\f251", + "chat-left-text": "\f252", + "chat-left": "\f253", + "chat-quote-fill": "\f254", + "chat-quote": "\f255", + "chat-right-dots-fill": "\f256", + "chat-right-dots": "\f257", + "chat-right-fill": "\f258", + "chat-right-quote-fill": "\f259", + "chat-right-quote": "\f25a", + "chat-right-text-fill": "\f25b", + "chat-right-text": "\f25c", + "chat-right": "\f25d", + "chat-square-dots-fill": "\f25e", + "chat-square-dots": "\f25f", + "chat-square-fill": "\f260", + "chat-square-quote-fill": "\f261", + "chat-square-quote": "\f262", + "chat-square-text-fill": "\f263", + "chat-square-text": "\f264", + "chat-square": "\f265", + "chat-text-fill": "\f266", + "chat-text": "\f267", + "chat": "\f268", + "check-all": "\f269", + "check-circle-fill": "\f26a", + "check-circle": "\f26b", + "check-square-fill": "\f26c", + "check-square": "\f26d", + "check": "\f26e", + "check2-all": "\f26f", + "check2-circle": "\f270", + "check2-square": "\f271", + "check2": "\f272", + "chevron-bar-contract": "\f273", + "chevron-bar-down": "\f274", + "chevron-bar-expand": "\f275", + "chevron-bar-left": "\f276", + "chevron-bar-right": "\f277", + "chevron-bar-up": "\f278", + "chevron-compact-down": "\f279", + "chevron-compact-left": "\f27a", + "chevron-compact-right": "\f27b", + "chevron-compact-up": "\f27c", + "chevron-contract": "\f27d", + "chevron-double-down": "\f27e", + "chevron-double-left": "\f27f", + "chevron-double-right": "\f280", + "chevron-double-up": "\f281", + "chevron-down": "\f282", + "chevron-expand": "\f283", + "chevron-left": "\f284", + "chevron-right": "\f285", + "chevron-up": "\f286", + "circle-fill": "\f287", + "circle-half": "\f288", + "circle-square": "\f289", + "circle": "\f28a", + "clipboard-check": "\f28b", + "clipboard-data": "\f28c", + "clipboard-minus": "\f28d", + "clipboard-plus": "\f28e", + "clipboard-x": "\f28f", + "clipboard": "\f290", + "clock-fill": "\f291", + "clock-history": "\f292", + "clock": "\f293", + "cloud-arrow-down-fill": "\f294", + "cloud-arrow-down": "\f295", + "cloud-arrow-up-fill": "\f296", + "cloud-arrow-up": "\f297", + "cloud-check-fill": "\f298", + "cloud-check": "\f299", + "cloud-download-fill": "\f29a", + "cloud-download": "\f29b", + "cloud-drizzle-fill": "\f29c", + "cloud-drizzle": "\f29d", + "cloud-fill": "\f29e", + "cloud-fog-fill": "\f29f", + "cloud-fog": "\f2a0", + "cloud-fog2-fill": "\f2a1", + "cloud-fog2": "\f2a2", + "cloud-hail-fill": "\f2a3", + "cloud-hail": "\f2a4", + "cloud-haze-fill": "\f2a6", + "cloud-haze": "\f2a7", + "cloud-haze2-fill": "\f2a8", + "cloud-lightning-fill": "\f2a9", + "cloud-lightning-rain-fill": "\f2aa", + "cloud-lightning-rain": "\f2ab", + "cloud-lightning": "\f2ac", + "cloud-minus-fill": "\f2ad", + "cloud-minus": "\f2ae", + "cloud-moon-fill": "\f2af", + "cloud-moon": "\f2b0", + "cloud-plus-fill": "\f2b1", + "cloud-plus": "\f2b2", + "cloud-rain-fill": "\f2b3", + "cloud-rain-heavy-fill": "\f2b4", + "cloud-rain-heavy": "\f2b5", + "cloud-rain": "\f2b6", + "cloud-slash-fill": "\f2b7", + "cloud-slash": "\f2b8", + "cloud-sleet-fill": "\f2b9", + "cloud-sleet": "\f2ba", + "cloud-snow-fill": "\f2bb", + "cloud-snow": "\f2bc", + "cloud-sun-fill": "\f2bd", + "cloud-sun": "\f2be", + "cloud-upload-fill": "\f2bf", + "cloud-upload": "\f2c0", + "cloud": "\f2c1", + "clouds-fill": "\f2c2", + "clouds": "\f2c3", + "cloudy-fill": "\f2c4", + "cloudy": "\f2c5", + "code-slash": "\f2c6", + "code-square": "\f2c7", + "code": "\f2c8", + "collection-fill": "\f2c9", + "collection-play-fill": "\f2ca", + "collection-play": "\f2cb", + "collection": "\f2cc", + "columns-gap": "\f2cd", + "columns": "\f2ce", + "command": "\f2cf", + "compass-fill": "\f2d0", + "compass": "\f2d1", + "cone-striped": "\f2d2", + "cone": "\f2d3", + "controller": "\f2d4", + "cpu-fill": "\f2d5", + "cpu": "\f2d6", + "credit-card-2-back-fill": "\f2d7", + "credit-card-2-back": "\f2d8", + "credit-card-2-front-fill": "\f2d9", + "credit-card-2-front": "\f2da", + "credit-card-fill": "\f2db", + "credit-card": "\f2dc", + "crop": "\f2dd", + "cup-fill": "\f2de", + "cup-straw": "\f2df", + "cup": "\f2e0", + "cursor-fill": "\f2e1", + "cursor-text": "\f2e2", + "cursor": "\f2e3", + "dash-circle-dotted": "\f2e4", + "dash-circle-fill": "\f2e5", + "dash-circle": "\f2e6", + "dash-square-dotted": "\f2e7", + "dash-square-fill": "\f2e8", + "dash-square": "\f2e9", + "dash": "\f2ea", + "diagram-2-fill": "\f2eb", + "diagram-2": "\f2ec", + "diagram-3-fill": "\f2ed", + "diagram-3": "\f2ee", + "diamond-fill": "\f2ef", + "diamond-half": "\f2f0", + "diamond": "\f2f1", + "dice-1-fill": "\f2f2", + "dice-1": "\f2f3", + "dice-2-fill": "\f2f4", + "dice-2": "\f2f5", + "dice-3-fill": "\f2f6", + "dice-3": "\f2f7", + "dice-4-fill": "\f2f8", + "dice-4": "\f2f9", + "dice-5-fill": "\f2fa", + "dice-5": "\f2fb", + "dice-6-fill": "\f2fc", + "dice-6": "\f2fd", + "disc-fill": "\f2fe", + "disc": "\f2ff", + "discord": "\f300", + "display-fill": "\f301", + "display": "\f302", + "distribute-horizontal": "\f303", + "distribute-vertical": "\f304", + "door-closed-fill": "\f305", + "door-closed": "\f306", + "door-open-fill": "\f307", + "door-open": "\f308", + "dot": "\f309", + "download": "\f30a", + "droplet-fill": "\f30b", + "droplet-half": "\f30c", + "droplet": "\f30d", + "earbuds": "\f30e", + "easel-fill": "\f30f", + "easel": "\f310", + "egg-fill": "\f311", + "egg-fried": "\f312", + "egg": "\f313", + "eject-fill": "\f314", + "eject": "\f315", + "emoji-angry-fill": "\f316", + "emoji-angry": "\f317", + "emoji-dizzy-fill": "\f318", + "emoji-dizzy": "\f319", + "emoji-expressionless-fill": "\f31a", + "emoji-expressionless": "\f31b", + "emoji-frown-fill": "\f31c", + "emoji-frown": "\f31d", + "emoji-heart-eyes-fill": "\f31e", + "emoji-heart-eyes": "\f31f", + "emoji-laughing-fill": "\f320", + "emoji-laughing": "\f321", + "emoji-neutral-fill": "\f322", + "emoji-neutral": "\f323", + "emoji-smile-fill": "\f324", + "emoji-smile-upside-down-fill": "\f325", + "emoji-smile-upside-down": "\f326", + "emoji-smile": "\f327", + "emoji-sunglasses-fill": "\f328", + "emoji-sunglasses": "\f329", + "emoji-wink-fill": "\f32a", + "emoji-wink": "\f32b", + "envelope-fill": "\f32c", + "envelope-open-fill": "\f32d", + "envelope-open": "\f32e", + "envelope": "\f32f", + "eraser-fill": "\f330", + "eraser": "\f331", + "exclamation-circle-fill": "\f332", + "exclamation-circle": "\f333", + "exclamation-diamond-fill": "\f334", + "exclamation-diamond": "\f335", + "exclamation-octagon-fill": "\f336", + "exclamation-octagon": "\f337", + "exclamation-square-fill": "\f338", + "exclamation-square": "\f339", + "exclamation-triangle-fill": "\f33a", + "exclamation-triangle": "\f33b", + "exclamation": "\f33c", + "exclude": "\f33d", + "eye-fill": "\f33e", + "eye-slash-fill": "\f33f", + "eye-slash": "\f340", + "eye": "\f341", + "eyedropper": "\f342", + "eyeglasses": "\f343", + "facebook": "\f344", + "file-arrow-down-fill": "\f345", + "file-arrow-down": "\f346", + "file-arrow-up-fill": "\f347", + "file-arrow-up": "\f348", + "file-bar-graph-fill": "\f349", + "file-bar-graph": "\f34a", + "file-binary-fill": "\f34b", + "file-binary": "\f34c", + "file-break-fill": "\f34d", + "file-break": "\f34e", + "file-check-fill": "\f34f", + "file-check": "\f350", + "file-code-fill": "\f351", + "file-code": "\f352", + "file-diff-fill": "\f353", + "file-diff": "\f354", + "file-earmark-arrow-down-fill": "\f355", + "file-earmark-arrow-down": "\f356", + "file-earmark-arrow-up-fill": "\f357", + "file-earmark-arrow-up": "\f358", + "file-earmark-bar-graph-fill": "\f359", + "file-earmark-bar-graph": "\f35a", + "file-earmark-binary-fill": "\f35b", + "file-earmark-binary": "\f35c", + "file-earmark-break-fill": "\f35d", + "file-earmark-break": "\f35e", + "file-earmark-check-fill": "\f35f", + "file-earmark-check": "\f360", + "file-earmark-code-fill": "\f361", + "file-earmark-code": "\f362", + "file-earmark-diff-fill": "\f363", + "file-earmark-diff": "\f364", + "file-earmark-easel-fill": "\f365", + "file-earmark-easel": "\f366", + "file-earmark-excel-fill": "\f367", + "file-earmark-excel": "\f368", + "file-earmark-fill": "\f369", + "file-earmark-font-fill": "\f36a", + "file-earmark-font": "\f36b", + "file-earmark-image-fill": "\f36c", + "file-earmark-image": "\f36d", + "file-earmark-lock-fill": "\f36e", + "file-earmark-lock": "\f36f", + "file-earmark-lock2-fill": "\f370", + "file-earmark-lock2": "\f371", + "file-earmark-medical-fill": "\f372", + "file-earmark-medical": "\f373", + "file-earmark-minus-fill": "\f374", + "file-earmark-minus": "\f375", + "file-earmark-music-fill": "\f376", + "file-earmark-music": "\f377", + "file-earmark-person-fill": "\f378", + "file-earmark-person": "\f379", + "file-earmark-play-fill": "\f37a", + "file-earmark-play": "\f37b", + "file-earmark-plus-fill": "\f37c", + "file-earmark-plus": "\f37d", + "file-earmark-post-fill": "\f37e", + "file-earmark-post": "\f37f", + "file-earmark-ppt-fill": "\f380", + "file-earmark-ppt": "\f381", + "file-earmark-richtext-fill": "\f382", + "file-earmark-richtext": "\f383", + "file-earmark-ruled-fill": "\f384", + "file-earmark-ruled": "\f385", + "file-earmark-slides-fill": "\f386", + "file-earmark-slides": "\f387", + "file-earmark-spreadsheet-fill": "\f388", + "file-earmark-spreadsheet": "\f389", + "file-earmark-text-fill": "\f38a", + "file-earmark-text": "\f38b", + "file-earmark-word-fill": "\f38c", + "file-earmark-word": "\f38d", + "file-earmark-x-fill": "\f38e", + "file-earmark-x": "\f38f", + "file-earmark-zip-fill": "\f390", + "file-earmark-zip": "\f391", + "file-earmark": "\f392", + "file-easel-fill": "\f393", + "file-easel": "\f394", + "file-excel-fill": "\f395", + "file-excel": "\f396", + "file-fill": "\f397", + "file-font-fill": "\f398", + "file-font": "\f399", + "file-image-fill": "\f39a", + "file-image": "\f39b", + "file-lock-fill": "\f39c", + "file-lock": "\f39d", + "file-lock2-fill": "\f39e", + "file-lock2": "\f39f", + "file-medical-fill": "\f3a0", + "file-medical": "\f3a1", + "file-minus-fill": "\f3a2", + "file-minus": "\f3a3", + "file-music-fill": "\f3a4", + "file-music": "\f3a5", + "file-person-fill": "\f3a6", + "file-person": "\f3a7", + "file-play-fill": "\f3a8", + "file-play": "\f3a9", + "file-plus-fill": "\f3aa", + "file-plus": "\f3ab", + "file-post-fill": "\f3ac", + "file-post": "\f3ad", + "file-ppt-fill": "\f3ae", + "file-ppt": "\f3af", + "file-richtext-fill": "\f3b0", + "file-richtext": "\f3b1", + "file-ruled-fill": "\f3b2", + "file-ruled": "\f3b3", + "file-slides-fill": "\f3b4", + "file-slides": "\f3b5", + "file-spreadsheet-fill": "\f3b6", + "file-spreadsheet": "\f3b7", + "file-text-fill": "\f3b8", + "file-text": "\f3b9", + "file-word-fill": "\f3ba", + "file-word": "\f3bb", + "file-x-fill": "\f3bc", + "file-x": "\f3bd", + "file-zip-fill": "\f3be", + "file-zip": "\f3bf", + "file": "\f3c0", + "files-alt": "\f3c1", + "files": "\f3c2", + "film": "\f3c3", + "filter-circle-fill": "\f3c4", + "filter-circle": "\f3c5", + "filter-left": "\f3c6", + "filter-right": "\f3c7", + "filter-square-fill": "\f3c8", + "filter-square": "\f3c9", + "filter": "\f3ca", + "flag-fill": "\f3cb", + "flag": "\f3cc", + "flower1": "\f3cd", + "flower2": "\f3ce", + "flower3": "\f3cf", + "folder-check": "\f3d0", + "folder-fill": "\f3d1", + "folder-minus": "\f3d2", + "folder-plus": "\f3d3", + "folder-symlink-fill": "\f3d4", + "folder-symlink": "\f3d5", + "folder-x": "\f3d6", + "folder": "\f3d7", + "folder2-open": "\f3d8", + "folder2": "\f3d9", + "fonts": "\f3da", + "forward-fill": "\f3db", + "forward": "\f3dc", + "front": "\f3dd", + "fullscreen-exit": "\f3de", + "fullscreen": "\f3df", + "funnel-fill": "\f3e0", + "funnel": "\f3e1", + "gear-fill": "\f3e2", + "gear-wide-connected": "\f3e3", + "gear-wide": "\f3e4", + "gear": "\f3e5", + "gem": "\f3e6", + "geo-alt-fill": "\f3e7", + "geo-alt": "\f3e8", + "geo-fill": "\f3e9", + "geo": "\f3ea", + "gift-fill": "\f3eb", + "gift": "\f3ec", + "github": "\f3ed", + "globe": "\f3ee", + "globe2": "\f3ef", + "google": "\f3f0", + "graph-down": "\f3f1", + "graph-up": "\f3f2", + "grid-1x2-fill": "\f3f3", + "grid-1x2": "\f3f4", + "grid-3x2-gap-fill": "\f3f5", + "grid-3x2-gap": "\f3f6", + "grid-3x2": "\f3f7", + "grid-3x3-gap-fill": "\f3f8", + "grid-3x3-gap": "\f3f9", + "grid-3x3": "\f3fa", + "grid-fill": "\f3fb", + "grid": "\f3fc", + "grip-horizontal": "\f3fd", + "grip-vertical": "\f3fe", + "hammer": "\f3ff", + "hand-index-fill": "\f400", + "hand-index-thumb-fill": "\f401", + "hand-index-thumb": "\f402", + "hand-index": "\f403", + "hand-thumbs-down-fill": "\f404", + "hand-thumbs-down": "\f405", + "hand-thumbs-up-fill": "\f406", + "hand-thumbs-up": "\f407", + "handbag-fill": "\f408", + "handbag": "\f409", + "hash": "\f40a", + "hdd-fill": "\f40b", + "hdd-network-fill": "\f40c", + "hdd-network": "\f40d", + "hdd-rack-fill": "\f40e", + "hdd-rack": "\f40f", + "hdd-stack-fill": "\f410", + "hdd-stack": "\f411", + "hdd": "\f412", + "headphones": "\f413", + "headset": "\f414", + "heart-fill": "\f415", + "heart-half": "\f416", + "heart": "\f417", + "heptagon-fill": "\f418", + "heptagon-half": "\f419", + "heptagon": "\f41a", + "hexagon-fill": "\f41b", + "hexagon-half": "\f41c", + "hexagon": "\f41d", + "hourglass-bottom": "\f41e", + "hourglass-split": "\f41f", + "hourglass-top": "\f420", + "hourglass": "\f421", + "house-door-fill": "\f422", + "house-door": "\f423", + "house-fill": "\f424", + "house": "\f425", + "hr": "\f426", + "hurricane": "\f427", + "image-alt": "\f428", + "image-fill": "\f429", + "image": "\f42a", + "images": "\f42b", + "inbox-fill": "\f42c", + "inbox": "\f42d", + "inboxes-fill": "\f42e", + "inboxes": "\f42f", + "info-circle-fill": "\f430", + "info-circle": "\f431", + "info-square-fill": "\f432", + "info-square": "\f433", + "info": "\f434", + "input-cursor-text": "\f435", + "input-cursor": "\f436", + "instagram": "\f437", + "intersect": "\f438", + "journal-album": "\f439", + "journal-arrow-down": "\f43a", + "journal-arrow-up": "\f43b", + "journal-bookmark-fill": "\f43c", + "journal-bookmark": "\f43d", + "journal-check": "\f43e", + "journal-code": "\f43f", + "journal-medical": "\f440", + "journal-minus": "\f441", + "journal-plus": "\f442", + "journal-richtext": "\f443", + "journal-text": "\f444", + "journal-x": "\f445", + "journal": "\f446", + "journals": "\f447", + "joystick": "\f448", + "justify-left": "\f449", + "justify-right": "\f44a", + "justify": "\f44b", + "kanban-fill": "\f44c", + "kanban": "\f44d", + "key-fill": "\f44e", + "key": "\f44f", + "keyboard-fill": "\f450", + "keyboard": "\f451", + "ladder": "\f452", + "lamp-fill": "\f453", + "lamp": "\f454", + "laptop-fill": "\f455", + "laptop": "\f456", + "layer-backward": "\f457", + "layer-forward": "\f458", + "layers-fill": "\f459", + "layers-half": "\f45a", + "layers": "\f45b", + "layout-sidebar-inset-reverse": "\f45c", + "layout-sidebar-inset": "\f45d", + "layout-sidebar-reverse": "\f45e", + "layout-sidebar": "\f45f", + "layout-split": "\f460", + "layout-text-sidebar-reverse": "\f461", + "layout-text-sidebar": "\f462", + "layout-text-window-reverse": "\f463", + "layout-text-window": "\f464", + "layout-three-columns": "\f465", + "layout-wtf": "\f466", + "life-preserver": "\f467", + "lightbulb-fill": "\f468", + "lightbulb-off-fill": "\f469", + "lightbulb-off": "\f46a", + "lightbulb": "\f46b", + "lightning-charge-fill": "\f46c", + "lightning-charge": "\f46d", + "lightning-fill": "\f46e", + "lightning": "\f46f", + "link-45deg": "\f470", + "link": "\f471", + "linkedin": "\f472", + "list-check": "\f473", + "list-nested": "\f474", + "list-ol": "\f475", + "list-stars": "\f476", + "list-task": "\f477", + "list-ul": "\f478", + "list": "\f479", + "lock-fill": "\f47a", + "lock": "\f47b", + "mailbox": "\f47c", + "mailbox2": "\f47d", + "map-fill": "\f47e", + "map": "\f47f", + "markdown-fill": "\f480", + "markdown": "\f481", + "mask": "\f482", + "megaphone-fill": "\f483", + "megaphone": "\f484", + "menu-app-fill": "\f485", + "menu-app": "\f486", + "menu-button-fill": "\f487", + "menu-button-wide-fill": "\f488", + "menu-button-wide": "\f489", + "menu-button": "\f48a", + "menu-down": "\f48b", + "menu-up": "\f48c", + "mic-fill": "\f48d", + "mic-mute-fill": "\f48e", + "mic-mute": "\f48f", + "mic": "\f490", + "minecart-loaded": "\f491", + "minecart": "\f492", + "moisture": "\f493", + "moon-fill": "\f494", + "moon-stars-fill": "\f495", + "moon-stars": "\f496", + "moon": "\f497", + "mouse-fill": "\f498", + "mouse": "\f499", + "mouse2-fill": "\f49a", + "mouse2": "\f49b", + "mouse3-fill": "\f49c", + "mouse3": "\f49d", + "music-note-beamed": "\f49e", + "music-note-list": "\f49f", + "music-note": "\f4a0", + "music-player-fill": "\f4a1", + "music-player": "\f4a2", + "newspaper": "\f4a3", + "node-minus-fill": "\f4a4", + "node-minus": "\f4a5", + "node-plus-fill": "\f4a6", + "node-plus": "\f4a7", + "nut-fill": "\f4a8", + "nut": "\f4a9", + "octagon-fill": "\f4aa", + "octagon-half": "\f4ab", + "octagon": "\f4ac", + "option": "\f4ad", + "outlet": "\f4ae", + "paint-bucket": "\f4af", + "palette-fill": "\f4b0", + "palette": "\f4b1", + "palette2": "\f4b2", + "paperclip": "\f4b3", + "paragraph": "\f4b4", + "patch-check-fill": "\f4b5", + "patch-check": "\f4b6", + "patch-exclamation-fill": "\f4b7", + "patch-exclamation": "\f4b8", + "patch-minus-fill": "\f4b9", + "patch-minus": "\f4ba", + "patch-plus-fill": "\f4bb", + "patch-plus": "\f4bc", + "patch-question-fill": "\f4bd", + "patch-question": "\f4be", + "pause-btn-fill": "\f4bf", + "pause-btn": "\f4c0", + "pause-circle-fill": "\f4c1", + "pause-circle": "\f4c2", + "pause-fill": "\f4c3", + "pause": "\f4c4", + "peace-fill": "\f4c5", + "peace": "\f4c6", + "pen-fill": "\f4c7", + "pen": "\f4c8", + "pencil-fill": "\f4c9", + "pencil-square": "\f4ca", + "pencil": "\f4cb", + "pentagon-fill": "\f4cc", + "pentagon-half": "\f4cd", + "pentagon": "\f4ce", + "people-fill": "\f4cf", + "people": "\f4d0", + "percent": "\f4d1", + "person-badge-fill": "\f4d2", + "person-badge": "\f4d3", + "person-bounding-box": "\f4d4", + "person-check-fill": "\f4d5", + "person-check": "\f4d6", + "person-circle": "\f4d7", + "person-dash-fill": "\f4d8", + "person-dash": "\f4d9", + "person-fill": "\f4da", + "person-lines-fill": "\f4db", + "person-plus-fill": "\f4dc", + "person-plus": "\f4dd", + "person-square": "\f4de", + "person-x-fill": "\f4df", + "person-x": "\f4e0", + "person": "\f4e1", + "phone-fill": "\f4e2", + "phone-landscape-fill": "\f4e3", + "phone-landscape": "\f4e4", + "phone-vibrate-fill": "\f4e5", + "phone-vibrate": "\f4e6", + "phone": "\f4e7", + "pie-chart-fill": "\f4e8", + "pie-chart": "\f4e9", + "pin-angle-fill": "\f4ea", + "pin-angle": "\f4eb", + "pin-fill": "\f4ec", + "pin": "\f4ed", + "pip-fill": "\f4ee", + "pip": "\f4ef", + "play-btn-fill": "\f4f0", + "play-btn": "\f4f1", + "play-circle-fill": "\f4f2", + "play-circle": "\f4f3", + "play-fill": "\f4f4", + "play": "\f4f5", + "plug-fill": "\f4f6", + "plug": "\f4f7", + "plus-circle-dotted": "\f4f8", + "plus-circle-fill": "\f4f9", + "plus-circle": "\f4fa", + "plus-square-dotted": "\f4fb", + "plus-square-fill": "\f4fc", + "plus-square": "\f4fd", + "plus": "\f4fe", + "power": "\f4ff", + "printer-fill": "\f500", + "printer": "\f501", + "puzzle-fill": "\f502", + "puzzle": "\f503", + "question-circle-fill": "\f504", + "question-circle": "\f505", + "question-diamond-fill": "\f506", + "question-diamond": "\f507", + "question-octagon-fill": "\f508", + "question-octagon": "\f509", + "question-square-fill": "\f50a", + "question-square": "\f50b", + "question": "\f50c", + "rainbow": "\f50d", + "receipt-cutoff": "\f50e", + "receipt": "\f50f", + "reception-0": "\f510", + "reception-1": "\f511", + "reception-2": "\f512", + "reception-3": "\f513", + "reception-4": "\f514", + "record-btn-fill": "\f515", + "record-btn": "\f516", + "record-circle-fill": "\f517", + "record-circle": "\f518", + "record-fill": "\f519", + "record": "\f51a", + "record2-fill": "\f51b", + "record2": "\f51c", + "reply-all-fill": "\f51d", + "reply-all": "\f51e", + "reply-fill": "\f51f", + "reply": "\f520", + "rss-fill": "\f521", + "rss": "\f522", + "rulers": "\f523", + "save-fill": "\f524", + "save": "\f525", + "save2-fill": "\f526", + "save2": "\f527", + "scissors": "\f528", + "screwdriver": "\f529", + "search": "\f52a", + "segmented-nav": "\f52b", + "server": "\f52c", + "share-fill": "\f52d", + "share": "\f52e", + "shield-check": "\f52f", + "shield-exclamation": "\f530", + "shield-fill-check": "\f531", + "shield-fill-exclamation": "\f532", + "shield-fill-minus": "\f533", + "shield-fill-plus": "\f534", + "shield-fill-x": "\f535", + "shield-fill": "\f536", + "shield-lock-fill": "\f537", + "shield-lock": "\f538", + "shield-minus": "\f539", + "shield-plus": "\f53a", + "shield-shaded": "\f53b", + "shield-slash-fill": "\f53c", + "shield-slash": "\f53d", + "shield-x": "\f53e", + "shield": "\f53f", + "shift-fill": "\f540", + "shift": "\f541", + "shop-window": "\f542", + "shop": "\f543", + "shuffle": "\f544", + "signpost-2-fill": "\f545", + "signpost-2": "\f546", + "signpost-fill": "\f547", + "signpost-split-fill": "\f548", + "signpost-split": "\f549", + "signpost": "\f54a", + "sim-fill": "\f54b", + "sim": "\f54c", + "skip-backward-btn-fill": "\f54d", + "skip-backward-btn": "\f54e", + "skip-backward-circle-fill": "\f54f", + "skip-backward-circle": "\f550", + "skip-backward-fill": "\f551", + "skip-backward": "\f552", + "skip-end-btn-fill": "\f553", + "skip-end-btn": "\f554", + "skip-end-circle-fill": "\f555", + "skip-end-circle": "\f556", + "skip-end-fill": "\f557", + "skip-end": "\f558", + "skip-forward-btn-fill": "\f559", + "skip-forward-btn": "\f55a", + "skip-forward-circle-fill": "\f55b", + "skip-forward-circle": "\f55c", + "skip-forward-fill": "\f55d", + "skip-forward": "\f55e", + "skip-start-btn-fill": "\f55f", + "skip-start-btn": "\f560", + "skip-start-circle-fill": "\f561", + "skip-start-circle": "\f562", + "skip-start-fill": "\f563", + "skip-start": "\f564", + "slack": "\f565", + "slash-circle-fill": "\f566", + "slash-circle": "\f567", + "slash-square-fill": "\f568", + "slash-square": "\f569", + "slash": "\f56a", + "sliders": "\f56b", + "smartwatch": "\f56c", + "snow": "\f56d", + "snow2": "\f56e", + "snow3": "\f56f", + "sort-alpha-down-alt": "\f570", + "sort-alpha-down": "\f571", + "sort-alpha-up-alt": "\f572", + "sort-alpha-up": "\f573", + "sort-down-alt": "\f574", + "sort-down": "\f575", + "sort-numeric-down-alt": "\f576", + "sort-numeric-down": "\f577", + "sort-numeric-up-alt": "\f578", + "sort-numeric-up": "\f579", + "sort-up-alt": "\f57a", + "sort-up": "\f57b", + "soundwave": "\f57c", + "speaker-fill": "\f57d", + "speaker": "\f57e", + "speedometer": "\f57f", + "speedometer2": "\f580", + "spellcheck": "\f581", + "square-fill": "\f582", + "square-half": "\f583", + "square": "\f584", + "stack": "\f585", + "star-fill": "\f586", + "star-half": "\f587", + "star": "\f588", + "stars": "\f589", + "stickies-fill": "\f58a", + "stickies": "\f58b", + "sticky-fill": "\f58c", + "sticky": "\f58d", + "stop-btn-fill": "\f58e", + "stop-btn": "\f58f", + "stop-circle-fill": "\f590", + "stop-circle": "\f591", + "stop-fill": "\f592", + "stop": "\f593", + "stoplights-fill": "\f594", + "stoplights": "\f595", + "stopwatch-fill": "\f596", + "stopwatch": "\f597", + "subtract": "\f598", + "suit-club-fill": "\f599", + "suit-club": "\f59a", + "suit-diamond-fill": "\f59b", + "suit-diamond": "\f59c", + "suit-heart-fill": "\f59d", + "suit-heart": "\f59e", + "suit-spade-fill": "\f59f", + "suit-spade": "\f5a0", + "sun-fill": "\f5a1", + "sun": "\f5a2", + "sunglasses": "\f5a3", + "sunrise-fill": "\f5a4", + "sunrise": "\f5a5", + "sunset-fill": "\f5a6", + "sunset": "\f5a7", + "symmetry-horizontal": "\f5a8", + "symmetry-vertical": "\f5a9", + "table": "\f5aa", + "tablet-fill": "\f5ab", + "tablet-landscape-fill": "\f5ac", + "tablet-landscape": "\f5ad", + "tablet": "\f5ae", + "tag-fill": "\f5af", + "tag": "\f5b0", + "tags-fill": "\f5b1", + "tags": "\f5b2", + "telegram": "\f5b3", + "telephone-fill": "\f5b4", + "telephone-forward-fill": "\f5b5", + "telephone-forward": "\f5b6", + "telephone-inbound-fill": "\f5b7", + "telephone-inbound": "\f5b8", + "telephone-minus-fill": "\f5b9", + "telephone-minus": "\f5ba", + "telephone-outbound-fill": "\f5bb", + "telephone-outbound": "\f5bc", + "telephone-plus-fill": "\f5bd", + "telephone-plus": "\f5be", + "telephone-x-fill": "\f5bf", + "telephone-x": "\f5c0", + "telephone": "\f5c1", + "terminal-fill": "\f5c2", + "terminal": "\f5c3", + "text-center": "\f5c4", + "text-indent-left": "\f5c5", + "text-indent-right": "\f5c6", + "text-left": "\f5c7", + "text-paragraph": "\f5c8", + "text-right": "\f5c9", + "textarea-resize": "\f5ca", + "textarea-t": "\f5cb", + "textarea": "\f5cc", + "thermometer-half": "\f5cd", + "thermometer-high": "\f5ce", + "thermometer-low": "\f5cf", + "thermometer-snow": "\f5d0", + "thermometer-sun": "\f5d1", + "thermometer": "\f5d2", + "three-dots-vertical": "\f5d3", + "three-dots": "\f5d4", + "toggle-off": "\f5d5", + "toggle-on": "\f5d6", + "toggle2-off": "\f5d7", + "toggle2-on": "\f5d8", + "toggles": "\f5d9", + "toggles2": "\f5da", + "tools": "\f5db", + "tornado": "\f5dc", + "trash-fill": "\f5dd", + "trash": "\f5de", + "trash2-fill": "\f5df", + "trash2": "\f5e0", + "tree-fill": "\f5e1", + "tree": "\f5e2", + "triangle-fill": "\f5e3", + "triangle-half": "\f5e4", + "triangle": "\f5e5", + "trophy-fill": "\f5e6", + "trophy": "\f5e7", + "tropical-storm": "\f5e8", + "truck-flatbed": "\f5e9", + "truck": "\f5ea", + "tsunami": "\f5eb", + "tv-fill": "\f5ec", + "tv": "\f5ed", + "twitch": "\f5ee", + "twitter": "\f5ef", + "type-bold": "\f5f0", + "type-h1": "\f5f1", + "type-h2": "\f5f2", + "type-h3": "\f5f3", + "type-italic": "\f5f4", + "type-strikethrough": "\f5f5", + "type-underline": "\f5f6", + "type": "\f5f7", + "ui-checks-grid": "\f5f8", + "ui-checks": "\f5f9", + "ui-radios-grid": "\f5fa", + "ui-radios": "\f5fb", + "umbrella-fill": "\f5fc", + "umbrella": "\f5fd", + "union": "\f5fe", + "unlock-fill": "\f5ff", + "unlock": "\f600", + "upc-scan": "\f601", + "upc": "\f602", + "upload": "\f603", + "vector-pen": "\f604", + "view-list": "\f605", + "view-stacked": "\f606", + "vinyl-fill": "\f607", + "vinyl": "\f608", + "voicemail": "\f609", + "volume-down-fill": "\f60a", + "volume-down": "\f60b", + "volume-mute-fill": "\f60c", + "volume-mute": "\f60d", + "volume-off-fill": "\f60e", + "volume-off": "\f60f", + "volume-up-fill": "\f610", + "volume-up": "\f611", + "vr": "\f612", + "wallet-fill": "\f613", + "wallet": "\f614", + "wallet2": "\f615", + "watch": "\f616", + "water": "\f617", + "whatsapp": "\f618", + "wifi-1": "\f619", + "wifi-2": "\f61a", + "wifi-off": "\f61b", + "wifi": "\f61c", + "wind": "\f61d", + "window-dock": "\f61e", + "window-sidebar": "\f61f", + "window": "\f620", + "wrench": "\f621", + "x-circle-fill": "\f622", + "x-circle": "\f623", + "x-diamond-fill": "\f624", + "x-diamond": "\f625", + "x-octagon-fill": "\f626", + "x-octagon": "\f627", + "x-square-fill": "\f628", + "x-square": "\f629", + "x": "\f62a", + "youtube": "\f62b", + "zoom-in": "\f62c", + "zoom-out": "\f62d", + "bank": "\f62e", + "bank2": "\f62f", + "bell-slash-fill": "\f630", + "bell-slash": "\f631", + "cash-coin": "\f632", + "check-lg": "\f633", + "coin": "\f634", + "currency-bitcoin": "\f635", + "currency-dollar": "\f636", + "currency-euro": "\f637", + "currency-exchange": "\f638", + "currency-pound": "\f639", + "currency-yen": "\f63a", + "dash-lg": "\f63b", + "exclamation-lg": "\f63c", + "file-earmark-pdf-fill": "\f63d", + "file-earmark-pdf": "\f63e", + "file-pdf-fill": "\f63f", + "file-pdf": "\f640", + "gender-ambiguous": "\f641", + "gender-female": "\f642", + "gender-male": "\f643", + "gender-trans": "\f644", + "headset-vr": "\f645", + "info-lg": "\f646", + "mastodon": "\f647", + "messenger": "\f648", + "piggy-bank-fill": "\f649", + "piggy-bank": "\f64a", + "pin-map-fill": "\f64b", + "pin-map": "\f64c", + "plus-lg": "\f64d", + "question-lg": "\f64e", + "recycle": "\f64f", + "reddit": "\f650", + "safe-fill": "\f651", + "safe2-fill": "\f652", + "safe2": "\f653", + "sd-card-fill": "\f654", + "sd-card": "\f655", + "skype": "\f656", + "slash-lg": "\f657", + "translate": "\f658", + "x-lg": "\f659", + "safe": "\f65a", + "apple": "\f65b", + "microsoft": "\f65d", + "windows": "\f65e", + "behance": "\f65c", + "dribbble": "\f65f", + "line": "\f660", + "medium": "\f661", + "paypal": "\f662", + "pinterest": "\f663", + "signal": "\f664", + "snapchat": "\f665", + "spotify": "\f666", + "stack-overflow": "\f667", + "strava": "\f668", + "wordpress": "\f669", + "vimeo": "\f66a", + "activity": "\f66b", + "easel2-fill": "\f66c", + "easel2": "\f66d", + "easel3-fill": "\f66e", + "easel3": "\f66f", + "fan": "\f670", + "fingerprint": "\f671", + "graph-down-arrow": "\f672", + "graph-up-arrow": "\f673", + "hypnotize": "\f674", + "magic": "\f675", + "person-rolodex": "\f676", + "person-video": "\f677", + "person-video2": "\f678", + "person-video3": "\f679", + "person-workspace": "\f67a", + "radioactive": "\f67b", + "webcam-fill": "\f67c", + "webcam": "\f67d", + "yin-yang": "\f67e", + "bandaid-fill": "\f680", + "bandaid": "\f681", + "bluetooth": "\f682", + "body-text": "\f683", + "boombox": "\f684", + "boxes": "\f685", + "dpad-fill": "\f686", + "dpad": "\f687", + "ear-fill": "\f688", + "ear": "\f689", + "envelope-check-fill": "\f68b", + "envelope-check": "\f68c", + "envelope-dash-fill": "\f68e", + "envelope-dash": "\f68f", + "envelope-exclamation-fill": "\f691", + "envelope-exclamation": "\f692", + "envelope-plus-fill": "\f693", + "envelope-plus": "\f694", + "envelope-slash-fill": "\f696", + "envelope-slash": "\f697", + "envelope-x-fill": "\f699", + "envelope-x": "\f69a", + "explicit-fill": "\f69b", + "explicit": "\f69c", + "git": "\f69d", + "infinity": "\f69e", + "list-columns-reverse": "\f69f", + "list-columns": "\f6a0", + "meta": "\f6a1", + "nintendo-switch": "\f6a4", + "pc-display-horizontal": "\f6a5", + "pc-display": "\f6a6", + "pc-horizontal": "\f6a7", + "pc": "\f6a8", + "playstation": "\f6a9", + "plus-slash-minus": "\f6aa", + "projector-fill": "\f6ab", + "projector": "\f6ac", + "qr-code-scan": "\f6ad", + "qr-code": "\f6ae", + "quora": "\f6af", + "quote": "\f6b0", + "robot": "\f6b1", + "send-check-fill": "\f6b2", + "send-check": "\f6b3", + "send-dash-fill": "\f6b4", + "send-dash": "\f6b5", + "send-exclamation-fill": "\f6b7", + "send-exclamation": "\f6b8", + "send-fill": "\f6b9", + "send-plus-fill": "\f6ba", + "send-plus": "\f6bb", + "send-slash-fill": "\f6bc", + "send-slash": "\f6bd", + "send-x-fill": "\f6be", + "send-x": "\f6bf", + "send": "\f6c0", + "steam": "\f6c1", + "terminal-dash": "\f6c3", + "terminal-plus": "\f6c4", + "terminal-split": "\f6c5", + "ticket-detailed-fill": "\f6c6", + "ticket-detailed": "\f6c7", + "ticket-fill": "\f6c8", + "ticket-perforated-fill": "\f6c9", + "ticket-perforated": "\f6ca", + "ticket": "\f6cb", + "tiktok": "\f6cc", + "window-dash": "\f6cd", + "window-desktop": "\f6ce", + "window-fullscreen": "\f6cf", + "window-plus": "\f6d0", + "window-split": "\f6d1", + "window-stack": "\f6d2", + "window-x": "\f6d3", + "xbox": "\f6d4", + "ethernet": "\f6d5", + "hdmi-fill": "\f6d6", + "hdmi": "\f6d7", + "usb-c-fill": "\f6d8", + "usb-c": "\f6d9", + "usb-fill": "\f6da", + "usb-plug-fill": "\f6db", + "usb-plug": "\f6dc", + "usb-symbol": "\f6dd", + "usb": "\f6de", + "boombox-fill": "\f6df", + "displayport": "\f6e1", + "gpu-card": "\f6e2", + "memory": "\f6e3", + "modem-fill": "\f6e4", + "modem": "\f6e5", + "motherboard-fill": "\f6e6", + "motherboard": "\f6e7", + "optical-audio-fill": "\f6e8", + "optical-audio": "\f6e9", + "pci-card": "\f6ea", + "router-fill": "\f6eb", + "router": "\f6ec", + "thunderbolt-fill": "\f6ef", + "thunderbolt": "\f6f0", + "usb-drive-fill": "\f6f1", + "usb-drive": "\f6f2", + "usb-micro-fill": "\f6f3", + "usb-micro": "\f6f4", + "usb-mini-fill": "\f6f5", + "usb-mini": "\f6f6", + "cloud-haze2": "\f6f7", + "device-hdd-fill": "\f6f8", + "device-hdd": "\f6f9", + "device-ssd-fill": "\f6fa", + "device-ssd": "\f6fb", + "displayport-fill": "\f6fc", + "mortarboard-fill": "\f6fd", + "mortarboard": "\f6fe", + "terminal-x": "\f6ff", + "arrow-through-heart-fill": "\f700", + "arrow-through-heart": "\f701", + "badge-sd-fill": "\f702", + "badge-sd": "\f703", + "bag-heart-fill": "\f704", + "bag-heart": "\f705", + "balloon-fill": "\f706", + "balloon-heart-fill": "\f707", + "balloon-heart": "\f708", + "balloon": "\f709", + "box2-fill": "\f70a", + "box2-heart-fill": "\f70b", + "box2-heart": "\f70c", + "box2": "\f70d", + "braces-asterisk": "\f70e", + "calendar-heart-fill": "\f70f", + "calendar-heart": "\f710", + "calendar2-heart-fill": "\f711", + "calendar2-heart": "\f712", + "chat-heart-fill": "\f713", + "chat-heart": "\f714", + "chat-left-heart-fill": "\f715", + "chat-left-heart": "\f716", + "chat-right-heart-fill": "\f717", + "chat-right-heart": "\f718", + "chat-square-heart-fill": "\f719", + "chat-square-heart": "\f71a", + "clipboard-check-fill": "\f71b", + "clipboard-data-fill": "\f71c", + "clipboard-fill": "\f71d", + "clipboard-heart-fill": "\f71e", + "clipboard-heart": "\f71f", + "clipboard-minus-fill": "\f720", + "clipboard-plus-fill": "\f721", + "clipboard-pulse": "\f722", + "clipboard-x-fill": "\f723", + "clipboard2-check-fill": "\f724", + "clipboard2-check": "\f725", + "clipboard2-data-fill": "\f726", + "clipboard2-data": "\f727", + "clipboard2-fill": "\f728", + "clipboard2-heart-fill": "\f729", + "clipboard2-heart": "\f72a", + "clipboard2-minus-fill": "\f72b", + "clipboard2-minus": "\f72c", + "clipboard2-plus-fill": "\f72d", + "clipboard2-plus": "\f72e", + "clipboard2-pulse-fill": "\f72f", + "clipboard2-pulse": "\f730", + "clipboard2-x-fill": "\f731", + "clipboard2-x": "\f732", + "clipboard2": "\f733", + "emoji-kiss-fill": "\f734", + "emoji-kiss": "\f735", + "envelope-heart-fill": "\f736", + "envelope-heart": "\f737", + "envelope-open-heart-fill": "\f738", + "envelope-open-heart": "\f739", + "envelope-paper-fill": "\f73a", + "envelope-paper-heart-fill": "\f73b", + "envelope-paper-heart": "\f73c", + "envelope-paper": "\f73d", + "filetype-aac": "\f73e", + "filetype-ai": "\f73f", + "filetype-bmp": "\f740", + "filetype-cs": "\f741", + "filetype-css": "\f742", + "filetype-csv": "\f743", + "filetype-doc": "\f744", + "filetype-docx": "\f745", + "filetype-exe": "\f746", + "filetype-gif": "\f747", + "filetype-heic": "\f748", + "filetype-html": "\f749", + "filetype-java": "\f74a", + "filetype-jpg": "\f74b", + "filetype-js": "\f74c", + "filetype-jsx": "\f74d", + "filetype-key": "\f74e", + "filetype-m4p": "\f74f", + "filetype-md": "\f750", + "filetype-mdx": "\f751", + "filetype-mov": "\f752", + "filetype-mp3": "\f753", + "filetype-mp4": "\f754", + "filetype-otf": "\f755", + "filetype-pdf": "\f756", + "filetype-php": "\f757", + "filetype-png": "\f758", + "filetype-ppt": "\f75a", + "filetype-psd": "\f75b", + "filetype-py": "\f75c", + "filetype-raw": "\f75d", + "filetype-rb": "\f75e", + "filetype-sass": "\f75f", + "filetype-scss": "\f760", + "filetype-sh": "\f761", + "filetype-svg": "\f762", + "filetype-tiff": "\f763", + "filetype-tsx": "\f764", + "filetype-ttf": "\f765", + "filetype-txt": "\f766", + "filetype-wav": "\f767", + "filetype-woff": "\f768", + "filetype-xls": "\f76a", + "filetype-xml": "\f76b", + "filetype-yml": "\f76c", + "heart-arrow": "\f76d", + "heart-pulse-fill": "\f76e", + "heart-pulse": "\f76f", + "heartbreak-fill": "\f770", + "heartbreak": "\f771", + "hearts": "\f772", + "hospital-fill": "\f773", + "hospital": "\f774", + "house-heart-fill": "\f775", + "house-heart": "\f776", + "incognito": "\f777", + "magnet-fill": "\f778", + "magnet": "\f779", + "person-heart": "\f77a", + "person-hearts": "\f77b", + "phone-flip": "\f77c", + "plugin": "\f77d", + "postage-fill": "\f77e", + "postage-heart-fill": "\f77f", + "postage-heart": "\f780", + "postage": "\f781", + "postcard-fill": "\f782", + "postcard-heart-fill": "\f783", + "postcard-heart": "\f784", + "postcard": "\f785", + "search-heart-fill": "\f786", + "search-heart": "\f787", + "sliders2-vertical": "\f788", + "sliders2": "\f789", + "trash3-fill": "\f78a", + "trash3": "\f78b", + "valentine": "\f78c", + "valentine2": "\f78d", + "wrench-adjustable-circle-fill": "\f78e", + "wrench-adjustable-circle": "\f78f", + "wrench-adjustable": "\f790", + "filetype-json": "\f791", + "filetype-pptx": "\f792", + "filetype-xlsx": "\f793", + "1-circle-fill": "\f796", + "1-circle": "\f797", + "1-square-fill": "\f798", + "1-square": "\f799", + "2-circle-fill": "\f79c", + "2-circle": "\f79d", + "2-square-fill": "\f79e", + "2-square": "\f79f", + "3-circle-fill": "\f7a2", + "3-circle": "\f7a3", + "3-square-fill": "\f7a4", + "3-square": "\f7a5", + "4-circle-fill": "\f7a8", + "4-circle": "\f7a9", + "4-square-fill": "\f7aa", + "4-square": "\f7ab", + "5-circle-fill": "\f7ae", + "5-circle": "\f7af", + "5-square-fill": "\f7b0", + "5-square": "\f7b1", + "6-circle-fill": "\f7b4", + "6-circle": "\f7b5", + "6-square-fill": "\f7b6", + "6-square": "\f7b7", + "7-circle-fill": "\f7ba", + "7-circle": "\f7bb", + "7-square-fill": "\f7bc", + "7-square": "\f7bd", + "8-circle-fill": "\f7c0", + "8-circle": "\f7c1", + "8-square-fill": "\f7c2", + "8-square": "\f7c3", + "9-circle-fill": "\f7c6", + "9-circle": "\f7c7", + "9-square-fill": "\f7c8", + "9-square": "\f7c9", + "airplane-engines-fill": "\f7ca", + "airplane-engines": "\f7cb", + "airplane-fill": "\f7cc", + "airplane": "\f7cd", + "alexa": "\f7ce", + "alipay": "\f7cf", + "android": "\f7d0", + "android2": "\f7d1", + "box-fill": "\f7d2", + "box-seam-fill": "\f7d3", + "browser-chrome": "\f7d4", + "browser-edge": "\f7d5", + "browser-firefox": "\f7d6", + "browser-safari": "\f7d7", + "c-circle-fill": "\f7da", + "c-circle": "\f7db", + "c-square-fill": "\f7dc", + "c-square": "\f7dd", + "capsule-pill": "\f7de", + "capsule": "\f7df", + "car-front-fill": "\f7e0", + "car-front": "\f7e1", + "cassette-fill": "\f7e2", + "cassette": "\f7e3", + "cc-circle-fill": "\f7e6", + "cc-circle": "\f7e7", + "cc-square-fill": "\f7e8", + "cc-square": "\f7e9", + "cup-hot-fill": "\f7ea", + "cup-hot": "\f7eb", + "currency-rupee": "\f7ec", + "dropbox": "\f7ed", + "escape": "\f7ee", + "fast-forward-btn-fill": "\f7ef", + "fast-forward-btn": "\f7f0", + "fast-forward-circle-fill": "\f7f1", + "fast-forward-circle": "\f7f2", + "fast-forward-fill": "\f7f3", + "fast-forward": "\f7f4", + "filetype-sql": "\f7f5", + "fire": "\f7f6", + "google-play": "\f7f7", + "h-circle-fill": "\f7fa", + "h-circle": "\f7fb", + "h-square-fill": "\f7fc", + "h-square": "\f7fd", + "indent": "\f7fe", + "lungs-fill": "\f7ff", + "lungs": "\f800", + "microsoft-teams": "\f801", + "p-circle-fill": "\f804", + "p-circle": "\f805", + "p-square-fill": "\f806", + "p-square": "\f807", + "pass-fill": "\f808", + "pass": "\f809", + "prescription": "\f80a", + "prescription2": "\f80b", + "r-circle-fill": "\f80e", + "r-circle": "\f80f", + "r-square-fill": "\f810", + "r-square": "\f811", + "repeat-1": "\f812", + "repeat": "\f813", + "rewind-btn-fill": "\f814", + "rewind-btn": "\f815", + "rewind-circle-fill": "\f816", + "rewind-circle": "\f817", + "rewind-fill": "\f818", + "rewind": "\f819", + "train-freight-front-fill": "\f81a", + "train-freight-front": "\f81b", + "train-front-fill": "\f81c", + "train-front": "\f81d", + "train-lightrail-front-fill": "\f81e", + "train-lightrail-front": "\f81f", + "truck-front-fill": "\f820", + "truck-front": "\f821", + "ubuntu": "\f822", + "unindent": "\f823", + "unity": "\f824", + "universal-access-circle": "\f825", + "universal-access": "\f826", + "virus": "\f827", + "virus2": "\f828", + "wechat": "\f829", + "yelp": "\f82a", + "sign-stop-fill": "\f82b", + "sign-stop-lights-fill": "\f82c", + "sign-stop-lights": "\f82d", + "sign-stop": "\f82e", + "sign-turn-left-fill": "\f82f", + "sign-turn-left": "\f830", + "sign-turn-right-fill": "\f831", + "sign-turn-right": "\f832", + "sign-turn-slight-left-fill": "\f833", + "sign-turn-slight-left": "\f834", + "sign-turn-slight-right-fill": "\f835", + "sign-turn-slight-right": "\f836", + "sign-yield-fill": "\f837", + "sign-yield": "\f838", + "ev-station-fill": "\f839", + "ev-station": "\f83a", + "fuel-pump-diesel-fill": "\f83b", + "fuel-pump-diesel": "\f83c", + "fuel-pump-fill": "\f83d", + "fuel-pump": "\f83e", + "0-circle-fill": "\f83f", + "0-circle": "\f840", + "0-square-fill": "\f841", + "0-square": "\f842", + "rocket-fill": "\f843", + "rocket-takeoff-fill": "\f844", + "rocket-takeoff": "\f845", + "rocket": "\f846", + "stripe": "\f847", + "subscript": "\f848", + "superscript": "\f849", + "trello": "\f84a", + "envelope-at-fill": "\f84b", + "envelope-at": "\f84c", + "regex": "\f84d", + "text-wrap": "\f84e", + "sign-dead-end-fill": "\f84f", + "sign-dead-end": "\f850", + "sign-do-not-enter-fill": "\f851", + "sign-do-not-enter": "\f852", + "sign-intersection-fill": "\f853", + "sign-intersection-side-fill": "\f854", + "sign-intersection-side": "\f855", + "sign-intersection-t-fill": "\f856", + "sign-intersection-t": "\f857", + "sign-intersection-y-fill": "\f858", + "sign-intersection-y": "\f859", + "sign-intersection": "\f85a", + "sign-merge-left-fill": "\f85b", + "sign-merge-left": "\f85c", + "sign-merge-right-fill": "\f85d", + "sign-merge-right": "\f85e", + "sign-no-left-turn-fill": "\f85f", + "sign-no-left-turn": "\f860", + "sign-no-parking-fill": "\f861", + "sign-no-parking": "\f862", + "sign-no-right-turn-fill": "\f863", + "sign-no-right-turn": "\f864", + "sign-railroad-fill": "\f865", + "sign-railroad": "\f866", + "building-add": "\f867", + "building-check": "\f868", + "building-dash": "\f869", + "building-down": "\f86a", + "building-exclamation": "\f86b", + "building-fill-add": "\f86c", + "building-fill-check": "\f86d", + "building-fill-dash": "\f86e", + "building-fill-down": "\f86f", + "building-fill-exclamation": "\f870", + "building-fill-gear": "\f871", + "building-fill-lock": "\f872", + "building-fill-slash": "\f873", + "building-fill-up": "\f874", + "building-fill-x": "\f875", + "building-fill": "\f876", + "building-gear": "\f877", + "building-lock": "\f878", + "building-slash": "\f879", + "building-up": "\f87a", + "building-x": "\f87b", + "buildings-fill": "\f87c", + "buildings": "\f87d", + "bus-front-fill": "\f87e", + "bus-front": "\f87f", + "ev-front-fill": "\f880", + "ev-front": "\f881", + "globe-americas": "\f882", + "globe-asia-australia": "\f883", + "globe-central-south-asia": "\f884", + "globe-europe-africa": "\f885", + "house-add-fill": "\f886", + "house-add": "\f887", + "house-check-fill": "\f888", + "house-check": "\f889", + "house-dash-fill": "\f88a", + "house-dash": "\f88b", + "house-down-fill": "\f88c", + "house-down": "\f88d", + "house-exclamation-fill": "\f88e", + "house-exclamation": "\f88f", + "house-gear-fill": "\f890", + "house-gear": "\f891", + "house-lock-fill": "\f892", + "house-lock": "\f893", + "house-slash-fill": "\f894", + "house-slash": "\f895", + "house-up-fill": "\f896", + "house-up": "\f897", + "house-x-fill": "\f898", + "house-x": "\f899", + "person-add": "\f89a", + "person-down": "\f89b", + "person-exclamation": "\f89c", + "person-fill-add": "\f89d", + "person-fill-check": "\f89e", + "person-fill-dash": "\f89f", + "person-fill-down": "\f8a0", + "person-fill-exclamation": "\f8a1", + "person-fill-gear": "\f8a2", + "person-fill-lock": "\f8a3", + "person-fill-slash": "\f8a4", + "person-fill-up": "\f8a5", + "person-fill-x": "\f8a6", + "person-gear": "\f8a7", + "person-lock": "\f8a8", + "person-slash": "\f8a9", + "person-up": "\f8aa", + "scooter": "\f8ab", + "taxi-front-fill": "\f8ac", + "taxi-front": "\f8ad", + "amd": "\f8ae", + "database-add": "\f8af", + "database-check": "\f8b0", + "database-dash": "\f8b1", + "database-down": "\f8b2", + "database-exclamation": "\f8b3", + "database-fill-add": "\f8b4", + "database-fill-check": "\f8b5", + "database-fill-dash": "\f8b6", + "database-fill-down": "\f8b7", + "database-fill-exclamation": "\f8b8", + "database-fill-gear": "\f8b9", + "database-fill-lock": "\f8ba", + "database-fill-slash": "\f8bb", + "database-fill-up": "\f8bc", + "database-fill-x": "\f8bd", + "database-fill": "\f8be", + "database-gear": "\f8bf", + "database-lock": "\f8c0", + "database-slash": "\f8c1", + "database-up": "\f8c2", + "database-x": "\f8c3", + "database": "\f8c4", + "houses-fill": "\f8c5", + "houses": "\f8c6", + "nvidia": "\f8c7", + "person-vcard-fill": "\f8c8", + "person-vcard": "\f8c9", + "sina-weibo": "\f8ca", + "tencent-qq": "\f8cb", + "wikipedia": "\f8cc", + "alphabet-uppercase": "\f2a5", + "alphabet": "\f68a", + "amazon": "\f68d", + "arrows-collapse-vertical": "\f690", + "arrows-expand-vertical": "\f695", + "arrows-vertical": "\f698", + "arrows": "\f6a2", + "ban-fill": "\f6a3", + "ban": "\f6b6", + "bing": "\f6c2", + "cake": "\f6e0", + "cake2": "\f6ed", + "cookie": "\f6ee", + "copy": "\f759", + "crosshair": "\f769", + "crosshair2": "\f794", + "emoji-astonished-fill": "\f795", + "emoji-astonished": "\f79a", + "emoji-grimace-fill": "\f79b", + "emoji-grimace": "\f7a0", + "emoji-grin-fill": "\f7a1", + "emoji-grin": "\f7a6", + "emoji-surprise-fill": "\f7a7", + "emoji-surprise": "\f7ac", + "emoji-tear-fill": "\f7ad", + "emoji-tear": "\f7b2", + "envelope-arrow-down-fill": "\f7b3", + "envelope-arrow-down": "\f7b8", + "envelope-arrow-up-fill": "\f7b9", + "envelope-arrow-up": "\f7be", + "feather": "\f7bf", + "feather2": "\f7c4", + "floppy-fill": "\f7c5", + "floppy": "\f7d8", + "floppy2-fill": "\f7d9", + "floppy2": "\f7e4", + "gitlab": "\f7e5", + "highlighter": "\f7f8", + "marker-tip": "\f802", + "nvme-fill": "\f803", + "nvme": "\f80c", + "opencollective": "\f80d", + "pci-card-network": "\f8cd", + "pci-card-sound": "\f8ce", + "radar": "\f8cf", + "send-arrow-down-fill": "\f8d0", + "send-arrow-down": "\f8d1", + "send-arrow-up-fill": "\f8d2", + "send-arrow-up": "\f8d3", + "sim-slash-fill": "\f8d4", + "sim-slash": "\f8d5", + "sourceforge": "\f8d6", + "substack": "\f8d7", + "threads-fill": "\f8d8", + "threads": "\f8d9", + "transparency": "\f8da", + "twitter-x": "\f8db", + "type-h4": "\f8dc", + "type-h5": "\f8dd", + "type-h6": "\f8de", + "backpack-fill": "\f8df", + "backpack": "\f8e0", + "backpack2-fill": "\f8e1", + "backpack2": "\f8e2", + "backpack3-fill": "\f8e3", + "backpack3": "\f8e4", + "backpack4-fill": "\f8e5", + "backpack4": "\f8e6", + "brilliance": "\f8e7", + "cake-fill": "\f8e8", + "cake2-fill": "\f8e9", + "duffle-fill": "\f8ea", + "duffle": "\f8eb", + "exposure": "\f8ec", + "gender-neuter": "\f8ed", + "highlights": "\f8ee", + "luggage-fill": "\f8ef", + "luggage": "\f8f0", + "mailbox-flag": "\f8f1", + "mailbox2-flag": "\f8f2", + "noise-reduction": "\f8f3", + "passport-fill": "\f8f4", + "passport": "\f8f5", + "person-arms-up": "\f8f6", + "person-raised-hand": "\f8f7", + "person-standing-dress": "\f8f8", + "person-standing": "\f8f9", + "person-walking": "\f8fa", + "person-wheelchair": "\f8fb", + "shadows": "\f8fc", + "suitcase-fill": "\f8fd", + "suitcase-lg-fill": "\f8fe", + "suitcase-lg": "\f8ff", + "suitcase": "\f900", + "suitcase2-fill": "\f901", + "suitcase2": "\f902", + "vignette": "\f903", + "bluesky": "\f7f9", + "tux": "\f904", + "beaker-fill": "\f905", + "beaker": "\f906", + "flask-fill": "\f907", + "flask-florence-fill": "\f908", + "flask-florence": "\f909", + "flask": "\f90a", + "leaf-fill": "\f90b", + "leaf": "\f90c", + "measuring-cup-fill": "\f90d", + "measuring-cup": "\f90e", + "unlock2-fill": "\f90f", + "unlock2": "\f910", + "battery-low": "\f911", + "anthropic": "\f912", + "apple-music": "\f913", + "claude": "\f914", + "openai": "\f915", + "perplexity": "\f916", + "css": "\f917", + "javascript": "\f918", + "typescript": "\f919", + "fork-knife": "\f91a", + "globe-americas-fill": "\f91b", + "globe-asia-australia-fill": "\f91c", + "globe-central-south-asia-fill": "\f91d", + "globe-europe-africa-fill": "\f91e", +); + +@each $icon, $codepoint in $bootstrap-icons-map { + .bi-#{$icon}::before { content: $codepoint; } +} diff --git a/web/vendor/bootstrap-icons/bootstrap-icons.svg b/web/vendor/bootstrap-icons/bootstrap-icons.svg new file mode 100644 index 0000000..fa7e620 --- /dev/null +++ b/web/vendor/bootstrap-icons/bootstrap-icons.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bootstrap-reboot.svg b/web/vendor/bootstrap-icons/bootstrap-reboot.svg new file mode 100644 index 0000000..8d21030 --- /dev/null +++ b/web/vendor/bootstrap-icons/bootstrap-reboot.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bootstrap.svg b/web/vendor/bootstrap-icons/bootstrap.svg new file mode 100644 index 0000000..089e31f --- /dev/null +++ b/web/vendor/bootstrap-icons/bootstrap.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/border-all.svg b/web/vendor/bootstrap-icons/border-all.svg new file mode 100644 index 0000000..19128f2 --- /dev/null +++ b/web/vendor/bootstrap-icons/border-all.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/border-bottom.svg b/web/vendor/bootstrap-icons/border-bottom.svg new file mode 100644 index 0000000..84edcca --- /dev/null +++ b/web/vendor/bootstrap-icons/border-bottom.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/border-center.svg b/web/vendor/bootstrap-icons/border-center.svg new file mode 100644 index 0000000..a9cf9c4 --- /dev/null +++ b/web/vendor/bootstrap-icons/border-center.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/border-inner.svg b/web/vendor/bootstrap-icons/border-inner.svg new file mode 100644 index 0000000..6369007 --- /dev/null +++ b/web/vendor/bootstrap-icons/border-inner.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/border-left.svg b/web/vendor/bootstrap-icons/border-left.svg new file mode 100644 index 0000000..483c804 --- /dev/null +++ b/web/vendor/bootstrap-icons/border-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/border-middle.svg b/web/vendor/bootstrap-icons/border-middle.svg new file mode 100644 index 0000000..c9de407 --- /dev/null +++ b/web/vendor/bootstrap-icons/border-middle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/border-outer.svg b/web/vendor/bootstrap-icons/border-outer.svg new file mode 100644 index 0000000..4791bcb --- /dev/null +++ b/web/vendor/bootstrap-icons/border-outer.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/border-right.svg b/web/vendor/bootstrap-icons/border-right.svg new file mode 100644 index 0000000..23e09dc --- /dev/null +++ b/web/vendor/bootstrap-icons/border-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/border-style.svg b/web/vendor/bootstrap-icons/border-style.svg new file mode 100644 index 0000000..cec3fef --- /dev/null +++ b/web/vendor/bootstrap-icons/border-style.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/border-top.svg b/web/vendor/bootstrap-icons/border-top.svg new file mode 100644 index 0000000..77189df --- /dev/null +++ b/web/vendor/bootstrap-icons/border-top.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/border-width.svg b/web/vendor/bootstrap-icons/border-width.svg new file mode 100644 index 0000000..6175326 --- /dev/null +++ b/web/vendor/bootstrap-icons/border-width.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/border.svg b/web/vendor/bootstrap-icons/border.svg new file mode 100644 index 0000000..a6390f9 --- /dev/null +++ b/web/vendor/bootstrap-icons/border.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bounding-box-circles.svg b/web/vendor/bootstrap-icons/bounding-box-circles.svg new file mode 100644 index 0000000..02113ba --- /dev/null +++ b/web/vendor/bootstrap-icons/bounding-box-circles.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bounding-box.svg b/web/vendor/bootstrap-icons/bounding-box.svg new file mode 100644 index 0000000..e8be147 --- /dev/null +++ b/web/vendor/bootstrap-icons/bounding-box.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-arrow-down-left.svg b/web/vendor/bootstrap-icons/box-arrow-down-left.svg new file mode 100644 index 0000000..20ffed9 --- /dev/null +++ b/web/vendor/bootstrap-icons/box-arrow-down-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-arrow-down-right.svg b/web/vendor/bootstrap-icons/box-arrow-down-right.svg new file mode 100644 index 0000000..33780ef --- /dev/null +++ b/web/vendor/bootstrap-icons/box-arrow-down-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-arrow-down.svg b/web/vendor/bootstrap-icons/box-arrow-down.svg new file mode 100644 index 0000000..bf33d51 --- /dev/null +++ b/web/vendor/bootstrap-icons/box-arrow-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-arrow-in-down-left.svg b/web/vendor/bootstrap-icons/box-arrow-in-down-left.svg new file mode 100644 index 0000000..fe3c579 --- /dev/null +++ b/web/vendor/bootstrap-icons/box-arrow-in-down-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-arrow-in-down-right.svg b/web/vendor/bootstrap-icons/box-arrow-in-down-right.svg new file mode 100644 index 0000000..07082eb --- /dev/null +++ b/web/vendor/bootstrap-icons/box-arrow-in-down-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-arrow-in-down.svg b/web/vendor/bootstrap-icons/box-arrow-in-down.svg new file mode 100644 index 0000000..3b185d6 --- /dev/null +++ b/web/vendor/bootstrap-icons/box-arrow-in-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-arrow-in-left.svg b/web/vendor/bootstrap-icons/box-arrow-in-left.svg new file mode 100644 index 0000000..1e1bc9a --- /dev/null +++ b/web/vendor/bootstrap-icons/box-arrow-in-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-arrow-in-right.svg b/web/vendor/bootstrap-icons/box-arrow-in-right.svg new file mode 100644 index 0000000..5d78def --- /dev/null +++ b/web/vendor/bootstrap-icons/box-arrow-in-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-arrow-in-up-left.svg b/web/vendor/bootstrap-icons/box-arrow-in-up-left.svg new file mode 100644 index 0000000..8401c43 --- /dev/null +++ b/web/vendor/bootstrap-icons/box-arrow-in-up-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-arrow-in-up-right.svg b/web/vendor/bootstrap-icons/box-arrow-in-up-right.svg new file mode 100644 index 0000000..8a95e00 --- /dev/null +++ b/web/vendor/bootstrap-icons/box-arrow-in-up-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-arrow-in-up.svg b/web/vendor/bootstrap-icons/box-arrow-in-up.svg new file mode 100644 index 0000000..6197bc3 --- /dev/null +++ b/web/vendor/bootstrap-icons/box-arrow-in-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-arrow-left.svg b/web/vendor/bootstrap-icons/box-arrow-left.svg new file mode 100644 index 0000000..5d142b4 --- /dev/null +++ b/web/vendor/bootstrap-icons/box-arrow-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-arrow-right.svg b/web/vendor/bootstrap-icons/box-arrow-right.svg new file mode 100644 index 0000000..682e033 --- /dev/null +++ b/web/vendor/bootstrap-icons/box-arrow-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-arrow-up-left.svg b/web/vendor/bootstrap-icons/box-arrow-up-left.svg new file mode 100644 index 0000000..7dec12d --- /dev/null +++ b/web/vendor/bootstrap-icons/box-arrow-up-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-arrow-up-right.svg b/web/vendor/bootstrap-icons/box-arrow-up-right.svg new file mode 100644 index 0000000..03f68d5 --- /dev/null +++ b/web/vendor/bootstrap-icons/box-arrow-up-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-arrow-up.svg b/web/vendor/bootstrap-icons/box-arrow-up.svg new file mode 100644 index 0000000..8f76892 --- /dev/null +++ b/web/vendor/bootstrap-icons/box-arrow-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-fill.svg b/web/vendor/bootstrap-icons/box-fill.svg new file mode 100644 index 0000000..b1fe407 --- /dev/null +++ b/web/vendor/bootstrap-icons/box-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-seam-fill.svg b/web/vendor/bootstrap-icons/box-seam-fill.svg new file mode 100644 index 0000000..b9283c7 --- /dev/null +++ b/web/vendor/bootstrap-icons/box-seam-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box-seam.svg b/web/vendor/bootstrap-icons/box-seam.svg new file mode 100644 index 0000000..ec2cb8a --- /dev/null +++ b/web/vendor/bootstrap-icons/box-seam.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box.svg b/web/vendor/bootstrap-icons/box.svg new file mode 100644 index 0000000..01b34c7 --- /dev/null +++ b/web/vendor/bootstrap-icons/box.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box2-fill.svg b/web/vendor/bootstrap-icons/box2-fill.svg new file mode 100644 index 0000000..78e7583 --- /dev/null +++ b/web/vendor/bootstrap-icons/box2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box2-heart-fill.svg b/web/vendor/bootstrap-icons/box2-heart-fill.svg new file mode 100644 index 0000000..49da486 --- /dev/null +++ b/web/vendor/bootstrap-icons/box2-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box2-heart.svg b/web/vendor/bootstrap-icons/box2-heart.svg new file mode 100644 index 0000000..a5e413a --- /dev/null +++ b/web/vendor/bootstrap-icons/box2-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/box2.svg b/web/vendor/bootstrap-icons/box2.svg new file mode 100644 index 0000000..bfeb554 --- /dev/null +++ b/web/vendor/bootstrap-icons/box2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/boxes.svg b/web/vendor/bootstrap-icons/boxes.svg new file mode 100644 index 0000000..af0d1d0 --- /dev/null +++ b/web/vendor/bootstrap-icons/boxes.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/braces-asterisk.svg b/web/vendor/bootstrap-icons/braces-asterisk.svg new file mode 100644 index 0000000..e159e9c --- /dev/null +++ b/web/vendor/bootstrap-icons/braces-asterisk.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/braces.svg b/web/vendor/bootstrap-icons/braces.svg new file mode 100644 index 0000000..d345d3b --- /dev/null +++ b/web/vendor/bootstrap-icons/braces.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bricks.svg b/web/vendor/bootstrap-icons/bricks.svg new file mode 100644 index 0000000..23c2c36 --- /dev/null +++ b/web/vendor/bootstrap-icons/bricks.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/briefcase-fill.svg b/web/vendor/bootstrap-icons/briefcase-fill.svg new file mode 100644 index 0000000..b37f2be --- /dev/null +++ b/web/vendor/bootstrap-icons/briefcase-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/briefcase.svg b/web/vendor/bootstrap-icons/briefcase.svg new file mode 100644 index 0000000..712998d --- /dev/null +++ b/web/vendor/bootstrap-icons/briefcase.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/brightness-alt-high-fill.svg b/web/vendor/bootstrap-icons/brightness-alt-high-fill.svg new file mode 100644 index 0000000..06f7d0c --- /dev/null +++ b/web/vendor/bootstrap-icons/brightness-alt-high-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/brightness-alt-high.svg b/web/vendor/bootstrap-icons/brightness-alt-high.svg new file mode 100644 index 0000000..e519ca7 --- /dev/null +++ b/web/vendor/bootstrap-icons/brightness-alt-high.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/brightness-alt-low-fill.svg b/web/vendor/bootstrap-icons/brightness-alt-low-fill.svg new file mode 100644 index 0000000..ab30837 --- /dev/null +++ b/web/vendor/bootstrap-icons/brightness-alt-low-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/brightness-alt-low.svg b/web/vendor/bootstrap-icons/brightness-alt-low.svg new file mode 100644 index 0000000..58bf6ed --- /dev/null +++ b/web/vendor/bootstrap-icons/brightness-alt-low.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/brightness-high-fill.svg b/web/vendor/bootstrap-icons/brightness-high-fill.svg new file mode 100644 index 0000000..b759b04 --- /dev/null +++ b/web/vendor/bootstrap-icons/brightness-high-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/brightness-high.svg b/web/vendor/bootstrap-icons/brightness-high.svg new file mode 100644 index 0000000..f00d050 --- /dev/null +++ b/web/vendor/bootstrap-icons/brightness-high.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/brightness-low-fill.svg b/web/vendor/bootstrap-icons/brightness-low-fill.svg new file mode 100644 index 0000000..fc55680 --- /dev/null +++ b/web/vendor/bootstrap-icons/brightness-low-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/brightness-low.svg b/web/vendor/bootstrap-icons/brightness-low.svg new file mode 100644 index 0000000..317918e --- /dev/null +++ b/web/vendor/bootstrap-icons/brightness-low.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/brilliance.svg b/web/vendor/bootstrap-icons/brilliance.svg new file mode 100644 index 0000000..f6b5da6 --- /dev/null +++ b/web/vendor/bootstrap-icons/brilliance.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/broadcast-pin.svg b/web/vendor/bootstrap-icons/broadcast-pin.svg new file mode 100644 index 0000000..9c5f4a6 --- /dev/null +++ b/web/vendor/bootstrap-icons/broadcast-pin.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/broadcast.svg b/web/vendor/bootstrap-icons/broadcast.svg new file mode 100644 index 0000000..b420a0b --- /dev/null +++ b/web/vendor/bootstrap-icons/broadcast.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/browser-chrome.svg b/web/vendor/bootstrap-icons/browser-chrome.svg new file mode 100644 index 0000000..63c344b --- /dev/null +++ b/web/vendor/bootstrap-icons/browser-chrome.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/browser-edge.svg b/web/vendor/bootstrap-icons/browser-edge.svg new file mode 100644 index 0000000..ed1dc7c --- /dev/null +++ b/web/vendor/bootstrap-icons/browser-edge.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/browser-firefox.svg b/web/vendor/bootstrap-icons/browser-firefox.svg new file mode 100644 index 0000000..ce0eabb --- /dev/null +++ b/web/vendor/bootstrap-icons/browser-firefox.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/browser-safari.svg b/web/vendor/bootstrap-icons/browser-safari.svg new file mode 100644 index 0000000..8c01296 --- /dev/null +++ b/web/vendor/bootstrap-icons/browser-safari.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/brush-fill.svg b/web/vendor/bootstrap-icons/brush-fill.svg new file mode 100644 index 0000000..db77615 --- /dev/null +++ b/web/vendor/bootstrap-icons/brush-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/brush.svg b/web/vendor/bootstrap-icons/brush.svg new file mode 100644 index 0000000..86d88ef --- /dev/null +++ b/web/vendor/bootstrap-icons/brush.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bucket-fill.svg b/web/vendor/bootstrap-icons/bucket-fill.svg new file mode 100644 index 0000000..c0c95ab --- /dev/null +++ b/web/vendor/bootstrap-icons/bucket-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bucket.svg b/web/vendor/bootstrap-icons/bucket.svg new file mode 100644 index 0000000..252e75b --- /dev/null +++ b/web/vendor/bootstrap-icons/bucket.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bug-fill.svg b/web/vendor/bootstrap-icons/bug-fill.svg new file mode 100644 index 0000000..a36ff37 --- /dev/null +++ b/web/vendor/bootstrap-icons/bug-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bug.svg b/web/vendor/bootstrap-icons/bug.svg new file mode 100644 index 0000000..296ef32 --- /dev/null +++ b/web/vendor/bootstrap-icons/bug.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-add.svg b/web/vendor/bootstrap-icons/building-add.svg new file mode 100644 index 0000000..c2c3670 --- /dev/null +++ b/web/vendor/bootstrap-icons/building-add.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-check.svg b/web/vendor/bootstrap-icons/building-check.svg new file mode 100644 index 0000000..95c3c54 --- /dev/null +++ b/web/vendor/bootstrap-icons/building-check.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-dash.svg b/web/vendor/bootstrap-icons/building-dash.svg new file mode 100644 index 0000000..1e1634b --- /dev/null +++ b/web/vendor/bootstrap-icons/building-dash.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-down.svg b/web/vendor/bootstrap-icons/building-down.svg new file mode 100644 index 0000000..8538cf6 --- /dev/null +++ b/web/vendor/bootstrap-icons/building-down.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-exclamation.svg b/web/vendor/bootstrap-icons/building-exclamation.svg new file mode 100644 index 0000000..ebfc709 --- /dev/null +++ b/web/vendor/bootstrap-icons/building-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-fill-add.svg b/web/vendor/bootstrap-icons/building-fill-add.svg new file mode 100644 index 0000000..6bbe567 --- /dev/null +++ b/web/vendor/bootstrap-icons/building-fill-add.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-fill-check.svg b/web/vendor/bootstrap-icons/building-fill-check.svg new file mode 100644 index 0000000..c4f1881 --- /dev/null +++ b/web/vendor/bootstrap-icons/building-fill-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-fill-dash.svg b/web/vendor/bootstrap-icons/building-fill-dash.svg new file mode 100644 index 0000000..1ce28a6 --- /dev/null +++ b/web/vendor/bootstrap-icons/building-fill-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-fill-down.svg b/web/vendor/bootstrap-icons/building-fill-down.svg new file mode 100644 index 0000000..b1c55cd --- /dev/null +++ b/web/vendor/bootstrap-icons/building-fill-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-fill-exclamation.svg b/web/vendor/bootstrap-icons/building-fill-exclamation.svg new file mode 100644 index 0000000..3491f24 --- /dev/null +++ b/web/vendor/bootstrap-icons/building-fill-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-fill-gear.svg b/web/vendor/bootstrap-icons/building-fill-gear.svg new file mode 100644 index 0000000..747a1bc --- /dev/null +++ b/web/vendor/bootstrap-icons/building-fill-gear.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-fill-lock.svg b/web/vendor/bootstrap-icons/building-fill-lock.svg new file mode 100644 index 0000000..be73a41 --- /dev/null +++ b/web/vendor/bootstrap-icons/building-fill-lock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-fill-slash.svg b/web/vendor/bootstrap-icons/building-fill-slash.svg new file mode 100644 index 0000000..d867309 --- /dev/null +++ b/web/vendor/bootstrap-icons/building-fill-slash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-fill-up.svg b/web/vendor/bootstrap-icons/building-fill-up.svg new file mode 100644 index 0000000..d8cc4bc --- /dev/null +++ b/web/vendor/bootstrap-icons/building-fill-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-fill-x.svg b/web/vendor/bootstrap-icons/building-fill-x.svg new file mode 100644 index 0000000..236aae3 --- /dev/null +++ b/web/vendor/bootstrap-icons/building-fill-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-fill.svg b/web/vendor/bootstrap-icons/building-fill.svg new file mode 100644 index 0000000..6924b41 --- /dev/null +++ b/web/vendor/bootstrap-icons/building-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-gear.svg b/web/vendor/bootstrap-icons/building-gear.svg new file mode 100644 index 0000000..eabe790 --- /dev/null +++ b/web/vendor/bootstrap-icons/building-gear.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-lock.svg b/web/vendor/bootstrap-icons/building-lock.svg new file mode 100644 index 0000000..591a2e9 --- /dev/null +++ b/web/vendor/bootstrap-icons/building-lock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-slash.svg b/web/vendor/bootstrap-icons/building-slash.svg new file mode 100644 index 0000000..c3f7787 --- /dev/null +++ b/web/vendor/bootstrap-icons/building-slash.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-up.svg b/web/vendor/bootstrap-icons/building-up.svg new file mode 100644 index 0000000..ff2d5d9 --- /dev/null +++ b/web/vendor/bootstrap-icons/building-up.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building-x.svg b/web/vendor/bootstrap-icons/building-x.svg new file mode 100644 index 0000000..70e67a3 --- /dev/null +++ b/web/vendor/bootstrap-icons/building-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/building.svg b/web/vendor/bootstrap-icons/building.svg new file mode 100644 index 0000000..916b049 --- /dev/null +++ b/web/vendor/bootstrap-icons/building.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/buildings-fill.svg b/web/vendor/bootstrap-icons/buildings-fill.svg new file mode 100644 index 0000000..6aea68d --- /dev/null +++ b/web/vendor/bootstrap-icons/buildings-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/buildings.svg b/web/vendor/bootstrap-icons/buildings.svg new file mode 100644 index 0000000..3028498 --- /dev/null +++ b/web/vendor/bootstrap-icons/buildings.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bullseye.svg b/web/vendor/bootstrap-icons/bullseye.svg new file mode 100644 index 0000000..16c2207 --- /dev/null +++ b/web/vendor/bootstrap-icons/bullseye.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bus-front-fill.svg b/web/vendor/bootstrap-icons/bus-front-fill.svg new file mode 100644 index 0000000..de21228 --- /dev/null +++ b/web/vendor/bootstrap-icons/bus-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/bus-front.svg b/web/vendor/bootstrap-icons/bus-front.svg new file mode 100644 index 0000000..95c5df5 --- /dev/null +++ b/web/vendor/bootstrap-icons/bus-front.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/c-circle-fill.svg b/web/vendor/bootstrap-icons/c-circle-fill.svg new file mode 100644 index 0000000..c0adc18 --- /dev/null +++ b/web/vendor/bootstrap-icons/c-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/c-circle.svg b/web/vendor/bootstrap-icons/c-circle.svg new file mode 100644 index 0000000..ac3dfac --- /dev/null +++ b/web/vendor/bootstrap-icons/c-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/c-square-fill.svg b/web/vendor/bootstrap-icons/c-square-fill.svg new file mode 100644 index 0000000..b26a27e --- /dev/null +++ b/web/vendor/bootstrap-icons/c-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/c-square.svg b/web/vendor/bootstrap-icons/c-square.svg new file mode 100644 index 0000000..cdd74a3 --- /dev/null +++ b/web/vendor/bootstrap-icons/c-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cake-fill.svg b/web/vendor/bootstrap-icons/cake-fill.svg new file mode 100644 index 0000000..4370e02 --- /dev/null +++ b/web/vendor/bootstrap-icons/cake-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cake.svg b/web/vendor/bootstrap-icons/cake.svg new file mode 100644 index 0000000..500747b --- /dev/null +++ b/web/vendor/bootstrap-icons/cake.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cake2-fill.svg b/web/vendor/bootstrap-icons/cake2-fill.svg new file mode 100644 index 0000000..1ed25f7 --- /dev/null +++ b/web/vendor/bootstrap-icons/cake2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cake2.svg b/web/vendor/bootstrap-icons/cake2.svg new file mode 100644 index 0000000..a10dc80 --- /dev/null +++ b/web/vendor/bootstrap-icons/cake2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calculator-fill.svg b/web/vendor/bootstrap-icons/calculator-fill.svg new file mode 100644 index 0000000..2933419 --- /dev/null +++ b/web/vendor/bootstrap-icons/calculator-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calculator.svg b/web/vendor/bootstrap-icons/calculator.svg new file mode 100644 index 0000000..cc9761e --- /dev/null +++ b/web/vendor/bootstrap-icons/calculator.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-check-fill.svg b/web/vendor/bootstrap-icons/calendar-check-fill.svg new file mode 100644 index 0000000..967d182 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-check.svg b/web/vendor/bootstrap-icons/calendar-check.svg new file mode 100644 index 0000000..f778cd2 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-date-fill.svg b/web/vendor/bootstrap-icons/calendar-date-fill.svg new file mode 100644 index 0000000..59b31f2 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-date-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-date.svg b/web/vendor/bootstrap-icons/calendar-date.svg new file mode 100644 index 0000000..b73c8f5 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-date.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-day-fill.svg b/web/vendor/bootstrap-icons/calendar-day-fill.svg new file mode 100644 index 0000000..b9bcbf8 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-day-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-day.svg b/web/vendor/bootstrap-icons/calendar-day.svg new file mode 100644 index 0000000..6f8d871 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-day.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-event-fill.svg b/web/vendor/bootstrap-icons/calendar-event-fill.svg new file mode 100644 index 0000000..5b09eea --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-event-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-event.svg b/web/vendor/bootstrap-icons/calendar-event.svg new file mode 100644 index 0000000..57c734b --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-event.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-fill.svg b/web/vendor/bootstrap-icons/calendar-fill.svg new file mode 100644 index 0000000..789eb8b --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-heart-fill.svg b/web/vendor/bootstrap-icons/calendar-heart-fill.svg new file mode 100644 index 0000000..63d9e4c --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-heart.svg b/web/vendor/bootstrap-icons/calendar-heart.svg new file mode 100644 index 0000000..8ed9c38 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-minus-fill.svg b/web/vendor/bootstrap-icons/calendar-minus-fill.svg new file mode 100644 index 0000000..8dad6e1 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-minus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-minus.svg b/web/vendor/bootstrap-icons/calendar-minus.svg new file mode 100644 index 0000000..ecd4e97 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-minus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-month-fill.svg b/web/vendor/bootstrap-icons/calendar-month-fill.svg new file mode 100644 index 0000000..d8d56fe --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-month-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-month.svg b/web/vendor/bootstrap-icons/calendar-month.svg new file mode 100644 index 0000000..95b6419 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-month.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-plus-fill.svg b/web/vendor/bootstrap-icons/calendar-plus-fill.svg new file mode 100644 index 0000000..0ed0c83 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-plus.svg b/web/vendor/bootstrap-icons/calendar-plus.svg new file mode 100644 index 0000000..189b152 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-range-fill.svg b/web/vendor/bootstrap-icons/calendar-range-fill.svg new file mode 100644 index 0000000..324def0 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-range-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-range.svg b/web/vendor/bootstrap-icons/calendar-range.svg new file mode 100644 index 0000000..7db0947 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-range.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-week-fill.svg b/web/vendor/bootstrap-icons/calendar-week-fill.svg new file mode 100644 index 0000000..ab2128d --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-week-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-week.svg b/web/vendor/bootstrap-icons/calendar-week.svg new file mode 100644 index 0000000..b5dbcc9 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-week.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-x-fill.svg b/web/vendor/bootstrap-icons/calendar-x-fill.svg new file mode 100644 index 0000000..450e114 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar-x.svg b/web/vendor/bootstrap-icons/calendar-x.svg new file mode 100644 index 0000000..dc85a91 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar.svg b/web/vendor/bootstrap-icons/calendar.svg new file mode 100644 index 0000000..d32ebe7 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-check-fill.svg b/web/vendor/bootstrap-icons/calendar2-check-fill.svg new file mode 100644 index 0000000..a0c36c5 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-check.svg b/web/vendor/bootstrap-icons/calendar2-check.svg new file mode 100644 index 0000000..5429842 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-check.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-date-fill.svg b/web/vendor/bootstrap-icons/calendar2-date-fill.svg new file mode 100644 index 0000000..93b3941 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-date-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-date.svg b/web/vendor/bootstrap-icons/calendar2-date.svg new file mode 100644 index 0000000..61193cd --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-date.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-day-fill.svg b/web/vendor/bootstrap-icons/calendar2-day-fill.svg new file mode 100644 index 0000000..b605453 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-day-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-day.svg b/web/vendor/bootstrap-icons/calendar2-day.svg new file mode 100644 index 0000000..ce59878 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-day.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-event-fill.svg b/web/vendor/bootstrap-icons/calendar2-event-fill.svg new file mode 100644 index 0000000..2b245d1 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-event-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-event.svg b/web/vendor/bootstrap-icons/calendar2-event.svg new file mode 100644 index 0000000..36910dd --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-event.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-fill.svg b/web/vendor/bootstrap-icons/calendar2-fill.svg new file mode 100644 index 0000000..b28e594 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-heart-fill.svg b/web/vendor/bootstrap-icons/calendar2-heart-fill.svg new file mode 100644 index 0000000..f3723cd --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-heart.svg b/web/vendor/bootstrap-icons/calendar2-heart.svg new file mode 100644 index 0000000..995d9b8 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-minus-fill.svg b/web/vendor/bootstrap-icons/calendar2-minus-fill.svg new file mode 100644 index 0000000..bf52a36 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-minus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-minus.svg b/web/vendor/bootstrap-icons/calendar2-minus.svg new file mode 100644 index 0000000..62e6bbc --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-minus.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-month-fill.svg b/web/vendor/bootstrap-icons/calendar2-month-fill.svg new file mode 100644 index 0000000..24b9c69 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-month-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-month.svg b/web/vendor/bootstrap-icons/calendar2-month.svg new file mode 100644 index 0000000..65d8295 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-month.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-plus-fill.svg b/web/vendor/bootstrap-icons/calendar2-plus-fill.svg new file mode 100644 index 0000000..26a2047 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-plus.svg b/web/vendor/bootstrap-icons/calendar2-plus.svg new file mode 100644 index 0000000..728148f --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-range-fill.svg b/web/vendor/bootstrap-icons/calendar2-range-fill.svg new file mode 100644 index 0000000..1ba46b6 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-range-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-range.svg b/web/vendor/bootstrap-icons/calendar2-range.svg new file mode 100644 index 0000000..9a657f4 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-range.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-week-fill.svg b/web/vendor/bootstrap-icons/calendar2-week-fill.svg new file mode 100644 index 0000000..f358667 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-week-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-week.svg b/web/vendor/bootstrap-icons/calendar2-week.svg new file mode 100644 index 0000000..07906a9 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-week.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-x-fill.svg b/web/vendor/bootstrap-icons/calendar2-x-fill.svg new file mode 100644 index 0000000..def799d --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2-x.svg b/web/vendor/bootstrap-icons/calendar2-x.svg new file mode 100644 index 0000000..d6f9e6f --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2-x.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar2.svg b/web/vendor/bootstrap-icons/calendar2.svg new file mode 100644 index 0000000..957f993 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar3-event-fill.svg b/web/vendor/bootstrap-icons/calendar3-event-fill.svg new file mode 100644 index 0000000..0901710 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar3-event-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar3-event.svg b/web/vendor/bootstrap-icons/calendar3-event.svg new file mode 100644 index 0000000..f702c36 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar3-event.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar3-fill.svg b/web/vendor/bootstrap-icons/calendar3-fill.svg new file mode 100644 index 0000000..f3bc116 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar3-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar3-range-fill.svg b/web/vendor/bootstrap-icons/calendar3-range-fill.svg new file mode 100644 index 0000000..7d16dc5 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar3-range-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar3-range.svg b/web/vendor/bootstrap-icons/calendar3-range.svg new file mode 100644 index 0000000..c19d9ca --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar3-range.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar3-week-fill.svg b/web/vendor/bootstrap-icons/calendar3-week-fill.svg new file mode 100644 index 0000000..1b66709 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar3-week-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar3-week.svg b/web/vendor/bootstrap-icons/calendar3-week.svg new file mode 100644 index 0000000..6d577b7 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar3-week.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar3.svg b/web/vendor/bootstrap-icons/calendar3.svg new file mode 100644 index 0000000..8e2aedf --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar3.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar4-event.svg b/web/vendor/bootstrap-icons/calendar4-event.svg new file mode 100644 index 0000000..0d29c0c --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar4-event.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar4-range.svg b/web/vendor/bootstrap-icons/calendar4-range.svg new file mode 100644 index 0000000..b260479 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar4-range.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar4-week.svg b/web/vendor/bootstrap-icons/calendar4-week.svg new file mode 100644 index 0000000..d934881 --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar4-week.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/calendar4.svg b/web/vendor/bootstrap-icons/calendar4.svg new file mode 100644 index 0000000..69c474c --- /dev/null +++ b/web/vendor/bootstrap-icons/calendar4.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/camera-fill.svg b/web/vendor/bootstrap-icons/camera-fill.svg new file mode 100644 index 0000000..6aa0240 --- /dev/null +++ b/web/vendor/bootstrap-icons/camera-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/camera-reels-fill.svg b/web/vendor/bootstrap-icons/camera-reels-fill.svg new file mode 100644 index 0000000..6bd48de --- /dev/null +++ b/web/vendor/bootstrap-icons/camera-reels-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/camera-reels.svg b/web/vendor/bootstrap-icons/camera-reels.svg new file mode 100644 index 0000000..0c6eca8 --- /dev/null +++ b/web/vendor/bootstrap-icons/camera-reels.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/camera-video-fill.svg b/web/vendor/bootstrap-icons/camera-video-fill.svg new file mode 100644 index 0000000..72dee37 --- /dev/null +++ b/web/vendor/bootstrap-icons/camera-video-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/camera-video-off-fill.svg b/web/vendor/bootstrap-icons/camera-video-off-fill.svg new file mode 100644 index 0000000..290dc19 --- /dev/null +++ b/web/vendor/bootstrap-icons/camera-video-off-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/camera-video-off.svg b/web/vendor/bootstrap-icons/camera-video-off.svg new file mode 100644 index 0000000..c9eb587 --- /dev/null +++ b/web/vendor/bootstrap-icons/camera-video-off.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/camera-video.svg b/web/vendor/bootstrap-icons/camera-video.svg new file mode 100644 index 0000000..a042d1a --- /dev/null +++ b/web/vendor/bootstrap-icons/camera-video.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/camera.svg b/web/vendor/bootstrap-icons/camera.svg new file mode 100644 index 0000000..3a926d5 --- /dev/null +++ b/web/vendor/bootstrap-icons/camera.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/camera2.svg b/web/vendor/bootstrap-icons/camera2.svg new file mode 100644 index 0000000..ba9521e --- /dev/null +++ b/web/vendor/bootstrap-icons/camera2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/capslock-fill.svg b/web/vendor/bootstrap-icons/capslock-fill.svg new file mode 100644 index 0000000..f1c0bab --- /dev/null +++ b/web/vendor/bootstrap-icons/capslock-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/capslock.svg b/web/vendor/bootstrap-icons/capslock.svg new file mode 100644 index 0000000..b0b894a --- /dev/null +++ b/web/vendor/bootstrap-icons/capslock.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/capsule-pill.svg b/web/vendor/bootstrap-icons/capsule-pill.svg new file mode 100644 index 0000000..b9f3b54 --- /dev/null +++ b/web/vendor/bootstrap-icons/capsule-pill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/capsule.svg b/web/vendor/bootstrap-icons/capsule.svg new file mode 100644 index 0000000..53d1a66 --- /dev/null +++ b/web/vendor/bootstrap-icons/capsule.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/car-front-fill.svg b/web/vendor/bootstrap-icons/car-front-fill.svg new file mode 100644 index 0000000..a47a870 --- /dev/null +++ b/web/vendor/bootstrap-icons/car-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/car-front.svg b/web/vendor/bootstrap-icons/car-front.svg new file mode 100644 index 0000000..890e4cf --- /dev/null +++ b/web/vendor/bootstrap-icons/car-front.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/card-checklist.svg b/web/vendor/bootstrap-icons/card-checklist.svg new file mode 100644 index 0000000..3044e68 --- /dev/null +++ b/web/vendor/bootstrap-icons/card-checklist.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/card-heading.svg b/web/vendor/bootstrap-icons/card-heading.svg new file mode 100644 index 0000000..a6be873 --- /dev/null +++ b/web/vendor/bootstrap-icons/card-heading.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/card-image.svg b/web/vendor/bootstrap-icons/card-image.svg new file mode 100644 index 0000000..7343f77 --- /dev/null +++ b/web/vendor/bootstrap-icons/card-image.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/card-list.svg b/web/vendor/bootstrap-icons/card-list.svg new file mode 100644 index 0000000..6270802 --- /dev/null +++ b/web/vendor/bootstrap-icons/card-list.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/card-text.svg b/web/vendor/bootstrap-icons/card-text.svg new file mode 100644 index 0000000..8f7470c --- /dev/null +++ b/web/vendor/bootstrap-icons/card-text.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/caret-down-fill.svg b/web/vendor/bootstrap-icons/caret-down-fill.svg new file mode 100644 index 0000000..d7c3990 --- /dev/null +++ b/web/vendor/bootstrap-icons/caret-down-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/caret-down-square-fill.svg b/web/vendor/bootstrap-icons/caret-down-square-fill.svg new file mode 100644 index 0000000..63199bb --- /dev/null +++ b/web/vendor/bootstrap-icons/caret-down-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/caret-down-square.svg b/web/vendor/bootstrap-icons/caret-down-square.svg new file mode 100644 index 0000000..0372625 --- /dev/null +++ b/web/vendor/bootstrap-icons/caret-down-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/caret-down.svg b/web/vendor/bootstrap-icons/caret-down.svg new file mode 100644 index 0000000..627258a --- /dev/null +++ b/web/vendor/bootstrap-icons/caret-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/caret-left-fill.svg b/web/vendor/bootstrap-icons/caret-left-fill.svg new file mode 100644 index 0000000..d989dff --- /dev/null +++ b/web/vendor/bootstrap-icons/caret-left-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/caret-left-square-fill.svg b/web/vendor/bootstrap-icons/caret-left-square-fill.svg new file mode 100644 index 0000000..cc7e3a8 --- /dev/null +++ b/web/vendor/bootstrap-icons/caret-left-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/caret-left-square.svg b/web/vendor/bootstrap-icons/caret-left-square.svg new file mode 100644 index 0000000..5e8cb20 --- /dev/null +++ b/web/vendor/bootstrap-icons/caret-left-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/caret-left.svg b/web/vendor/bootstrap-icons/caret-left.svg new file mode 100644 index 0000000..4415336 --- /dev/null +++ b/web/vendor/bootstrap-icons/caret-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/caret-right-fill.svg b/web/vendor/bootstrap-icons/caret-right-fill.svg new file mode 100644 index 0000000..b445551 --- /dev/null +++ b/web/vendor/bootstrap-icons/caret-right-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/caret-right-square-fill.svg b/web/vendor/bootstrap-icons/caret-right-square-fill.svg new file mode 100644 index 0000000..2aded36 --- /dev/null +++ b/web/vendor/bootstrap-icons/caret-right-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/caret-right-square.svg b/web/vendor/bootstrap-icons/caret-right-square.svg new file mode 100644 index 0000000..a3a44e2 --- /dev/null +++ b/web/vendor/bootstrap-icons/caret-right-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/caret-right.svg b/web/vendor/bootstrap-icons/caret-right.svg new file mode 100644 index 0000000..7bcd8bb --- /dev/null +++ b/web/vendor/bootstrap-icons/caret-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/caret-up-fill.svg b/web/vendor/bootstrap-icons/caret-up-fill.svg new file mode 100644 index 0000000..a87820e --- /dev/null +++ b/web/vendor/bootstrap-icons/caret-up-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/caret-up-square-fill.svg b/web/vendor/bootstrap-icons/caret-up-square-fill.svg new file mode 100644 index 0000000..348fcf2 --- /dev/null +++ b/web/vendor/bootstrap-icons/caret-up-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/caret-up-square.svg b/web/vendor/bootstrap-icons/caret-up-square.svg new file mode 100644 index 0000000..8ac2af4 --- /dev/null +++ b/web/vendor/bootstrap-icons/caret-up-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/caret-up.svg b/web/vendor/bootstrap-icons/caret-up.svg new file mode 100644 index 0000000..8e33519 --- /dev/null +++ b/web/vendor/bootstrap-icons/caret-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cart-check-fill.svg b/web/vendor/bootstrap-icons/cart-check-fill.svg new file mode 100644 index 0000000..612358c --- /dev/null +++ b/web/vendor/bootstrap-icons/cart-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cart-check.svg b/web/vendor/bootstrap-icons/cart-check.svg new file mode 100644 index 0000000..68301db --- /dev/null +++ b/web/vendor/bootstrap-icons/cart-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cart-dash-fill.svg b/web/vendor/bootstrap-icons/cart-dash-fill.svg new file mode 100644 index 0000000..a335b07 --- /dev/null +++ b/web/vendor/bootstrap-icons/cart-dash-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cart-dash.svg b/web/vendor/bootstrap-icons/cart-dash.svg new file mode 100644 index 0000000..9c97c3b --- /dev/null +++ b/web/vendor/bootstrap-icons/cart-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cart-fill.svg b/web/vendor/bootstrap-icons/cart-fill.svg new file mode 100644 index 0000000..974fc29 --- /dev/null +++ b/web/vendor/bootstrap-icons/cart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cart-plus-fill.svg b/web/vendor/bootstrap-icons/cart-plus-fill.svg new file mode 100644 index 0000000..59e46e4 --- /dev/null +++ b/web/vendor/bootstrap-icons/cart-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cart-plus.svg b/web/vendor/bootstrap-icons/cart-plus.svg new file mode 100644 index 0000000..2baaae4 --- /dev/null +++ b/web/vendor/bootstrap-icons/cart-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cart-x-fill.svg b/web/vendor/bootstrap-icons/cart-x-fill.svg new file mode 100644 index 0000000..7ca0688 --- /dev/null +++ b/web/vendor/bootstrap-icons/cart-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cart-x.svg b/web/vendor/bootstrap-icons/cart-x.svg new file mode 100644 index 0000000..2d8f213 --- /dev/null +++ b/web/vendor/bootstrap-icons/cart-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cart.svg b/web/vendor/bootstrap-icons/cart.svg new file mode 100644 index 0000000..0e0f96c --- /dev/null +++ b/web/vendor/bootstrap-icons/cart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cart2.svg b/web/vendor/bootstrap-icons/cart2.svg new file mode 100644 index 0000000..ea7f696 --- /dev/null +++ b/web/vendor/bootstrap-icons/cart2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cart3.svg b/web/vendor/bootstrap-icons/cart3.svg new file mode 100644 index 0000000..af1b3c5 --- /dev/null +++ b/web/vendor/bootstrap-icons/cart3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cart4.svg b/web/vendor/bootstrap-icons/cart4.svg new file mode 100644 index 0000000..4631ac9 --- /dev/null +++ b/web/vendor/bootstrap-icons/cart4.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cash-coin.svg b/web/vendor/bootstrap-icons/cash-coin.svg new file mode 100644 index 0000000..2904f15 --- /dev/null +++ b/web/vendor/bootstrap-icons/cash-coin.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cash-stack.svg b/web/vendor/bootstrap-icons/cash-stack.svg new file mode 100644 index 0000000..fc8c282 --- /dev/null +++ b/web/vendor/bootstrap-icons/cash-stack.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cash.svg b/web/vendor/bootstrap-icons/cash.svg new file mode 100644 index 0000000..18cbff3 --- /dev/null +++ b/web/vendor/bootstrap-icons/cash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cassette-fill.svg b/web/vendor/bootstrap-icons/cassette-fill.svg new file mode 100644 index 0000000..18fd5e4 --- /dev/null +++ b/web/vendor/bootstrap-icons/cassette-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cassette.svg b/web/vendor/bootstrap-icons/cassette.svg new file mode 100644 index 0000000..2effe71 --- /dev/null +++ b/web/vendor/bootstrap-icons/cassette.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cast.svg b/web/vendor/bootstrap-icons/cast.svg new file mode 100644 index 0000000..01a9795 --- /dev/null +++ b/web/vendor/bootstrap-icons/cast.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cc-circle-fill.svg b/web/vendor/bootstrap-icons/cc-circle-fill.svg new file mode 100644 index 0000000..483d90c --- /dev/null +++ b/web/vendor/bootstrap-icons/cc-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cc-circle.svg b/web/vendor/bootstrap-icons/cc-circle.svg new file mode 100644 index 0000000..2dc2b4b --- /dev/null +++ b/web/vendor/bootstrap-icons/cc-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cc-square-fill.svg b/web/vendor/bootstrap-icons/cc-square-fill.svg new file mode 100644 index 0000000..b0a8350 --- /dev/null +++ b/web/vendor/bootstrap-icons/cc-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cc-square.svg b/web/vendor/bootstrap-icons/cc-square.svg new file mode 100644 index 0000000..b0f05b6 --- /dev/null +++ b/web/vendor/bootstrap-icons/cc-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-dots-fill.svg b/web/vendor/bootstrap-icons/chat-dots-fill.svg new file mode 100644 index 0000000..5f74345 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-dots-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-dots.svg b/web/vendor/bootstrap-icons/chat-dots.svg new file mode 100644 index 0000000..20137cc --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-dots.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-fill.svg b/web/vendor/bootstrap-icons/chat-fill.svg new file mode 100644 index 0000000..c896939 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-heart-fill.svg b/web/vendor/bootstrap-icons/chat-heart-fill.svg new file mode 100644 index 0000000..ea01c34 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-heart.svg b/web/vendor/bootstrap-icons/chat-heart.svg new file mode 100644 index 0000000..8ea104e --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-left-dots-fill.svg b/web/vendor/bootstrap-icons/chat-left-dots-fill.svg new file mode 100644 index 0000000..a6614c3 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-left-dots-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-left-dots.svg b/web/vendor/bootstrap-icons/chat-left-dots.svg new file mode 100644 index 0000000..35f466a --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-left-dots.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-left-fill.svg b/web/vendor/bootstrap-icons/chat-left-fill.svg new file mode 100644 index 0000000..0de6e13 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-left-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-left-heart-fill.svg b/web/vendor/bootstrap-icons/chat-left-heart-fill.svg new file mode 100644 index 0000000..cc9502c --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-left-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-left-heart.svg b/web/vendor/bootstrap-icons/chat-left-heart.svg new file mode 100644 index 0000000..ec11692 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-left-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-left-quote-fill.svg b/web/vendor/bootstrap-icons/chat-left-quote-fill.svg new file mode 100644 index 0000000..d634a12 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-left-quote-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-left-quote.svg b/web/vendor/bootstrap-icons/chat-left-quote.svg new file mode 100644 index 0000000..376ceb1 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-left-quote.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-left-text-fill.svg b/web/vendor/bootstrap-icons/chat-left-text-fill.svg new file mode 100644 index 0000000..a78e343 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-left-text-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-left-text.svg b/web/vendor/bootstrap-icons/chat-left-text.svg new file mode 100644 index 0000000..88d1906 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-left-text.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-left.svg b/web/vendor/bootstrap-icons/chat-left.svg new file mode 100644 index 0000000..d93f0af --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-quote-fill.svg b/web/vendor/bootstrap-icons/chat-quote-fill.svg new file mode 100644 index 0000000..7150c44 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-quote-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-quote.svg b/web/vendor/bootstrap-icons/chat-quote.svg new file mode 100644 index 0000000..aa0edc4 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-quote.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-right-dots-fill.svg b/web/vendor/bootstrap-icons/chat-right-dots-fill.svg new file mode 100644 index 0000000..1020581 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-right-dots-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-right-dots.svg b/web/vendor/bootstrap-icons/chat-right-dots.svg new file mode 100644 index 0000000..d9b8bd2 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-right-dots.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-right-fill.svg b/web/vendor/bootstrap-icons/chat-right-fill.svg new file mode 100644 index 0000000..6381ddc --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-right-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-right-heart-fill.svg b/web/vendor/bootstrap-icons/chat-right-heart-fill.svg new file mode 100644 index 0000000..cf4abfe --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-right-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-right-heart.svg b/web/vendor/bootstrap-icons/chat-right-heart.svg new file mode 100644 index 0000000..e6b3880 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-right-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-right-quote-fill.svg b/web/vendor/bootstrap-icons/chat-right-quote-fill.svg new file mode 100644 index 0000000..1c4e536 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-right-quote-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-right-quote.svg b/web/vendor/bootstrap-icons/chat-right-quote.svg new file mode 100644 index 0000000..e9091bc --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-right-quote.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-right-text-fill.svg b/web/vendor/bootstrap-icons/chat-right-text-fill.svg new file mode 100644 index 0000000..3455983 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-right-text-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-right-text.svg b/web/vendor/bootstrap-icons/chat-right-text.svg new file mode 100644 index 0000000..88341af --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-right-text.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-right.svg b/web/vendor/bootstrap-icons/chat-right.svg new file mode 100644 index 0000000..a930c9a --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-square-dots-fill.svg b/web/vendor/bootstrap-icons/chat-square-dots-fill.svg new file mode 100644 index 0000000..09c97d1 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-square-dots-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-square-dots.svg b/web/vendor/bootstrap-icons/chat-square-dots.svg new file mode 100644 index 0000000..b06c02f --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-square-dots.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-square-fill.svg b/web/vendor/bootstrap-icons/chat-square-fill.svg new file mode 100644 index 0000000..4688831 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-square-heart-fill.svg b/web/vendor/bootstrap-icons/chat-square-heart-fill.svg new file mode 100644 index 0000000..902e0b5 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-square-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-square-heart.svg b/web/vendor/bootstrap-icons/chat-square-heart.svg new file mode 100644 index 0000000..6ba687e --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-square-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-square-quote-fill.svg b/web/vendor/bootstrap-icons/chat-square-quote-fill.svg new file mode 100644 index 0000000..2496b70 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-square-quote-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-square-quote.svg b/web/vendor/bootstrap-icons/chat-square-quote.svg new file mode 100644 index 0000000..a8f6b09 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-square-quote.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-square-text-fill.svg b/web/vendor/bootstrap-icons/chat-square-text-fill.svg new file mode 100644 index 0000000..6ebf567 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-square-text-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-square-text.svg b/web/vendor/bootstrap-icons/chat-square-text.svg new file mode 100644 index 0000000..1296f92 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-square-text.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-square.svg b/web/vendor/bootstrap-icons/chat-square.svg new file mode 100644 index 0000000..4e13ae8 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-text-fill.svg b/web/vendor/bootstrap-icons/chat-text-fill.svg new file mode 100644 index 0000000..93639f1 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-text-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat-text.svg b/web/vendor/bootstrap-icons/chat-text.svg new file mode 100644 index 0000000..f64f43f --- /dev/null +++ b/web/vendor/bootstrap-icons/chat-text.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chat.svg b/web/vendor/bootstrap-icons/chat.svg new file mode 100644 index 0000000..487d142 --- /dev/null +++ b/web/vendor/bootstrap-icons/chat.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/check-all.svg b/web/vendor/bootstrap-icons/check-all.svg new file mode 100644 index 0000000..f91fd77 --- /dev/null +++ b/web/vendor/bootstrap-icons/check-all.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/check-circle-fill.svg b/web/vendor/bootstrap-icons/check-circle-fill.svg new file mode 100644 index 0000000..0b7f412 --- /dev/null +++ b/web/vendor/bootstrap-icons/check-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/check-circle.svg b/web/vendor/bootstrap-icons/check-circle.svg new file mode 100644 index 0000000..016f607 --- /dev/null +++ b/web/vendor/bootstrap-icons/check-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/check-lg.svg b/web/vendor/bootstrap-icons/check-lg.svg new file mode 100644 index 0000000..63a8a3d --- /dev/null +++ b/web/vendor/bootstrap-icons/check-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/check-square-fill.svg b/web/vendor/bootstrap-icons/check-square-fill.svg new file mode 100644 index 0000000..cbb56ed --- /dev/null +++ b/web/vendor/bootstrap-icons/check-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/check-square.svg b/web/vendor/bootstrap-icons/check-square.svg new file mode 100644 index 0000000..b7d1116 --- /dev/null +++ b/web/vendor/bootstrap-icons/check-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/check.svg b/web/vendor/bootstrap-icons/check.svg new file mode 100644 index 0000000..11ab547 --- /dev/null +++ b/web/vendor/bootstrap-icons/check.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/check2-all.svg b/web/vendor/bootstrap-icons/check2-all.svg new file mode 100644 index 0000000..cccc0b7 --- /dev/null +++ b/web/vendor/bootstrap-icons/check2-all.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/check2-circle.svg b/web/vendor/bootstrap-icons/check2-circle.svg new file mode 100644 index 0000000..166e661 --- /dev/null +++ b/web/vendor/bootstrap-icons/check2-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/check2-square.svg b/web/vendor/bootstrap-icons/check2-square.svg new file mode 100644 index 0000000..64c3669 --- /dev/null +++ b/web/vendor/bootstrap-icons/check2-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/check2.svg b/web/vendor/bootstrap-icons/check2.svg new file mode 100644 index 0000000..87168de --- /dev/null +++ b/web/vendor/bootstrap-icons/check2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-bar-contract.svg b/web/vendor/bootstrap-icons/chevron-bar-contract.svg new file mode 100644 index 0000000..52ec3f6 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-bar-contract.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-bar-down.svg b/web/vendor/bootstrap-icons/chevron-bar-down.svg new file mode 100644 index 0000000..8c10216 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-bar-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-bar-expand.svg b/web/vendor/bootstrap-icons/chevron-bar-expand.svg new file mode 100644 index 0000000..1260a20 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-bar-expand.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-bar-left.svg b/web/vendor/bootstrap-icons/chevron-bar-left.svg new file mode 100644 index 0000000..36afeb7 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-bar-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-bar-right.svg b/web/vendor/bootstrap-icons/chevron-bar-right.svg new file mode 100644 index 0000000..b71e040 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-bar-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-bar-up.svg b/web/vendor/bootstrap-icons/chevron-bar-up.svg new file mode 100644 index 0000000..c5da175 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-bar-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-compact-down.svg b/web/vendor/bootstrap-icons/chevron-compact-down.svg new file mode 100644 index 0000000..53d9d9a --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-compact-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-compact-left.svg b/web/vendor/bootstrap-icons/chevron-compact-left.svg new file mode 100644 index 0000000..277ddd8 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-compact-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-compact-right.svg b/web/vendor/bootstrap-icons/chevron-compact-right.svg new file mode 100644 index 0000000..24b5309 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-compact-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-compact-up.svg b/web/vendor/bootstrap-icons/chevron-compact-up.svg new file mode 100644 index 0000000..2a4f354 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-compact-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-contract.svg b/web/vendor/bootstrap-icons/chevron-contract.svg new file mode 100644 index 0000000..354ee86 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-contract.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-double-down.svg b/web/vendor/bootstrap-icons/chevron-double-down.svg new file mode 100644 index 0000000..bc99e59 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-double-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-double-left.svg b/web/vendor/bootstrap-icons/chevron-double-left.svg new file mode 100644 index 0000000..c4cd7f2 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-double-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-double-right.svg b/web/vendor/bootstrap-icons/chevron-double-right.svg new file mode 100644 index 0000000..dccd6c5 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-double-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-double-up.svg b/web/vendor/bootstrap-icons/chevron-double-up.svg new file mode 100644 index 0000000..ad7ba12 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-double-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-down.svg b/web/vendor/bootstrap-icons/chevron-down.svg new file mode 100644 index 0000000..a281907 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-expand.svg b/web/vendor/bootstrap-icons/chevron-expand.svg new file mode 100644 index 0000000..33e4ad8 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-expand.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-left.svg b/web/vendor/bootstrap-icons/chevron-left.svg new file mode 100644 index 0000000..5bcc1bb --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-right.svg b/web/vendor/bootstrap-icons/chevron-right.svg new file mode 100644 index 0000000..ab39af8 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/chevron-up.svg b/web/vendor/bootstrap-icons/chevron-up.svg new file mode 100644 index 0000000..4f3c7a0 --- /dev/null +++ b/web/vendor/bootstrap-icons/chevron-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/circle-fill.svg b/web/vendor/bootstrap-icons/circle-fill.svg new file mode 100644 index 0000000..e0d1b51 --- /dev/null +++ b/web/vendor/bootstrap-icons/circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/circle-half.svg b/web/vendor/bootstrap-icons/circle-half.svg new file mode 100644 index 0000000..497f6b7 --- /dev/null +++ b/web/vendor/bootstrap-icons/circle-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/circle-square.svg b/web/vendor/bootstrap-icons/circle-square.svg new file mode 100644 index 0000000..c0f62b7 --- /dev/null +++ b/web/vendor/bootstrap-icons/circle-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/circle.svg b/web/vendor/bootstrap-icons/circle.svg new file mode 100644 index 0000000..9bbabca --- /dev/null +++ b/web/vendor/bootstrap-icons/circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/claude.svg b/web/vendor/bootstrap-icons/claude.svg new file mode 100644 index 0000000..1403b27 --- /dev/null +++ b/web/vendor/bootstrap-icons/claude.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard-check-fill.svg b/web/vendor/bootstrap-icons/clipboard-check-fill.svg new file mode 100644 index 0000000..598e850 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard-check-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard-check.svg b/web/vendor/bootstrap-icons/clipboard-check.svg new file mode 100644 index 0000000..cb9d8a2 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard-check.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard-data-fill.svg b/web/vendor/bootstrap-icons/clipboard-data-fill.svg new file mode 100644 index 0000000..e4a9425 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard-data-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard-data.svg b/web/vendor/bootstrap-icons/clipboard-data.svg new file mode 100644 index 0000000..622acbf --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard-data.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard-fill.svg b/web/vendor/bootstrap-icons/clipboard-fill.svg new file mode 100644 index 0000000..176c5e4 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard-heart-fill.svg b/web/vendor/bootstrap-icons/clipboard-heart-fill.svg new file mode 100644 index 0000000..92de0a8 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard-heart-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard-heart.svg b/web/vendor/bootstrap-icons/clipboard-heart.svg new file mode 100644 index 0000000..c430ed2 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard-heart.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard-minus-fill.svg b/web/vendor/bootstrap-icons/clipboard-minus-fill.svg new file mode 100644 index 0000000..e47f43f --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard-minus-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard-minus.svg b/web/vendor/bootstrap-icons/clipboard-minus.svg new file mode 100644 index 0000000..d3675c4 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard-minus.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard-plus-fill.svg b/web/vendor/bootstrap-icons/clipboard-plus-fill.svg new file mode 100644 index 0000000..8140aa8 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard-plus-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard-plus.svg b/web/vendor/bootstrap-icons/clipboard-plus.svg new file mode 100644 index 0000000..1d095d7 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard-plus.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard-pulse.svg b/web/vendor/bootstrap-icons/clipboard-pulse.svg new file mode 100644 index 0000000..a357209 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard-pulse.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard-x-fill.svg b/web/vendor/bootstrap-icons/clipboard-x-fill.svg new file mode 100644 index 0000000..10fba82 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard-x-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard-x.svg b/web/vendor/bootstrap-icons/clipboard-x.svg new file mode 100644 index 0000000..46df235 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard-x.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard.svg b/web/vendor/bootstrap-icons/clipboard.svg new file mode 100644 index 0000000..b92f42a --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard2-check-fill.svg b/web/vendor/bootstrap-icons/clipboard2-check-fill.svg new file mode 100644 index 0000000..b640432 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard2-check-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard2-check.svg b/web/vendor/bootstrap-icons/clipboard2-check.svg new file mode 100644 index 0000000..aba15bf --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard2-check.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard2-data-fill.svg b/web/vendor/bootstrap-icons/clipboard2-data-fill.svg new file mode 100644 index 0000000..56c127e --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard2-data-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard2-data.svg b/web/vendor/bootstrap-icons/clipboard2-data.svg new file mode 100644 index 0000000..75ac6c6 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard2-data.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard2-fill.svg b/web/vendor/bootstrap-icons/clipboard2-fill.svg new file mode 100644 index 0000000..6898571 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard2-heart-fill.svg b/web/vendor/bootstrap-icons/clipboard2-heart-fill.svg new file mode 100644 index 0000000..ce98945 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard2-heart-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard2-heart.svg b/web/vendor/bootstrap-icons/clipboard2-heart.svg new file mode 100644 index 0000000..879fef2 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard2-heart.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard2-minus-fill.svg b/web/vendor/bootstrap-icons/clipboard2-minus-fill.svg new file mode 100644 index 0000000..fcd4b56 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard2-minus-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard2-minus.svg b/web/vendor/bootstrap-icons/clipboard2-minus.svg new file mode 100644 index 0000000..f8c10e3 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard2-minus.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard2-plus-fill.svg b/web/vendor/bootstrap-icons/clipboard2-plus-fill.svg new file mode 100644 index 0000000..be310e5 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard2-plus-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard2-plus.svg b/web/vendor/bootstrap-icons/clipboard2-plus.svg new file mode 100644 index 0000000..33eaa28 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard2-plus.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard2-pulse-fill.svg b/web/vendor/bootstrap-icons/clipboard2-pulse-fill.svg new file mode 100644 index 0000000..bc7d6b3 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard2-pulse-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard2-pulse.svg b/web/vendor/bootstrap-icons/clipboard2-pulse.svg new file mode 100644 index 0000000..c641c61 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard2-pulse.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard2-x-fill.svg b/web/vendor/bootstrap-icons/clipboard2-x-fill.svg new file mode 100644 index 0000000..08828c6 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard2-x-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard2-x.svg b/web/vendor/bootstrap-icons/clipboard2-x.svg new file mode 100644 index 0000000..06832cc --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard2-x.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clipboard2.svg b/web/vendor/bootstrap-icons/clipboard2.svg new file mode 100644 index 0000000..d0f4529 --- /dev/null +++ b/web/vendor/bootstrap-icons/clipboard2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clock-fill.svg b/web/vendor/bootstrap-icons/clock-fill.svg new file mode 100644 index 0000000..148abcf --- /dev/null +++ b/web/vendor/bootstrap-icons/clock-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clock-history.svg b/web/vendor/bootstrap-icons/clock-history.svg new file mode 100644 index 0000000..f685e10 --- /dev/null +++ b/web/vendor/bootstrap-icons/clock-history.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clock.svg b/web/vendor/bootstrap-icons/clock.svg new file mode 100644 index 0000000..31c3c64 --- /dev/null +++ b/web/vendor/bootstrap-icons/clock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-arrow-down-fill.svg b/web/vendor/bootstrap-icons/cloud-arrow-down-fill.svg new file mode 100644 index 0000000..1b23dc9 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-arrow-down-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-arrow-down.svg b/web/vendor/bootstrap-icons/cloud-arrow-down.svg new file mode 100644 index 0000000..bb79bbe --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-arrow-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-arrow-up-fill.svg b/web/vendor/bootstrap-icons/cloud-arrow-up-fill.svg new file mode 100644 index 0000000..8366f05 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-arrow-up-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-arrow-up.svg b/web/vendor/bootstrap-icons/cloud-arrow-up.svg new file mode 100644 index 0000000..704756b --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-arrow-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-check-fill.svg b/web/vendor/bootstrap-icons/cloud-check-fill.svg new file mode 100644 index 0000000..a71feee --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-check.svg b/web/vendor/bootstrap-icons/cloud-check.svg new file mode 100644 index 0000000..d7599e9 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-download-fill.svg b/web/vendor/bootstrap-icons/cloud-download-fill.svg new file mode 100644 index 0000000..c8a44ba --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-download-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-download.svg b/web/vendor/bootstrap-icons/cloud-download.svg new file mode 100644 index 0000000..b71d7d7 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-download.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-drizzle-fill.svg b/web/vendor/bootstrap-icons/cloud-drizzle-fill.svg new file mode 100644 index 0000000..0d381ae --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-drizzle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-drizzle.svg b/web/vendor/bootstrap-icons/cloud-drizzle.svg new file mode 100644 index 0000000..f3c8599 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-drizzle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-fill.svg b/web/vendor/bootstrap-icons/cloud-fill.svg new file mode 100644 index 0000000..8849faa --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-fog-fill.svg b/web/vendor/bootstrap-icons/cloud-fog-fill.svg new file mode 100644 index 0000000..214caba --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-fog-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-fog.svg b/web/vendor/bootstrap-icons/cloud-fog.svg new file mode 100644 index 0000000..26a574a --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-fog.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-fog2-fill.svg b/web/vendor/bootstrap-icons/cloud-fog2-fill.svg new file mode 100644 index 0000000..8f67dea --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-fog2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-fog2.svg b/web/vendor/bootstrap-icons/cloud-fog2.svg new file mode 100644 index 0000000..9b0664f --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-fog2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-hail-fill.svg b/web/vendor/bootstrap-icons/cloud-hail-fill.svg new file mode 100644 index 0000000..0fa737f --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-hail-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-hail.svg b/web/vendor/bootstrap-icons/cloud-hail.svg new file mode 100644 index 0000000..3206a02 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-hail.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-haze-fill.svg b/web/vendor/bootstrap-icons/cloud-haze-fill.svg new file mode 100644 index 0000000..aa16c2c --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-haze-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-haze.svg b/web/vendor/bootstrap-icons/cloud-haze.svg new file mode 100644 index 0000000..578a565 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-haze.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-haze2-fill.svg b/web/vendor/bootstrap-icons/cloud-haze2-fill.svg new file mode 100644 index 0000000..3e22656 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-haze2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-haze2.svg b/web/vendor/bootstrap-icons/cloud-haze2.svg new file mode 100644 index 0000000..c43d91c --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-haze2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-lightning-fill.svg b/web/vendor/bootstrap-icons/cloud-lightning-fill.svg new file mode 100644 index 0000000..88fd930 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-lightning-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-lightning-rain-fill.svg b/web/vendor/bootstrap-icons/cloud-lightning-rain-fill.svg new file mode 100644 index 0000000..f5cd845 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-lightning-rain-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-lightning-rain.svg b/web/vendor/bootstrap-icons/cloud-lightning-rain.svg new file mode 100644 index 0000000..588b274 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-lightning-rain.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-lightning.svg b/web/vendor/bootstrap-icons/cloud-lightning.svg new file mode 100644 index 0000000..20c2680 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-lightning.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-minus-fill.svg b/web/vendor/bootstrap-icons/cloud-minus-fill.svg new file mode 100644 index 0000000..2fcc2bb --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-minus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-minus.svg b/web/vendor/bootstrap-icons/cloud-minus.svg new file mode 100644 index 0000000..54f47b2 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-minus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-moon-fill.svg b/web/vendor/bootstrap-icons/cloud-moon-fill.svg new file mode 100644 index 0000000..232dd4e --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-moon-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-moon.svg b/web/vendor/bootstrap-icons/cloud-moon.svg new file mode 100644 index 0000000..cc91617 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-moon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-plus-fill.svg b/web/vendor/bootstrap-icons/cloud-plus-fill.svg new file mode 100644 index 0000000..5337dc4 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-plus.svg b/web/vendor/bootstrap-icons/cloud-plus.svg new file mode 100644 index 0000000..9448796 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-rain-fill.svg b/web/vendor/bootstrap-icons/cloud-rain-fill.svg new file mode 100644 index 0000000..3ffee56 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-rain-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-rain-heavy-fill.svg b/web/vendor/bootstrap-icons/cloud-rain-heavy-fill.svg new file mode 100644 index 0000000..d92411b --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-rain-heavy-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-rain-heavy.svg b/web/vendor/bootstrap-icons/cloud-rain-heavy.svg new file mode 100644 index 0000000..ee9ef85 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-rain-heavy.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-rain.svg b/web/vendor/bootstrap-icons/cloud-rain.svg new file mode 100644 index 0000000..e22f16c --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-rain.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-slash-fill.svg b/web/vendor/bootstrap-icons/cloud-slash-fill.svg new file mode 100644 index 0000000..08a709b --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-slash-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-slash.svg b/web/vendor/bootstrap-icons/cloud-slash.svg new file mode 100644 index 0000000..d7b680c --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-slash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-sleet-fill.svg b/web/vendor/bootstrap-icons/cloud-sleet-fill.svg new file mode 100644 index 0000000..1df3f33 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-sleet-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-sleet.svg b/web/vendor/bootstrap-icons/cloud-sleet.svg new file mode 100644 index 0000000..edc48c6 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-sleet.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-snow-fill.svg b/web/vendor/bootstrap-icons/cloud-snow-fill.svg new file mode 100644 index 0000000..32cda8d --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-snow-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-snow.svg b/web/vendor/bootstrap-icons/cloud-snow.svg new file mode 100644 index 0000000..26150c4 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-snow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-sun-fill.svg b/web/vendor/bootstrap-icons/cloud-sun-fill.svg new file mode 100644 index 0000000..da5ecac --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-sun-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-sun.svg b/web/vendor/bootstrap-icons/cloud-sun.svg new file mode 100644 index 0000000..caa95e9 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-sun.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-upload-fill.svg b/web/vendor/bootstrap-icons/cloud-upload-fill.svg new file mode 100644 index 0000000..2d0df59 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-upload-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud-upload.svg b/web/vendor/bootstrap-icons/cloud-upload.svg new file mode 100644 index 0000000..e5ca56e --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud-upload.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloud.svg b/web/vendor/bootstrap-icons/cloud.svg new file mode 100644 index 0000000..de877ab --- /dev/null +++ b/web/vendor/bootstrap-icons/cloud.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clouds-fill.svg b/web/vendor/bootstrap-icons/clouds-fill.svg new file mode 100644 index 0000000..d70e817 --- /dev/null +++ b/web/vendor/bootstrap-icons/clouds-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/clouds.svg b/web/vendor/bootstrap-icons/clouds.svg new file mode 100644 index 0000000..7e253e7 --- /dev/null +++ b/web/vendor/bootstrap-icons/clouds.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloudy-fill.svg b/web/vendor/bootstrap-icons/cloudy-fill.svg new file mode 100644 index 0000000..7bf27b7 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloudy-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cloudy.svg b/web/vendor/bootstrap-icons/cloudy.svg new file mode 100644 index 0000000..87c2017 --- /dev/null +++ b/web/vendor/bootstrap-icons/cloudy.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/code-slash.svg b/web/vendor/bootstrap-icons/code-slash.svg new file mode 100644 index 0000000..51a5c57 --- /dev/null +++ b/web/vendor/bootstrap-icons/code-slash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/code-square.svg b/web/vendor/bootstrap-icons/code-square.svg new file mode 100644 index 0000000..30fdef3 --- /dev/null +++ b/web/vendor/bootstrap-icons/code-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/code.svg b/web/vendor/bootstrap-icons/code.svg new file mode 100644 index 0000000..c0760e9 --- /dev/null +++ b/web/vendor/bootstrap-icons/code.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/coin.svg b/web/vendor/bootstrap-icons/coin.svg new file mode 100644 index 0000000..fb94cc5 --- /dev/null +++ b/web/vendor/bootstrap-icons/coin.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/collection-fill.svg b/web/vendor/bootstrap-icons/collection-fill.svg new file mode 100644 index 0000000..4e5fbce --- /dev/null +++ b/web/vendor/bootstrap-icons/collection-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/collection-play-fill.svg b/web/vendor/bootstrap-icons/collection-play-fill.svg new file mode 100644 index 0000000..b6820d0 --- /dev/null +++ b/web/vendor/bootstrap-icons/collection-play-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/collection-play.svg b/web/vendor/bootstrap-icons/collection-play.svg new file mode 100644 index 0000000..0c59f5d --- /dev/null +++ b/web/vendor/bootstrap-icons/collection-play.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/collection.svg b/web/vendor/bootstrap-icons/collection.svg new file mode 100644 index 0000000..8b5d5fd --- /dev/null +++ b/web/vendor/bootstrap-icons/collection.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/columns-gap.svg b/web/vendor/bootstrap-icons/columns-gap.svg new file mode 100644 index 0000000..8b4bb4e --- /dev/null +++ b/web/vendor/bootstrap-icons/columns-gap.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/columns.svg b/web/vendor/bootstrap-icons/columns.svg new file mode 100644 index 0000000..17632df --- /dev/null +++ b/web/vendor/bootstrap-icons/columns.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/command.svg b/web/vendor/bootstrap-icons/command.svg new file mode 100644 index 0000000..64fa00b --- /dev/null +++ b/web/vendor/bootstrap-icons/command.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/compass-fill.svg b/web/vendor/bootstrap-icons/compass-fill.svg new file mode 100644 index 0000000..1396c1f --- /dev/null +++ b/web/vendor/bootstrap-icons/compass-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/compass.svg b/web/vendor/bootstrap-icons/compass.svg new file mode 100644 index 0000000..9b402f3 --- /dev/null +++ b/web/vendor/bootstrap-icons/compass.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cone-striped.svg b/web/vendor/bootstrap-icons/cone-striped.svg new file mode 100644 index 0000000..28a9529 --- /dev/null +++ b/web/vendor/bootstrap-icons/cone-striped.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cone.svg b/web/vendor/bootstrap-icons/cone.svg new file mode 100644 index 0000000..b1a7d97 --- /dev/null +++ b/web/vendor/bootstrap-icons/cone.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/controller.svg b/web/vendor/bootstrap-icons/controller.svg new file mode 100644 index 0000000..b7ceedb --- /dev/null +++ b/web/vendor/bootstrap-icons/controller.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cookie.svg b/web/vendor/bootstrap-icons/cookie.svg new file mode 100644 index 0000000..7a4b2fa --- /dev/null +++ b/web/vendor/bootstrap-icons/cookie.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/copy.svg b/web/vendor/bootstrap-icons/copy.svg new file mode 100644 index 0000000..b590680 --- /dev/null +++ b/web/vendor/bootstrap-icons/copy.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cpu-fill.svg b/web/vendor/bootstrap-icons/cpu-fill.svg new file mode 100644 index 0000000..ce6e294 --- /dev/null +++ b/web/vendor/bootstrap-icons/cpu-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cpu.svg b/web/vendor/bootstrap-icons/cpu.svg new file mode 100644 index 0000000..88c0d56 --- /dev/null +++ b/web/vendor/bootstrap-icons/cpu.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/credit-card-2-back-fill.svg b/web/vendor/bootstrap-icons/credit-card-2-back-fill.svg new file mode 100644 index 0000000..032fb4a --- /dev/null +++ b/web/vendor/bootstrap-icons/credit-card-2-back-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/credit-card-2-back.svg b/web/vendor/bootstrap-icons/credit-card-2-back.svg new file mode 100644 index 0000000..b29419c --- /dev/null +++ b/web/vendor/bootstrap-icons/credit-card-2-back.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/credit-card-2-front-fill.svg b/web/vendor/bootstrap-icons/credit-card-2-front-fill.svg new file mode 100644 index 0000000..06684d5 --- /dev/null +++ b/web/vendor/bootstrap-icons/credit-card-2-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/credit-card-2-front.svg b/web/vendor/bootstrap-icons/credit-card-2-front.svg new file mode 100644 index 0000000..0bbc290 --- /dev/null +++ b/web/vendor/bootstrap-icons/credit-card-2-front.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/credit-card-fill.svg b/web/vendor/bootstrap-icons/credit-card-fill.svg new file mode 100644 index 0000000..a4f899a --- /dev/null +++ b/web/vendor/bootstrap-icons/credit-card-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/credit-card.svg b/web/vendor/bootstrap-icons/credit-card.svg new file mode 100644 index 0000000..406233d --- /dev/null +++ b/web/vendor/bootstrap-icons/credit-card.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/crop.svg b/web/vendor/bootstrap-icons/crop.svg new file mode 100644 index 0000000..3b4bb60 --- /dev/null +++ b/web/vendor/bootstrap-icons/crop.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/crosshair.svg b/web/vendor/bootstrap-icons/crosshair.svg new file mode 100644 index 0000000..13bed74 --- /dev/null +++ b/web/vendor/bootstrap-icons/crosshair.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/crosshair2.svg b/web/vendor/bootstrap-icons/crosshair2.svg new file mode 100644 index 0000000..3c28586 --- /dev/null +++ b/web/vendor/bootstrap-icons/crosshair2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/css.svg b/web/vendor/bootstrap-icons/css.svg new file mode 100644 index 0000000..e336af1 --- /dev/null +++ b/web/vendor/bootstrap-icons/css.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cup-fill.svg b/web/vendor/bootstrap-icons/cup-fill.svg new file mode 100644 index 0000000..7173787 --- /dev/null +++ b/web/vendor/bootstrap-icons/cup-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cup-hot-fill.svg b/web/vendor/bootstrap-icons/cup-hot-fill.svg new file mode 100644 index 0000000..9d7c465 --- /dev/null +++ b/web/vendor/bootstrap-icons/cup-hot-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cup-hot.svg b/web/vendor/bootstrap-icons/cup-hot.svg new file mode 100644 index 0000000..a6f7e89 --- /dev/null +++ b/web/vendor/bootstrap-icons/cup-hot.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cup-straw.svg b/web/vendor/bootstrap-icons/cup-straw.svg new file mode 100644 index 0000000..9388da9 --- /dev/null +++ b/web/vendor/bootstrap-icons/cup-straw.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cup.svg b/web/vendor/bootstrap-icons/cup.svg new file mode 100644 index 0000000..2694ac8 --- /dev/null +++ b/web/vendor/bootstrap-icons/cup.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/currency-bitcoin.svg b/web/vendor/bootstrap-icons/currency-bitcoin.svg new file mode 100644 index 0000000..0477ff8 --- /dev/null +++ b/web/vendor/bootstrap-icons/currency-bitcoin.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/currency-dollar.svg b/web/vendor/bootstrap-icons/currency-dollar.svg new file mode 100644 index 0000000..7ead9a7 --- /dev/null +++ b/web/vendor/bootstrap-icons/currency-dollar.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/currency-euro.svg b/web/vendor/bootstrap-icons/currency-euro.svg new file mode 100644 index 0000000..90c83d5 --- /dev/null +++ b/web/vendor/bootstrap-icons/currency-euro.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/currency-exchange.svg b/web/vendor/bootstrap-icons/currency-exchange.svg new file mode 100644 index 0000000..e332aa7 --- /dev/null +++ b/web/vendor/bootstrap-icons/currency-exchange.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/currency-pound.svg b/web/vendor/bootstrap-icons/currency-pound.svg new file mode 100644 index 0000000..4650876 --- /dev/null +++ b/web/vendor/bootstrap-icons/currency-pound.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/currency-rupee.svg b/web/vendor/bootstrap-icons/currency-rupee.svg new file mode 100644 index 0000000..4fdf9a2 --- /dev/null +++ b/web/vendor/bootstrap-icons/currency-rupee.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/currency-yen.svg b/web/vendor/bootstrap-icons/currency-yen.svg new file mode 100644 index 0000000..5bbf1a2 --- /dev/null +++ b/web/vendor/bootstrap-icons/currency-yen.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cursor-fill.svg b/web/vendor/bootstrap-icons/cursor-fill.svg new file mode 100644 index 0000000..093372b --- /dev/null +++ b/web/vendor/bootstrap-icons/cursor-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cursor-text.svg b/web/vendor/bootstrap-icons/cursor-text.svg new file mode 100644 index 0000000..27c057b --- /dev/null +++ b/web/vendor/bootstrap-icons/cursor-text.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/cursor.svg b/web/vendor/bootstrap-icons/cursor.svg new file mode 100644 index 0000000..e23e3fd --- /dev/null +++ b/web/vendor/bootstrap-icons/cursor.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dash-circle-dotted.svg b/web/vendor/bootstrap-icons/dash-circle-dotted.svg new file mode 100644 index 0000000..1c011e2 --- /dev/null +++ b/web/vendor/bootstrap-icons/dash-circle-dotted.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dash-circle-fill.svg b/web/vendor/bootstrap-icons/dash-circle-fill.svg new file mode 100644 index 0000000..ac4eae0 --- /dev/null +++ b/web/vendor/bootstrap-icons/dash-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dash-circle.svg b/web/vendor/bootstrap-icons/dash-circle.svg new file mode 100644 index 0000000..c4abdd2 --- /dev/null +++ b/web/vendor/bootstrap-icons/dash-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dash-lg.svg b/web/vendor/bootstrap-icons/dash-lg.svg new file mode 100644 index 0000000..454aa7d --- /dev/null +++ b/web/vendor/bootstrap-icons/dash-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dash-square-dotted.svg b/web/vendor/bootstrap-icons/dash-square-dotted.svg new file mode 100644 index 0000000..90886c3 --- /dev/null +++ b/web/vendor/bootstrap-icons/dash-square-dotted.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dash-square-fill.svg b/web/vendor/bootstrap-icons/dash-square-fill.svg new file mode 100644 index 0000000..dbe0db2 --- /dev/null +++ b/web/vendor/bootstrap-icons/dash-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dash-square.svg b/web/vendor/bootstrap-icons/dash-square.svg new file mode 100644 index 0000000..9381872 --- /dev/null +++ b/web/vendor/bootstrap-icons/dash-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dash.svg b/web/vendor/bootstrap-icons/dash.svg new file mode 100644 index 0000000..c3834b4 --- /dev/null +++ b/web/vendor/bootstrap-icons/dash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-add.svg b/web/vendor/bootstrap-icons/database-add.svg new file mode 100644 index 0000000..5f76340 --- /dev/null +++ b/web/vendor/bootstrap-icons/database-add.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-check.svg b/web/vendor/bootstrap-icons/database-check.svg new file mode 100644 index 0000000..29c02b8 --- /dev/null +++ b/web/vendor/bootstrap-icons/database-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-dash.svg b/web/vendor/bootstrap-icons/database-dash.svg new file mode 100644 index 0000000..184db0a --- /dev/null +++ b/web/vendor/bootstrap-icons/database-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-down.svg b/web/vendor/bootstrap-icons/database-down.svg new file mode 100644 index 0000000..e077452 --- /dev/null +++ b/web/vendor/bootstrap-icons/database-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-exclamation.svg b/web/vendor/bootstrap-icons/database-exclamation.svg new file mode 100644 index 0000000..dbde50f --- /dev/null +++ b/web/vendor/bootstrap-icons/database-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-fill-add.svg b/web/vendor/bootstrap-icons/database-fill-add.svg new file mode 100644 index 0000000..4273d5d --- /dev/null +++ b/web/vendor/bootstrap-icons/database-fill-add.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-fill-check.svg b/web/vendor/bootstrap-icons/database-fill-check.svg new file mode 100644 index 0000000..7690eed --- /dev/null +++ b/web/vendor/bootstrap-icons/database-fill-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-fill-dash.svg b/web/vendor/bootstrap-icons/database-fill-dash.svg new file mode 100644 index 0000000..48c468d --- /dev/null +++ b/web/vendor/bootstrap-icons/database-fill-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-fill-down.svg b/web/vendor/bootstrap-icons/database-fill-down.svg new file mode 100644 index 0000000..c3560d8 --- /dev/null +++ b/web/vendor/bootstrap-icons/database-fill-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-fill-exclamation.svg b/web/vendor/bootstrap-icons/database-fill-exclamation.svg new file mode 100644 index 0000000..00073d0 --- /dev/null +++ b/web/vendor/bootstrap-icons/database-fill-exclamation.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-fill-gear.svg b/web/vendor/bootstrap-icons/database-fill-gear.svg new file mode 100644 index 0000000..94fc2e6 --- /dev/null +++ b/web/vendor/bootstrap-icons/database-fill-gear.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-fill-lock.svg b/web/vendor/bootstrap-icons/database-fill-lock.svg new file mode 100644 index 0000000..a948205 --- /dev/null +++ b/web/vendor/bootstrap-icons/database-fill-lock.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-fill-slash.svg b/web/vendor/bootstrap-icons/database-fill-slash.svg new file mode 100644 index 0000000..467e6bb --- /dev/null +++ b/web/vendor/bootstrap-icons/database-fill-slash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-fill-up.svg b/web/vendor/bootstrap-icons/database-fill-up.svg new file mode 100644 index 0000000..07f2d39 --- /dev/null +++ b/web/vendor/bootstrap-icons/database-fill-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-fill-x.svg b/web/vendor/bootstrap-icons/database-fill-x.svg new file mode 100644 index 0000000..73ff269 --- /dev/null +++ b/web/vendor/bootstrap-icons/database-fill-x.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-fill.svg b/web/vendor/bootstrap-icons/database-fill.svg new file mode 100644 index 0000000..8603874 --- /dev/null +++ b/web/vendor/bootstrap-icons/database-fill.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-gear.svg b/web/vendor/bootstrap-icons/database-gear.svg new file mode 100644 index 0000000..451763c --- /dev/null +++ b/web/vendor/bootstrap-icons/database-gear.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-lock.svg b/web/vendor/bootstrap-icons/database-lock.svg new file mode 100644 index 0000000..e150cd2 --- /dev/null +++ b/web/vendor/bootstrap-icons/database-lock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-slash.svg b/web/vendor/bootstrap-icons/database-slash.svg new file mode 100644 index 0000000..e0cc9f2 --- /dev/null +++ b/web/vendor/bootstrap-icons/database-slash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-up.svg b/web/vendor/bootstrap-icons/database-up.svg new file mode 100644 index 0000000..63f7a10 --- /dev/null +++ b/web/vendor/bootstrap-icons/database-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database-x.svg b/web/vendor/bootstrap-icons/database-x.svg new file mode 100644 index 0000000..f97779b --- /dev/null +++ b/web/vendor/bootstrap-icons/database-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/database.svg b/web/vendor/bootstrap-icons/database.svg new file mode 100644 index 0000000..231c50c --- /dev/null +++ b/web/vendor/bootstrap-icons/database.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/device-hdd-fill.svg b/web/vendor/bootstrap-icons/device-hdd-fill.svg new file mode 100644 index 0000000..d5380c0 --- /dev/null +++ b/web/vendor/bootstrap-icons/device-hdd-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/device-hdd.svg b/web/vendor/bootstrap-icons/device-hdd.svg new file mode 100644 index 0000000..5163a58 --- /dev/null +++ b/web/vendor/bootstrap-icons/device-hdd.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/device-ssd-fill.svg b/web/vendor/bootstrap-icons/device-ssd-fill.svg new file mode 100644 index 0000000..0d1f9c3 --- /dev/null +++ b/web/vendor/bootstrap-icons/device-ssd-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/device-ssd.svg b/web/vendor/bootstrap-icons/device-ssd.svg new file mode 100644 index 0000000..8405f21 --- /dev/null +++ b/web/vendor/bootstrap-icons/device-ssd.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/diagram-2-fill.svg b/web/vendor/bootstrap-icons/diagram-2-fill.svg new file mode 100644 index 0000000..397ae15 --- /dev/null +++ b/web/vendor/bootstrap-icons/diagram-2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/diagram-2.svg b/web/vendor/bootstrap-icons/diagram-2.svg new file mode 100644 index 0000000..a6e5439 --- /dev/null +++ b/web/vendor/bootstrap-icons/diagram-2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/diagram-3-fill.svg b/web/vendor/bootstrap-icons/diagram-3-fill.svg new file mode 100644 index 0000000..7e47423 --- /dev/null +++ b/web/vendor/bootstrap-icons/diagram-3-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/diagram-3.svg b/web/vendor/bootstrap-icons/diagram-3.svg new file mode 100644 index 0000000..ee3fd6f --- /dev/null +++ b/web/vendor/bootstrap-icons/diagram-3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/diamond-fill.svg b/web/vendor/bootstrap-icons/diamond-fill.svg new file mode 100644 index 0000000..1f86d1f --- /dev/null +++ b/web/vendor/bootstrap-icons/diamond-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/diamond-half.svg b/web/vendor/bootstrap-icons/diamond-half.svg new file mode 100644 index 0000000..68254b6 --- /dev/null +++ b/web/vendor/bootstrap-icons/diamond-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/diamond.svg b/web/vendor/bootstrap-icons/diamond.svg new file mode 100644 index 0000000..44e2855 --- /dev/null +++ b/web/vendor/bootstrap-icons/diamond.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dice-1-fill.svg b/web/vendor/bootstrap-icons/dice-1-fill.svg new file mode 100644 index 0000000..a32e2cf --- /dev/null +++ b/web/vendor/bootstrap-icons/dice-1-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dice-1.svg b/web/vendor/bootstrap-icons/dice-1.svg new file mode 100644 index 0000000..afc64b0 --- /dev/null +++ b/web/vendor/bootstrap-icons/dice-1.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dice-2-fill.svg b/web/vendor/bootstrap-icons/dice-2-fill.svg new file mode 100644 index 0000000..131013e --- /dev/null +++ b/web/vendor/bootstrap-icons/dice-2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dice-2.svg b/web/vendor/bootstrap-icons/dice-2.svg new file mode 100644 index 0000000..ba1a79c --- /dev/null +++ b/web/vendor/bootstrap-icons/dice-2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dice-3-fill.svg b/web/vendor/bootstrap-icons/dice-3-fill.svg new file mode 100644 index 0000000..158065d --- /dev/null +++ b/web/vendor/bootstrap-icons/dice-3-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dice-3.svg b/web/vendor/bootstrap-icons/dice-3.svg new file mode 100644 index 0000000..b64c675 --- /dev/null +++ b/web/vendor/bootstrap-icons/dice-3.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dice-4-fill.svg b/web/vendor/bootstrap-icons/dice-4-fill.svg new file mode 100644 index 0000000..7cf6e2c --- /dev/null +++ b/web/vendor/bootstrap-icons/dice-4-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dice-4.svg b/web/vendor/bootstrap-icons/dice-4.svg new file mode 100644 index 0000000..bd8bbf7 --- /dev/null +++ b/web/vendor/bootstrap-icons/dice-4.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dice-5-fill.svg b/web/vendor/bootstrap-icons/dice-5-fill.svg new file mode 100644 index 0000000..289cb45 --- /dev/null +++ b/web/vendor/bootstrap-icons/dice-5-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dice-5.svg b/web/vendor/bootstrap-icons/dice-5.svg new file mode 100644 index 0000000..cc96a35 --- /dev/null +++ b/web/vendor/bootstrap-icons/dice-5.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dice-6-fill.svg b/web/vendor/bootstrap-icons/dice-6-fill.svg new file mode 100644 index 0000000..9b3d652 --- /dev/null +++ b/web/vendor/bootstrap-icons/dice-6-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dice-6.svg b/web/vendor/bootstrap-icons/dice-6.svg new file mode 100644 index 0000000..47ba0aa --- /dev/null +++ b/web/vendor/bootstrap-icons/dice-6.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/disc-fill.svg b/web/vendor/bootstrap-icons/disc-fill.svg new file mode 100644 index 0000000..0d2d7f1 --- /dev/null +++ b/web/vendor/bootstrap-icons/disc-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/disc.svg b/web/vendor/bootstrap-icons/disc.svg new file mode 100644 index 0000000..360034c --- /dev/null +++ b/web/vendor/bootstrap-icons/disc.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/discord.svg b/web/vendor/bootstrap-icons/discord.svg new file mode 100644 index 0000000..9905364 --- /dev/null +++ b/web/vendor/bootstrap-icons/discord.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/display-fill.svg b/web/vendor/bootstrap-icons/display-fill.svg new file mode 100644 index 0000000..ed8e17e --- /dev/null +++ b/web/vendor/bootstrap-icons/display-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/display.svg b/web/vendor/bootstrap-icons/display.svg new file mode 100644 index 0000000..40a7d4d --- /dev/null +++ b/web/vendor/bootstrap-icons/display.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/displayport-fill.svg b/web/vendor/bootstrap-icons/displayport-fill.svg new file mode 100644 index 0000000..503a960 --- /dev/null +++ b/web/vendor/bootstrap-icons/displayport-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/displayport.svg b/web/vendor/bootstrap-icons/displayport.svg new file mode 100644 index 0000000..6b9e0bf --- /dev/null +++ b/web/vendor/bootstrap-icons/displayport.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/distribute-horizontal.svg b/web/vendor/bootstrap-icons/distribute-horizontal.svg new file mode 100644 index 0000000..3f7044f --- /dev/null +++ b/web/vendor/bootstrap-icons/distribute-horizontal.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/distribute-vertical.svg b/web/vendor/bootstrap-icons/distribute-vertical.svg new file mode 100644 index 0000000..cb77d1e --- /dev/null +++ b/web/vendor/bootstrap-icons/distribute-vertical.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/door-closed-fill.svg b/web/vendor/bootstrap-icons/door-closed-fill.svg new file mode 100644 index 0000000..1cad66b --- /dev/null +++ b/web/vendor/bootstrap-icons/door-closed-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/door-closed.svg b/web/vendor/bootstrap-icons/door-closed.svg new file mode 100644 index 0000000..e20b918 --- /dev/null +++ b/web/vendor/bootstrap-icons/door-closed.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/door-open-fill.svg b/web/vendor/bootstrap-icons/door-open-fill.svg new file mode 100644 index 0000000..38eaff0 --- /dev/null +++ b/web/vendor/bootstrap-icons/door-open-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/door-open.svg b/web/vendor/bootstrap-icons/door-open.svg new file mode 100644 index 0000000..328f353 --- /dev/null +++ b/web/vendor/bootstrap-icons/door-open.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dot.svg b/web/vendor/bootstrap-icons/dot.svg new file mode 100644 index 0000000..edc674e --- /dev/null +++ b/web/vendor/bootstrap-icons/dot.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/download.svg b/web/vendor/bootstrap-icons/download.svg new file mode 100644 index 0000000..90a34a3 --- /dev/null +++ b/web/vendor/bootstrap-icons/download.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dpad-fill.svg b/web/vendor/bootstrap-icons/dpad-fill.svg new file mode 100644 index 0000000..1c1153a --- /dev/null +++ b/web/vendor/bootstrap-icons/dpad-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dpad.svg b/web/vendor/bootstrap-icons/dpad.svg new file mode 100644 index 0000000..71ddb24 --- /dev/null +++ b/web/vendor/bootstrap-icons/dpad.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dribbble.svg b/web/vendor/bootstrap-icons/dribbble.svg new file mode 100644 index 0000000..725ff7f --- /dev/null +++ b/web/vendor/bootstrap-icons/dribbble.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/dropbox.svg b/web/vendor/bootstrap-icons/dropbox.svg new file mode 100644 index 0000000..d052f25 --- /dev/null +++ b/web/vendor/bootstrap-icons/dropbox.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/droplet-fill.svg b/web/vendor/bootstrap-icons/droplet-fill.svg new file mode 100644 index 0000000..85feddf --- /dev/null +++ b/web/vendor/bootstrap-icons/droplet-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/droplet-half.svg b/web/vendor/bootstrap-icons/droplet-half.svg new file mode 100644 index 0000000..bcd1c76 --- /dev/null +++ b/web/vendor/bootstrap-icons/droplet-half.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/droplet.svg b/web/vendor/bootstrap-icons/droplet.svg new file mode 100644 index 0000000..204ec67 --- /dev/null +++ b/web/vendor/bootstrap-icons/droplet.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/duffle-fill.svg b/web/vendor/bootstrap-icons/duffle-fill.svg new file mode 100644 index 0000000..885ee80 --- /dev/null +++ b/web/vendor/bootstrap-icons/duffle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/duffle.svg b/web/vendor/bootstrap-icons/duffle.svg new file mode 100644 index 0000000..1180de8 --- /dev/null +++ b/web/vendor/bootstrap-icons/duffle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ear-fill.svg b/web/vendor/bootstrap-icons/ear-fill.svg new file mode 100644 index 0000000..2d135d6 --- /dev/null +++ b/web/vendor/bootstrap-icons/ear-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ear.svg b/web/vendor/bootstrap-icons/ear.svg new file mode 100644 index 0000000..061fe2f --- /dev/null +++ b/web/vendor/bootstrap-icons/ear.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/earbuds.svg b/web/vendor/bootstrap-icons/earbuds.svg new file mode 100644 index 0000000..923bfca --- /dev/null +++ b/web/vendor/bootstrap-icons/earbuds.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/easel-fill.svg b/web/vendor/bootstrap-icons/easel-fill.svg new file mode 100644 index 0000000..8086507 --- /dev/null +++ b/web/vendor/bootstrap-icons/easel-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/easel.svg b/web/vendor/bootstrap-icons/easel.svg new file mode 100644 index 0000000..5c0f5a2 --- /dev/null +++ b/web/vendor/bootstrap-icons/easel.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/easel2-fill.svg b/web/vendor/bootstrap-icons/easel2-fill.svg new file mode 100644 index 0000000..309b438 --- /dev/null +++ b/web/vendor/bootstrap-icons/easel2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/easel2.svg b/web/vendor/bootstrap-icons/easel2.svg new file mode 100644 index 0000000..74372fb --- /dev/null +++ b/web/vendor/bootstrap-icons/easel2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/easel3-fill.svg b/web/vendor/bootstrap-icons/easel3-fill.svg new file mode 100644 index 0000000..fc547ea --- /dev/null +++ b/web/vendor/bootstrap-icons/easel3-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/easel3.svg b/web/vendor/bootstrap-icons/easel3.svg new file mode 100644 index 0000000..f06a868 --- /dev/null +++ b/web/vendor/bootstrap-icons/easel3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/egg-fill.svg b/web/vendor/bootstrap-icons/egg-fill.svg new file mode 100644 index 0000000..b70cf16 --- /dev/null +++ b/web/vendor/bootstrap-icons/egg-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/egg-fried.svg b/web/vendor/bootstrap-icons/egg-fried.svg new file mode 100644 index 0000000..b0cefbc --- /dev/null +++ b/web/vendor/bootstrap-icons/egg-fried.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/egg.svg b/web/vendor/bootstrap-icons/egg.svg new file mode 100644 index 0000000..f23d8d4 --- /dev/null +++ b/web/vendor/bootstrap-icons/egg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/eject-fill.svg b/web/vendor/bootstrap-icons/eject-fill.svg new file mode 100644 index 0000000..9604988 --- /dev/null +++ b/web/vendor/bootstrap-icons/eject-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/eject.svg b/web/vendor/bootstrap-icons/eject.svg new file mode 100644 index 0000000..71a3ab6 --- /dev/null +++ b/web/vendor/bootstrap-icons/eject.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-angry-fill.svg b/web/vendor/bootstrap-icons/emoji-angry-fill.svg new file mode 100644 index 0000000..d14d92d --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-angry-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-angry.svg b/web/vendor/bootstrap-icons/emoji-angry.svg new file mode 100644 index 0000000..ee925fe --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-angry.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-astonished-fill.svg b/web/vendor/bootstrap-icons/emoji-astonished-fill.svg new file mode 100644 index 0000000..22a566f --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-astonished-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-astonished.svg b/web/vendor/bootstrap-icons/emoji-astonished.svg new file mode 100644 index 0000000..13f7cdd --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-astonished.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-dizzy-fill.svg b/web/vendor/bootstrap-icons/emoji-dizzy-fill.svg new file mode 100644 index 0000000..98ab490 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-dizzy-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-dizzy.svg b/web/vendor/bootstrap-icons/emoji-dizzy.svg new file mode 100644 index 0000000..fcef602 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-dizzy.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-expressionless-fill.svg b/web/vendor/bootstrap-icons/emoji-expressionless-fill.svg new file mode 100644 index 0000000..17ac348 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-expressionless-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-expressionless.svg b/web/vendor/bootstrap-icons/emoji-expressionless.svg new file mode 100644 index 0000000..8d7f68f --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-expressionless.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-frown-fill.svg b/web/vendor/bootstrap-icons/emoji-frown-fill.svg new file mode 100644 index 0000000..7a16dfb --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-frown-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-frown.svg b/web/vendor/bootstrap-icons/emoji-frown.svg new file mode 100644 index 0000000..696031b --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-frown.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-grimace-fill.svg b/web/vendor/bootstrap-icons/emoji-grimace-fill.svg new file mode 100644 index 0000000..6cabf80 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-grimace-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-grimace.svg b/web/vendor/bootstrap-icons/emoji-grimace.svg new file mode 100644 index 0000000..75a2a09 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-grimace.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-grin-fill.svg b/web/vendor/bootstrap-icons/emoji-grin-fill.svg new file mode 100644 index 0000000..08c675e --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-grin-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-grin.svg b/web/vendor/bootstrap-icons/emoji-grin.svg new file mode 100644 index 0000000..32bbf51 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-grin.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-heart-eyes-fill.svg b/web/vendor/bootstrap-icons/emoji-heart-eyes-fill.svg new file mode 100644 index 0000000..d34f6e8 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-heart-eyes-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-heart-eyes.svg b/web/vendor/bootstrap-icons/emoji-heart-eyes.svg new file mode 100644 index 0000000..5832822 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-heart-eyes.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-kiss-fill.svg b/web/vendor/bootstrap-icons/emoji-kiss-fill.svg new file mode 100644 index 0000000..15a9cdd --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-kiss-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-kiss.svg b/web/vendor/bootstrap-icons/emoji-kiss.svg new file mode 100644 index 0000000..2348d97 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-kiss.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-laughing-fill.svg b/web/vendor/bootstrap-icons/emoji-laughing-fill.svg new file mode 100644 index 0000000..0130bf4 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-laughing-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-laughing.svg b/web/vendor/bootstrap-icons/emoji-laughing.svg new file mode 100644 index 0000000..76b87f5 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-laughing.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-neutral-fill.svg b/web/vendor/bootstrap-icons/emoji-neutral-fill.svg new file mode 100644 index 0000000..662603a --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-neutral-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-neutral.svg b/web/vendor/bootstrap-icons/emoji-neutral.svg new file mode 100644 index 0000000..d6b60f8 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-neutral.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-smile-fill.svg b/web/vendor/bootstrap-icons/emoji-smile-fill.svg new file mode 100644 index 0000000..439dff0 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-smile-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-smile-upside-down-fill.svg b/web/vendor/bootstrap-icons/emoji-smile-upside-down-fill.svg new file mode 100644 index 0000000..2d6acca --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-smile-upside-down-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-smile-upside-down.svg b/web/vendor/bootstrap-icons/emoji-smile-upside-down.svg new file mode 100644 index 0000000..d2d93ed --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-smile-upside-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-smile.svg b/web/vendor/bootstrap-icons/emoji-smile.svg new file mode 100644 index 0000000..bba78da --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-smile.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-sunglasses-fill.svg b/web/vendor/bootstrap-icons/emoji-sunglasses-fill.svg new file mode 100644 index 0000000..a1318c2 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-sunglasses-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-sunglasses.svg b/web/vendor/bootstrap-icons/emoji-sunglasses.svg new file mode 100644 index 0000000..188b56c --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-sunglasses.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-surprise-fill.svg b/web/vendor/bootstrap-icons/emoji-surprise-fill.svg new file mode 100644 index 0000000..9f6f620 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-surprise-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-surprise.svg b/web/vendor/bootstrap-icons/emoji-surprise.svg new file mode 100644 index 0000000..af246bf --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-surprise.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-tear-fill.svg b/web/vendor/bootstrap-icons/emoji-tear-fill.svg new file mode 100644 index 0000000..3ccf87d --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-tear-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-tear.svg b/web/vendor/bootstrap-icons/emoji-tear.svg new file mode 100644 index 0000000..31b6597 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-tear.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-wink-fill.svg b/web/vendor/bootstrap-icons/emoji-wink-fill.svg new file mode 100644 index 0000000..2f3e480 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-wink-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/emoji-wink.svg b/web/vendor/bootstrap-icons/emoji-wink.svg new file mode 100644 index 0000000..7fe9116 --- /dev/null +++ b/web/vendor/bootstrap-icons/emoji-wink.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-arrow-down-fill.svg b/web/vendor/bootstrap-icons/envelope-arrow-down-fill.svg new file mode 100644 index 0000000..a5160e7 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-arrow-down-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-arrow-down.svg b/web/vendor/bootstrap-icons/envelope-arrow-down.svg new file mode 100644 index 0000000..36b6f54 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-arrow-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-arrow-up-fill.svg b/web/vendor/bootstrap-icons/envelope-arrow-up-fill.svg new file mode 100644 index 0000000..2757974 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-arrow-up-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-arrow-up.svg b/web/vendor/bootstrap-icons/envelope-arrow-up.svg new file mode 100644 index 0000000..ff2fae0 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-arrow-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-at-fill.svg b/web/vendor/bootstrap-icons/envelope-at-fill.svg new file mode 100644 index 0000000..e39ff38 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-at-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-at.svg b/web/vendor/bootstrap-icons/envelope-at.svg new file mode 100644 index 0000000..163c3ba --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-at.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-check-fill.svg b/web/vendor/bootstrap-icons/envelope-check-fill.svg new file mode 100644 index 0000000..26d753a --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-check-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-check.svg b/web/vendor/bootstrap-icons/envelope-check.svg new file mode 100644 index 0000000..fbc765b --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-dash-fill.svg b/web/vendor/bootstrap-icons/envelope-dash-fill.svg new file mode 100644 index 0000000..6e9e745 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-dash-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-dash.svg b/web/vendor/bootstrap-icons/envelope-dash.svg new file mode 100644 index 0000000..d6457cf --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-exclamation-fill.svg b/web/vendor/bootstrap-icons/envelope-exclamation-fill.svg new file mode 100644 index 0000000..e14f047 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-exclamation-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-exclamation.svg b/web/vendor/bootstrap-icons/envelope-exclamation.svg new file mode 100644 index 0000000..4aca0a9 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-fill.svg b/web/vendor/bootstrap-icons/envelope-fill.svg new file mode 100644 index 0000000..966ef94 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-heart-fill.svg b/web/vendor/bootstrap-icons/envelope-heart-fill.svg new file mode 100644 index 0000000..4158841 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-heart-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-heart.svg b/web/vendor/bootstrap-icons/envelope-heart.svg new file mode 100644 index 0000000..c886df2 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-open-fill.svg b/web/vendor/bootstrap-icons/envelope-open-fill.svg new file mode 100644 index 0000000..972d0e3 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-open-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-open-heart-fill.svg b/web/vendor/bootstrap-icons/envelope-open-heart-fill.svg new file mode 100644 index 0000000..13263fa --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-open-heart-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-open-heart.svg b/web/vendor/bootstrap-icons/envelope-open-heart.svg new file mode 100644 index 0000000..7018116 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-open-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-open.svg b/web/vendor/bootstrap-icons/envelope-open.svg new file mode 100644 index 0000000..3daa2eb --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-open.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-paper-fill.svg b/web/vendor/bootstrap-icons/envelope-paper-fill.svg new file mode 100644 index 0000000..c8a187c --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-paper-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-paper-heart-fill.svg b/web/vendor/bootstrap-icons/envelope-paper-heart-fill.svg new file mode 100644 index 0000000..7f58d57 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-paper-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-paper-heart.svg b/web/vendor/bootstrap-icons/envelope-paper-heart.svg new file mode 100644 index 0000000..73b91d9 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-paper-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-paper.svg b/web/vendor/bootstrap-icons/envelope-paper.svg new file mode 100644 index 0000000..20fcc2a --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-paper.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-plus-fill.svg b/web/vendor/bootstrap-icons/envelope-plus-fill.svg new file mode 100644 index 0000000..453a9fd --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-plus-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-plus.svg b/web/vendor/bootstrap-icons/envelope-plus.svg new file mode 100644 index 0000000..7e960a0 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-slash-fill.svg b/web/vendor/bootstrap-icons/envelope-slash-fill.svg new file mode 100644 index 0000000..90eb7ef --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-slash-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-slash.svg b/web/vendor/bootstrap-icons/envelope-slash.svg new file mode 100644 index 0000000..65cb167 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-slash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-x-fill.svg b/web/vendor/bootstrap-icons/envelope-x-fill.svg new file mode 100644 index 0000000..8f6a79c --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-x-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope-x.svg b/web/vendor/bootstrap-icons/envelope-x.svg new file mode 100644 index 0000000..ea74027 --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/envelope.svg b/web/vendor/bootstrap-icons/envelope.svg new file mode 100644 index 0000000..78bf1de --- /dev/null +++ b/web/vendor/bootstrap-icons/envelope.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/eraser-fill.svg b/web/vendor/bootstrap-icons/eraser-fill.svg new file mode 100644 index 0000000..c3866e1 --- /dev/null +++ b/web/vendor/bootstrap-icons/eraser-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/eraser.svg b/web/vendor/bootstrap-icons/eraser.svg new file mode 100644 index 0000000..fe62336 --- /dev/null +++ b/web/vendor/bootstrap-icons/eraser.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/escape.svg b/web/vendor/bootstrap-icons/escape.svg new file mode 100644 index 0000000..66176b6 --- /dev/null +++ b/web/vendor/bootstrap-icons/escape.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ethernet.svg b/web/vendor/bootstrap-icons/ethernet.svg new file mode 100644 index 0000000..739a2de --- /dev/null +++ b/web/vendor/bootstrap-icons/ethernet.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ev-front-fill.svg b/web/vendor/bootstrap-icons/ev-front-fill.svg new file mode 100644 index 0000000..53b947d --- /dev/null +++ b/web/vendor/bootstrap-icons/ev-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ev-front.svg b/web/vendor/bootstrap-icons/ev-front.svg new file mode 100644 index 0000000..7f053a5 --- /dev/null +++ b/web/vendor/bootstrap-icons/ev-front.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ev-station-fill.svg b/web/vendor/bootstrap-icons/ev-station-fill.svg new file mode 100644 index 0000000..a1ad007 --- /dev/null +++ b/web/vendor/bootstrap-icons/ev-station-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ev-station.svg b/web/vendor/bootstrap-icons/ev-station.svg new file mode 100644 index 0000000..90470f6 --- /dev/null +++ b/web/vendor/bootstrap-icons/ev-station.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/exclamation-circle-fill.svg b/web/vendor/bootstrap-icons/exclamation-circle-fill.svg new file mode 100644 index 0000000..13ce7ab --- /dev/null +++ b/web/vendor/bootstrap-icons/exclamation-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/exclamation-circle.svg b/web/vendor/bootstrap-icons/exclamation-circle.svg new file mode 100644 index 0000000..f3befe0 --- /dev/null +++ b/web/vendor/bootstrap-icons/exclamation-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/exclamation-diamond-fill.svg b/web/vendor/bootstrap-icons/exclamation-diamond-fill.svg new file mode 100644 index 0000000..cb14aee --- /dev/null +++ b/web/vendor/bootstrap-icons/exclamation-diamond-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/exclamation-diamond.svg b/web/vendor/bootstrap-icons/exclamation-diamond.svg new file mode 100644 index 0000000..4881e6d --- /dev/null +++ b/web/vendor/bootstrap-icons/exclamation-diamond.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/exclamation-lg.svg b/web/vendor/bootstrap-icons/exclamation-lg.svg new file mode 100644 index 0000000..18f6a87 --- /dev/null +++ b/web/vendor/bootstrap-icons/exclamation-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/exclamation-octagon-fill.svg b/web/vendor/bootstrap-icons/exclamation-octagon-fill.svg new file mode 100644 index 0000000..494010b --- /dev/null +++ b/web/vendor/bootstrap-icons/exclamation-octagon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/exclamation-octagon.svg b/web/vendor/bootstrap-icons/exclamation-octagon.svg new file mode 100644 index 0000000..7f25938 --- /dev/null +++ b/web/vendor/bootstrap-icons/exclamation-octagon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/exclamation-square-fill.svg b/web/vendor/bootstrap-icons/exclamation-square-fill.svg new file mode 100644 index 0000000..d80a4e9 --- /dev/null +++ b/web/vendor/bootstrap-icons/exclamation-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/exclamation-square.svg b/web/vendor/bootstrap-icons/exclamation-square.svg new file mode 100644 index 0000000..2a0f2ae --- /dev/null +++ b/web/vendor/bootstrap-icons/exclamation-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/exclamation-triangle-fill.svg b/web/vendor/bootstrap-icons/exclamation-triangle-fill.svg new file mode 100644 index 0000000..52fd508 --- /dev/null +++ b/web/vendor/bootstrap-icons/exclamation-triangle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/exclamation-triangle.svg b/web/vendor/bootstrap-icons/exclamation-triangle.svg new file mode 100644 index 0000000..506b777 --- /dev/null +++ b/web/vendor/bootstrap-icons/exclamation-triangle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/exclamation.svg b/web/vendor/bootstrap-icons/exclamation.svg new file mode 100644 index 0000000..d39cb95 --- /dev/null +++ b/web/vendor/bootstrap-icons/exclamation.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/exclude.svg b/web/vendor/bootstrap-icons/exclude.svg new file mode 100644 index 0000000..ef18355 --- /dev/null +++ b/web/vendor/bootstrap-icons/exclude.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/explicit-fill.svg b/web/vendor/bootstrap-icons/explicit-fill.svg new file mode 100644 index 0000000..c0cb6f0 --- /dev/null +++ b/web/vendor/bootstrap-icons/explicit-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/explicit.svg b/web/vendor/bootstrap-icons/explicit.svg new file mode 100644 index 0000000..a7ffae7 --- /dev/null +++ b/web/vendor/bootstrap-icons/explicit.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/exposure.svg b/web/vendor/bootstrap-icons/exposure.svg new file mode 100644 index 0000000..9de0e64 --- /dev/null +++ b/web/vendor/bootstrap-icons/exposure.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/eye-fill.svg b/web/vendor/bootstrap-icons/eye-fill.svg new file mode 100644 index 0000000..288d2eb --- /dev/null +++ b/web/vendor/bootstrap-icons/eye-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/eye-slash-fill.svg b/web/vendor/bootstrap-icons/eye-slash-fill.svg new file mode 100644 index 0000000..10cca74 --- /dev/null +++ b/web/vendor/bootstrap-icons/eye-slash-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/eye-slash.svg b/web/vendor/bootstrap-icons/eye-slash.svg new file mode 100644 index 0000000..359c270 --- /dev/null +++ b/web/vendor/bootstrap-icons/eye-slash.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/eye.svg b/web/vendor/bootstrap-icons/eye.svg new file mode 100644 index 0000000..393b485 --- /dev/null +++ b/web/vendor/bootstrap-icons/eye.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/eyedropper.svg b/web/vendor/bootstrap-icons/eyedropper.svg new file mode 100644 index 0000000..4579888 --- /dev/null +++ b/web/vendor/bootstrap-icons/eyedropper.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/eyeglasses.svg b/web/vendor/bootstrap-icons/eyeglasses.svg new file mode 100644 index 0000000..6b2eb97 --- /dev/null +++ b/web/vendor/bootstrap-icons/eyeglasses.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/facebook.svg b/web/vendor/bootstrap-icons/facebook.svg new file mode 100644 index 0000000..5fc7cec --- /dev/null +++ b/web/vendor/bootstrap-icons/facebook.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/fan.svg b/web/vendor/bootstrap-icons/fan.svg new file mode 100644 index 0000000..ec8fe20 --- /dev/null +++ b/web/vendor/bootstrap-icons/fan.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/fast-forward-btn-fill.svg b/web/vendor/bootstrap-icons/fast-forward-btn-fill.svg new file mode 100644 index 0000000..fd750fe --- /dev/null +++ b/web/vendor/bootstrap-icons/fast-forward-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/fast-forward-btn.svg b/web/vendor/bootstrap-icons/fast-forward-btn.svg new file mode 100644 index 0000000..5e68554 --- /dev/null +++ b/web/vendor/bootstrap-icons/fast-forward-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/fast-forward-circle-fill.svg b/web/vendor/bootstrap-icons/fast-forward-circle-fill.svg new file mode 100644 index 0000000..3946fa3 --- /dev/null +++ b/web/vendor/bootstrap-icons/fast-forward-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/fast-forward-circle.svg b/web/vendor/bootstrap-icons/fast-forward-circle.svg new file mode 100644 index 0000000..e7f7158 --- /dev/null +++ b/web/vendor/bootstrap-icons/fast-forward-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/fast-forward-fill.svg b/web/vendor/bootstrap-icons/fast-forward-fill.svg new file mode 100644 index 0000000..ae17a7e --- /dev/null +++ b/web/vendor/bootstrap-icons/fast-forward-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/fast-forward.svg b/web/vendor/bootstrap-icons/fast-forward.svg new file mode 100644 index 0000000..2142979 --- /dev/null +++ b/web/vendor/bootstrap-icons/fast-forward.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/feather.svg b/web/vendor/bootstrap-icons/feather.svg new file mode 100644 index 0000000..f0462c2 --- /dev/null +++ b/web/vendor/bootstrap-icons/feather.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/feather2.svg b/web/vendor/bootstrap-icons/feather2.svg new file mode 100644 index 0000000..badc17a --- /dev/null +++ b/web/vendor/bootstrap-icons/feather2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-arrow-down-fill.svg b/web/vendor/bootstrap-icons/file-arrow-down-fill.svg new file mode 100644 index 0000000..5b5c552 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-arrow-down-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-arrow-down.svg b/web/vendor/bootstrap-icons/file-arrow-down.svg new file mode 100644 index 0000000..f504b98 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-arrow-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-arrow-up-fill.svg b/web/vendor/bootstrap-icons/file-arrow-up-fill.svg new file mode 100644 index 0000000..ef56199 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-arrow-up-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-arrow-up.svg b/web/vendor/bootstrap-icons/file-arrow-up.svg new file mode 100644 index 0000000..9c88467 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-arrow-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-bar-graph-fill.svg b/web/vendor/bootstrap-icons/file-bar-graph-fill.svg new file mode 100644 index 0000000..686b60b --- /dev/null +++ b/web/vendor/bootstrap-icons/file-bar-graph-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-bar-graph.svg b/web/vendor/bootstrap-icons/file-bar-graph.svg new file mode 100644 index 0000000..f953927 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-bar-graph.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-binary-fill.svg b/web/vendor/bootstrap-icons/file-binary-fill.svg new file mode 100644 index 0000000..920c2a7 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-binary-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-binary.svg b/web/vendor/bootstrap-icons/file-binary.svg new file mode 100644 index 0000000..0ecece7 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-binary.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-break-fill.svg b/web/vendor/bootstrap-icons/file-break-fill.svg new file mode 100644 index 0000000..bdbe1b9 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-break-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-break.svg b/web/vendor/bootstrap-icons/file-break.svg new file mode 100644 index 0000000..e94b3a3 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-break.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-check-fill.svg b/web/vendor/bootstrap-icons/file-check-fill.svg new file mode 100644 index 0000000..cf165d3 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-check.svg b/web/vendor/bootstrap-icons/file-check.svg new file mode 100644 index 0000000..10863e1 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-code-fill.svg b/web/vendor/bootstrap-icons/file-code-fill.svg new file mode 100644 index 0000000..912ed0c --- /dev/null +++ b/web/vendor/bootstrap-icons/file-code-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-code.svg b/web/vendor/bootstrap-icons/file-code.svg new file mode 100644 index 0000000..58b0014 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-code.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-diff-fill.svg b/web/vendor/bootstrap-icons/file-diff-fill.svg new file mode 100644 index 0000000..c108b87 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-diff-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-diff.svg b/web/vendor/bootstrap-icons/file-diff.svg new file mode 100644 index 0000000..088c6de --- /dev/null +++ b/web/vendor/bootstrap-icons/file-diff.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-arrow-down-fill.svg b/web/vendor/bootstrap-icons/file-earmark-arrow-down-fill.svg new file mode 100644 index 0000000..3941f1f --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-arrow-down-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-arrow-down.svg b/web/vendor/bootstrap-icons/file-earmark-arrow-down.svg new file mode 100644 index 0000000..37c4cd5 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-arrow-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-arrow-up-fill.svg b/web/vendor/bootstrap-icons/file-earmark-arrow-up-fill.svg new file mode 100644 index 0000000..97a339d --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-arrow-up-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-arrow-up.svg b/web/vendor/bootstrap-icons/file-earmark-arrow-up.svg new file mode 100644 index 0000000..1c827e9 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-arrow-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-bar-graph-fill.svg b/web/vendor/bootstrap-icons/file-earmark-bar-graph-fill.svg new file mode 100644 index 0000000..a4c69b5 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-bar-graph-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-bar-graph.svg b/web/vendor/bootstrap-icons/file-earmark-bar-graph.svg new file mode 100644 index 0000000..d367eca --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-bar-graph.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-binary-fill.svg b/web/vendor/bootstrap-icons/file-earmark-binary-fill.svg new file mode 100644 index 0000000..a1f9933 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-binary-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-binary.svg b/web/vendor/bootstrap-icons/file-earmark-binary.svg new file mode 100644 index 0000000..1528578 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-binary.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-break-fill.svg b/web/vendor/bootstrap-icons/file-earmark-break-fill.svg new file mode 100644 index 0000000..e9aadce --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-break-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-break.svg b/web/vendor/bootstrap-icons/file-earmark-break.svg new file mode 100644 index 0000000..4874715 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-break.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-check-fill.svg b/web/vendor/bootstrap-icons/file-earmark-check-fill.svg new file mode 100644 index 0000000..f3e9eb3 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-check.svg b/web/vendor/bootstrap-icons/file-earmark-check.svg new file mode 100644 index 0000000..dc36963 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-code-fill.svg b/web/vendor/bootstrap-icons/file-earmark-code-fill.svg new file mode 100644 index 0000000..2c154fa --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-code-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-code.svg b/web/vendor/bootstrap-icons/file-earmark-code.svg new file mode 100644 index 0000000..ccd3528 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-code.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-diff-fill.svg b/web/vendor/bootstrap-icons/file-earmark-diff-fill.svg new file mode 100644 index 0000000..3b71e66 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-diff-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-diff.svg b/web/vendor/bootstrap-icons/file-earmark-diff.svg new file mode 100644 index 0000000..97dfc0b --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-diff.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-easel-fill.svg b/web/vendor/bootstrap-icons/file-earmark-easel-fill.svg new file mode 100644 index 0000000..e74c974 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-easel-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-easel.svg b/web/vendor/bootstrap-icons/file-earmark-easel.svg new file mode 100644 index 0000000..2feeabc --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-easel.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-excel-fill.svg b/web/vendor/bootstrap-icons/file-earmark-excel-fill.svg new file mode 100644 index 0000000..405a572 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-excel-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-excel.svg b/web/vendor/bootstrap-icons/file-earmark-excel.svg new file mode 100644 index 0000000..5432bcf --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-excel.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-fill.svg b/web/vendor/bootstrap-icons/file-earmark-fill.svg new file mode 100644 index 0000000..2f3ef6c --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-font-fill.svg b/web/vendor/bootstrap-icons/file-earmark-font-fill.svg new file mode 100644 index 0000000..d3014bf --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-font-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-font.svg b/web/vendor/bootstrap-icons/file-earmark-font.svg new file mode 100644 index 0000000..c9864cd --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-font.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-image-fill.svg b/web/vendor/bootstrap-icons/file-earmark-image-fill.svg new file mode 100644 index 0000000..3ec76dc --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-image-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-image.svg b/web/vendor/bootstrap-icons/file-earmark-image.svg new file mode 100644 index 0000000..1c3815d --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-image.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-lock-fill.svg b/web/vendor/bootstrap-icons/file-earmark-lock-fill.svg new file mode 100644 index 0000000..4c45a61 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-lock-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-lock.svg b/web/vendor/bootstrap-icons/file-earmark-lock.svg new file mode 100644 index 0000000..c8319a6 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-lock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-lock2-fill.svg b/web/vendor/bootstrap-icons/file-earmark-lock2-fill.svg new file mode 100644 index 0000000..76e8bd8 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-lock2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-lock2.svg b/web/vendor/bootstrap-icons/file-earmark-lock2.svg new file mode 100644 index 0000000..bd8f592 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-lock2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-medical-fill.svg b/web/vendor/bootstrap-icons/file-earmark-medical-fill.svg new file mode 100644 index 0000000..42a0581 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-medical-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-medical.svg b/web/vendor/bootstrap-icons/file-earmark-medical.svg new file mode 100644 index 0000000..e24c90c --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-medical.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-minus-fill.svg b/web/vendor/bootstrap-icons/file-earmark-minus-fill.svg new file mode 100644 index 0000000..a5dca2d --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-minus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-minus.svg b/web/vendor/bootstrap-icons/file-earmark-minus.svg new file mode 100644 index 0000000..cdc0026 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-minus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-music-fill.svg b/web/vendor/bootstrap-icons/file-earmark-music-fill.svg new file mode 100644 index 0000000..b865e4e --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-music-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-music.svg b/web/vendor/bootstrap-icons/file-earmark-music.svg new file mode 100644 index 0000000..e18ec85 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-music.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-pdf-fill.svg b/web/vendor/bootstrap-icons/file-earmark-pdf-fill.svg new file mode 100644 index 0000000..219c5a3 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-pdf-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-pdf.svg b/web/vendor/bootstrap-icons/file-earmark-pdf.svg new file mode 100644 index 0000000..51b9975 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-pdf.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-person-fill.svg b/web/vendor/bootstrap-icons/file-earmark-person-fill.svg new file mode 100644 index 0000000..49ceda6 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-person-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-person.svg b/web/vendor/bootstrap-icons/file-earmark-person.svg new file mode 100644 index 0000000..08a78cc --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-person.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-play-fill.svg b/web/vendor/bootstrap-icons/file-earmark-play-fill.svg new file mode 100644 index 0000000..341eb37 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-play-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-play.svg b/web/vendor/bootstrap-icons/file-earmark-play.svg new file mode 100644 index 0000000..abe215b --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-play.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-plus-fill.svg b/web/vendor/bootstrap-icons/file-earmark-plus-fill.svg new file mode 100644 index 0000000..ef99c8a --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-plus.svg b/web/vendor/bootstrap-icons/file-earmark-plus.svg new file mode 100644 index 0000000..964e855 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-post-fill.svg b/web/vendor/bootstrap-icons/file-earmark-post-fill.svg new file mode 100644 index 0000000..548773f --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-post-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-post.svg b/web/vendor/bootstrap-icons/file-earmark-post.svg new file mode 100644 index 0000000..d9f44a1 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-post.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-ppt-fill.svg b/web/vendor/bootstrap-icons/file-earmark-ppt-fill.svg new file mode 100644 index 0000000..e96a461 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-ppt-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-ppt.svg b/web/vendor/bootstrap-icons/file-earmark-ppt.svg new file mode 100644 index 0000000..cab71bc --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-ppt.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-richtext-fill.svg b/web/vendor/bootstrap-icons/file-earmark-richtext-fill.svg new file mode 100644 index 0000000..55da25c --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-richtext-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-richtext.svg b/web/vendor/bootstrap-icons/file-earmark-richtext.svg new file mode 100644 index 0000000..3f3a6ad --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-richtext.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-ruled-fill.svg b/web/vendor/bootstrap-icons/file-earmark-ruled-fill.svg new file mode 100644 index 0000000..ee90c80 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-ruled-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-ruled.svg b/web/vendor/bootstrap-icons/file-earmark-ruled.svg new file mode 100644 index 0000000..ebd617e --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-ruled.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-slides-fill.svg b/web/vendor/bootstrap-icons/file-earmark-slides-fill.svg new file mode 100644 index 0000000..e7f76f4 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-slides-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-slides.svg b/web/vendor/bootstrap-icons/file-earmark-slides.svg new file mode 100644 index 0000000..e643cd3 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-slides.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-spreadsheet-fill.svg b/web/vendor/bootstrap-icons/file-earmark-spreadsheet-fill.svg new file mode 100644 index 0000000..02ac9ec --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-spreadsheet-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-spreadsheet.svg b/web/vendor/bootstrap-icons/file-earmark-spreadsheet.svg new file mode 100644 index 0000000..a6bb6e4 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-spreadsheet.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-text-fill.svg b/web/vendor/bootstrap-icons/file-earmark-text-fill.svg new file mode 100644 index 0000000..bfedd6b --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-text-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-text.svg b/web/vendor/bootstrap-icons/file-earmark-text.svg new file mode 100644 index 0000000..7ae53fc --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-text.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-word-fill.svg b/web/vendor/bootstrap-icons/file-earmark-word-fill.svg new file mode 100644 index 0000000..259e767 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-word-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-word.svg b/web/vendor/bootstrap-icons/file-earmark-word.svg new file mode 100644 index 0000000..ef4727c --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-word.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-x-fill.svg b/web/vendor/bootstrap-icons/file-earmark-x-fill.svg new file mode 100644 index 0000000..f683966 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-x.svg b/web/vendor/bootstrap-icons/file-earmark-x.svg new file mode 100644 index 0000000..4dd9da9 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-zip-fill.svg b/web/vendor/bootstrap-icons/file-earmark-zip-fill.svg new file mode 100644 index 0000000..a17fa9e --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-zip-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark-zip.svg b/web/vendor/bootstrap-icons/file-earmark-zip.svg new file mode 100644 index 0000000..f5f8ccc --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark-zip.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-earmark.svg b/web/vendor/bootstrap-icons/file-earmark.svg new file mode 100644 index 0000000..d8d8774 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-earmark.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-easel-fill.svg b/web/vendor/bootstrap-icons/file-easel-fill.svg new file mode 100644 index 0000000..fa9f915 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-easel-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-easel.svg b/web/vendor/bootstrap-icons/file-easel.svg new file mode 100644 index 0000000..6366bc0 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-easel.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-excel-fill.svg b/web/vendor/bootstrap-icons/file-excel-fill.svg new file mode 100644 index 0000000..bddcea2 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-excel-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-excel.svg b/web/vendor/bootstrap-icons/file-excel.svg new file mode 100644 index 0000000..8bf2f5e --- /dev/null +++ b/web/vendor/bootstrap-icons/file-excel.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-fill.svg b/web/vendor/bootstrap-icons/file-fill.svg new file mode 100644 index 0000000..e5f8c4a --- /dev/null +++ b/web/vendor/bootstrap-icons/file-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-font-fill.svg b/web/vendor/bootstrap-icons/file-font-fill.svg new file mode 100644 index 0000000..6bda7b1 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-font-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-font.svg b/web/vendor/bootstrap-icons/file-font.svg new file mode 100644 index 0000000..b75f9a4 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-font.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-image-fill.svg b/web/vendor/bootstrap-icons/file-image-fill.svg new file mode 100644 index 0000000..7c73ece --- /dev/null +++ b/web/vendor/bootstrap-icons/file-image-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-image.svg b/web/vendor/bootstrap-icons/file-image.svg new file mode 100644 index 0000000..b063628 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-image.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-lock-fill.svg b/web/vendor/bootstrap-icons/file-lock-fill.svg new file mode 100644 index 0000000..1f7c3f2 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-lock-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-lock.svg b/web/vendor/bootstrap-icons/file-lock.svg new file mode 100644 index 0000000..195deef --- /dev/null +++ b/web/vendor/bootstrap-icons/file-lock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-lock2-fill.svg b/web/vendor/bootstrap-icons/file-lock2-fill.svg new file mode 100644 index 0000000..82426e8 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-lock2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-lock2.svg b/web/vendor/bootstrap-icons/file-lock2.svg new file mode 100644 index 0000000..125a747 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-lock2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-medical-fill.svg b/web/vendor/bootstrap-icons/file-medical-fill.svg new file mode 100644 index 0000000..2f4d3b2 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-medical-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-medical.svg b/web/vendor/bootstrap-icons/file-medical.svg new file mode 100644 index 0000000..07e8495 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-medical.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-minus-fill.svg b/web/vendor/bootstrap-icons/file-minus-fill.svg new file mode 100644 index 0000000..99f7d53 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-minus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-minus.svg b/web/vendor/bootstrap-icons/file-minus.svg new file mode 100644 index 0000000..880409b --- /dev/null +++ b/web/vendor/bootstrap-icons/file-minus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-music-fill.svg b/web/vendor/bootstrap-icons/file-music-fill.svg new file mode 100644 index 0000000..38099f3 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-music-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-music.svg b/web/vendor/bootstrap-icons/file-music.svg new file mode 100644 index 0000000..a24d41e --- /dev/null +++ b/web/vendor/bootstrap-icons/file-music.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-pdf-fill.svg b/web/vendor/bootstrap-icons/file-pdf-fill.svg new file mode 100644 index 0000000..c88d1b8 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-pdf-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-pdf.svg b/web/vendor/bootstrap-icons/file-pdf.svg new file mode 100644 index 0000000..e7bdcba --- /dev/null +++ b/web/vendor/bootstrap-icons/file-pdf.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-person-fill.svg b/web/vendor/bootstrap-icons/file-person-fill.svg new file mode 100644 index 0000000..c212b00 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-person-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-person.svg b/web/vendor/bootstrap-icons/file-person.svg new file mode 100644 index 0000000..e102abf --- /dev/null +++ b/web/vendor/bootstrap-icons/file-person.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-play-fill.svg b/web/vendor/bootstrap-icons/file-play-fill.svg new file mode 100644 index 0000000..a6dce8a --- /dev/null +++ b/web/vendor/bootstrap-icons/file-play-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-play.svg b/web/vendor/bootstrap-icons/file-play.svg new file mode 100644 index 0000000..d5505e3 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-play.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-plus-fill.svg b/web/vendor/bootstrap-icons/file-plus-fill.svg new file mode 100644 index 0000000..bdb7ee0 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-plus.svg b/web/vendor/bootstrap-icons/file-plus.svg new file mode 100644 index 0000000..af41ae1 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-post-fill.svg b/web/vendor/bootstrap-icons/file-post-fill.svg new file mode 100644 index 0000000..336f219 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-post-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-post.svg b/web/vendor/bootstrap-icons/file-post.svg new file mode 100644 index 0000000..6807724 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-post.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-ppt-fill.svg b/web/vendor/bootstrap-icons/file-ppt-fill.svg new file mode 100644 index 0000000..b8c3973 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-ppt-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-ppt.svg b/web/vendor/bootstrap-icons/file-ppt.svg new file mode 100644 index 0000000..bee27d4 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-ppt.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-richtext-fill.svg b/web/vendor/bootstrap-icons/file-richtext-fill.svg new file mode 100644 index 0000000..a98e5d7 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-richtext-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-richtext.svg b/web/vendor/bootstrap-icons/file-richtext.svg new file mode 100644 index 0000000..3ceb420 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-richtext.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-ruled-fill.svg b/web/vendor/bootstrap-icons/file-ruled-fill.svg new file mode 100644 index 0000000..8bfe726 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-ruled-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-ruled.svg b/web/vendor/bootstrap-icons/file-ruled.svg new file mode 100644 index 0000000..7236cfc --- /dev/null +++ b/web/vendor/bootstrap-icons/file-ruled.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-slides-fill.svg b/web/vendor/bootstrap-icons/file-slides-fill.svg new file mode 100644 index 0000000..b75d3f7 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-slides-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-slides.svg b/web/vendor/bootstrap-icons/file-slides.svg new file mode 100644 index 0000000..0e63548 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-slides.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-spreadsheet-fill.svg b/web/vendor/bootstrap-icons/file-spreadsheet-fill.svg new file mode 100644 index 0000000..6db7eb6 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-spreadsheet-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-spreadsheet.svg b/web/vendor/bootstrap-icons/file-spreadsheet.svg new file mode 100644 index 0000000..55b53ec --- /dev/null +++ b/web/vendor/bootstrap-icons/file-spreadsheet.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-text-fill.svg b/web/vendor/bootstrap-icons/file-text-fill.svg new file mode 100644 index 0000000..6da36b2 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-text-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-text.svg b/web/vendor/bootstrap-icons/file-text.svg new file mode 100644 index 0000000..95dc704 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-text.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-word-fill.svg b/web/vendor/bootstrap-icons/file-word-fill.svg new file mode 100644 index 0000000..6f578f0 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-word-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-word.svg b/web/vendor/bootstrap-icons/file-word.svg new file mode 100644 index 0000000..732b59a --- /dev/null +++ b/web/vendor/bootstrap-icons/file-word.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-x-fill.svg b/web/vendor/bootstrap-icons/file-x-fill.svg new file mode 100644 index 0000000..0455659 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-x.svg b/web/vendor/bootstrap-icons/file-x.svg new file mode 100644 index 0000000..5ab0b48 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-zip-fill.svg b/web/vendor/bootstrap-icons/file-zip-fill.svg new file mode 100644 index 0000000..1d80366 --- /dev/null +++ b/web/vendor/bootstrap-icons/file-zip-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file-zip.svg b/web/vendor/bootstrap-icons/file-zip.svg new file mode 100644 index 0000000..e3b633e --- /dev/null +++ b/web/vendor/bootstrap-icons/file-zip.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/file.svg b/web/vendor/bootstrap-icons/file.svg new file mode 100644 index 0000000..4a5dd73 --- /dev/null +++ b/web/vendor/bootstrap-icons/file.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/files-alt.svg b/web/vendor/bootstrap-icons/files-alt.svg new file mode 100644 index 0000000..b42d764 --- /dev/null +++ b/web/vendor/bootstrap-icons/files-alt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/files.svg b/web/vendor/bootstrap-icons/files.svg new file mode 100644 index 0000000..6170ab5 --- /dev/null +++ b/web/vendor/bootstrap-icons/files.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-aac.svg b/web/vendor/bootstrap-icons/filetype-aac.svg new file mode 100644 index 0000000..b6a5c47 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-aac.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-ai.svg b/web/vendor/bootstrap-icons/filetype-ai.svg new file mode 100644 index 0000000..fe2bcaa --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-ai.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-bmp.svg b/web/vendor/bootstrap-icons/filetype-bmp.svg new file mode 100644 index 0000000..587381c --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-bmp.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-cs.svg b/web/vendor/bootstrap-icons/filetype-cs.svg new file mode 100644 index 0000000..90ed8de --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-cs.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-css.svg b/web/vendor/bootstrap-icons/filetype-css.svg new file mode 100644 index 0000000..8f0864f --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-css.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-csv.svg b/web/vendor/bootstrap-icons/filetype-csv.svg new file mode 100644 index 0000000..fa097aa --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-csv.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-doc.svg b/web/vendor/bootstrap-icons/filetype-doc.svg new file mode 100644 index 0000000..f75847f --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-doc.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-docx.svg b/web/vendor/bootstrap-icons/filetype-docx.svg new file mode 100644 index 0000000..1b6c172 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-docx.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-exe.svg b/web/vendor/bootstrap-icons/filetype-exe.svg new file mode 100644 index 0000000..cdafeb1 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-exe.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-gif.svg b/web/vendor/bootstrap-icons/filetype-gif.svg new file mode 100644 index 0000000..b39234f --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-gif.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-heic.svg b/web/vendor/bootstrap-icons/filetype-heic.svg new file mode 100644 index 0000000..a022060 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-heic.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-html.svg b/web/vendor/bootstrap-icons/filetype-html.svg new file mode 100644 index 0000000..1661a94 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-html.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-java.svg b/web/vendor/bootstrap-icons/filetype-java.svg new file mode 100644 index 0000000..eeeab41 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-java.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-jpg.svg b/web/vendor/bootstrap-icons/filetype-jpg.svg new file mode 100644 index 0000000..7d939ec --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-jpg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-js.svg b/web/vendor/bootstrap-icons/filetype-js.svg new file mode 100644 index 0000000..4f4a00c --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-js.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-json.svg b/web/vendor/bootstrap-icons/filetype-json.svg new file mode 100644 index 0000000..a4ccced --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-json.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-jsx.svg b/web/vendor/bootstrap-icons/filetype-jsx.svg new file mode 100644 index 0000000..256b5c5 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-jsx.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-key.svg b/web/vendor/bootstrap-icons/filetype-key.svg new file mode 100644 index 0000000..d164bc8 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-key.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-m4p.svg b/web/vendor/bootstrap-icons/filetype-m4p.svg new file mode 100644 index 0000000..ae8f611 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-m4p.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-md.svg b/web/vendor/bootstrap-icons/filetype-md.svg new file mode 100644 index 0000000..40e5139 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-md.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-mdx.svg b/web/vendor/bootstrap-icons/filetype-mdx.svg new file mode 100644 index 0000000..43a9153 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-mdx.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-mov.svg b/web/vendor/bootstrap-icons/filetype-mov.svg new file mode 100644 index 0000000..27e6391 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-mov.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-mp3.svg b/web/vendor/bootstrap-icons/filetype-mp3.svg new file mode 100644 index 0000000..f25e6a8 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-mp3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-mp4.svg b/web/vendor/bootstrap-icons/filetype-mp4.svg new file mode 100644 index 0000000..d27e9ff --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-mp4.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-otf.svg b/web/vendor/bootstrap-icons/filetype-otf.svg new file mode 100644 index 0000000..f16eb61 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-otf.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-pdf.svg b/web/vendor/bootstrap-icons/filetype-pdf.svg new file mode 100644 index 0000000..e8bb772 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-pdf.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-php.svg b/web/vendor/bootstrap-icons/filetype-php.svg new file mode 100644 index 0000000..4d532df --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-php.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-png.svg b/web/vendor/bootstrap-icons/filetype-png.svg new file mode 100644 index 0000000..659e266 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-png.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-ppt.svg b/web/vendor/bootstrap-icons/filetype-ppt.svg new file mode 100644 index 0000000..e53b1ec --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-ppt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-pptx.svg b/web/vendor/bootstrap-icons/filetype-pptx.svg new file mode 100644 index 0000000..f68e939 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-pptx.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-psd.svg b/web/vendor/bootstrap-icons/filetype-psd.svg new file mode 100644 index 0000000..6fefd08 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-psd.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-py.svg b/web/vendor/bootstrap-icons/filetype-py.svg new file mode 100644 index 0000000..14fd4ef --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-py.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-raw.svg b/web/vendor/bootstrap-icons/filetype-raw.svg new file mode 100644 index 0000000..da98185 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-raw.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-rb.svg b/web/vendor/bootstrap-icons/filetype-rb.svg new file mode 100644 index 0000000..3466a1f --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-rb.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-sass.svg b/web/vendor/bootstrap-icons/filetype-sass.svg new file mode 100644 index 0000000..3632662 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-sass.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-scss.svg b/web/vendor/bootstrap-icons/filetype-scss.svg new file mode 100644 index 0000000..8d1935f --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-scss.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-sh.svg b/web/vendor/bootstrap-icons/filetype-sh.svg new file mode 100644 index 0000000..592c408 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-sh.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-sql.svg b/web/vendor/bootstrap-icons/filetype-sql.svg new file mode 100644 index 0000000..814137d --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-sql.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-svg.svg b/web/vendor/bootstrap-icons/filetype-svg.svg new file mode 100644 index 0000000..222d9ac --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-svg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-tiff.svg b/web/vendor/bootstrap-icons/filetype-tiff.svg new file mode 100644 index 0000000..e101575 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-tiff.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-tsx.svg b/web/vendor/bootstrap-icons/filetype-tsx.svg new file mode 100644 index 0000000..73dd643 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-tsx.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-ttf.svg b/web/vendor/bootstrap-icons/filetype-ttf.svg new file mode 100644 index 0000000..9c93584 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-ttf.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-txt.svg b/web/vendor/bootstrap-icons/filetype-txt.svg new file mode 100644 index 0000000..1e27bcf --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-txt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-wav.svg b/web/vendor/bootstrap-icons/filetype-wav.svg new file mode 100644 index 0000000..6725640 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-wav.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-woff.svg b/web/vendor/bootstrap-icons/filetype-woff.svg new file mode 100644 index 0000000..f29a4b1 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-woff.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-xls.svg b/web/vendor/bootstrap-icons/filetype-xls.svg new file mode 100644 index 0000000..5f79b16 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-xls.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-xlsx.svg b/web/vendor/bootstrap-icons/filetype-xlsx.svg new file mode 100644 index 0000000..5202bf7 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-xlsx.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-xml.svg b/web/vendor/bootstrap-icons/filetype-xml.svg new file mode 100644 index 0000000..ba9ffb6 --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-xml.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filetype-yml.svg b/web/vendor/bootstrap-icons/filetype-yml.svg new file mode 100644 index 0000000..17a9ebe --- /dev/null +++ b/web/vendor/bootstrap-icons/filetype-yml.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/film.svg b/web/vendor/bootstrap-icons/film.svg new file mode 100644 index 0000000..40c2eb9 --- /dev/null +++ b/web/vendor/bootstrap-icons/film.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filter-circle-fill.svg b/web/vendor/bootstrap-icons/filter-circle-fill.svg new file mode 100644 index 0000000..1aa0f39 --- /dev/null +++ b/web/vendor/bootstrap-icons/filter-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filter-circle.svg b/web/vendor/bootstrap-icons/filter-circle.svg new file mode 100644 index 0000000..42c1b84 --- /dev/null +++ b/web/vendor/bootstrap-icons/filter-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filter-left.svg b/web/vendor/bootstrap-icons/filter-left.svg new file mode 100644 index 0000000..bb1ee92 --- /dev/null +++ b/web/vendor/bootstrap-icons/filter-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filter-right.svg b/web/vendor/bootstrap-icons/filter-right.svg new file mode 100644 index 0000000..6a5083c --- /dev/null +++ b/web/vendor/bootstrap-icons/filter-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filter-square-fill.svg b/web/vendor/bootstrap-icons/filter-square-fill.svg new file mode 100644 index 0000000..438b8c2 --- /dev/null +++ b/web/vendor/bootstrap-icons/filter-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filter-square.svg b/web/vendor/bootstrap-icons/filter-square.svg new file mode 100644 index 0000000..d243b0b --- /dev/null +++ b/web/vendor/bootstrap-icons/filter-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/filter.svg b/web/vendor/bootstrap-icons/filter.svg new file mode 100644 index 0000000..a7d7dac --- /dev/null +++ b/web/vendor/bootstrap-icons/filter.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/fingerprint.svg b/web/vendor/bootstrap-icons/fingerprint.svg new file mode 100644 index 0000000..08252bb --- /dev/null +++ b/web/vendor/bootstrap-icons/fingerprint.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/fire.svg b/web/vendor/bootstrap-icons/fire.svg new file mode 100644 index 0000000..a58e6dd --- /dev/null +++ b/web/vendor/bootstrap-icons/fire.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/flag-fill.svg b/web/vendor/bootstrap-icons/flag-fill.svg new file mode 100644 index 0000000..8b92331 --- /dev/null +++ b/web/vendor/bootstrap-icons/flag-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/flag.svg b/web/vendor/bootstrap-icons/flag.svg new file mode 100644 index 0000000..f8b6dab --- /dev/null +++ b/web/vendor/bootstrap-icons/flag.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/flask-fill.svg b/web/vendor/bootstrap-icons/flask-fill.svg new file mode 100644 index 0000000..61207af --- /dev/null +++ b/web/vendor/bootstrap-icons/flask-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/flask-florence-fill.svg b/web/vendor/bootstrap-icons/flask-florence-fill.svg new file mode 100644 index 0000000..70896a6 --- /dev/null +++ b/web/vendor/bootstrap-icons/flask-florence-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/flask-florence.svg b/web/vendor/bootstrap-icons/flask-florence.svg new file mode 100644 index 0000000..6df75f7 --- /dev/null +++ b/web/vendor/bootstrap-icons/flask-florence.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/flask.svg b/web/vendor/bootstrap-icons/flask.svg new file mode 100644 index 0000000..01cc1ba --- /dev/null +++ b/web/vendor/bootstrap-icons/flask.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/floppy-fill.svg b/web/vendor/bootstrap-icons/floppy-fill.svg new file mode 100644 index 0000000..87a43ce --- /dev/null +++ b/web/vendor/bootstrap-icons/floppy-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/floppy.svg b/web/vendor/bootstrap-icons/floppy.svg new file mode 100644 index 0000000..65ae562 --- /dev/null +++ b/web/vendor/bootstrap-icons/floppy.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/floppy2-fill.svg b/web/vendor/bootstrap-icons/floppy2-fill.svg new file mode 100644 index 0000000..61a6cdb --- /dev/null +++ b/web/vendor/bootstrap-icons/floppy2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/floppy2.svg b/web/vendor/bootstrap-icons/floppy2.svg new file mode 100644 index 0000000..2412389 --- /dev/null +++ b/web/vendor/bootstrap-icons/floppy2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/flower1.svg b/web/vendor/bootstrap-icons/flower1.svg new file mode 100644 index 0000000..3495858 --- /dev/null +++ b/web/vendor/bootstrap-icons/flower1.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/flower2.svg b/web/vendor/bootstrap-icons/flower2.svg new file mode 100644 index 0000000..664a9c2 --- /dev/null +++ b/web/vendor/bootstrap-icons/flower2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/flower3.svg b/web/vendor/bootstrap-icons/flower3.svg new file mode 100644 index 0000000..66845c3 --- /dev/null +++ b/web/vendor/bootstrap-icons/flower3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/folder-check.svg b/web/vendor/bootstrap-icons/folder-check.svg new file mode 100644 index 0000000..57c6466 --- /dev/null +++ b/web/vendor/bootstrap-icons/folder-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/folder-fill.svg b/web/vendor/bootstrap-icons/folder-fill.svg new file mode 100644 index 0000000..113350c --- /dev/null +++ b/web/vendor/bootstrap-icons/folder-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/folder-minus.svg b/web/vendor/bootstrap-icons/folder-minus.svg new file mode 100644 index 0000000..41db30b --- /dev/null +++ b/web/vendor/bootstrap-icons/folder-minus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/folder-plus.svg b/web/vendor/bootstrap-icons/folder-plus.svg new file mode 100644 index 0000000..85b5a18 --- /dev/null +++ b/web/vendor/bootstrap-icons/folder-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/folder-symlink-fill.svg b/web/vendor/bootstrap-icons/folder-symlink-fill.svg new file mode 100644 index 0000000..6407400 --- /dev/null +++ b/web/vendor/bootstrap-icons/folder-symlink-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/folder-symlink.svg b/web/vendor/bootstrap-icons/folder-symlink.svg new file mode 100644 index 0000000..7137637 --- /dev/null +++ b/web/vendor/bootstrap-icons/folder-symlink.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/folder-x.svg b/web/vendor/bootstrap-icons/folder-x.svg new file mode 100644 index 0000000..a6ed341 --- /dev/null +++ b/web/vendor/bootstrap-icons/folder-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/folder.svg b/web/vendor/bootstrap-icons/folder.svg new file mode 100644 index 0000000..a30c452 --- /dev/null +++ b/web/vendor/bootstrap-icons/folder.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/folder2-open.svg b/web/vendor/bootstrap-icons/folder2-open.svg new file mode 100644 index 0000000..7ffbb54 --- /dev/null +++ b/web/vendor/bootstrap-icons/folder2-open.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/folder2.svg b/web/vendor/bootstrap-icons/folder2.svg new file mode 100644 index 0000000..ce6a1af --- /dev/null +++ b/web/vendor/bootstrap-icons/folder2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/fonts.svg b/web/vendor/bootstrap-icons/fonts.svg new file mode 100644 index 0000000..5e1f3c3 --- /dev/null +++ b/web/vendor/bootstrap-icons/fonts.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/fonts/bootstrap-icons.woff b/web/vendor/bootstrap-icons/fonts/bootstrap-icons.woff new file mode 100644 index 0000000000000000000000000000000000000000..a4fa4f024c2171080ebaf3112fccbf90cdb98479 GIT binary patch literal 180288 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 DSDONf literal 0 HcmV?d00001 diff --git a/web/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2 b/web/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..4d8c490e1ec1153df2a4d80d1342f1d8820e792d GIT binary patch literal 134044 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

    I_iT~F!-V*$H;*%98q;k6<1RxCZS#LpiY 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 K8>{rTe*gfoWh&qR literal 0 HcmV?d00001 diff --git a/web/vendor/bootstrap-icons/fork-knife.svg b/web/vendor/bootstrap-icons/fork-knife.svg new file mode 100644 index 0000000..31277b4 --- /dev/null +++ b/web/vendor/bootstrap-icons/fork-knife.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/forward-fill.svg b/web/vendor/bootstrap-icons/forward-fill.svg new file mode 100644 index 0000000..27462e2 --- /dev/null +++ b/web/vendor/bootstrap-icons/forward-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/forward.svg b/web/vendor/bootstrap-icons/forward.svg new file mode 100644 index 0000000..ffe887c --- /dev/null +++ b/web/vendor/bootstrap-icons/forward.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/front.svg b/web/vendor/bootstrap-icons/front.svg new file mode 100644 index 0000000..59d854e --- /dev/null +++ b/web/vendor/bootstrap-icons/front.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/fuel-pump-diesel-fill.svg b/web/vendor/bootstrap-icons/fuel-pump-diesel-fill.svg new file mode 100644 index 0000000..997d6f8 --- /dev/null +++ b/web/vendor/bootstrap-icons/fuel-pump-diesel-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/fuel-pump-diesel.svg b/web/vendor/bootstrap-icons/fuel-pump-diesel.svg new file mode 100644 index 0000000..e170eeb --- /dev/null +++ b/web/vendor/bootstrap-icons/fuel-pump-diesel.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/fuel-pump-fill.svg b/web/vendor/bootstrap-icons/fuel-pump-fill.svg new file mode 100644 index 0000000..46f92c3 --- /dev/null +++ b/web/vendor/bootstrap-icons/fuel-pump-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/fuel-pump.svg b/web/vendor/bootstrap-icons/fuel-pump.svg new file mode 100644 index 0000000..1704a6f --- /dev/null +++ b/web/vendor/bootstrap-icons/fuel-pump.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/fullscreen-exit.svg b/web/vendor/bootstrap-icons/fullscreen-exit.svg new file mode 100644 index 0000000..cfde3a3 --- /dev/null +++ b/web/vendor/bootstrap-icons/fullscreen-exit.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/fullscreen.svg b/web/vendor/bootstrap-icons/fullscreen.svg new file mode 100644 index 0000000..d4f8a83 --- /dev/null +++ b/web/vendor/bootstrap-icons/fullscreen.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/funnel-fill.svg b/web/vendor/bootstrap-icons/funnel-fill.svg new file mode 100644 index 0000000..04d31a6 --- /dev/null +++ b/web/vendor/bootstrap-icons/funnel-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/funnel.svg b/web/vendor/bootstrap-icons/funnel.svg new file mode 100644 index 0000000..28bfcf2 --- /dev/null +++ b/web/vendor/bootstrap-icons/funnel.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/gear-fill.svg b/web/vendor/bootstrap-icons/gear-fill.svg new file mode 100644 index 0000000..ba8e2c5 --- /dev/null +++ b/web/vendor/bootstrap-icons/gear-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/gear-wide-connected.svg b/web/vendor/bootstrap-icons/gear-wide-connected.svg new file mode 100644 index 0000000..19ddda9 --- /dev/null +++ b/web/vendor/bootstrap-icons/gear-wide-connected.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/gear-wide.svg b/web/vendor/bootstrap-icons/gear-wide.svg new file mode 100644 index 0000000..c5de567 --- /dev/null +++ b/web/vendor/bootstrap-icons/gear-wide.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/gear.svg b/web/vendor/bootstrap-icons/gear.svg new file mode 100644 index 0000000..30cfaa3 --- /dev/null +++ b/web/vendor/bootstrap-icons/gear.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/gem.svg b/web/vendor/bootstrap-icons/gem.svg new file mode 100644 index 0000000..f56d871 --- /dev/null +++ b/web/vendor/bootstrap-icons/gem.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/gender-ambiguous.svg b/web/vendor/bootstrap-icons/gender-ambiguous.svg new file mode 100644 index 0000000..674c526 --- /dev/null +++ b/web/vendor/bootstrap-icons/gender-ambiguous.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/gender-female.svg b/web/vendor/bootstrap-icons/gender-female.svg new file mode 100644 index 0000000..ae6dc27 --- /dev/null +++ b/web/vendor/bootstrap-icons/gender-female.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/gender-male.svg b/web/vendor/bootstrap-icons/gender-male.svg new file mode 100644 index 0000000..3931921 --- /dev/null +++ b/web/vendor/bootstrap-icons/gender-male.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/gender-neuter.svg b/web/vendor/bootstrap-icons/gender-neuter.svg new file mode 100644 index 0000000..133db1a --- /dev/null +++ b/web/vendor/bootstrap-icons/gender-neuter.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/gender-trans.svg b/web/vendor/bootstrap-icons/gender-trans.svg new file mode 100644 index 0000000..005e6f8 --- /dev/null +++ b/web/vendor/bootstrap-icons/gender-trans.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/geo-alt-fill.svg b/web/vendor/bootstrap-icons/geo-alt-fill.svg new file mode 100644 index 0000000..77f0478 --- /dev/null +++ b/web/vendor/bootstrap-icons/geo-alt-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/geo-alt.svg b/web/vendor/bootstrap-icons/geo-alt.svg new file mode 100644 index 0000000..20e18ba --- /dev/null +++ b/web/vendor/bootstrap-icons/geo-alt.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/geo-fill.svg b/web/vendor/bootstrap-icons/geo-fill.svg new file mode 100644 index 0000000..9678fa0 --- /dev/null +++ b/web/vendor/bootstrap-icons/geo-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/geo.svg b/web/vendor/bootstrap-icons/geo.svg new file mode 100644 index 0000000..2382b91 --- /dev/null +++ b/web/vendor/bootstrap-icons/geo.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/gift-fill.svg b/web/vendor/bootstrap-icons/gift-fill.svg new file mode 100644 index 0000000..bd78a8c --- /dev/null +++ b/web/vendor/bootstrap-icons/gift-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/gift.svg b/web/vendor/bootstrap-icons/gift.svg new file mode 100644 index 0000000..5921507 --- /dev/null +++ b/web/vendor/bootstrap-icons/gift.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/git.svg b/web/vendor/bootstrap-icons/git.svg new file mode 100644 index 0000000..0979cdb --- /dev/null +++ b/web/vendor/bootstrap-icons/git.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/github.svg b/web/vendor/bootstrap-icons/github.svg new file mode 100644 index 0000000..013e025 --- /dev/null +++ b/web/vendor/bootstrap-icons/github.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/gitlab.svg b/web/vendor/bootstrap-icons/gitlab.svg new file mode 100644 index 0000000..f8875f8 --- /dev/null +++ b/web/vendor/bootstrap-icons/gitlab.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/globe-americas-fill.svg b/web/vendor/bootstrap-icons/globe-americas-fill.svg new file mode 100644 index 0000000..42259b2 --- /dev/null +++ b/web/vendor/bootstrap-icons/globe-americas-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/globe-americas.svg b/web/vendor/bootstrap-icons/globe-americas.svg new file mode 100644 index 0000000..5dcc7b2 --- /dev/null +++ b/web/vendor/bootstrap-icons/globe-americas.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/globe-asia-australia-fill.svg b/web/vendor/bootstrap-icons/globe-asia-australia-fill.svg new file mode 100644 index 0000000..8dfde0c --- /dev/null +++ b/web/vendor/bootstrap-icons/globe-asia-australia-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/globe-asia-australia.svg b/web/vendor/bootstrap-icons/globe-asia-australia.svg new file mode 100644 index 0000000..8c27539 --- /dev/null +++ b/web/vendor/bootstrap-icons/globe-asia-australia.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/globe-central-south-asia-fill.svg b/web/vendor/bootstrap-icons/globe-central-south-asia-fill.svg new file mode 100644 index 0000000..8f52f93 --- /dev/null +++ b/web/vendor/bootstrap-icons/globe-central-south-asia-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/globe-central-south-asia.svg b/web/vendor/bootstrap-icons/globe-central-south-asia.svg new file mode 100644 index 0000000..80a13c1 --- /dev/null +++ b/web/vendor/bootstrap-icons/globe-central-south-asia.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/globe-europe-africa-fill.svg b/web/vendor/bootstrap-icons/globe-europe-africa-fill.svg new file mode 100644 index 0000000..3fcdf0b --- /dev/null +++ b/web/vendor/bootstrap-icons/globe-europe-africa-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/globe-europe-africa.svg b/web/vendor/bootstrap-icons/globe-europe-africa.svg new file mode 100644 index 0000000..c1c5dcb --- /dev/null +++ b/web/vendor/bootstrap-icons/globe-europe-africa.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/globe.svg b/web/vendor/bootstrap-icons/globe.svg new file mode 100644 index 0000000..835ff66 --- /dev/null +++ b/web/vendor/bootstrap-icons/globe.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/globe2.svg b/web/vendor/bootstrap-icons/globe2.svg new file mode 100644 index 0000000..b302063 --- /dev/null +++ b/web/vendor/bootstrap-icons/globe2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/google-play.svg b/web/vendor/bootstrap-icons/google-play.svg new file mode 100644 index 0000000..0751c90 --- /dev/null +++ b/web/vendor/bootstrap-icons/google-play.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/google.svg b/web/vendor/bootstrap-icons/google.svg new file mode 100644 index 0000000..9f603de --- /dev/null +++ b/web/vendor/bootstrap-icons/google.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/gpu-card.svg b/web/vendor/bootstrap-icons/gpu-card.svg new file mode 100644 index 0000000..6ec3152 --- /dev/null +++ b/web/vendor/bootstrap-icons/gpu-card.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/graph-down-arrow.svg b/web/vendor/bootstrap-icons/graph-down-arrow.svg new file mode 100644 index 0000000..d811884 --- /dev/null +++ b/web/vendor/bootstrap-icons/graph-down-arrow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/graph-down.svg b/web/vendor/bootstrap-icons/graph-down.svg new file mode 100644 index 0000000..47dd647 --- /dev/null +++ b/web/vendor/bootstrap-icons/graph-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/graph-up-arrow.svg b/web/vendor/bootstrap-icons/graph-up-arrow.svg new file mode 100644 index 0000000..7eda5f4 --- /dev/null +++ b/web/vendor/bootstrap-icons/graph-up-arrow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/graph-up.svg b/web/vendor/bootstrap-icons/graph-up.svg new file mode 100644 index 0000000..15e0bbf --- /dev/null +++ b/web/vendor/bootstrap-icons/graph-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/grid-1x2-fill.svg b/web/vendor/bootstrap-icons/grid-1x2-fill.svg new file mode 100644 index 0000000..cc568cb --- /dev/null +++ b/web/vendor/bootstrap-icons/grid-1x2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/grid-1x2.svg b/web/vendor/bootstrap-icons/grid-1x2.svg new file mode 100644 index 0000000..69ec79f --- /dev/null +++ b/web/vendor/bootstrap-icons/grid-1x2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/grid-3x2-gap-fill.svg b/web/vendor/bootstrap-icons/grid-3x2-gap-fill.svg new file mode 100644 index 0000000..9c0e855 --- /dev/null +++ b/web/vendor/bootstrap-icons/grid-3x2-gap-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/grid-3x2-gap.svg b/web/vendor/bootstrap-icons/grid-3x2-gap.svg new file mode 100644 index 0000000..730ae65 --- /dev/null +++ b/web/vendor/bootstrap-icons/grid-3x2-gap.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/grid-3x2.svg b/web/vendor/bootstrap-icons/grid-3x2.svg new file mode 100644 index 0000000..55ff9bb --- /dev/null +++ b/web/vendor/bootstrap-icons/grid-3x2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/grid-3x3-gap-fill.svg b/web/vendor/bootstrap-icons/grid-3x3-gap-fill.svg new file mode 100644 index 0000000..982cb70 --- /dev/null +++ b/web/vendor/bootstrap-icons/grid-3x3-gap-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/grid-3x3-gap.svg b/web/vendor/bootstrap-icons/grid-3x3-gap.svg new file mode 100644 index 0000000..bbf8ce4 --- /dev/null +++ b/web/vendor/bootstrap-icons/grid-3x3-gap.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/grid-3x3.svg b/web/vendor/bootstrap-icons/grid-3x3.svg new file mode 100644 index 0000000..d56aed7 --- /dev/null +++ b/web/vendor/bootstrap-icons/grid-3x3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/grid-fill.svg b/web/vendor/bootstrap-icons/grid-fill.svg new file mode 100644 index 0000000..356cc8f --- /dev/null +++ b/web/vendor/bootstrap-icons/grid-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/grid.svg b/web/vendor/bootstrap-icons/grid.svg new file mode 100644 index 0000000..eebab73 --- /dev/null +++ b/web/vendor/bootstrap-icons/grid.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/grip-horizontal.svg b/web/vendor/bootstrap-icons/grip-horizontal.svg new file mode 100644 index 0000000..85f7e27 --- /dev/null +++ b/web/vendor/bootstrap-icons/grip-horizontal.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/grip-vertical.svg b/web/vendor/bootstrap-icons/grip-vertical.svg new file mode 100644 index 0000000..a8718ab --- /dev/null +++ b/web/vendor/bootstrap-icons/grip-vertical.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/h-circle-fill.svg b/web/vendor/bootstrap-icons/h-circle-fill.svg new file mode 100644 index 0000000..9106472 --- /dev/null +++ b/web/vendor/bootstrap-icons/h-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/h-circle.svg b/web/vendor/bootstrap-icons/h-circle.svg new file mode 100644 index 0000000..53c34b6 --- /dev/null +++ b/web/vendor/bootstrap-icons/h-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/h-square-fill.svg b/web/vendor/bootstrap-icons/h-square-fill.svg new file mode 100644 index 0000000..06269e0 --- /dev/null +++ b/web/vendor/bootstrap-icons/h-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/h-square.svg b/web/vendor/bootstrap-icons/h-square.svg new file mode 100644 index 0000000..2c5ad2c --- /dev/null +++ b/web/vendor/bootstrap-icons/h-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hammer.svg b/web/vendor/bootstrap-icons/hammer.svg new file mode 100644 index 0000000..8e07b5b --- /dev/null +++ b/web/vendor/bootstrap-icons/hammer.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hand-index-fill.svg b/web/vendor/bootstrap-icons/hand-index-fill.svg new file mode 100644 index 0000000..b2a7d64 --- /dev/null +++ b/web/vendor/bootstrap-icons/hand-index-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hand-index-thumb-fill.svg b/web/vendor/bootstrap-icons/hand-index-thumb-fill.svg new file mode 100644 index 0000000..774b18e --- /dev/null +++ b/web/vendor/bootstrap-icons/hand-index-thumb-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hand-index-thumb.svg b/web/vendor/bootstrap-icons/hand-index-thumb.svg new file mode 100644 index 0000000..13b5475 --- /dev/null +++ b/web/vendor/bootstrap-icons/hand-index-thumb.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hand-index.svg b/web/vendor/bootstrap-icons/hand-index.svg new file mode 100644 index 0000000..725757b --- /dev/null +++ b/web/vendor/bootstrap-icons/hand-index.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hand-thumbs-down-fill.svg b/web/vendor/bootstrap-icons/hand-thumbs-down-fill.svg new file mode 100644 index 0000000..53584f3 --- /dev/null +++ b/web/vendor/bootstrap-icons/hand-thumbs-down-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hand-thumbs-down.svg b/web/vendor/bootstrap-icons/hand-thumbs-down.svg new file mode 100644 index 0000000..f87f523 --- /dev/null +++ b/web/vendor/bootstrap-icons/hand-thumbs-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hand-thumbs-up-fill.svg b/web/vendor/bootstrap-icons/hand-thumbs-up-fill.svg new file mode 100644 index 0000000..c68bc07 --- /dev/null +++ b/web/vendor/bootstrap-icons/hand-thumbs-up-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hand-thumbs-up.svg b/web/vendor/bootstrap-icons/hand-thumbs-up.svg new file mode 100644 index 0000000..dc46d4d --- /dev/null +++ b/web/vendor/bootstrap-icons/hand-thumbs-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/handbag-fill.svg b/web/vendor/bootstrap-icons/handbag-fill.svg new file mode 100644 index 0000000..5f8f23f --- /dev/null +++ b/web/vendor/bootstrap-icons/handbag-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/handbag.svg b/web/vendor/bootstrap-icons/handbag.svg new file mode 100644 index 0000000..c9ef874 --- /dev/null +++ b/web/vendor/bootstrap-icons/handbag.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hash.svg b/web/vendor/bootstrap-icons/hash.svg new file mode 100644 index 0000000..f67d000 --- /dev/null +++ b/web/vendor/bootstrap-icons/hash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hdd-fill.svg b/web/vendor/bootstrap-icons/hdd-fill.svg new file mode 100644 index 0000000..dbeda24 --- /dev/null +++ b/web/vendor/bootstrap-icons/hdd-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hdd-network-fill.svg b/web/vendor/bootstrap-icons/hdd-network-fill.svg new file mode 100644 index 0000000..a74874d --- /dev/null +++ b/web/vendor/bootstrap-icons/hdd-network-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hdd-network.svg b/web/vendor/bootstrap-icons/hdd-network.svg new file mode 100644 index 0000000..7223542 --- /dev/null +++ b/web/vendor/bootstrap-icons/hdd-network.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hdd-rack-fill.svg b/web/vendor/bootstrap-icons/hdd-rack-fill.svg new file mode 100644 index 0000000..7c33aec --- /dev/null +++ b/web/vendor/bootstrap-icons/hdd-rack-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hdd-rack.svg b/web/vendor/bootstrap-icons/hdd-rack.svg new file mode 100644 index 0000000..d19a514 --- /dev/null +++ b/web/vendor/bootstrap-icons/hdd-rack.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hdd-stack-fill.svg b/web/vendor/bootstrap-icons/hdd-stack-fill.svg new file mode 100644 index 0000000..27e8719 --- /dev/null +++ b/web/vendor/bootstrap-icons/hdd-stack-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hdd-stack.svg b/web/vendor/bootstrap-icons/hdd-stack.svg new file mode 100644 index 0000000..f9095e5 --- /dev/null +++ b/web/vendor/bootstrap-icons/hdd-stack.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hdd.svg b/web/vendor/bootstrap-icons/hdd.svg new file mode 100644 index 0000000..92358f7 --- /dev/null +++ b/web/vendor/bootstrap-icons/hdd.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hdmi-fill.svg b/web/vendor/bootstrap-icons/hdmi-fill.svg new file mode 100644 index 0000000..435b39d --- /dev/null +++ b/web/vendor/bootstrap-icons/hdmi-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hdmi.svg b/web/vendor/bootstrap-icons/hdmi.svg new file mode 100644 index 0000000..09d0849 --- /dev/null +++ b/web/vendor/bootstrap-icons/hdmi.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/headphones.svg b/web/vendor/bootstrap-icons/headphones.svg new file mode 100644 index 0000000..d50b3ee --- /dev/null +++ b/web/vendor/bootstrap-icons/headphones.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/headset-vr.svg b/web/vendor/bootstrap-icons/headset-vr.svg new file mode 100644 index 0000000..0498bd6 --- /dev/null +++ b/web/vendor/bootstrap-icons/headset-vr.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/headset.svg b/web/vendor/bootstrap-icons/headset.svg new file mode 100644 index 0000000..a921156 --- /dev/null +++ b/web/vendor/bootstrap-icons/headset.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/heart-arrow.svg b/web/vendor/bootstrap-icons/heart-arrow.svg new file mode 100644 index 0000000..45eb6a5 --- /dev/null +++ b/web/vendor/bootstrap-icons/heart-arrow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/heart-fill.svg b/web/vendor/bootstrap-icons/heart-fill.svg new file mode 100644 index 0000000..5e6b8ee --- /dev/null +++ b/web/vendor/bootstrap-icons/heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/heart-half.svg b/web/vendor/bootstrap-icons/heart-half.svg new file mode 100644 index 0000000..2e0dd31 --- /dev/null +++ b/web/vendor/bootstrap-icons/heart-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/heart-pulse-fill.svg b/web/vendor/bootstrap-icons/heart-pulse-fill.svg new file mode 100644 index 0000000..fc5e219 --- /dev/null +++ b/web/vendor/bootstrap-icons/heart-pulse-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/heart-pulse.svg b/web/vendor/bootstrap-icons/heart-pulse.svg new file mode 100644 index 0000000..dd957b3 --- /dev/null +++ b/web/vendor/bootstrap-icons/heart-pulse.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/heart.svg b/web/vendor/bootstrap-icons/heart.svg new file mode 100644 index 0000000..cd8eeb1 --- /dev/null +++ b/web/vendor/bootstrap-icons/heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/heartbreak-fill.svg b/web/vendor/bootstrap-icons/heartbreak-fill.svg new file mode 100644 index 0000000..335cb6a --- /dev/null +++ b/web/vendor/bootstrap-icons/heartbreak-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/heartbreak.svg b/web/vendor/bootstrap-icons/heartbreak.svg new file mode 100644 index 0000000..dcffc89 --- /dev/null +++ b/web/vendor/bootstrap-icons/heartbreak.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hearts.svg b/web/vendor/bootstrap-icons/hearts.svg new file mode 100644 index 0000000..ebd2dbb --- /dev/null +++ b/web/vendor/bootstrap-icons/hearts.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/heptagon-fill.svg b/web/vendor/bootstrap-icons/heptagon-fill.svg new file mode 100644 index 0000000..a339328 --- /dev/null +++ b/web/vendor/bootstrap-icons/heptagon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/heptagon-half.svg b/web/vendor/bootstrap-icons/heptagon-half.svg new file mode 100644 index 0000000..b4fadcf --- /dev/null +++ b/web/vendor/bootstrap-icons/heptagon-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/heptagon.svg b/web/vendor/bootstrap-icons/heptagon.svg new file mode 100644 index 0000000..3140b8b --- /dev/null +++ b/web/vendor/bootstrap-icons/heptagon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hexagon-fill.svg b/web/vendor/bootstrap-icons/hexagon-fill.svg new file mode 100644 index 0000000..50fdbfb --- /dev/null +++ b/web/vendor/bootstrap-icons/hexagon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hexagon-half.svg b/web/vendor/bootstrap-icons/hexagon-half.svg new file mode 100644 index 0000000..452cb6e --- /dev/null +++ b/web/vendor/bootstrap-icons/hexagon-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hexagon.svg b/web/vendor/bootstrap-icons/hexagon.svg new file mode 100644 index 0000000..6e83939 --- /dev/null +++ b/web/vendor/bootstrap-icons/hexagon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/highlighter.svg b/web/vendor/bootstrap-icons/highlighter.svg new file mode 100644 index 0000000..e26f1f7 --- /dev/null +++ b/web/vendor/bootstrap-icons/highlighter.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/highlights.svg b/web/vendor/bootstrap-icons/highlights.svg new file mode 100644 index 0000000..b43fca0 --- /dev/null +++ b/web/vendor/bootstrap-icons/highlights.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hospital-fill.svg b/web/vendor/bootstrap-icons/hospital-fill.svg new file mode 100644 index 0000000..55bde0f --- /dev/null +++ b/web/vendor/bootstrap-icons/hospital-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hospital.svg b/web/vendor/bootstrap-icons/hospital.svg new file mode 100644 index 0000000..f6bd0da --- /dev/null +++ b/web/vendor/bootstrap-icons/hospital.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hourglass-bottom.svg b/web/vendor/bootstrap-icons/hourglass-bottom.svg new file mode 100644 index 0000000..946f882 --- /dev/null +++ b/web/vendor/bootstrap-icons/hourglass-bottom.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hourglass-split.svg b/web/vendor/bootstrap-icons/hourglass-split.svg new file mode 100644 index 0000000..a9d1c51 --- /dev/null +++ b/web/vendor/bootstrap-icons/hourglass-split.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hourglass-top.svg b/web/vendor/bootstrap-icons/hourglass-top.svg new file mode 100644 index 0000000..6a8a4a3 --- /dev/null +++ b/web/vendor/bootstrap-icons/hourglass-top.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hourglass.svg b/web/vendor/bootstrap-icons/hourglass.svg new file mode 100644 index 0000000..44ede0a --- /dev/null +++ b/web/vendor/bootstrap-icons/hourglass.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-add-fill.svg b/web/vendor/bootstrap-icons/house-add-fill.svg new file mode 100644 index 0000000..1e814ee --- /dev/null +++ b/web/vendor/bootstrap-icons/house-add-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-add.svg b/web/vendor/bootstrap-icons/house-add.svg new file mode 100644 index 0000000..2a89bbe --- /dev/null +++ b/web/vendor/bootstrap-icons/house-add.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-check-fill.svg b/web/vendor/bootstrap-icons/house-check-fill.svg new file mode 100644 index 0000000..f2ddeb9 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-check-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-check.svg b/web/vendor/bootstrap-icons/house-check.svg new file mode 100644 index 0000000..5bd7900 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-dash-fill.svg b/web/vendor/bootstrap-icons/house-dash-fill.svg new file mode 100644 index 0000000..2fa8c57 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-dash-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-dash.svg b/web/vendor/bootstrap-icons/house-dash.svg new file mode 100644 index 0000000..b1cb832 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-door-fill.svg b/web/vendor/bootstrap-icons/house-door-fill.svg new file mode 100644 index 0000000..cf6d439 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-door-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-door.svg b/web/vendor/bootstrap-icons/house-door.svg new file mode 100644 index 0000000..daa093b --- /dev/null +++ b/web/vendor/bootstrap-icons/house-door.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-down-fill.svg b/web/vendor/bootstrap-icons/house-down-fill.svg new file mode 100644 index 0000000..351904f --- /dev/null +++ b/web/vendor/bootstrap-icons/house-down-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-down.svg b/web/vendor/bootstrap-icons/house-down.svg new file mode 100644 index 0000000..4d1d905 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-exclamation-fill.svg b/web/vendor/bootstrap-icons/house-exclamation-fill.svg new file mode 100644 index 0000000..52fc0ae --- /dev/null +++ b/web/vendor/bootstrap-icons/house-exclamation-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-exclamation.svg b/web/vendor/bootstrap-icons/house-exclamation.svg new file mode 100644 index 0000000..6d414f3 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-fill.svg b/web/vendor/bootstrap-icons/house-fill.svg new file mode 100644 index 0000000..89db164 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-gear-fill.svg b/web/vendor/bootstrap-icons/house-gear-fill.svg new file mode 100644 index 0000000..9003152 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-gear-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-gear.svg b/web/vendor/bootstrap-icons/house-gear.svg new file mode 100644 index 0000000..65b5abb --- /dev/null +++ b/web/vendor/bootstrap-icons/house-gear.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-heart-fill.svg b/web/vendor/bootstrap-icons/house-heart-fill.svg new file mode 100644 index 0000000..be2e5f4 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-heart-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-heart.svg b/web/vendor/bootstrap-icons/house-heart.svg new file mode 100644 index 0000000..ece6c06 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-lock-fill.svg b/web/vendor/bootstrap-icons/house-lock-fill.svg new file mode 100644 index 0000000..90cc8c7 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-lock-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-lock.svg b/web/vendor/bootstrap-icons/house-lock.svg new file mode 100644 index 0000000..8dc5894 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-lock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-slash-fill.svg b/web/vendor/bootstrap-icons/house-slash-fill.svg new file mode 100644 index 0000000..df8d7c6 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-slash-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-slash.svg b/web/vendor/bootstrap-icons/house-slash.svg new file mode 100644 index 0000000..a81b0ed --- /dev/null +++ b/web/vendor/bootstrap-icons/house-slash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-up-fill.svg b/web/vendor/bootstrap-icons/house-up-fill.svg new file mode 100644 index 0000000..5e6a801 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-up-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-up.svg b/web/vendor/bootstrap-icons/house-up.svg new file mode 100644 index 0000000..da183d2 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-x-fill.svg b/web/vendor/bootstrap-icons/house-x-fill.svg new file mode 100644 index 0000000..729cdb5 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-x-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house-x.svg b/web/vendor/bootstrap-icons/house-x.svg new file mode 100644 index 0000000..68137c0 --- /dev/null +++ b/web/vendor/bootstrap-icons/house-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/house.svg b/web/vendor/bootstrap-icons/house.svg new file mode 100644 index 0000000..cb57f68 --- /dev/null +++ b/web/vendor/bootstrap-icons/house.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/houses-fill.svg b/web/vendor/bootstrap-icons/houses-fill.svg new file mode 100644 index 0000000..63047bb --- /dev/null +++ b/web/vendor/bootstrap-icons/houses-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/houses.svg b/web/vendor/bootstrap-icons/houses.svg new file mode 100644 index 0000000..3a906be --- /dev/null +++ b/web/vendor/bootstrap-icons/houses.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hr.svg b/web/vendor/bootstrap-icons/hr.svg new file mode 100644 index 0000000..6e9fbd8 --- /dev/null +++ b/web/vendor/bootstrap-icons/hr.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hurricane.svg b/web/vendor/bootstrap-icons/hurricane.svg new file mode 100644 index 0000000..5bd9ae1 --- /dev/null +++ b/web/vendor/bootstrap-icons/hurricane.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/hypnotize.svg b/web/vendor/bootstrap-icons/hypnotize.svg new file mode 100644 index 0000000..6a28997 --- /dev/null +++ b/web/vendor/bootstrap-icons/hypnotize.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/image-alt.svg b/web/vendor/bootstrap-icons/image-alt.svg new file mode 100644 index 0000000..e56ee20 --- /dev/null +++ b/web/vendor/bootstrap-icons/image-alt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/image-fill.svg b/web/vendor/bootstrap-icons/image-fill.svg new file mode 100644 index 0000000..db26ae8 --- /dev/null +++ b/web/vendor/bootstrap-icons/image-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/image.svg b/web/vendor/bootstrap-icons/image.svg new file mode 100644 index 0000000..152c333 --- /dev/null +++ b/web/vendor/bootstrap-icons/image.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/images.svg b/web/vendor/bootstrap-icons/images.svg new file mode 100644 index 0000000..adc7abf --- /dev/null +++ b/web/vendor/bootstrap-icons/images.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/inbox-fill.svg b/web/vendor/bootstrap-icons/inbox-fill.svg new file mode 100644 index 0000000..7e4816d --- /dev/null +++ b/web/vendor/bootstrap-icons/inbox-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/inbox.svg b/web/vendor/bootstrap-icons/inbox.svg new file mode 100644 index 0000000..b60e949 --- /dev/null +++ b/web/vendor/bootstrap-icons/inbox.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/inboxes-fill.svg b/web/vendor/bootstrap-icons/inboxes-fill.svg new file mode 100644 index 0000000..4d8c5f7 --- /dev/null +++ b/web/vendor/bootstrap-icons/inboxes-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/inboxes.svg b/web/vendor/bootstrap-icons/inboxes.svg new file mode 100644 index 0000000..1a074ac --- /dev/null +++ b/web/vendor/bootstrap-icons/inboxes.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/incognito.svg b/web/vendor/bootstrap-icons/incognito.svg new file mode 100644 index 0000000..f2c8f9d --- /dev/null +++ b/web/vendor/bootstrap-icons/incognito.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/indent.svg b/web/vendor/bootstrap-icons/indent.svg new file mode 100644 index 0000000..0065aba --- /dev/null +++ b/web/vendor/bootstrap-icons/indent.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/infinity.svg b/web/vendor/bootstrap-icons/infinity.svg new file mode 100644 index 0000000..3dca19b --- /dev/null +++ b/web/vendor/bootstrap-icons/infinity.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/info-circle-fill.svg b/web/vendor/bootstrap-icons/info-circle-fill.svg new file mode 100644 index 0000000..d2e382b --- /dev/null +++ b/web/vendor/bootstrap-icons/info-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/info-circle.svg b/web/vendor/bootstrap-icons/info-circle.svg new file mode 100644 index 0000000..e2b50eb --- /dev/null +++ b/web/vendor/bootstrap-icons/info-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/info-lg.svg b/web/vendor/bootstrap-icons/info-lg.svg new file mode 100644 index 0000000..ac064b9 --- /dev/null +++ b/web/vendor/bootstrap-icons/info-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/info-square-fill.svg b/web/vendor/bootstrap-icons/info-square-fill.svg new file mode 100644 index 0000000..49196b4 --- /dev/null +++ b/web/vendor/bootstrap-icons/info-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/info-square.svg b/web/vendor/bootstrap-icons/info-square.svg new file mode 100644 index 0000000..b64cfa8 --- /dev/null +++ b/web/vendor/bootstrap-icons/info-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/info.svg b/web/vendor/bootstrap-icons/info.svg new file mode 100644 index 0000000..43dc242 --- /dev/null +++ b/web/vendor/bootstrap-icons/info.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/input-cursor-text.svg b/web/vendor/bootstrap-icons/input-cursor-text.svg new file mode 100644 index 0000000..fc910f3 --- /dev/null +++ b/web/vendor/bootstrap-icons/input-cursor-text.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/input-cursor.svg b/web/vendor/bootstrap-icons/input-cursor.svg new file mode 100644 index 0000000..de6a35f --- /dev/null +++ b/web/vendor/bootstrap-icons/input-cursor.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/instagram.svg b/web/vendor/bootstrap-icons/instagram.svg new file mode 100644 index 0000000..855e653 --- /dev/null +++ b/web/vendor/bootstrap-icons/instagram.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/intersect.svg b/web/vendor/bootstrap-icons/intersect.svg new file mode 100644 index 0000000..220141d --- /dev/null +++ b/web/vendor/bootstrap-icons/intersect.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/javascript.svg b/web/vendor/bootstrap-icons/javascript.svg new file mode 100644 index 0000000..8a7e716 --- /dev/null +++ b/web/vendor/bootstrap-icons/javascript.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/journal-album.svg b/web/vendor/bootstrap-icons/journal-album.svg new file mode 100644 index 0000000..de49ccc --- /dev/null +++ b/web/vendor/bootstrap-icons/journal-album.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/journal-arrow-down.svg b/web/vendor/bootstrap-icons/journal-arrow-down.svg new file mode 100644 index 0000000..d922f3c --- /dev/null +++ b/web/vendor/bootstrap-icons/journal-arrow-down.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/journal-arrow-up.svg b/web/vendor/bootstrap-icons/journal-arrow-up.svg new file mode 100644 index 0000000..7edc400 --- /dev/null +++ b/web/vendor/bootstrap-icons/journal-arrow-up.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/journal-bookmark-fill.svg b/web/vendor/bootstrap-icons/journal-bookmark-fill.svg new file mode 100644 index 0000000..8e2f17a --- /dev/null +++ b/web/vendor/bootstrap-icons/journal-bookmark-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/journal-bookmark.svg b/web/vendor/bootstrap-icons/journal-bookmark.svg new file mode 100644 index 0000000..4a8f4bb --- /dev/null +++ b/web/vendor/bootstrap-icons/journal-bookmark.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/journal-check.svg b/web/vendor/bootstrap-icons/journal-check.svg new file mode 100644 index 0000000..eb398b9 --- /dev/null +++ b/web/vendor/bootstrap-icons/journal-check.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/journal-code.svg b/web/vendor/bootstrap-icons/journal-code.svg new file mode 100644 index 0000000..41430d2 --- /dev/null +++ b/web/vendor/bootstrap-icons/journal-code.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/journal-medical.svg b/web/vendor/bootstrap-icons/journal-medical.svg new file mode 100644 index 0000000..fb6d942 --- /dev/null +++ b/web/vendor/bootstrap-icons/journal-medical.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/journal-minus.svg b/web/vendor/bootstrap-icons/journal-minus.svg new file mode 100644 index 0000000..cbdfdd7 --- /dev/null +++ b/web/vendor/bootstrap-icons/journal-minus.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/journal-plus.svg b/web/vendor/bootstrap-icons/journal-plus.svg new file mode 100644 index 0000000..5cb82c3 --- /dev/null +++ b/web/vendor/bootstrap-icons/journal-plus.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/journal-richtext.svg b/web/vendor/bootstrap-icons/journal-richtext.svg new file mode 100644 index 0000000..db92c70 --- /dev/null +++ b/web/vendor/bootstrap-icons/journal-richtext.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/journal-text.svg b/web/vendor/bootstrap-icons/journal-text.svg new file mode 100644 index 0000000..13c58bc --- /dev/null +++ b/web/vendor/bootstrap-icons/journal-text.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/journal-x.svg b/web/vendor/bootstrap-icons/journal-x.svg new file mode 100644 index 0000000..fb3ea9f --- /dev/null +++ b/web/vendor/bootstrap-icons/journal-x.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/journal.svg b/web/vendor/bootstrap-icons/journal.svg new file mode 100644 index 0000000..4c166e2 --- /dev/null +++ b/web/vendor/bootstrap-icons/journal.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/journals.svg b/web/vendor/bootstrap-icons/journals.svg new file mode 100644 index 0000000..6e5386a --- /dev/null +++ b/web/vendor/bootstrap-icons/journals.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/joystick.svg b/web/vendor/bootstrap-icons/joystick.svg new file mode 100644 index 0000000..909369e --- /dev/null +++ b/web/vendor/bootstrap-icons/joystick.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/justify-left.svg b/web/vendor/bootstrap-icons/justify-left.svg new file mode 100644 index 0000000..17b45e4 --- /dev/null +++ b/web/vendor/bootstrap-icons/justify-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/justify-right.svg b/web/vendor/bootstrap-icons/justify-right.svg new file mode 100644 index 0000000..4d96c43 --- /dev/null +++ b/web/vendor/bootstrap-icons/justify-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/justify.svg b/web/vendor/bootstrap-icons/justify.svg new file mode 100644 index 0000000..3eedc74 --- /dev/null +++ b/web/vendor/bootstrap-icons/justify.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/kanban-fill.svg b/web/vendor/bootstrap-icons/kanban-fill.svg new file mode 100644 index 0000000..a8ed5bb --- /dev/null +++ b/web/vendor/bootstrap-icons/kanban-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/kanban.svg b/web/vendor/bootstrap-icons/kanban.svg new file mode 100644 index 0000000..cd13b32 --- /dev/null +++ b/web/vendor/bootstrap-icons/kanban.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/key-fill.svg b/web/vendor/bootstrap-icons/key-fill.svg new file mode 100644 index 0000000..fdab8d6 --- /dev/null +++ b/web/vendor/bootstrap-icons/key-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/key.svg b/web/vendor/bootstrap-icons/key.svg new file mode 100644 index 0000000..b0d1e16 --- /dev/null +++ b/web/vendor/bootstrap-icons/key.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/keyboard-fill.svg b/web/vendor/bootstrap-icons/keyboard-fill.svg new file mode 100644 index 0000000..b46ad2d --- /dev/null +++ b/web/vendor/bootstrap-icons/keyboard-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/keyboard.svg b/web/vendor/bootstrap-icons/keyboard.svg new file mode 100644 index 0000000..8ba49b6 --- /dev/null +++ b/web/vendor/bootstrap-icons/keyboard.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ladder.svg b/web/vendor/bootstrap-icons/ladder.svg new file mode 100644 index 0000000..7c6864f --- /dev/null +++ b/web/vendor/bootstrap-icons/ladder.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/lamp-fill.svg b/web/vendor/bootstrap-icons/lamp-fill.svg new file mode 100644 index 0000000..836b0db --- /dev/null +++ b/web/vendor/bootstrap-icons/lamp-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/lamp.svg b/web/vendor/bootstrap-icons/lamp.svg new file mode 100644 index 0000000..b3fa1d6 --- /dev/null +++ b/web/vendor/bootstrap-icons/lamp.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/laptop-fill.svg b/web/vendor/bootstrap-icons/laptop-fill.svg new file mode 100644 index 0000000..31e5880 --- /dev/null +++ b/web/vendor/bootstrap-icons/laptop-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/laptop.svg b/web/vendor/bootstrap-icons/laptop.svg new file mode 100644 index 0000000..8e71020 --- /dev/null +++ b/web/vendor/bootstrap-icons/laptop.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/layer-backward.svg b/web/vendor/bootstrap-icons/layer-backward.svg new file mode 100644 index 0000000..ed43c70 --- /dev/null +++ b/web/vendor/bootstrap-icons/layer-backward.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/layer-forward.svg b/web/vendor/bootstrap-icons/layer-forward.svg new file mode 100644 index 0000000..d0a4abf --- /dev/null +++ b/web/vendor/bootstrap-icons/layer-forward.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/layers-fill.svg b/web/vendor/bootstrap-icons/layers-fill.svg new file mode 100644 index 0000000..3b6cdf6 --- /dev/null +++ b/web/vendor/bootstrap-icons/layers-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/layers-half.svg b/web/vendor/bootstrap-icons/layers-half.svg new file mode 100644 index 0000000..8ceaaad --- /dev/null +++ b/web/vendor/bootstrap-icons/layers-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/layers.svg b/web/vendor/bootstrap-icons/layers.svg new file mode 100644 index 0000000..52dbe79 --- /dev/null +++ b/web/vendor/bootstrap-icons/layers.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/layout-sidebar-inset-reverse.svg b/web/vendor/bootstrap-icons/layout-sidebar-inset-reverse.svg new file mode 100644 index 0000000..0d8dc7f --- /dev/null +++ b/web/vendor/bootstrap-icons/layout-sidebar-inset-reverse.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/layout-sidebar-inset.svg b/web/vendor/bootstrap-icons/layout-sidebar-inset.svg new file mode 100644 index 0000000..cc19c86 --- /dev/null +++ b/web/vendor/bootstrap-icons/layout-sidebar-inset.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/layout-sidebar-reverse.svg b/web/vendor/bootstrap-icons/layout-sidebar-reverse.svg new file mode 100644 index 0000000..7c03f73 --- /dev/null +++ b/web/vendor/bootstrap-icons/layout-sidebar-reverse.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/layout-sidebar.svg b/web/vendor/bootstrap-icons/layout-sidebar.svg new file mode 100644 index 0000000..ff40858 --- /dev/null +++ b/web/vendor/bootstrap-icons/layout-sidebar.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/layout-split.svg b/web/vendor/bootstrap-icons/layout-split.svg new file mode 100644 index 0000000..4805b25 --- /dev/null +++ b/web/vendor/bootstrap-icons/layout-split.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/layout-text-sidebar-reverse.svg b/web/vendor/bootstrap-icons/layout-text-sidebar-reverse.svg new file mode 100644 index 0000000..9179285 --- /dev/null +++ b/web/vendor/bootstrap-icons/layout-text-sidebar-reverse.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/layout-text-sidebar.svg b/web/vendor/bootstrap-icons/layout-text-sidebar.svg new file mode 100644 index 0000000..6d89f67 --- /dev/null +++ b/web/vendor/bootstrap-icons/layout-text-sidebar.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/layout-text-window-reverse.svg b/web/vendor/bootstrap-icons/layout-text-window-reverse.svg new file mode 100644 index 0000000..8258ad3 --- /dev/null +++ b/web/vendor/bootstrap-icons/layout-text-window-reverse.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/layout-text-window.svg b/web/vendor/bootstrap-icons/layout-text-window.svg new file mode 100644 index 0000000..4d27cf9 --- /dev/null +++ b/web/vendor/bootstrap-icons/layout-text-window.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/layout-three-columns.svg b/web/vendor/bootstrap-icons/layout-three-columns.svg new file mode 100644 index 0000000..7117f07 --- /dev/null +++ b/web/vendor/bootstrap-icons/layout-three-columns.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/layout-wtf.svg b/web/vendor/bootstrap-icons/layout-wtf.svg new file mode 100644 index 0000000..fd8f5a1 --- /dev/null +++ b/web/vendor/bootstrap-icons/layout-wtf.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/leaf-fill.svg b/web/vendor/bootstrap-icons/leaf-fill.svg new file mode 100644 index 0000000..094ab20 --- /dev/null +++ b/web/vendor/bootstrap-icons/leaf-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/leaf.svg b/web/vendor/bootstrap-icons/leaf.svg new file mode 100644 index 0000000..37b51e3 --- /dev/null +++ b/web/vendor/bootstrap-icons/leaf.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/life-preserver.svg b/web/vendor/bootstrap-icons/life-preserver.svg new file mode 100644 index 0000000..7282baa --- /dev/null +++ b/web/vendor/bootstrap-icons/life-preserver.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/lightbulb-fill.svg b/web/vendor/bootstrap-icons/lightbulb-fill.svg new file mode 100644 index 0000000..0ef90ea --- /dev/null +++ b/web/vendor/bootstrap-icons/lightbulb-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/lightbulb-off-fill.svg b/web/vendor/bootstrap-icons/lightbulb-off-fill.svg new file mode 100644 index 0000000..e533739 --- /dev/null +++ b/web/vendor/bootstrap-icons/lightbulb-off-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/lightbulb-off.svg b/web/vendor/bootstrap-icons/lightbulb-off.svg new file mode 100644 index 0000000..15e8200 --- /dev/null +++ b/web/vendor/bootstrap-icons/lightbulb-off.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/lightbulb.svg b/web/vendor/bootstrap-icons/lightbulb.svg new file mode 100644 index 0000000..67bf5bd --- /dev/null +++ b/web/vendor/bootstrap-icons/lightbulb.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/lightning-charge-fill.svg b/web/vendor/bootstrap-icons/lightning-charge-fill.svg new file mode 100644 index 0000000..5e197fb --- /dev/null +++ b/web/vendor/bootstrap-icons/lightning-charge-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/lightning-charge.svg b/web/vendor/bootstrap-icons/lightning-charge.svg new file mode 100644 index 0000000..5352e72 --- /dev/null +++ b/web/vendor/bootstrap-icons/lightning-charge.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/lightning-fill.svg b/web/vendor/bootstrap-icons/lightning-fill.svg new file mode 100644 index 0000000..b98af68 --- /dev/null +++ b/web/vendor/bootstrap-icons/lightning-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/lightning.svg b/web/vendor/bootstrap-icons/lightning.svg new file mode 100644 index 0000000..d2faa0f --- /dev/null +++ b/web/vendor/bootstrap-icons/lightning.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/line.svg b/web/vendor/bootstrap-icons/line.svg new file mode 100644 index 0000000..3e4bfd3 --- /dev/null +++ b/web/vendor/bootstrap-icons/line.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/link-45deg.svg b/web/vendor/bootstrap-icons/link-45deg.svg new file mode 100644 index 0000000..abdc8cb --- /dev/null +++ b/web/vendor/bootstrap-icons/link-45deg.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/link.svg b/web/vendor/bootstrap-icons/link.svg new file mode 100644 index 0000000..823e4cd --- /dev/null +++ b/web/vendor/bootstrap-icons/link.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/linkedin.svg b/web/vendor/bootstrap-icons/linkedin.svg new file mode 100644 index 0000000..30fc0e3 --- /dev/null +++ b/web/vendor/bootstrap-icons/linkedin.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/list-check.svg b/web/vendor/bootstrap-icons/list-check.svg new file mode 100644 index 0000000..e1db377 --- /dev/null +++ b/web/vendor/bootstrap-icons/list-check.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/list-columns-reverse.svg b/web/vendor/bootstrap-icons/list-columns-reverse.svg new file mode 100644 index 0000000..f5e2876 --- /dev/null +++ b/web/vendor/bootstrap-icons/list-columns-reverse.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/list-columns.svg b/web/vendor/bootstrap-icons/list-columns.svg new file mode 100644 index 0000000..07d0b1a --- /dev/null +++ b/web/vendor/bootstrap-icons/list-columns.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/list-nested.svg b/web/vendor/bootstrap-icons/list-nested.svg new file mode 100644 index 0000000..26607c9 --- /dev/null +++ b/web/vendor/bootstrap-icons/list-nested.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/list-ol.svg b/web/vendor/bootstrap-icons/list-ol.svg new file mode 100644 index 0000000..d111f73 --- /dev/null +++ b/web/vendor/bootstrap-icons/list-ol.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/list-stars.svg b/web/vendor/bootstrap-icons/list-stars.svg new file mode 100644 index 0000000..c520bdf --- /dev/null +++ b/web/vendor/bootstrap-icons/list-stars.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/list-task.svg b/web/vendor/bootstrap-icons/list-task.svg new file mode 100644 index 0000000..3905d7a --- /dev/null +++ b/web/vendor/bootstrap-icons/list-task.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/list-ul.svg b/web/vendor/bootstrap-icons/list-ul.svg new file mode 100644 index 0000000..f1cc202 --- /dev/null +++ b/web/vendor/bootstrap-icons/list-ul.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/list.svg b/web/vendor/bootstrap-icons/list.svg new file mode 100644 index 0000000..de58858 --- /dev/null +++ b/web/vendor/bootstrap-icons/list.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/lock-fill.svg b/web/vendor/bootstrap-icons/lock-fill.svg new file mode 100644 index 0000000..9e9ff14 --- /dev/null +++ b/web/vendor/bootstrap-icons/lock-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/lock.svg b/web/vendor/bootstrap-icons/lock.svg new file mode 100644 index 0000000..c38aa42 --- /dev/null +++ b/web/vendor/bootstrap-icons/lock.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/luggage-fill.svg b/web/vendor/bootstrap-icons/luggage-fill.svg new file mode 100644 index 0000000..eb7378f --- /dev/null +++ b/web/vendor/bootstrap-icons/luggage-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/luggage.svg b/web/vendor/bootstrap-icons/luggage.svg new file mode 100644 index 0000000..ad037ba --- /dev/null +++ b/web/vendor/bootstrap-icons/luggage.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/lungs-fill.svg b/web/vendor/bootstrap-icons/lungs-fill.svg new file mode 100644 index 0000000..2880fa6 --- /dev/null +++ b/web/vendor/bootstrap-icons/lungs-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/lungs.svg b/web/vendor/bootstrap-icons/lungs.svg new file mode 100644 index 0000000..082e7de --- /dev/null +++ b/web/vendor/bootstrap-icons/lungs.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/magic.svg b/web/vendor/bootstrap-icons/magic.svg new file mode 100644 index 0000000..0b2f1fd --- /dev/null +++ b/web/vendor/bootstrap-icons/magic.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/magnet-fill.svg b/web/vendor/bootstrap-icons/magnet-fill.svg new file mode 100644 index 0000000..026d0de --- /dev/null +++ b/web/vendor/bootstrap-icons/magnet-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/magnet.svg b/web/vendor/bootstrap-icons/magnet.svg new file mode 100644 index 0000000..36b238b --- /dev/null +++ b/web/vendor/bootstrap-icons/magnet.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mailbox-flag.svg b/web/vendor/bootstrap-icons/mailbox-flag.svg new file mode 100644 index 0000000..8e24db0 --- /dev/null +++ b/web/vendor/bootstrap-icons/mailbox-flag.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mailbox.svg b/web/vendor/bootstrap-icons/mailbox.svg new file mode 100644 index 0000000..1048e2a --- /dev/null +++ b/web/vendor/bootstrap-icons/mailbox.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mailbox2-flag.svg b/web/vendor/bootstrap-icons/mailbox2-flag.svg new file mode 100644 index 0000000..a253700 --- /dev/null +++ b/web/vendor/bootstrap-icons/mailbox2-flag.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mailbox2.svg b/web/vendor/bootstrap-icons/mailbox2.svg new file mode 100644 index 0000000..33e22a6 --- /dev/null +++ b/web/vendor/bootstrap-icons/mailbox2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/map-fill.svg b/web/vendor/bootstrap-icons/map-fill.svg new file mode 100644 index 0000000..7134540 --- /dev/null +++ b/web/vendor/bootstrap-icons/map-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/map.svg b/web/vendor/bootstrap-icons/map.svg new file mode 100644 index 0000000..2b579ce --- /dev/null +++ b/web/vendor/bootstrap-icons/map.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/markdown-fill.svg b/web/vendor/bootstrap-icons/markdown-fill.svg new file mode 100644 index 0000000..a932fbb --- /dev/null +++ b/web/vendor/bootstrap-icons/markdown-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/markdown.svg b/web/vendor/bootstrap-icons/markdown.svg new file mode 100644 index 0000000..33962c6 --- /dev/null +++ b/web/vendor/bootstrap-icons/markdown.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/marker-tip.svg b/web/vendor/bootstrap-icons/marker-tip.svg new file mode 100644 index 0000000..e00f931 --- /dev/null +++ b/web/vendor/bootstrap-icons/marker-tip.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mask.svg b/web/vendor/bootstrap-icons/mask.svg new file mode 100644 index 0000000..b51158c --- /dev/null +++ b/web/vendor/bootstrap-icons/mask.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mastodon.svg b/web/vendor/bootstrap-icons/mastodon.svg new file mode 100644 index 0000000..a8c2a26 --- /dev/null +++ b/web/vendor/bootstrap-icons/mastodon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/measuring-cup-fill.svg b/web/vendor/bootstrap-icons/measuring-cup-fill.svg new file mode 100644 index 0000000..a62ef9e --- /dev/null +++ b/web/vendor/bootstrap-icons/measuring-cup-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/measuring-cup.svg b/web/vendor/bootstrap-icons/measuring-cup.svg new file mode 100644 index 0000000..6020df9 --- /dev/null +++ b/web/vendor/bootstrap-icons/measuring-cup.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/medium.svg b/web/vendor/bootstrap-icons/medium.svg new file mode 100644 index 0000000..065ace1 --- /dev/null +++ b/web/vendor/bootstrap-icons/medium.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/megaphone-fill.svg b/web/vendor/bootstrap-icons/megaphone-fill.svg new file mode 100644 index 0000000..9f44f2e --- /dev/null +++ b/web/vendor/bootstrap-icons/megaphone-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/megaphone.svg b/web/vendor/bootstrap-icons/megaphone.svg new file mode 100644 index 0000000..1cedb30 --- /dev/null +++ b/web/vendor/bootstrap-icons/megaphone.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/memory.svg b/web/vendor/bootstrap-icons/memory.svg new file mode 100644 index 0000000..48764d2 --- /dev/null +++ b/web/vendor/bootstrap-icons/memory.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/menu-app-fill.svg b/web/vendor/bootstrap-icons/menu-app-fill.svg new file mode 100644 index 0000000..65cfdcf --- /dev/null +++ b/web/vendor/bootstrap-icons/menu-app-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/menu-app.svg b/web/vendor/bootstrap-icons/menu-app.svg new file mode 100644 index 0000000..ecda144 --- /dev/null +++ b/web/vendor/bootstrap-icons/menu-app.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/menu-button-fill.svg b/web/vendor/bootstrap-icons/menu-button-fill.svg new file mode 100644 index 0000000..09b2805 --- /dev/null +++ b/web/vendor/bootstrap-icons/menu-button-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/menu-button-wide-fill.svg b/web/vendor/bootstrap-icons/menu-button-wide-fill.svg new file mode 100644 index 0000000..d97ce7f --- /dev/null +++ b/web/vendor/bootstrap-icons/menu-button-wide-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/menu-button-wide.svg b/web/vendor/bootstrap-icons/menu-button-wide.svg new file mode 100644 index 0000000..5636c10 --- /dev/null +++ b/web/vendor/bootstrap-icons/menu-button-wide.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/menu-button.svg b/web/vendor/bootstrap-icons/menu-button.svg new file mode 100644 index 0000000..ec4c70a --- /dev/null +++ b/web/vendor/bootstrap-icons/menu-button.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/menu-down.svg b/web/vendor/bootstrap-icons/menu-down.svg new file mode 100644 index 0000000..e53a5e9 --- /dev/null +++ b/web/vendor/bootstrap-icons/menu-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/menu-up.svg b/web/vendor/bootstrap-icons/menu-up.svg new file mode 100644 index 0000000..96ff58b --- /dev/null +++ b/web/vendor/bootstrap-icons/menu-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/messenger.svg b/web/vendor/bootstrap-icons/messenger.svg new file mode 100644 index 0000000..e896a79 --- /dev/null +++ b/web/vendor/bootstrap-icons/messenger.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/meta.svg b/web/vendor/bootstrap-icons/meta.svg new file mode 100644 index 0000000..7c7510b --- /dev/null +++ b/web/vendor/bootstrap-icons/meta.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mic-fill.svg b/web/vendor/bootstrap-icons/mic-fill.svg new file mode 100644 index 0000000..c92ade7 --- /dev/null +++ b/web/vendor/bootstrap-icons/mic-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mic-mute-fill.svg b/web/vendor/bootstrap-icons/mic-mute-fill.svg new file mode 100644 index 0000000..a10a1bc --- /dev/null +++ b/web/vendor/bootstrap-icons/mic-mute-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mic-mute.svg b/web/vendor/bootstrap-icons/mic-mute.svg new file mode 100644 index 0000000..59b04be --- /dev/null +++ b/web/vendor/bootstrap-icons/mic-mute.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mic.svg b/web/vendor/bootstrap-icons/mic.svg new file mode 100644 index 0000000..f07bf14 --- /dev/null +++ b/web/vendor/bootstrap-icons/mic.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/microsoft-teams.svg b/web/vendor/bootstrap-icons/microsoft-teams.svg new file mode 100644 index 0000000..6bf3a0c --- /dev/null +++ b/web/vendor/bootstrap-icons/microsoft-teams.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/microsoft.svg b/web/vendor/bootstrap-icons/microsoft.svg new file mode 100644 index 0000000..8d2a03c --- /dev/null +++ b/web/vendor/bootstrap-icons/microsoft.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/minecart-loaded.svg b/web/vendor/bootstrap-icons/minecart-loaded.svg new file mode 100644 index 0000000..48e523f --- /dev/null +++ b/web/vendor/bootstrap-icons/minecart-loaded.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/minecart.svg b/web/vendor/bootstrap-icons/minecart.svg new file mode 100644 index 0000000..c4869c2 --- /dev/null +++ b/web/vendor/bootstrap-icons/minecart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/modem-fill.svg b/web/vendor/bootstrap-icons/modem-fill.svg new file mode 100644 index 0000000..a5dd5e2 --- /dev/null +++ b/web/vendor/bootstrap-icons/modem-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/modem.svg b/web/vendor/bootstrap-icons/modem.svg new file mode 100644 index 0000000..f90ad6b --- /dev/null +++ b/web/vendor/bootstrap-icons/modem.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/moisture.svg b/web/vendor/bootstrap-icons/moisture.svg new file mode 100644 index 0000000..490fb49 --- /dev/null +++ b/web/vendor/bootstrap-icons/moisture.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/moon-fill.svg b/web/vendor/bootstrap-icons/moon-fill.svg new file mode 100644 index 0000000..67f6739 --- /dev/null +++ b/web/vendor/bootstrap-icons/moon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/moon-stars-fill.svg b/web/vendor/bootstrap-icons/moon-stars-fill.svg new file mode 100644 index 0000000..c50e070 --- /dev/null +++ b/web/vendor/bootstrap-icons/moon-stars-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/moon-stars.svg b/web/vendor/bootstrap-icons/moon-stars.svg new file mode 100644 index 0000000..ae138c2 --- /dev/null +++ b/web/vendor/bootstrap-icons/moon-stars.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/moon.svg b/web/vendor/bootstrap-icons/moon.svg new file mode 100644 index 0000000..46458ec --- /dev/null +++ b/web/vendor/bootstrap-icons/moon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mortarboard-fill.svg b/web/vendor/bootstrap-icons/mortarboard-fill.svg new file mode 100644 index 0000000..02f6c8c --- /dev/null +++ b/web/vendor/bootstrap-icons/mortarboard-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mortarboard.svg b/web/vendor/bootstrap-icons/mortarboard.svg new file mode 100644 index 0000000..94f9e97 --- /dev/null +++ b/web/vendor/bootstrap-icons/mortarboard.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/motherboard-fill.svg b/web/vendor/bootstrap-icons/motherboard-fill.svg new file mode 100644 index 0000000..fabff97 --- /dev/null +++ b/web/vendor/bootstrap-icons/motherboard-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/motherboard.svg b/web/vendor/bootstrap-icons/motherboard.svg new file mode 100644 index 0000000..d29e255 --- /dev/null +++ b/web/vendor/bootstrap-icons/motherboard.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mouse-fill.svg b/web/vendor/bootstrap-icons/mouse-fill.svg new file mode 100644 index 0000000..24d275e --- /dev/null +++ b/web/vendor/bootstrap-icons/mouse-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mouse.svg b/web/vendor/bootstrap-icons/mouse.svg new file mode 100644 index 0000000..e018811 --- /dev/null +++ b/web/vendor/bootstrap-icons/mouse.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mouse2-fill.svg b/web/vendor/bootstrap-icons/mouse2-fill.svg new file mode 100644 index 0000000..6277b44 --- /dev/null +++ b/web/vendor/bootstrap-icons/mouse2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mouse2.svg b/web/vendor/bootstrap-icons/mouse2.svg new file mode 100644 index 0000000..fd15e7c --- /dev/null +++ b/web/vendor/bootstrap-icons/mouse2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mouse3-fill.svg b/web/vendor/bootstrap-icons/mouse3-fill.svg new file mode 100644 index 0000000..16c1705 --- /dev/null +++ b/web/vendor/bootstrap-icons/mouse3-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/mouse3.svg b/web/vendor/bootstrap-icons/mouse3.svg new file mode 100644 index 0000000..548b244 --- /dev/null +++ b/web/vendor/bootstrap-icons/mouse3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/music-note-beamed.svg b/web/vendor/bootstrap-icons/music-note-beamed.svg new file mode 100644 index 0000000..9eb1506 --- /dev/null +++ b/web/vendor/bootstrap-icons/music-note-beamed.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/music-note-list.svg b/web/vendor/bootstrap-icons/music-note-list.svg new file mode 100644 index 0000000..d33767d --- /dev/null +++ b/web/vendor/bootstrap-icons/music-note-list.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/music-note.svg b/web/vendor/bootstrap-icons/music-note.svg new file mode 100644 index 0000000..d6fe21e --- /dev/null +++ b/web/vendor/bootstrap-icons/music-note.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/music-player-fill.svg b/web/vendor/bootstrap-icons/music-player-fill.svg new file mode 100644 index 0000000..68a65b5 --- /dev/null +++ b/web/vendor/bootstrap-icons/music-player-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/music-player.svg b/web/vendor/bootstrap-icons/music-player.svg new file mode 100644 index 0000000..7eb9c92 --- /dev/null +++ b/web/vendor/bootstrap-icons/music-player.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/newspaper.svg b/web/vendor/bootstrap-icons/newspaper.svg new file mode 100644 index 0000000..9a1cf6d --- /dev/null +++ b/web/vendor/bootstrap-icons/newspaper.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/nintendo-switch.svg b/web/vendor/bootstrap-icons/nintendo-switch.svg new file mode 100644 index 0000000..5849493 --- /dev/null +++ b/web/vendor/bootstrap-icons/nintendo-switch.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/node-minus-fill.svg b/web/vendor/bootstrap-icons/node-minus-fill.svg new file mode 100644 index 0000000..802d678 --- /dev/null +++ b/web/vendor/bootstrap-icons/node-minus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/node-minus.svg b/web/vendor/bootstrap-icons/node-minus.svg new file mode 100644 index 0000000..8ffaa38 --- /dev/null +++ b/web/vendor/bootstrap-icons/node-minus.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/node-plus-fill.svg b/web/vendor/bootstrap-icons/node-plus-fill.svg new file mode 100644 index 0000000..9559b26 --- /dev/null +++ b/web/vendor/bootstrap-icons/node-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/node-plus.svg b/web/vendor/bootstrap-icons/node-plus.svg new file mode 100644 index 0000000..028ef28 --- /dev/null +++ b/web/vendor/bootstrap-icons/node-plus.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/noise-reduction.svg b/web/vendor/bootstrap-icons/noise-reduction.svg new file mode 100644 index 0000000..cd5e288 --- /dev/null +++ b/web/vendor/bootstrap-icons/noise-reduction.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/nut-fill.svg b/web/vendor/bootstrap-icons/nut-fill.svg new file mode 100644 index 0000000..18dfeb1 --- /dev/null +++ b/web/vendor/bootstrap-icons/nut-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/nut.svg b/web/vendor/bootstrap-icons/nut.svg new file mode 100644 index 0000000..75a401d --- /dev/null +++ b/web/vendor/bootstrap-icons/nut.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/nvidia.svg b/web/vendor/bootstrap-icons/nvidia.svg new file mode 100644 index 0000000..438a6fc --- /dev/null +++ b/web/vendor/bootstrap-icons/nvidia.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/nvme-fill.svg b/web/vendor/bootstrap-icons/nvme-fill.svg new file mode 100644 index 0000000..962c3c6 --- /dev/null +++ b/web/vendor/bootstrap-icons/nvme-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/nvme.svg b/web/vendor/bootstrap-icons/nvme.svg new file mode 100644 index 0000000..31a2fb6 --- /dev/null +++ b/web/vendor/bootstrap-icons/nvme.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/octagon-fill.svg b/web/vendor/bootstrap-icons/octagon-fill.svg new file mode 100644 index 0000000..73c80f0 --- /dev/null +++ b/web/vendor/bootstrap-icons/octagon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/octagon-half.svg b/web/vendor/bootstrap-icons/octagon-half.svg new file mode 100644 index 0000000..fe6eb41 --- /dev/null +++ b/web/vendor/bootstrap-icons/octagon-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/octagon.svg b/web/vendor/bootstrap-icons/octagon.svg new file mode 100644 index 0000000..d2d9c5c --- /dev/null +++ b/web/vendor/bootstrap-icons/octagon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/openai.svg b/web/vendor/bootstrap-icons/openai.svg new file mode 100644 index 0000000..ad018a2 --- /dev/null +++ b/web/vendor/bootstrap-icons/openai.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/opencollective.svg b/web/vendor/bootstrap-icons/opencollective.svg new file mode 100644 index 0000000..b9a0c9f --- /dev/null +++ b/web/vendor/bootstrap-icons/opencollective.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/optical-audio-fill.svg b/web/vendor/bootstrap-icons/optical-audio-fill.svg new file mode 100644 index 0000000..9b74060 --- /dev/null +++ b/web/vendor/bootstrap-icons/optical-audio-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/optical-audio.svg b/web/vendor/bootstrap-icons/optical-audio.svg new file mode 100644 index 0000000..253d1d7 --- /dev/null +++ b/web/vendor/bootstrap-icons/optical-audio.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/option.svg b/web/vendor/bootstrap-icons/option.svg new file mode 100644 index 0000000..32cce4c --- /dev/null +++ b/web/vendor/bootstrap-icons/option.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/outlet.svg b/web/vendor/bootstrap-icons/outlet.svg new file mode 100644 index 0000000..7787f35 --- /dev/null +++ b/web/vendor/bootstrap-icons/outlet.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/p-circle-fill.svg b/web/vendor/bootstrap-icons/p-circle-fill.svg new file mode 100644 index 0000000..e57d158 --- /dev/null +++ b/web/vendor/bootstrap-icons/p-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/p-circle.svg b/web/vendor/bootstrap-icons/p-circle.svg new file mode 100644 index 0000000..bfe68d9 --- /dev/null +++ b/web/vendor/bootstrap-icons/p-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/p-square-fill.svg b/web/vendor/bootstrap-icons/p-square-fill.svg new file mode 100644 index 0000000..164f5eb --- /dev/null +++ b/web/vendor/bootstrap-icons/p-square-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/p-square.svg b/web/vendor/bootstrap-icons/p-square.svg new file mode 100644 index 0000000..1f6335d --- /dev/null +++ b/web/vendor/bootstrap-icons/p-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/paint-bucket.svg b/web/vendor/bootstrap-icons/paint-bucket.svg new file mode 100644 index 0000000..9ac2df4 --- /dev/null +++ b/web/vendor/bootstrap-icons/paint-bucket.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/palette-fill.svg b/web/vendor/bootstrap-icons/palette-fill.svg new file mode 100644 index 0000000..d7a6a3b --- /dev/null +++ b/web/vendor/bootstrap-icons/palette-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/palette.svg b/web/vendor/bootstrap-icons/palette.svg new file mode 100644 index 0000000..1cd490f --- /dev/null +++ b/web/vendor/bootstrap-icons/palette.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/palette2.svg b/web/vendor/bootstrap-icons/palette2.svg new file mode 100644 index 0000000..ae65e88 --- /dev/null +++ b/web/vendor/bootstrap-icons/palette2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/paperclip.svg b/web/vendor/bootstrap-icons/paperclip.svg new file mode 100644 index 0000000..c02950b --- /dev/null +++ b/web/vendor/bootstrap-icons/paperclip.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/paragraph.svg b/web/vendor/bootstrap-icons/paragraph.svg new file mode 100644 index 0000000..38c65d4 --- /dev/null +++ b/web/vendor/bootstrap-icons/paragraph.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pass-fill.svg b/web/vendor/bootstrap-icons/pass-fill.svg new file mode 100644 index 0000000..1e15dd9 --- /dev/null +++ b/web/vendor/bootstrap-icons/pass-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pass.svg b/web/vendor/bootstrap-icons/pass.svg new file mode 100644 index 0000000..20a06bc --- /dev/null +++ b/web/vendor/bootstrap-icons/pass.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/passport-fill.svg b/web/vendor/bootstrap-icons/passport-fill.svg new file mode 100644 index 0000000..d42c1b9 --- /dev/null +++ b/web/vendor/bootstrap-icons/passport-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/passport.svg b/web/vendor/bootstrap-icons/passport.svg new file mode 100644 index 0000000..2ecee5a --- /dev/null +++ b/web/vendor/bootstrap-icons/passport.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/patch-check-fill.svg b/web/vendor/bootstrap-icons/patch-check-fill.svg new file mode 100644 index 0000000..91283e2 --- /dev/null +++ b/web/vendor/bootstrap-icons/patch-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/patch-check.svg b/web/vendor/bootstrap-icons/patch-check.svg new file mode 100644 index 0000000..1fd0a2e --- /dev/null +++ b/web/vendor/bootstrap-icons/patch-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/patch-exclamation-fill.svg b/web/vendor/bootstrap-icons/patch-exclamation-fill.svg new file mode 100644 index 0000000..e745268 --- /dev/null +++ b/web/vendor/bootstrap-icons/patch-exclamation-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/patch-exclamation.svg b/web/vendor/bootstrap-icons/patch-exclamation.svg new file mode 100644 index 0000000..2372cc6 --- /dev/null +++ b/web/vendor/bootstrap-icons/patch-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/patch-minus-fill.svg b/web/vendor/bootstrap-icons/patch-minus-fill.svg new file mode 100644 index 0000000..bfeb96e --- /dev/null +++ b/web/vendor/bootstrap-icons/patch-minus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/patch-minus.svg b/web/vendor/bootstrap-icons/patch-minus.svg new file mode 100644 index 0000000..35a380c --- /dev/null +++ b/web/vendor/bootstrap-icons/patch-minus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/patch-plus-fill.svg b/web/vendor/bootstrap-icons/patch-plus-fill.svg new file mode 100644 index 0000000..b475098 --- /dev/null +++ b/web/vendor/bootstrap-icons/patch-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/patch-plus.svg b/web/vendor/bootstrap-icons/patch-plus.svg new file mode 100644 index 0000000..4f332da --- /dev/null +++ b/web/vendor/bootstrap-icons/patch-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/patch-question-fill.svg b/web/vendor/bootstrap-icons/patch-question-fill.svg new file mode 100644 index 0000000..101c255 --- /dev/null +++ b/web/vendor/bootstrap-icons/patch-question-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/patch-question.svg b/web/vendor/bootstrap-icons/patch-question.svg new file mode 100644 index 0000000..a777cef --- /dev/null +++ b/web/vendor/bootstrap-icons/patch-question.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pause-btn-fill.svg b/web/vendor/bootstrap-icons/pause-btn-fill.svg new file mode 100644 index 0000000..81c0720 --- /dev/null +++ b/web/vendor/bootstrap-icons/pause-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pause-btn.svg b/web/vendor/bootstrap-icons/pause-btn.svg new file mode 100644 index 0000000..e2d68f9 --- /dev/null +++ b/web/vendor/bootstrap-icons/pause-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pause-circle-fill.svg b/web/vendor/bootstrap-icons/pause-circle-fill.svg new file mode 100644 index 0000000..90c4ca5 --- /dev/null +++ b/web/vendor/bootstrap-icons/pause-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pause-circle.svg b/web/vendor/bootstrap-icons/pause-circle.svg new file mode 100644 index 0000000..6d3aeff --- /dev/null +++ b/web/vendor/bootstrap-icons/pause-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pause-fill.svg b/web/vendor/bootstrap-icons/pause-fill.svg new file mode 100644 index 0000000..92e1588 --- /dev/null +++ b/web/vendor/bootstrap-icons/pause-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pause.svg b/web/vendor/bootstrap-icons/pause.svg new file mode 100644 index 0000000..7bfde2c --- /dev/null +++ b/web/vendor/bootstrap-icons/pause.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/paypal.svg b/web/vendor/bootstrap-icons/paypal.svg new file mode 100644 index 0000000..b2cec88 --- /dev/null +++ b/web/vendor/bootstrap-icons/paypal.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pc-display-horizontal.svg b/web/vendor/bootstrap-icons/pc-display-horizontal.svg new file mode 100644 index 0000000..724ba86 --- /dev/null +++ b/web/vendor/bootstrap-icons/pc-display-horizontal.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pc-display.svg b/web/vendor/bootstrap-icons/pc-display.svg new file mode 100644 index 0000000..c3cf9dd --- /dev/null +++ b/web/vendor/bootstrap-icons/pc-display.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pc-horizontal.svg b/web/vendor/bootstrap-icons/pc-horizontal.svg new file mode 100644 index 0000000..a8ae72f --- /dev/null +++ b/web/vendor/bootstrap-icons/pc-horizontal.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pc.svg b/web/vendor/bootstrap-icons/pc.svg new file mode 100644 index 0000000..a8c023a --- /dev/null +++ b/web/vendor/bootstrap-icons/pc.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pci-card-network.svg b/web/vendor/bootstrap-icons/pci-card-network.svg new file mode 100644 index 0000000..a2b4359 --- /dev/null +++ b/web/vendor/bootstrap-icons/pci-card-network.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pci-card-sound.svg b/web/vendor/bootstrap-icons/pci-card-sound.svg new file mode 100644 index 0000000..2bb98f2 --- /dev/null +++ b/web/vendor/bootstrap-icons/pci-card-sound.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pci-card.svg b/web/vendor/bootstrap-icons/pci-card.svg new file mode 100644 index 0000000..66ff052 --- /dev/null +++ b/web/vendor/bootstrap-icons/pci-card.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/peace-fill.svg b/web/vendor/bootstrap-icons/peace-fill.svg new file mode 100644 index 0000000..a93e64d --- /dev/null +++ b/web/vendor/bootstrap-icons/peace-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/peace.svg b/web/vendor/bootstrap-icons/peace.svg new file mode 100644 index 0000000..22367e0 --- /dev/null +++ b/web/vendor/bootstrap-icons/peace.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pen-fill.svg b/web/vendor/bootstrap-icons/pen-fill.svg new file mode 100644 index 0000000..59bbb2e --- /dev/null +++ b/web/vendor/bootstrap-icons/pen-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pen.svg b/web/vendor/bootstrap-icons/pen.svg new file mode 100644 index 0000000..a63b250 --- /dev/null +++ b/web/vendor/bootstrap-icons/pen.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pencil-fill.svg b/web/vendor/bootstrap-icons/pencil-fill.svg new file mode 100644 index 0000000..4b3bdd7 --- /dev/null +++ b/web/vendor/bootstrap-icons/pencil-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pencil-square.svg b/web/vendor/bootstrap-icons/pencil-square.svg new file mode 100644 index 0000000..95c0529 --- /dev/null +++ b/web/vendor/bootstrap-icons/pencil-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pencil.svg b/web/vendor/bootstrap-icons/pencil.svg new file mode 100644 index 0000000..0b84e36 --- /dev/null +++ b/web/vendor/bootstrap-icons/pencil.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pentagon-fill.svg b/web/vendor/bootstrap-icons/pentagon-fill.svg new file mode 100644 index 0000000..9c80789 --- /dev/null +++ b/web/vendor/bootstrap-icons/pentagon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pentagon-half.svg b/web/vendor/bootstrap-icons/pentagon-half.svg new file mode 100644 index 0000000..6811a93 --- /dev/null +++ b/web/vendor/bootstrap-icons/pentagon-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pentagon.svg b/web/vendor/bootstrap-icons/pentagon.svg new file mode 100644 index 0000000..b6f5fe3 --- /dev/null +++ b/web/vendor/bootstrap-icons/pentagon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/people-fill.svg b/web/vendor/bootstrap-icons/people-fill.svg new file mode 100644 index 0000000..2b9f768 --- /dev/null +++ b/web/vendor/bootstrap-icons/people-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/people.svg b/web/vendor/bootstrap-icons/people.svg new file mode 100644 index 0000000..341861a --- /dev/null +++ b/web/vendor/bootstrap-icons/people.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/percent.svg b/web/vendor/bootstrap-icons/percent.svg new file mode 100644 index 0000000..c0fd22d --- /dev/null +++ b/web/vendor/bootstrap-icons/percent.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/perplexity.svg b/web/vendor/bootstrap-icons/perplexity.svg new file mode 100644 index 0000000..8cab953 --- /dev/null +++ b/web/vendor/bootstrap-icons/perplexity.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-add.svg b/web/vendor/bootstrap-icons/person-add.svg new file mode 100644 index 0000000..66e2508 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-add.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-arms-up.svg b/web/vendor/bootstrap-icons/person-arms-up.svg new file mode 100644 index 0000000..deb50e8 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-arms-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-badge-fill.svg b/web/vendor/bootstrap-icons/person-badge-fill.svg new file mode 100644 index 0000000..7110ed3 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-badge-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-badge.svg b/web/vendor/bootstrap-icons/person-badge.svg new file mode 100644 index 0000000..680aee1 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-badge.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-bounding-box.svg b/web/vendor/bootstrap-icons/person-bounding-box.svg new file mode 100644 index 0000000..d9be675 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-bounding-box.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-check-fill.svg b/web/vendor/bootstrap-icons/person-check-fill.svg new file mode 100644 index 0000000..04b95d3 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-check-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-check.svg b/web/vendor/bootstrap-icons/person-check.svg new file mode 100644 index 0000000..39b4219 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-circle.svg b/web/vendor/bootstrap-icons/person-circle.svg new file mode 100644 index 0000000..a75f25f --- /dev/null +++ b/web/vendor/bootstrap-icons/person-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-dash-fill.svg b/web/vendor/bootstrap-icons/person-dash-fill.svg new file mode 100644 index 0000000..9879e6e --- /dev/null +++ b/web/vendor/bootstrap-icons/person-dash-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-dash.svg b/web/vendor/bootstrap-icons/person-dash.svg new file mode 100644 index 0000000..b61190b --- /dev/null +++ b/web/vendor/bootstrap-icons/person-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-down.svg b/web/vendor/bootstrap-icons/person-down.svg new file mode 100644 index 0000000..79cf29a --- /dev/null +++ b/web/vendor/bootstrap-icons/person-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-exclamation.svg b/web/vendor/bootstrap-icons/person-exclamation.svg new file mode 100644 index 0000000..46fb506 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-fill-add.svg b/web/vendor/bootstrap-icons/person-fill-add.svg new file mode 100644 index 0000000..d6d15f9 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-fill-add.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-fill-check.svg b/web/vendor/bootstrap-icons/person-fill-check.svg new file mode 100644 index 0000000..19b88a4 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-fill-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-fill-dash.svg b/web/vendor/bootstrap-icons/person-fill-dash.svg new file mode 100644 index 0000000..24c2944 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-fill-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-fill-down.svg b/web/vendor/bootstrap-icons/person-fill-down.svg new file mode 100644 index 0000000..714ae50 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-fill-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-fill-exclamation.svg b/web/vendor/bootstrap-icons/person-fill-exclamation.svg new file mode 100644 index 0000000..5c3b7f5 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-fill-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-fill-gear.svg b/web/vendor/bootstrap-icons/person-fill-gear.svg new file mode 100644 index 0000000..33b120a --- /dev/null +++ b/web/vendor/bootstrap-icons/person-fill-gear.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-fill-lock.svg b/web/vendor/bootstrap-icons/person-fill-lock.svg new file mode 100644 index 0000000..adbccff --- /dev/null +++ b/web/vendor/bootstrap-icons/person-fill-lock.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-fill-slash.svg b/web/vendor/bootstrap-icons/person-fill-slash.svg new file mode 100644 index 0000000..398d563 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-fill-slash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-fill-up.svg b/web/vendor/bootstrap-icons/person-fill-up.svg new file mode 100644 index 0000000..1edd97b --- /dev/null +++ b/web/vendor/bootstrap-icons/person-fill-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-fill-x.svg b/web/vendor/bootstrap-icons/person-fill-x.svg new file mode 100644 index 0000000..e3a66ed --- /dev/null +++ b/web/vendor/bootstrap-icons/person-fill-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-fill.svg b/web/vendor/bootstrap-icons/person-fill.svg new file mode 100644 index 0000000..46d1a75 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-gear.svg b/web/vendor/bootstrap-icons/person-gear.svg new file mode 100644 index 0000000..93ec4da --- /dev/null +++ b/web/vendor/bootstrap-icons/person-gear.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-heart.svg b/web/vendor/bootstrap-icons/person-heart.svg new file mode 100644 index 0000000..51b236e --- /dev/null +++ b/web/vendor/bootstrap-icons/person-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-hearts.svg b/web/vendor/bootstrap-icons/person-hearts.svg new file mode 100644 index 0000000..70bb2e0 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-hearts.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-lines-fill.svg b/web/vendor/bootstrap-icons/person-lines-fill.svg new file mode 100644 index 0000000..cbe6c68 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-lines-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-lock.svg b/web/vendor/bootstrap-icons/person-lock.svg new file mode 100644 index 0000000..d3672cd --- /dev/null +++ b/web/vendor/bootstrap-icons/person-lock.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-plus-fill.svg b/web/vendor/bootstrap-icons/person-plus-fill.svg new file mode 100644 index 0000000..6c92aea --- /dev/null +++ b/web/vendor/bootstrap-icons/person-plus-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-plus.svg b/web/vendor/bootstrap-icons/person-plus.svg new file mode 100644 index 0000000..4b88424 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-raised-hand.svg b/web/vendor/bootstrap-icons/person-raised-hand.svg new file mode 100644 index 0000000..00ac301 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-raised-hand.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-rolodex.svg b/web/vendor/bootstrap-icons/person-rolodex.svg new file mode 100644 index 0000000..2039494 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-rolodex.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-slash.svg b/web/vendor/bootstrap-icons/person-slash.svg new file mode 100644 index 0000000..ab53647 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-slash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-square.svg b/web/vendor/bootstrap-icons/person-square.svg new file mode 100644 index 0000000..12a33c5 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-standing-dress.svg b/web/vendor/bootstrap-icons/person-standing-dress.svg new file mode 100644 index 0000000..4448606 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-standing-dress.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-standing.svg b/web/vendor/bootstrap-icons/person-standing.svg new file mode 100644 index 0000000..ccd7b35 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-standing.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-up.svg b/web/vendor/bootstrap-icons/person-up.svg new file mode 100644 index 0000000..93a430a --- /dev/null +++ b/web/vendor/bootstrap-icons/person-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-vcard-fill.svg b/web/vendor/bootstrap-icons/person-vcard-fill.svg new file mode 100644 index 0000000..9efb1b8 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-vcard-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-vcard.svg b/web/vendor/bootstrap-icons/person-vcard.svg new file mode 100644 index 0000000..40ec41e --- /dev/null +++ b/web/vendor/bootstrap-icons/person-vcard.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-video.svg b/web/vendor/bootstrap-icons/person-video.svg new file mode 100644 index 0000000..a991759 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-video.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-video2.svg b/web/vendor/bootstrap-icons/person-video2.svg new file mode 100644 index 0000000..80b3b8a --- /dev/null +++ b/web/vendor/bootstrap-icons/person-video2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-video3.svg b/web/vendor/bootstrap-icons/person-video3.svg new file mode 100644 index 0000000..472d998 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-video3.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-walking.svg b/web/vendor/bootstrap-icons/person-walking.svg new file mode 100644 index 0000000..16cc0b4 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-walking.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-wheelchair.svg b/web/vendor/bootstrap-icons/person-wheelchair.svg new file mode 100644 index 0000000..416cad2 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-wheelchair.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-workspace.svg b/web/vendor/bootstrap-icons/person-workspace.svg new file mode 100644 index 0000000..0b3cdce --- /dev/null +++ b/web/vendor/bootstrap-icons/person-workspace.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-x-fill.svg b/web/vendor/bootstrap-icons/person-x-fill.svg new file mode 100644 index 0000000..9e31903 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person-x.svg b/web/vendor/bootstrap-icons/person-x.svg new file mode 100644 index 0000000..7514c59 --- /dev/null +++ b/web/vendor/bootstrap-icons/person-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/person.svg b/web/vendor/bootstrap-icons/person.svg new file mode 100644 index 0000000..98ea060 --- /dev/null +++ b/web/vendor/bootstrap-icons/person.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/phone-fill.svg b/web/vendor/bootstrap-icons/phone-fill.svg new file mode 100644 index 0000000..f25bd51 --- /dev/null +++ b/web/vendor/bootstrap-icons/phone-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/phone-flip.svg b/web/vendor/bootstrap-icons/phone-flip.svg new file mode 100644 index 0000000..3ae28d3 --- /dev/null +++ b/web/vendor/bootstrap-icons/phone-flip.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/phone-landscape-fill.svg b/web/vendor/bootstrap-icons/phone-landscape-fill.svg new file mode 100644 index 0000000..669bf6e --- /dev/null +++ b/web/vendor/bootstrap-icons/phone-landscape-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/phone-landscape.svg b/web/vendor/bootstrap-icons/phone-landscape.svg new file mode 100644 index 0000000..4c30ef2 --- /dev/null +++ b/web/vendor/bootstrap-icons/phone-landscape.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/phone-vibrate-fill.svg b/web/vendor/bootstrap-icons/phone-vibrate-fill.svg new file mode 100644 index 0000000..dc35ca0 --- /dev/null +++ b/web/vendor/bootstrap-icons/phone-vibrate-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/phone-vibrate.svg b/web/vendor/bootstrap-icons/phone-vibrate.svg new file mode 100644 index 0000000..58acbf6 --- /dev/null +++ b/web/vendor/bootstrap-icons/phone-vibrate.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/phone.svg b/web/vendor/bootstrap-icons/phone.svg new file mode 100644 index 0000000..4839331 --- /dev/null +++ b/web/vendor/bootstrap-icons/phone.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pie-chart-fill.svg b/web/vendor/bootstrap-icons/pie-chart-fill.svg new file mode 100644 index 0000000..f667aea --- /dev/null +++ b/web/vendor/bootstrap-icons/pie-chart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pie-chart.svg b/web/vendor/bootstrap-icons/pie-chart.svg new file mode 100644 index 0000000..b49251b --- /dev/null +++ b/web/vendor/bootstrap-icons/pie-chart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/piggy-bank-fill.svg b/web/vendor/bootstrap-icons/piggy-bank-fill.svg new file mode 100644 index 0000000..592b31d --- /dev/null +++ b/web/vendor/bootstrap-icons/piggy-bank-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/piggy-bank.svg b/web/vendor/bootstrap-icons/piggy-bank.svg new file mode 100644 index 0000000..86e33eb --- /dev/null +++ b/web/vendor/bootstrap-icons/piggy-bank.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pin-angle-fill.svg b/web/vendor/bootstrap-icons/pin-angle-fill.svg new file mode 100644 index 0000000..bc3078c --- /dev/null +++ b/web/vendor/bootstrap-icons/pin-angle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pin-angle.svg b/web/vendor/bootstrap-icons/pin-angle.svg new file mode 100644 index 0000000..ecc4d16 --- /dev/null +++ b/web/vendor/bootstrap-icons/pin-angle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pin-fill.svg b/web/vendor/bootstrap-icons/pin-fill.svg new file mode 100644 index 0000000..f345059 --- /dev/null +++ b/web/vendor/bootstrap-icons/pin-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pin-map-fill.svg b/web/vendor/bootstrap-icons/pin-map-fill.svg new file mode 100644 index 0000000..9db0d29 --- /dev/null +++ b/web/vendor/bootstrap-icons/pin-map-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pin-map.svg b/web/vendor/bootstrap-icons/pin-map.svg new file mode 100644 index 0000000..0462a5a --- /dev/null +++ b/web/vendor/bootstrap-icons/pin-map.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pin.svg b/web/vendor/bootstrap-icons/pin.svg new file mode 100644 index 0000000..4655620 --- /dev/null +++ b/web/vendor/bootstrap-icons/pin.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pinterest.svg b/web/vendor/bootstrap-icons/pinterest.svg new file mode 100644 index 0000000..5c850b6 --- /dev/null +++ b/web/vendor/bootstrap-icons/pinterest.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pip-fill.svg b/web/vendor/bootstrap-icons/pip-fill.svg new file mode 100644 index 0000000..4865244 --- /dev/null +++ b/web/vendor/bootstrap-icons/pip-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/pip.svg b/web/vendor/bootstrap-icons/pip.svg new file mode 100644 index 0000000..458c9c9 --- /dev/null +++ b/web/vendor/bootstrap-icons/pip.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/play-btn-fill.svg b/web/vendor/bootstrap-icons/play-btn-fill.svg new file mode 100644 index 0000000..3d0d1c3 --- /dev/null +++ b/web/vendor/bootstrap-icons/play-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/play-btn.svg b/web/vendor/bootstrap-icons/play-btn.svg new file mode 100644 index 0000000..2fcbc5e --- /dev/null +++ b/web/vendor/bootstrap-icons/play-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/play-circle-fill.svg b/web/vendor/bootstrap-icons/play-circle-fill.svg new file mode 100644 index 0000000..93eeb93 --- /dev/null +++ b/web/vendor/bootstrap-icons/play-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/play-circle.svg b/web/vendor/bootstrap-icons/play-circle.svg new file mode 100644 index 0000000..a1d742e --- /dev/null +++ b/web/vendor/bootstrap-icons/play-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/play-fill.svg b/web/vendor/bootstrap-icons/play-fill.svg new file mode 100644 index 0000000..e538083 --- /dev/null +++ b/web/vendor/bootstrap-icons/play-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/play.svg b/web/vendor/bootstrap-icons/play.svg new file mode 100644 index 0000000..98954e7 --- /dev/null +++ b/web/vendor/bootstrap-icons/play.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/playstation.svg b/web/vendor/bootstrap-icons/playstation.svg new file mode 100644 index 0000000..3275d59 --- /dev/null +++ b/web/vendor/bootstrap-icons/playstation.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/plug-fill.svg b/web/vendor/bootstrap-icons/plug-fill.svg new file mode 100644 index 0000000..99858eb --- /dev/null +++ b/web/vendor/bootstrap-icons/plug-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/plug.svg b/web/vendor/bootstrap-icons/plug.svg new file mode 100644 index 0000000..9d6a85b --- /dev/null +++ b/web/vendor/bootstrap-icons/plug.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/plugin.svg b/web/vendor/bootstrap-icons/plugin.svg new file mode 100644 index 0000000..92e99d4 --- /dev/null +++ b/web/vendor/bootstrap-icons/plugin.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/plus-circle-dotted.svg b/web/vendor/bootstrap-icons/plus-circle-dotted.svg new file mode 100644 index 0000000..2a20e2d --- /dev/null +++ b/web/vendor/bootstrap-icons/plus-circle-dotted.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/plus-circle-fill.svg b/web/vendor/bootstrap-icons/plus-circle-fill.svg new file mode 100644 index 0000000..d1ec2d0 --- /dev/null +++ b/web/vendor/bootstrap-icons/plus-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/plus-circle.svg b/web/vendor/bootstrap-icons/plus-circle.svg new file mode 100644 index 0000000..2832373 --- /dev/null +++ b/web/vendor/bootstrap-icons/plus-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/plus-lg.svg b/web/vendor/bootstrap-icons/plus-lg.svg new file mode 100644 index 0000000..531e86c --- /dev/null +++ b/web/vendor/bootstrap-icons/plus-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/plus-slash-minus.svg b/web/vendor/bootstrap-icons/plus-slash-minus.svg new file mode 100644 index 0000000..e0fee7d --- /dev/null +++ b/web/vendor/bootstrap-icons/plus-slash-minus.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/plus-square-dotted.svg b/web/vendor/bootstrap-icons/plus-square-dotted.svg new file mode 100644 index 0000000..e230a08 --- /dev/null +++ b/web/vendor/bootstrap-icons/plus-square-dotted.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/plus-square-fill.svg b/web/vendor/bootstrap-icons/plus-square-fill.svg new file mode 100644 index 0000000..1dddd13 --- /dev/null +++ b/web/vendor/bootstrap-icons/plus-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/plus-square.svg b/web/vendor/bootstrap-icons/plus-square.svg new file mode 100644 index 0000000..ef11b48 --- /dev/null +++ b/web/vendor/bootstrap-icons/plus-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/plus.svg b/web/vendor/bootstrap-icons/plus.svg new file mode 100644 index 0000000..9012271 --- /dev/null +++ b/web/vendor/bootstrap-icons/plus.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/postage-fill.svg b/web/vendor/bootstrap-icons/postage-fill.svg new file mode 100644 index 0000000..861a3a1 --- /dev/null +++ b/web/vendor/bootstrap-icons/postage-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/postage-heart-fill.svg b/web/vendor/bootstrap-icons/postage-heart-fill.svg new file mode 100644 index 0000000..4737a4d --- /dev/null +++ b/web/vendor/bootstrap-icons/postage-heart-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/postage-heart.svg b/web/vendor/bootstrap-icons/postage-heart.svg new file mode 100644 index 0000000..aa35a6c --- /dev/null +++ b/web/vendor/bootstrap-icons/postage-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/postage.svg b/web/vendor/bootstrap-icons/postage.svg new file mode 100644 index 0000000..54dcfa6 --- /dev/null +++ b/web/vendor/bootstrap-icons/postage.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/postcard-fill.svg b/web/vendor/bootstrap-icons/postcard-fill.svg new file mode 100644 index 0000000..aeba518 --- /dev/null +++ b/web/vendor/bootstrap-icons/postcard-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/postcard-heart-fill.svg b/web/vendor/bootstrap-icons/postcard-heart-fill.svg new file mode 100644 index 0000000..1e371b8 --- /dev/null +++ b/web/vendor/bootstrap-icons/postcard-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/postcard-heart.svg b/web/vendor/bootstrap-icons/postcard-heart.svg new file mode 100644 index 0000000..52c0053 --- /dev/null +++ b/web/vendor/bootstrap-icons/postcard-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/postcard.svg b/web/vendor/bootstrap-icons/postcard.svg new file mode 100644 index 0000000..43ba40b --- /dev/null +++ b/web/vendor/bootstrap-icons/postcard.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/power.svg b/web/vendor/bootstrap-icons/power.svg new file mode 100644 index 0000000..937b842 --- /dev/null +++ b/web/vendor/bootstrap-icons/power.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/prescription.svg b/web/vendor/bootstrap-icons/prescription.svg new file mode 100644 index 0000000..b895b2b --- /dev/null +++ b/web/vendor/bootstrap-icons/prescription.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/prescription2.svg b/web/vendor/bootstrap-icons/prescription2.svg new file mode 100644 index 0000000..cb278b0 --- /dev/null +++ b/web/vendor/bootstrap-icons/prescription2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/printer-fill.svg b/web/vendor/bootstrap-icons/printer-fill.svg new file mode 100644 index 0000000..43cee36 --- /dev/null +++ b/web/vendor/bootstrap-icons/printer-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/printer.svg b/web/vendor/bootstrap-icons/printer.svg new file mode 100644 index 0000000..0886a57 --- /dev/null +++ b/web/vendor/bootstrap-icons/printer.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/projector-fill.svg b/web/vendor/bootstrap-icons/projector-fill.svg new file mode 100644 index 0000000..046166c --- /dev/null +++ b/web/vendor/bootstrap-icons/projector-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/projector.svg b/web/vendor/bootstrap-icons/projector.svg new file mode 100644 index 0000000..77e68b0 --- /dev/null +++ b/web/vendor/bootstrap-icons/projector.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/puzzle-fill.svg b/web/vendor/bootstrap-icons/puzzle-fill.svg new file mode 100644 index 0000000..92c4ea0 --- /dev/null +++ b/web/vendor/bootstrap-icons/puzzle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/puzzle.svg b/web/vendor/bootstrap-icons/puzzle.svg new file mode 100644 index 0000000..44903f7 --- /dev/null +++ b/web/vendor/bootstrap-icons/puzzle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/qr-code-scan.svg b/web/vendor/bootstrap-icons/qr-code-scan.svg new file mode 100644 index 0000000..3c53387 --- /dev/null +++ b/web/vendor/bootstrap-icons/qr-code-scan.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/qr-code.svg b/web/vendor/bootstrap-icons/qr-code.svg new file mode 100644 index 0000000..e09157a --- /dev/null +++ b/web/vendor/bootstrap-icons/qr-code.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/question-circle-fill.svg b/web/vendor/bootstrap-icons/question-circle-fill.svg new file mode 100644 index 0000000..8b2a2c0 --- /dev/null +++ b/web/vendor/bootstrap-icons/question-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/question-circle.svg b/web/vendor/bootstrap-icons/question-circle.svg new file mode 100644 index 0000000..283e653 --- /dev/null +++ b/web/vendor/bootstrap-icons/question-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/question-diamond-fill.svg b/web/vendor/bootstrap-icons/question-diamond-fill.svg new file mode 100644 index 0000000..6bf3512 --- /dev/null +++ b/web/vendor/bootstrap-icons/question-diamond-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/question-diamond.svg b/web/vendor/bootstrap-icons/question-diamond.svg new file mode 100644 index 0000000..a777b47 --- /dev/null +++ b/web/vendor/bootstrap-icons/question-diamond.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/question-lg.svg b/web/vendor/bootstrap-icons/question-lg.svg new file mode 100644 index 0000000..756ea0f --- /dev/null +++ b/web/vendor/bootstrap-icons/question-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/question-octagon-fill.svg b/web/vendor/bootstrap-icons/question-octagon-fill.svg new file mode 100644 index 0000000..c0c43ef --- /dev/null +++ b/web/vendor/bootstrap-icons/question-octagon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/question-octagon.svg b/web/vendor/bootstrap-icons/question-octagon.svg new file mode 100644 index 0000000..5116862 --- /dev/null +++ b/web/vendor/bootstrap-icons/question-octagon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/question-square-fill.svg b/web/vendor/bootstrap-icons/question-square-fill.svg new file mode 100644 index 0000000..a266f9f --- /dev/null +++ b/web/vendor/bootstrap-icons/question-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/question-square.svg b/web/vendor/bootstrap-icons/question-square.svg new file mode 100644 index 0000000..ad44a20 --- /dev/null +++ b/web/vendor/bootstrap-icons/question-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/question.svg b/web/vendor/bootstrap-icons/question.svg new file mode 100644 index 0000000..ba185ad --- /dev/null +++ b/web/vendor/bootstrap-icons/question.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/quora.svg b/web/vendor/bootstrap-icons/quora.svg new file mode 100644 index 0000000..85ca1bd --- /dev/null +++ b/web/vendor/bootstrap-icons/quora.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/quote.svg b/web/vendor/bootstrap-icons/quote.svg new file mode 100644 index 0000000..0aa0e17 --- /dev/null +++ b/web/vendor/bootstrap-icons/quote.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/r-circle-fill.svg b/web/vendor/bootstrap-icons/r-circle-fill.svg new file mode 100644 index 0000000..810423e --- /dev/null +++ b/web/vendor/bootstrap-icons/r-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/r-circle.svg b/web/vendor/bootstrap-icons/r-circle.svg new file mode 100644 index 0000000..bf2d8d6 --- /dev/null +++ b/web/vendor/bootstrap-icons/r-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/r-square-fill.svg b/web/vendor/bootstrap-icons/r-square-fill.svg new file mode 100644 index 0000000..b1151f3 --- /dev/null +++ b/web/vendor/bootstrap-icons/r-square-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/r-square.svg b/web/vendor/bootstrap-icons/r-square.svg new file mode 100644 index 0000000..e19e688 --- /dev/null +++ b/web/vendor/bootstrap-icons/r-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/radar.svg b/web/vendor/bootstrap-icons/radar.svg new file mode 100644 index 0000000..024f3fd --- /dev/null +++ b/web/vendor/bootstrap-icons/radar.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/radioactive.svg b/web/vendor/bootstrap-icons/radioactive.svg new file mode 100644 index 0000000..3eaaa56 --- /dev/null +++ b/web/vendor/bootstrap-icons/radioactive.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/rainbow.svg b/web/vendor/bootstrap-icons/rainbow.svg new file mode 100644 index 0000000..e864abf --- /dev/null +++ b/web/vendor/bootstrap-icons/rainbow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/receipt-cutoff.svg b/web/vendor/bootstrap-icons/receipt-cutoff.svg new file mode 100644 index 0000000..21c3bc8 --- /dev/null +++ b/web/vendor/bootstrap-icons/receipt-cutoff.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/receipt.svg b/web/vendor/bootstrap-icons/receipt.svg new file mode 100644 index 0000000..ab29fe6 --- /dev/null +++ b/web/vendor/bootstrap-icons/receipt.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/reception-0.svg b/web/vendor/bootstrap-icons/reception-0.svg new file mode 100644 index 0000000..a7c7872 --- /dev/null +++ b/web/vendor/bootstrap-icons/reception-0.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/reception-1.svg b/web/vendor/bootstrap-icons/reception-1.svg new file mode 100644 index 0000000..4081ceb --- /dev/null +++ b/web/vendor/bootstrap-icons/reception-1.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/reception-2.svg b/web/vendor/bootstrap-icons/reception-2.svg new file mode 100644 index 0000000..7e1acc5 --- /dev/null +++ b/web/vendor/bootstrap-icons/reception-2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/reception-3.svg b/web/vendor/bootstrap-icons/reception-3.svg new file mode 100644 index 0000000..e9ea476 --- /dev/null +++ b/web/vendor/bootstrap-icons/reception-3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/reception-4.svg b/web/vendor/bootstrap-icons/reception-4.svg new file mode 100644 index 0000000..7791e4b --- /dev/null +++ b/web/vendor/bootstrap-icons/reception-4.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/record-btn-fill.svg b/web/vendor/bootstrap-icons/record-btn-fill.svg new file mode 100644 index 0000000..83ee303 --- /dev/null +++ b/web/vendor/bootstrap-icons/record-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/record-btn.svg b/web/vendor/bootstrap-icons/record-btn.svg new file mode 100644 index 0000000..7ba84ce --- /dev/null +++ b/web/vendor/bootstrap-icons/record-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/record-circle-fill.svg b/web/vendor/bootstrap-icons/record-circle-fill.svg new file mode 100644 index 0000000..0db59d1 --- /dev/null +++ b/web/vendor/bootstrap-icons/record-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/record-circle.svg b/web/vendor/bootstrap-icons/record-circle.svg new file mode 100644 index 0000000..5dad17b --- /dev/null +++ b/web/vendor/bootstrap-icons/record-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/record-fill.svg b/web/vendor/bootstrap-icons/record-fill.svg new file mode 100644 index 0000000..ef31df0 --- /dev/null +++ b/web/vendor/bootstrap-icons/record-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/record.svg b/web/vendor/bootstrap-icons/record.svg new file mode 100644 index 0000000..5ec840c --- /dev/null +++ b/web/vendor/bootstrap-icons/record.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/record2-fill.svg b/web/vendor/bootstrap-icons/record2-fill.svg new file mode 100644 index 0000000..8ad4fe3 --- /dev/null +++ b/web/vendor/bootstrap-icons/record2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/record2.svg b/web/vendor/bootstrap-icons/record2.svg new file mode 100644 index 0000000..3b5c5ca --- /dev/null +++ b/web/vendor/bootstrap-icons/record2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/recycle.svg b/web/vendor/bootstrap-icons/recycle.svg new file mode 100644 index 0000000..21d1bd9 --- /dev/null +++ b/web/vendor/bootstrap-icons/recycle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/reddit.svg b/web/vendor/bootstrap-icons/reddit.svg new file mode 100644 index 0000000..777aead --- /dev/null +++ b/web/vendor/bootstrap-icons/reddit.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/regex.svg b/web/vendor/bootstrap-icons/regex.svg new file mode 100644 index 0000000..ec8bf00 --- /dev/null +++ b/web/vendor/bootstrap-icons/regex.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/repeat-1.svg b/web/vendor/bootstrap-icons/repeat-1.svg new file mode 100644 index 0000000..9357fcf --- /dev/null +++ b/web/vendor/bootstrap-icons/repeat-1.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/repeat.svg b/web/vendor/bootstrap-icons/repeat.svg new file mode 100644 index 0000000..51765c9 --- /dev/null +++ b/web/vendor/bootstrap-icons/repeat.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/reply-all-fill.svg b/web/vendor/bootstrap-icons/reply-all-fill.svg new file mode 100644 index 0000000..95e18a2 --- /dev/null +++ b/web/vendor/bootstrap-icons/reply-all-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/reply-all.svg b/web/vendor/bootstrap-icons/reply-all.svg new file mode 100644 index 0000000..decad51 --- /dev/null +++ b/web/vendor/bootstrap-icons/reply-all.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/reply-fill.svg b/web/vendor/bootstrap-icons/reply-fill.svg new file mode 100644 index 0000000..82358b1 --- /dev/null +++ b/web/vendor/bootstrap-icons/reply-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/reply.svg b/web/vendor/bootstrap-icons/reply.svg new file mode 100644 index 0000000..5bb432e --- /dev/null +++ b/web/vendor/bootstrap-icons/reply.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/rewind-btn-fill.svg b/web/vendor/bootstrap-icons/rewind-btn-fill.svg new file mode 100644 index 0000000..8ea4155 --- /dev/null +++ b/web/vendor/bootstrap-icons/rewind-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/rewind-btn.svg b/web/vendor/bootstrap-icons/rewind-btn.svg new file mode 100644 index 0000000..47bd717 --- /dev/null +++ b/web/vendor/bootstrap-icons/rewind-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/rewind-circle-fill.svg b/web/vendor/bootstrap-icons/rewind-circle-fill.svg new file mode 100644 index 0000000..b972044 --- /dev/null +++ b/web/vendor/bootstrap-icons/rewind-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/rewind-circle.svg b/web/vendor/bootstrap-icons/rewind-circle.svg new file mode 100644 index 0000000..4952147 --- /dev/null +++ b/web/vendor/bootstrap-icons/rewind-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/rewind-fill.svg b/web/vendor/bootstrap-icons/rewind-fill.svg new file mode 100644 index 0000000..5919f7e --- /dev/null +++ b/web/vendor/bootstrap-icons/rewind-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/rewind.svg b/web/vendor/bootstrap-icons/rewind.svg new file mode 100644 index 0000000..bc731e7 --- /dev/null +++ b/web/vendor/bootstrap-icons/rewind.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/robot.svg b/web/vendor/bootstrap-icons/robot.svg new file mode 100644 index 0000000..a224202 --- /dev/null +++ b/web/vendor/bootstrap-icons/robot.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/rocket-fill.svg b/web/vendor/bootstrap-icons/rocket-fill.svg new file mode 100644 index 0000000..f319029 --- /dev/null +++ b/web/vendor/bootstrap-icons/rocket-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/rocket-takeoff-fill.svg b/web/vendor/bootstrap-icons/rocket-takeoff-fill.svg new file mode 100644 index 0000000..707d205 --- /dev/null +++ b/web/vendor/bootstrap-icons/rocket-takeoff-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/rocket-takeoff.svg b/web/vendor/bootstrap-icons/rocket-takeoff.svg new file mode 100644 index 0000000..2abc6d4 --- /dev/null +++ b/web/vendor/bootstrap-icons/rocket-takeoff.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/rocket.svg b/web/vendor/bootstrap-icons/rocket.svg new file mode 100644 index 0000000..b760e1f --- /dev/null +++ b/web/vendor/bootstrap-icons/rocket.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/router-fill.svg b/web/vendor/bootstrap-icons/router-fill.svg new file mode 100644 index 0000000..74d1469 --- /dev/null +++ b/web/vendor/bootstrap-icons/router-fill.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/router.svg b/web/vendor/bootstrap-icons/router.svg new file mode 100644 index 0000000..62fac78 --- /dev/null +++ b/web/vendor/bootstrap-icons/router.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/rss-fill.svg b/web/vendor/bootstrap-icons/rss-fill.svg new file mode 100644 index 0000000..50d7cfd --- /dev/null +++ b/web/vendor/bootstrap-icons/rss-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/rss.svg b/web/vendor/bootstrap-icons/rss.svg new file mode 100644 index 0000000..18dc9f1 --- /dev/null +++ b/web/vendor/bootstrap-icons/rss.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/rulers.svg b/web/vendor/bootstrap-icons/rulers.svg new file mode 100644 index 0000000..90fb01c --- /dev/null +++ b/web/vendor/bootstrap-icons/rulers.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/safe-fill.svg b/web/vendor/bootstrap-icons/safe-fill.svg new file mode 100644 index 0000000..6da7a7d --- /dev/null +++ b/web/vendor/bootstrap-icons/safe-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/safe.svg b/web/vendor/bootstrap-icons/safe.svg new file mode 100644 index 0000000..d6d24c2 --- /dev/null +++ b/web/vendor/bootstrap-icons/safe.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/safe2-fill.svg b/web/vendor/bootstrap-icons/safe2-fill.svg new file mode 100644 index 0000000..064e073 --- /dev/null +++ b/web/vendor/bootstrap-icons/safe2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/safe2.svg b/web/vendor/bootstrap-icons/safe2.svg new file mode 100644 index 0000000..9c80f55 --- /dev/null +++ b/web/vendor/bootstrap-icons/safe2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/save-fill.svg b/web/vendor/bootstrap-icons/save-fill.svg new file mode 100644 index 0000000..1c42812 --- /dev/null +++ b/web/vendor/bootstrap-icons/save-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/save.svg b/web/vendor/bootstrap-icons/save.svg new file mode 100644 index 0000000..9dd7b2f --- /dev/null +++ b/web/vendor/bootstrap-icons/save.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/save2-fill.svg b/web/vendor/bootstrap-icons/save2-fill.svg new file mode 100644 index 0000000..207f91b --- /dev/null +++ b/web/vendor/bootstrap-icons/save2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/save2.svg b/web/vendor/bootstrap-icons/save2.svg new file mode 100644 index 0000000..988c4f1 --- /dev/null +++ b/web/vendor/bootstrap-icons/save2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/scissors.svg b/web/vendor/bootstrap-icons/scissors.svg new file mode 100644 index 0000000..2f566e4 --- /dev/null +++ b/web/vendor/bootstrap-icons/scissors.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/scooter.svg b/web/vendor/bootstrap-icons/scooter.svg new file mode 100644 index 0000000..8828452 --- /dev/null +++ b/web/vendor/bootstrap-icons/scooter.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/screwdriver.svg b/web/vendor/bootstrap-icons/screwdriver.svg new file mode 100644 index 0000000..54d5a2c --- /dev/null +++ b/web/vendor/bootstrap-icons/screwdriver.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sd-card-fill.svg b/web/vendor/bootstrap-icons/sd-card-fill.svg new file mode 100644 index 0000000..655a96d --- /dev/null +++ b/web/vendor/bootstrap-icons/sd-card-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sd-card.svg b/web/vendor/bootstrap-icons/sd-card.svg new file mode 100644 index 0000000..564661a --- /dev/null +++ b/web/vendor/bootstrap-icons/sd-card.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/search-heart-fill.svg b/web/vendor/bootstrap-icons/search-heart-fill.svg new file mode 100644 index 0000000..c57bb48 --- /dev/null +++ b/web/vendor/bootstrap-icons/search-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/search-heart.svg b/web/vendor/bootstrap-icons/search-heart.svg new file mode 100644 index 0000000..d76bfe5 --- /dev/null +++ b/web/vendor/bootstrap-icons/search-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/search.svg b/web/vendor/bootstrap-icons/search.svg new file mode 100644 index 0000000..3318054 --- /dev/null +++ b/web/vendor/bootstrap-icons/search.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/segmented-nav.svg b/web/vendor/bootstrap-icons/segmented-nav.svg new file mode 100644 index 0000000..b274b68 --- /dev/null +++ b/web/vendor/bootstrap-icons/segmented-nav.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send-arrow-down-fill.svg b/web/vendor/bootstrap-icons/send-arrow-down-fill.svg new file mode 100644 index 0000000..6d43965 --- /dev/null +++ b/web/vendor/bootstrap-icons/send-arrow-down-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send-arrow-down.svg b/web/vendor/bootstrap-icons/send-arrow-down.svg new file mode 100644 index 0000000..dcbae56 --- /dev/null +++ b/web/vendor/bootstrap-icons/send-arrow-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send-arrow-up-fill.svg b/web/vendor/bootstrap-icons/send-arrow-up-fill.svg new file mode 100644 index 0000000..19abab7 --- /dev/null +++ b/web/vendor/bootstrap-icons/send-arrow-up-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send-arrow-up.svg b/web/vendor/bootstrap-icons/send-arrow-up.svg new file mode 100644 index 0000000..a642dac --- /dev/null +++ b/web/vendor/bootstrap-icons/send-arrow-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send-check-fill.svg b/web/vendor/bootstrap-icons/send-check-fill.svg new file mode 100644 index 0000000..c4259c8 --- /dev/null +++ b/web/vendor/bootstrap-icons/send-check-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send-check.svg b/web/vendor/bootstrap-icons/send-check.svg new file mode 100644 index 0000000..5221868 --- /dev/null +++ b/web/vendor/bootstrap-icons/send-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send-dash-fill.svg b/web/vendor/bootstrap-icons/send-dash-fill.svg new file mode 100644 index 0000000..12a82df --- /dev/null +++ b/web/vendor/bootstrap-icons/send-dash-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send-dash.svg b/web/vendor/bootstrap-icons/send-dash.svg new file mode 100644 index 0000000..63fc38c --- /dev/null +++ b/web/vendor/bootstrap-icons/send-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send-exclamation-fill.svg b/web/vendor/bootstrap-icons/send-exclamation-fill.svg new file mode 100644 index 0000000..fce810f --- /dev/null +++ b/web/vendor/bootstrap-icons/send-exclamation-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send-exclamation.svg b/web/vendor/bootstrap-icons/send-exclamation.svg new file mode 100644 index 0000000..8a72f31 --- /dev/null +++ b/web/vendor/bootstrap-icons/send-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send-fill.svg b/web/vendor/bootstrap-icons/send-fill.svg new file mode 100644 index 0000000..6e95d27 --- /dev/null +++ b/web/vendor/bootstrap-icons/send-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send-plus-fill.svg b/web/vendor/bootstrap-icons/send-plus-fill.svg new file mode 100644 index 0000000..63b0482 --- /dev/null +++ b/web/vendor/bootstrap-icons/send-plus-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send-plus.svg b/web/vendor/bootstrap-icons/send-plus.svg new file mode 100644 index 0000000..350b388 --- /dev/null +++ b/web/vendor/bootstrap-icons/send-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send-slash-fill.svg b/web/vendor/bootstrap-icons/send-slash-fill.svg new file mode 100644 index 0000000..e98aa92 --- /dev/null +++ b/web/vendor/bootstrap-icons/send-slash-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send-slash.svg b/web/vendor/bootstrap-icons/send-slash.svg new file mode 100644 index 0000000..e434afe --- /dev/null +++ b/web/vendor/bootstrap-icons/send-slash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send-x-fill.svg b/web/vendor/bootstrap-icons/send-x-fill.svg new file mode 100644 index 0000000..45a98a4 --- /dev/null +++ b/web/vendor/bootstrap-icons/send-x-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send-x.svg b/web/vendor/bootstrap-icons/send-x.svg new file mode 100644 index 0000000..5b854c2 --- /dev/null +++ b/web/vendor/bootstrap-icons/send-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/send.svg b/web/vendor/bootstrap-icons/send.svg new file mode 100644 index 0000000..8db355e --- /dev/null +++ b/web/vendor/bootstrap-icons/send.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/server.svg b/web/vendor/bootstrap-icons/server.svg new file mode 100644 index 0000000..bb8ca8f --- /dev/null +++ b/web/vendor/bootstrap-icons/server.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shadows.svg b/web/vendor/bootstrap-icons/shadows.svg new file mode 100644 index 0000000..6b09f0f --- /dev/null +++ b/web/vendor/bootstrap-icons/shadows.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/share-fill.svg b/web/vendor/bootstrap-icons/share-fill.svg new file mode 100644 index 0000000..bdc07ca --- /dev/null +++ b/web/vendor/bootstrap-icons/share-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/share.svg b/web/vendor/bootstrap-icons/share.svg new file mode 100644 index 0000000..bc62b93 --- /dev/null +++ b/web/vendor/bootstrap-icons/share.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shield-check.svg b/web/vendor/bootstrap-icons/shield-check.svg new file mode 100644 index 0000000..3908fca --- /dev/null +++ b/web/vendor/bootstrap-icons/shield-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shield-exclamation.svg b/web/vendor/bootstrap-icons/shield-exclamation.svg new file mode 100644 index 0000000..9826504 --- /dev/null +++ b/web/vendor/bootstrap-icons/shield-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shield-fill-check.svg b/web/vendor/bootstrap-icons/shield-fill-check.svg new file mode 100644 index 0000000..f914f1f --- /dev/null +++ b/web/vendor/bootstrap-icons/shield-fill-check.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shield-fill-exclamation.svg b/web/vendor/bootstrap-icons/shield-fill-exclamation.svg new file mode 100644 index 0000000..99a6bf9 --- /dev/null +++ b/web/vendor/bootstrap-icons/shield-fill-exclamation.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shield-fill-minus.svg b/web/vendor/bootstrap-icons/shield-fill-minus.svg new file mode 100644 index 0000000..584f5ae --- /dev/null +++ b/web/vendor/bootstrap-icons/shield-fill-minus.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shield-fill-plus.svg b/web/vendor/bootstrap-icons/shield-fill-plus.svg new file mode 100644 index 0000000..43a3169 --- /dev/null +++ b/web/vendor/bootstrap-icons/shield-fill-plus.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shield-fill-x.svg b/web/vendor/bootstrap-icons/shield-fill-x.svg new file mode 100644 index 0000000..42267cf --- /dev/null +++ b/web/vendor/bootstrap-icons/shield-fill-x.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shield-fill.svg b/web/vendor/bootstrap-icons/shield-fill.svg new file mode 100644 index 0000000..12a61bc --- /dev/null +++ b/web/vendor/bootstrap-icons/shield-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shield-lock-fill.svg b/web/vendor/bootstrap-icons/shield-lock-fill.svg new file mode 100644 index 0000000..0fccf6f --- /dev/null +++ b/web/vendor/bootstrap-icons/shield-lock-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shield-lock.svg b/web/vendor/bootstrap-icons/shield-lock.svg new file mode 100644 index 0000000..316fb3c --- /dev/null +++ b/web/vendor/bootstrap-icons/shield-lock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shield-minus.svg b/web/vendor/bootstrap-icons/shield-minus.svg new file mode 100644 index 0000000..9fb8712 --- /dev/null +++ b/web/vendor/bootstrap-icons/shield-minus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shield-plus.svg b/web/vendor/bootstrap-icons/shield-plus.svg new file mode 100644 index 0000000..3b19b28 --- /dev/null +++ b/web/vendor/bootstrap-icons/shield-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shield-shaded.svg b/web/vendor/bootstrap-icons/shield-shaded.svg new file mode 100644 index 0000000..4908f5d --- /dev/null +++ b/web/vendor/bootstrap-icons/shield-shaded.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shield-slash-fill.svg b/web/vendor/bootstrap-icons/shield-slash-fill.svg new file mode 100644 index 0000000..d270d6d --- /dev/null +++ b/web/vendor/bootstrap-icons/shield-slash-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shield-slash.svg b/web/vendor/bootstrap-icons/shield-slash.svg new file mode 100644 index 0000000..abc01b1 --- /dev/null +++ b/web/vendor/bootstrap-icons/shield-slash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shield-x.svg b/web/vendor/bootstrap-icons/shield-x.svg new file mode 100644 index 0000000..cc9c59d --- /dev/null +++ b/web/vendor/bootstrap-icons/shield-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shield.svg b/web/vendor/bootstrap-icons/shield.svg new file mode 100644 index 0000000..7e18d1b --- /dev/null +++ b/web/vendor/bootstrap-icons/shield.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shift-fill.svg b/web/vendor/bootstrap-icons/shift-fill.svg new file mode 100644 index 0000000..37583e1 --- /dev/null +++ b/web/vendor/bootstrap-icons/shift-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shift.svg b/web/vendor/bootstrap-icons/shift.svg new file mode 100644 index 0000000..5d8a6e3 --- /dev/null +++ b/web/vendor/bootstrap-icons/shift.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shop-window.svg b/web/vendor/bootstrap-icons/shop-window.svg new file mode 100644 index 0000000..14e0d42 --- /dev/null +++ b/web/vendor/bootstrap-icons/shop-window.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shop.svg b/web/vendor/bootstrap-icons/shop.svg new file mode 100644 index 0000000..e6bb8c0 --- /dev/null +++ b/web/vendor/bootstrap-icons/shop.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/shuffle.svg b/web/vendor/bootstrap-icons/shuffle.svg new file mode 100644 index 0000000..2787bf2 --- /dev/null +++ b/web/vendor/bootstrap-icons/shuffle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-dead-end-fill.svg b/web/vendor/bootstrap-icons/sign-dead-end-fill.svg new file mode 100644 index 0000000..b362833 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-dead-end-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-dead-end.svg b/web/vendor/bootstrap-icons/sign-dead-end.svg new file mode 100644 index 0000000..b87d368 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-dead-end.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-do-not-enter-fill.svg b/web/vendor/bootstrap-icons/sign-do-not-enter-fill.svg new file mode 100644 index 0000000..f86ebfa --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-do-not-enter-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-do-not-enter.svg b/web/vendor/bootstrap-icons/sign-do-not-enter.svg new file mode 100644 index 0000000..2e2c877 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-do-not-enter.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-intersection-fill.svg b/web/vendor/bootstrap-icons/sign-intersection-fill.svg new file mode 100644 index 0000000..7fd8f3f --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-intersection-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-intersection-side-fill.svg b/web/vendor/bootstrap-icons/sign-intersection-side-fill.svg new file mode 100644 index 0000000..38870b5 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-intersection-side-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-intersection-side.svg b/web/vendor/bootstrap-icons/sign-intersection-side.svg new file mode 100644 index 0000000..df9015a --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-intersection-side.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-intersection-t-fill.svg b/web/vendor/bootstrap-icons/sign-intersection-t-fill.svg new file mode 100644 index 0000000..15a007e --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-intersection-t-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-intersection-t.svg b/web/vendor/bootstrap-icons/sign-intersection-t.svg new file mode 100644 index 0000000..4ba9f6f --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-intersection-t.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-intersection-y-fill.svg b/web/vendor/bootstrap-icons/sign-intersection-y-fill.svg new file mode 100644 index 0000000..01a03d0 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-intersection-y-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-intersection-y.svg b/web/vendor/bootstrap-icons/sign-intersection-y.svg new file mode 100644 index 0000000..e0e387f --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-intersection-y.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-intersection.svg b/web/vendor/bootstrap-icons/sign-intersection.svg new file mode 100644 index 0000000..be2ffdc --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-intersection.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-merge-left-fill.svg b/web/vendor/bootstrap-icons/sign-merge-left-fill.svg new file mode 100644 index 0000000..1408133 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-merge-left-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-merge-left.svg b/web/vendor/bootstrap-icons/sign-merge-left.svg new file mode 100644 index 0000000..3447bcf --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-merge-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-merge-right-fill.svg b/web/vendor/bootstrap-icons/sign-merge-right-fill.svg new file mode 100644 index 0000000..a952bb5 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-merge-right-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-merge-right.svg b/web/vendor/bootstrap-icons/sign-merge-right.svg new file mode 100644 index 0000000..ab3e08a --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-merge-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-no-left-turn-fill.svg b/web/vendor/bootstrap-icons/sign-no-left-turn-fill.svg new file mode 100644 index 0000000..85f421a --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-no-left-turn-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-no-left-turn.svg b/web/vendor/bootstrap-icons/sign-no-left-turn.svg new file mode 100644 index 0000000..d45f090 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-no-left-turn.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-no-parking-fill.svg b/web/vendor/bootstrap-icons/sign-no-parking-fill.svg new file mode 100644 index 0000000..c4100d9 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-no-parking-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-no-parking.svg b/web/vendor/bootstrap-icons/sign-no-parking.svg new file mode 100644 index 0000000..1679603 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-no-parking.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-no-right-turn-fill.svg b/web/vendor/bootstrap-icons/sign-no-right-turn-fill.svg new file mode 100644 index 0000000..c3883da --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-no-right-turn-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-no-right-turn.svg b/web/vendor/bootstrap-icons/sign-no-right-turn.svg new file mode 100644 index 0000000..209b918 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-no-right-turn.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-railroad-fill.svg b/web/vendor/bootstrap-icons/sign-railroad-fill.svg new file mode 100644 index 0000000..61d88a9 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-railroad-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-railroad.svg b/web/vendor/bootstrap-icons/sign-railroad.svg new file mode 100644 index 0000000..b5d7339 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-railroad.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-stop-fill.svg b/web/vendor/bootstrap-icons/sign-stop-fill.svg new file mode 100644 index 0000000..08efb9a --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-stop-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-stop-lights-fill.svg b/web/vendor/bootstrap-icons/sign-stop-lights-fill.svg new file mode 100644 index 0000000..9be8e0c --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-stop-lights-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-stop-lights.svg b/web/vendor/bootstrap-icons/sign-stop-lights.svg new file mode 100644 index 0000000..85918cf --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-stop-lights.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-stop.svg b/web/vendor/bootstrap-icons/sign-stop.svg new file mode 100644 index 0000000..49128dc --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-stop.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-turn-left-fill.svg b/web/vendor/bootstrap-icons/sign-turn-left-fill.svg new file mode 100644 index 0000000..4b8358e --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-turn-left-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-turn-left.svg b/web/vendor/bootstrap-icons/sign-turn-left.svg new file mode 100644 index 0000000..c1b34ed --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-turn-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-turn-right-fill.svg b/web/vendor/bootstrap-icons/sign-turn-right-fill.svg new file mode 100644 index 0000000..29d8d2c --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-turn-right-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-turn-right.svg b/web/vendor/bootstrap-icons/sign-turn-right.svg new file mode 100644 index 0000000..956614a --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-turn-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-turn-slight-left-fill.svg b/web/vendor/bootstrap-icons/sign-turn-slight-left-fill.svg new file mode 100644 index 0000000..80b2977 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-turn-slight-left-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-turn-slight-left.svg b/web/vendor/bootstrap-icons/sign-turn-slight-left.svg new file mode 100644 index 0000000..98f0a0a --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-turn-slight-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-turn-slight-right-fill.svg b/web/vendor/bootstrap-icons/sign-turn-slight-right-fill.svg new file mode 100644 index 0000000..2734952 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-turn-slight-right-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-turn-slight-right.svg b/web/vendor/bootstrap-icons/sign-turn-slight-right.svg new file mode 100644 index 0000000..c462f19 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-turn-slight-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-yield-fill.svg b/web/vendor/bootstrap-icons/sign-yield-fill.svg new file mode 100644 index 0000000..79fa190 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-yield-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sign-yield.svg b/web/vendor/bootstrap-icons/sign-yield.svg new file mode 100644 index 0000000..23bd623 --- /dev/null +++ b/web/vendor/bootstrap-icons/sign-yield.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/signal.svg b/web/vendor/bootstrap-icons/signal.svg new file mode 100644 index 0000000..1583f97 --- /dev/null +++ b/web/vendor/bootstrap-icons/signal.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/signpost-2-fill.svg b/web/vendor/bootstrap-icons/signpost-2-fill.svg new file mode 100644 index 0000000..58c05a6 --- /dev/null +++ b/web/vendor/bootstrap-icons/signpost-2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/signpost-2.svg b/web/vendor/bootstrap-icons/signpost-2.svg new file mode 100644 index 0000000..e3454bd --- /dev/null +++ b/web/vendor/bootstrap-icons/signpost-2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/signpost-fill.svg b/web/vendor/bootstrap-icons/signpost-fill.svg new file mode 100644 index 0000000..00989a6 --- /dev/null +++ b/web/vendor/bootstrap-icons/signpost-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/signpost-split-fill.svg b/web/vendor/bootstrap-icons/signpost-split-fill.svg new file mode 100644 index 0000000..9b720f0 --- /dev/null +++ b/web/vendor/bootstrap-icons/signpost-split-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/signpost-split.svg b/web/vendor/bootstrap-icons/signpost-split.svg new file mode 100644 index 0000000..7fb69b7 --- /dev/null +++ b/web/vendor/bootstrap-icons/signpost-split.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/signpost.svg b/web/vendor/bootstrap-icons/signpost.svg new file mode 100644 index 0000000..940e664 --- /dev/null +++ b/web/vendor/bootstrap-icons/signpost.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sim-fill.svg b/web/vendor/bootstrap-icons/sim-fill.svg new file mode 100644 index 0000000..c7922b6 --- /dev/null +++ b/web/vendor/bootstrap-icons/sim-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sim-slash-fill.svg b/web/vendor/bootstrap-icons/sim-slash-fill.svg new file mode 100644 index 0000000..b608de7 --- /dev/null +++ b/web/vendor/bootstrap-icons/sim-slash-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sim-slash.svg b/web/vendor/bootstrap-icons/sim-slash.svg new file mode 100644 index 0000000..c8e0dc4 --- /dev/null +++ b/web/vendor/bootstrap-icons/sim-slash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sim.svg b/web/vendor/bootstrap-icons/sim.svg new file mode 100644 index 0000000..0d71a11 --- /dev/null +++ b/web/vendor/bootstrap-icons/sim.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sina-weibo.svg b/web/vendor/bootstrap-icons/sina-weibo.svg new file mode 100644 index 0000000..6d484d2 --- /dev/null +++ b/web/vendor/bootstrap-icons/sina-weibo.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-backward-btn-fill.svg b/web/vendor/bootstrap-icons/skip-backward-btn-fill.svg new file mode 100644 index 0000000..2029489 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-backward-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-backward-btn.svg b/web/vendor/bootstrap-icons/skip-backward-btn.svg new file mode 100644 index 0000000..7cae681 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-backward-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-backward-circle-fill.svg b/web/vendor/bootstrap-icons/skip-backward-circle-fill.svg new file mode 100644 index 0000000..7526356 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-backward-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-backward-circle.svg b/web/vendor/bootstrap-icons/skip-backward-circle.svg new file mode 100644 index 0000000..8739f31 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-backward-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-backward-fill.svg b/web/vendor/bootstrap-icons/skip-backward-fill.svg new file mode 100644 index 0000000..bf8f63e --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-backward-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-backward.svg b/web/vendor/bootstrap-icons/skip-backward.svg new file mode 100644 index 0000000..ff5b821 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-backward.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-end-btn-fill.svg b/web/vendor/bootstrap-icons/skip-end-btn-fill.svg new file mode 100644 index 0000000..e721821 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-end-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-end-btn.svg b/web/vendor/bootstrap-icons/skip-end-btn.svg new file mode 100644 index 0000000..6815577 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-end-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-end-circle-fill.svg b/web/vendor/bootstrap-icons/skip-end-circle-fill.svg new file mode 100644 index 0000000..63c0f68 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-end-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-end-circle.svg b/web/vendor/bootstrap-icons/skip-end-circle.svg new file mode 100644 index 0000000..50f41d9 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-end-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-end-fill.svg b/web/vendor/bootstrap-icons/skip-end-fill.svg new file mode 100644 index 0000000..afa88e3 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-end-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-end.svg b/web/vendor/bootstrap-icons/skip-end.svg new file mode 100644 index 0000000..b2dfde6 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-end.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-forward-btn-fill.svg b/web/vendor/bootstrap-icons/skip-forward-btn-fill.svg new file mode 100644 index 0000000..9547957 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-forward-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-forward-btn.svg b/web/vendor/bootstrap-icons/skip-forward-btn.svg new file mode 100644 index 0000000..46a61b0 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-forward-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-forward-circle-fill.svg b/web/vendor/bootstrap-icons/skip-forward-circle-fill.svg new file mode 100644 index 0000000..aefb633 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-forward-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-forward-circle.svg b/web/vendor/bootstrap-icons/skip-forward-circle.svg new file mode 100644 index 0000000..7ebc928 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-forward-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-forward-fill.svg b/web/vendor/bootstrap-icons/skip-forward-fill.svg new file mode 100644 index 0000000..6c54d79 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-forward-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-forward.svg b/web/vendor/bootstrap-icons/skip-forward.svg new file mode 100644 index 0000000..c69cfc5 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-forward.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-start-btn-fill.svg b/web/vendor/bootstrap-icons/skip-start-btn-fill.svg new file mode 100644 index 0000000..a0af702 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-start-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-start-btn.svg b/web/vendor/bootstrap-icons/skip-start-btn.svg new file mode 100644 index 0000000..b829fdd --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-start-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-start-circle-fill.svg b/web/vendor/bootstrap-icons/skip-start-circle-fill.svg new file mode 100644 index 0000000..bb33ab0 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-start-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-start-circle.svg b/web/vendor/bootstrap-icons/skip-start-circle.svg new file mode 100644 index 0000000..d0e3323 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-start-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-start-fill.svg b/web/vendor/bootstrap-icons/skip-start-fill.svg new file mode 100644 index 0000000..56cccc3 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-start-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skip-start.svg b/web/vendor/bootstrap-icons/skip-start.svg new file mode 100644 index 0000000..76811a9 --- /dev/null +++ b/web/vendor/bootstrap-icons/skip-start.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/skype.svg b/web/vendor/bootstrap-icons/skype.svg new file mode 100644 index 0000000..ad4be4d --- /dev/null +++ b/web/vendor/bootstrap-icons/skype.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/slack.svg b/web/vendor/bootstrap-icons/slack.svg new file mode 100644 index 0000000..d914abe --- /dev/null +++ b/web/vendor/bootstrap-icons/slack.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/slash-circle-fill.svg b/web/vendor/bootstrap-icons/slash-circle-fill.svg new file mode 100644 index 0000000..5f71707 --- /dev/null +++ b/web/vendor/bootstrap-icons/slash-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/slash-circle.svg b/web/vendor/bootstrap-icons/slash-circle.svg new file mode 100644 index 0000000..eb26f19 --- /dev/null +++ b/web/vendor/bootstrap-icons/slash-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/slash-lg.svg b/web/vendor/bootstrap-icons/slash-lg.svg new file mode 100644 index 0000000..8b8b132 --- /dev/null +++ b/web/vendor/bootstrap-icons/slash-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/slash-square-fill.svg b/web/vendor/bootstrap-icons/slash-square-fill.svg new file mode 100644 index 0000000..6fc9153 --- /dev/null +++ b/web/vendor/bootstrap-icons/slash-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/slash-square.svg b/web/vendor/bootstrap-icons/slash-square.svg new file mode 100644 index 0000000..0757006 --- /dev/null +++ b/web/vendor/bootstrap-icons/slash-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/slash.svg b/web/vendor/bootstrap-icons/slash.svg new file mode 100644 index 0000000..6d18af4 --- /dev/null +++ b/web/vendor/bootstrap-icons/slash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sliders.svg b/web/vendor/bootstrap-icons/sliders.svg new file mode 100644 index 0000000..c64a06c --- /dev/null +++ b/web/vendor/bootstrap-icons/sliders.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sliders2-vertical.svg b/web/vendor/bootstrap-icons/sliders2-vertical.svg new file mode 100644 index 0000000..4fcb8ba --- /dev/null +++ b/web/vendor/bootstrap-icons/sliders2-vertical.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sliders2.svg b/web/vendor/bootstrap-icons/sliders2.svg new file mode 100644 index 0000000..975861e --- /dev/null +++ b/web/vendor/bootstrap-icons/sliders2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/smartwatch.svg b/web/vendor/bootstrap-icons/smartwatch.svg new file mode 100644 index 0000000..0a11991 --- /dev/null +++ b/web/vendor/bootstrap-icons/smartwatch.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/snapchat.svg b/web/vendor/bootstrap-icons/snapchat.svg new file mode 100644 index 0000000..01d3684 --- /dev/null +++ b/web/vendor/bootstrap-icons/snapchat.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/snow.svg b/web/vendor/bootstrap-icons/snow.svg new file mode 100644 index 0000000..9b648a5 --- /dev/null +++ b/web/vendor/bootstrap-icons/snow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/snow2.svg b/web/vendor/bootstrap-icons/snow2.svg new file mode 100644 index 0000000..6533d63 --- /dev/null +++ b/web/vendor/bootstrap-icons/snow2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/snow3.svg b/web/vendor/bootstrap-icons/snow3.svg new file mode 100644 index 0000000..01c0d73 --- /dev/null +++ b/web/vendor/bootstrap-icons/snow3.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sort-alpha-down-alt.svg b/web/vendor/bootstrap-icons/sort-alpha-down-alt.svg new file mode 100644 index 0000000..d03f1aa --- /dev/null +++ b/web/vendor/bootstrap-icons/sort-alpha-down-alt.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sort-alpha-down.svg b/web/vendor/bootstrap-icons/sort-alpha-down.svg new file mode 100644 index 0000000..6ac3e84 --- /dev/null +++ b/web/vendor/bootstrap-icons/sort-alpha-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sort-alpha-up-alt.svg b/web/vendor/bootstrap-icons/sort-alpha-up-alt.svg new file mode 100644 index 0000000..a7b332e --- /dev/null +++ b/web/vendor/bootstrap-icons/sort-alpha-up-alt.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sort-alpha-up.svg b/web/vendor/bootstrap-icons/sort-alpha-up.svg new file mode 100644 index 0000000..c5f0e3a --- /dev/null +++ b/web/vendor/bootstrap-icons/sort-alpha-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sort-down-alt.svg b/web/vendor/bootstrap-icons/sort-down-alt.svg new file mode 100644 index 0000000..86a1bf6 --- /dev/null +++ b/web/vendor/bootstrap-icons/sort-down-alt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sort-down.svg b/web/vendor/bootstrap-icons/sort-down.svg new file mode 100644 index 0000000..8cfdf23 --- /dev/null +++ b/web/vendor/bootstrap-icons/sort-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sort-numeric-down-alt.svg b/web/vendor/bootstrap-icons/sort-numeric-down-alt.svg new file mode 100644 index 0000000..ce4e3c5 --- /dev/null +++ b/web/vendor/bootstrap-icons/sort-numeric-down-alt.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sort-numeric-down.svg b/web/vendor/bootstrap-icons/sort-numeric-down.svg new file mode 100644 index 0000000..afa87be --- /dev/null +++ b/web/vendor/bootstrap-icons/sort-numeric-down.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sort-numeric-up-alt.svg b/web/vendor/bootstrap-icons/sort-numeric-up-alt.svg new file mode 100644 index 0000000..d83cbf9 --- /dev/null +++ b/web/vendor/bootstrap-icons/sort-numeric-up-alt.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sort-numeric-up.svg b/web/vendor/bootstrap-icons/sort-numeric-up.svg new file mode 100644 index 0000000..25a1e54 --- /dev/null +++ b/web/vendor/bootstrap-icons/sort-numeric-up.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sort-up-alt.svg b/web/vendor/bootstrap-icons/sort-up-alt.svg new file mode 100644 index 0000000..9f78a20 --- /dev/null +++ b/web/vendor/bootstrap-icons/sort-up-alt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sort-up.svg b/web/vendor/bootstrap-icons/sort-up.svg new file mode 100644 index 0000000..cda9ac7 --- /dev/null +++ b/web/vendor/bootstrap-icons/sort-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/soundwave.svg b/web/vendor/bootstrap-icons/soundwave.svg new file mode 100644 index 0000000..1444777 --- /dev/null +++ b/web/vendor/bootstrap-icons/soundwave.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sourceforge.svg b/web/vendor/bootstrap-icons/sourceforge.svg new file mode 100644 index 0000000..13d0c5f --- /dev/null +++ b/web/vendor/bootstrap-icons/sourceforge.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/speaker-fill.svg b/web/vendor/bootstrap-icons/speaker-fill.svg new file mode 100644 index 0000000..f6d9e33 --- /dev/null +++ b/web/vendor/bootstrap-icons/speaker-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/speaker.svg b/web/vendor/bootstrap-icons/speaker.svg new file mode 100644 index 0000000..1415b5d --- /dev/null +++ b/web/vendor/bootstrap-icons/speaker.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/speedometer.svg b/web/vendor/bootstrap-icons/speedometer.svg new file mode 100644 index 0000000..f6e3e61 --- /dev/null +++ b/web/vendor/bootstrap-icons/speedometer.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/speedometer2.svg b/web/vendor/bootstrap-icons/speedometer2.svg new file mode 100644 index 0000000..75e79c8 --- /dev/null +++ b/web/vendor/bootstrap-icons/speedometer2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/spellcheck.svg b/web/vendor/bootstrap-icons/spellcheck.svg new file mode 100644 index 0000000..69fec76 --- /dev/null +++ b/web/vendor/bootstrap-icons/spellcheck.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/spotify.svg b/web/vendor/bootstrap-icons/spotify.svg new file mode 100644 index 0000000..09d0e9f --- /dev/null +++ b/web/vendor/bootstrap-icons/spotify.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/square-fill.svg b/web/vendor/bootstrap-icons/square-fill.svg new file mode 100644 index 0000000..1e72d5e --- /dev/null +++ b/web/vendor/bootstrap-icons/square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/square-half.svg b/web/vendor/bootstrap-icons/square-half.svg new file mode 100644 index 0000000..aa3e349 --- /dev/null +++ b/web/vendor/bootstrap-icons/square-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/square.svg b/web/vendor/bootstrap-icons/square.svg new file mode 100644 index 0000000..0f086de --- /dev/null +++ b/web/vendor/bootstrap-icons/square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/stack-overflow.svg b/web/vendor/bootstrap-icons/stack-overflow.svg new file mode 100644 index 0000000..c5e5be6 --- /dev/null +++ b/web/vendor/bootstrap-icons/stack-overflow.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/stack.svg b/web/vendor/bootstrap-icons/stack.svg new file mode 100644 index 0000000..3cf0eca --- /dev/null +++ b/web/vendor/bootstrap-icons/stack.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/star-fill.svg b/web/vendor/bootstrap-icons/star-fill.svg new file mode 100644 index 0000000..de09c4a --- /dev/null +++ b/web/vendor/bootstrap-icons/star-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/star-half.svg b/web/vendor/bootstrap-icons/star-half.svg new file mode 100644 index 0000000..8a70f53 --- /dev/null +++ b/web/vendor/bootstrap-icons/star-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/star.svg b/web/vendor/bootstrap-icons/star.svg new file mode 100644 index 0000000..fcdcb1c --- /dev/null +++ b/web/vendor/bootstrap-icons/star.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/stars.svg b/web/vendor/bootstrap-icons/stars.svg new file mode 100644 index 0000000..b6fb4f2 --- /dev/null +++ b/web/vendor/bootstrap-icons/stars.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/steam.svg b/web/vendor/bootstrap-icons/steam.svg new file mode 100644 index 0000000..9daa3d3 --- /dev/null +++ b/web/vendor/bootstrap-icons/steam.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/stickies-fill.svg b/web/vendor/bootstrap-icons/stickies-fill.svg new file mode 100644 index 0000000..039c3b8 --- /dev/null +++ b/web/vendor/bootstrap-icons/stickies-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/stickies.svg b/web/vendor/bootstrap-icons/stickies.svg new file mode 100644 index 0000000..24e6492 --- /dev/null +++ b/web/vendor/bootstrap-icons/stickies.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sticky-fill.svg b/web/vendor/bootstrap-icons/sticky-fill.svg new file mode 100644 index 0000000..b36dcb1 --- /dev/null +++ b/web/vendor/bootstrap-icons/sticky-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sticky.svg b/web/vendor/bootstrap-icons/sticky.svg new file mode 100644 index 0000000..0d50e88 --- /dev/null +++ b/web/vendor/bootstrap-icons/sticky.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/stop-btn-fill.svg b/web/vendor/bootstrap-icons/stop-btn-fill.svg new file mode 100644 index 0000000..70e562e --- /dev/null +++ b/web/vendor/bootstrap-icons/stop-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/stop-btn.svg b/web/vendor/bootstrap-icons/stop-btn.svg new file mode 100644 index 0000000..26348d5 --- /dev/null +++ b/web/vendor/bootstrap-icons/stop-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/stop-circle-fill.svg b/web/vendor/bootstrap-icons/stop-circle-fill.svg new file mode 100644 index 0000000..141668e --- /dev/null +++ b/web/vendor/bootstrap-icons/stop-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/stop-circle.svg b/web/vendor/bootstrap-icons/stop-circle.svg new file mode 100644 index 0000000..3e1933a --- /dev/null +++ b/web/vendor/bootstrap-icons/stop-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/stop-fill.svg b/web/vendor/bootstrap-icons/stop-fill.svg new file mode 100644 index 0000000..ca1b957 --- /dev/null +++ b/web/vendor/bootstrap-icons/stop-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/stop.svg b/web/vendor/bootstrap-icons/stop.svg new file mode 100644 index 0000000..27f1fb6 --- /dev/null +++ b/web/vendor/bootstrap-icons/stop.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/stoplights-fill.svg b/web/vendor/bootstrap-icons/stoplights-fill.svg new file mode 100644 index 0000000..f0b2d76 --- /dev/null +++ b/web/vendor/bootstrap-icons/stoplights-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/stoplights.svg b/web/vendor/bootstrap-icons/stoplights.svg new file mode 100644 index 0000000..6db3e12 --- /dev/null +++ b/web/vendor/bootstrap-icons/stoplights.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/stopwatch-fill.svg b/web/vendor/bootstrap-icons/stopwatch-fill.svg new file mode 100644 index 0000000..1228cf2 --- /dev/null +++ b/web/vendor/bootstrap-icons/stopwatch-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/stopwatch.svg b/web/vendor/bootstrap-icons/stopwatch.svg new file mode 100644 index 0000000..aff8c33 --- /dev/null +++ b/web/vendor/bootstrap-icons/stopwatch.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/strava.svg b/web/vendor/bootstrap-icons/strava.svg new file mode 100644 index 0000000..0ed6bab --- /dev/null +++ b/web/vendor/bootstrap-icons/strava.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/stripe.svg b/web/vendor/bootstrap-icons/stripe.svg new file mode 100644 index 0000000..ba961a0 --- /dev/null +++ b/web/vendor/bootstrap-icons/stripe.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/subscript.svg b/web/vendor/bootstrap-icons/subscript.svg new file mode 100644 index 0000000..51f5eea --- /dev/null +++ b/web/vendor/bootstrap-icons/subscript.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/substack.svg b/web/vendor/bootstrap-icons/substack.svg new file mode 100644 index 0000000..e54179a --- /dev/null +++ b/web/vendor/bootstrap-icons/substack.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/subtract.svg b/web/vendor/bootstrap-icons/subtract.svg new file mode 100644 index 0000000..129c3d5 --- /dev/null +++ b/web/vendor/bootstrap-icons/subtract.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/suit-club-fill.svg b/web/vendor/bootstrap-icons/suit-club-fill.svg new file mode 100644 index 0000000..a787160 --- /dev/null +++ b/web/vendor/bootstrap-icons/suit-club-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/suit-club.svg b/web/vendor/bootstrap-icons/suit-club.svg new file mode 100644 index 0000000..3fbf98b --- /dev/null +++ b/web/vendor/bootstrap-icons/suit-club.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/suit-diamond-fill.svg b/web/vendor/bootstrap-icons/suit-diamond-fill.svg new file mode 100644 index 0000000..67617d6 --- /dev/null +++ b/web/vendor/bootstrap-icons/suit-diamond-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/suit-diamond.svg b/web/vendor/bootstrap-icons/suit-diamond.svg new file mode 100644 index 0000000..79b54c1 --- /dev/null +++ b/web/vendor/bootstrap-icons/suit-diamond.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/suit-heart-fill.svg b/web/vendor/bootstrap-icons/suit-heart-fill.svg new file mode 100644 index 0000000..d09850c --- /dev/null +++ b/web/vendor/bootstrap-icons/suit-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/suit-heart.svg b/web/vendor/bootstrap-icons/suit-heart.svg new file mode 100644 index 0000000..173b32f --- /dev/null +++ b/web/vendor/bootstrap-icons/suit-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/suit-spade-fill.svg b/web/vendor/bootstrap-icons/suit-spade-fill.svg new file mode 100644 index 0000000..cc465e5 --- /dev/null +++ b/web/vendor/bootstrap-icons/suit-spade-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/suit-spade.svg b/web/vendor/bootstrap-icons/suit-spade.svg new file mode 100644 index 0000000..7123c10 --- /dev/null +++ b/web/vendor/bootstrap-icons/suit-spade.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/suitcase-fill.svg b/web/vendor/bootstrap-icons/suitcase-fill.svg new file mode 100644 index 0000000..df62651 --- /dev/null +++ b/web/vendor/bootstrap-icons/suitcase-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/suitcase-lg-fill.svg b/web/vendor/bootstrap-icons/suitcase-lg-fill.svg new file mode 100644 index 0000000..cef1da9 --- /dev/null +++ b/web/vendor/bootstrap-icons/suitcase-lg-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/suitcase-lg.svg b/web/vendor/bootstrap-icons/suitcase-lg.svg new file mode 100644 index 0000000..ea447d2 --- /dev/null +++ b/web/vendor/bootstrap-icons/suitcase-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/suitcase.svg b/web/vendor/bootstrap-icons/suitcase.svg new file mode 100644 index 0000000..65e619d --- /dev/null +++ b/web/vendor/bootstrap-icons/suitcase.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/suitcase2-fill.svg b/web/vendor/bootstrap-icons/suitcase2-fill.svg new file mode 100644 index 0000000..a2cb410 --- /dev/null +++ b/web/vendor/bootstrap-icons/suitcase2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/suitcase2.svg b/web/vendor/bootstrap-icons/suitcase2.svg new file mode 100644 index 0000000..e6ea533 --- /dev/null +++ b/web/vendor/bootstrap-icons/suitcase2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sun-fill.svg b/web/vendor/bootstrap-icons/sun-fill.svg new file mode 100644 index 0000000..c83f69a --- /dev/null +++ b/web/vendor/bootstrap-icons/sun-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sun.svg b/web/vendor/bootstrap-icons/sun.svg new file mode 100644 index 0000000..3777f07 --- /dev/null +++ b/web/vendor/bootstrap-icons/sun.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sunglasses.svg b/web/vendor/bootstrap-icons/sunglasses.svg new file mode 100644 index 0000000..1ff81f7 --- /dev/null +++ b/web/vendor/bootstrap-icons/sunglasses.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sunrise-fill.svg b/web/vendor/bootstrap-icons/sunrise-fill.svg new file mode 100644 index 0000000..c922d7c --- /dev/null +++ b/web/vendor/bootstrap-icons/sunrise-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sunrise.svg b/web/vendor/bootstrap-icons/sunrise.svg new file mode 100644 index 0000000..98adcfb --- /dev/null +++ b/web/vendor/bootstrap-icons/sunrise.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sunset-fill.svg b/web/vendor/bootstrap-icons/sunset-fill.svg new file mode 100644 index 0000000..91a8d0e --- /dev/null +++ b/web/vendor/bootstrap-icons/sunset-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/sunset.svg b/web/vendor/bootstrap-icons/sunset.svg new file mode 100644 index 0000000..e72d634 --- /dev/null +++ b/web/vendor/bootstrap-icons/sunset.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/superscript.svg b/web/vendor/bootstrap-icons/superscript.svg new file mode 100644 index 0000000..81543ae --- /dev/null +++ b/web/vendor/bootstrap-icons/superscript.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/symmetry-horizontal.svg b/web/vendor/bootstrap-icons/symmetry-horizontal.svg new file mode 100644 index 0000000..594735b --- /dev/null +++ b/web/vendor/bootstrap-icons/symmetry-horizontal.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/symmetry-vertical.svg b/web/vendor/bootstrap-icons/symmetry-vertical.svg new file mode 100644 index 0000000..6907280 --- /dev/null +++ b/web/vendor/bootstrap-icons/symmetry-vertical.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/table.svg b/web/vendor/bootstrap-icons/table.svg new file mode 100644 index 0000000..8f70585 --- /dev/null +++ b/web/vendor/bootstrap-icons/table.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tablet-fill.svg b/web/vendor/bootstrap-icons/tablet-fill.svg new file mode 100644 index 0000000..0746ead --- /dev/null +++ b/web/vendor/bootstrap-icons/tablet-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tablet-landscape-fill.svg b/web/vendor/bootstrap-icons/tablet-landscape-fill.svg new file mode 100644 index 0000000..6290024 --- /dev/null +++ b/web/vendor/bootstrap-icons/tablet-landscape-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tablet-landscape.svg b/web/vendor/bootstrap-icons/tablet-landscape.svg new file mode 100644 index 0000000..438d4d1 --- /dev/null +++ b/web/vendor/bootstrap-icons/tablet-landscape.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tablet.svg b/web/vendor/bootstrap-icons/tablet.svg new file mode 100644 index 0000000..eebeee3 --- /dev/null +++ b/web/vendor/bootstrap-icons/tablet.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tag-fill.svg b/web/vendor/bootstrap-icons/tag-fill.svg new file mode 100644 index 0000000..6a95e2d --- /dev/null +++ b/web/vendor/bootstrap-icons/tag-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tag.svg b/web/vendor/bootstrap-icons/tag.svg new file mode 100644 index 0000000..01d19b5 --- /dev/null +++ b/web/vendor/bootstrap-icons/tag.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tags-fill.svg b/web/vendor/bootstrap-icons/tags-fill.svg new file mode 100644 index 0000000..1673abb --- /dev/null +++ b/web/vendor/bootstrap-icons/tags-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tags.svg b/web/vendor/bootstrap-icons/tags.svg new file mode 100644 index 0000000..ade5519 --- /dev/null +++ b/web/vendor/bootstrap-icons/tags.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/taxi-front-fill.svg b/web/vendor/bootstrap-icons/taxi-front-fill.svg new file mode 100644 index 0000000..ef7f45b --- /dev/null +++ b/web/vendor/bootstrap-icons/taxi-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/taxi-front.svg b/web/vendor/bootstrap-icons/taxi-front.svg new file mode 100644 index 0000000..1b4337a --- /dev/null +++ b/web/vendor/bootstrap-icons/taxi-front.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/telegram.svg b/web/vendor/bootstrap-icons/telegram.svg new file mode 100644 index 0000000..d260266 --- /dev/null +++ b/web/vendor/bootstrap-icons/telegram.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/telephone-fill.svg b/web/vendor/bootstrap-icons/telephone-fill.svg new file mode 100644 index 0000000..2e9de2e --- /dev/null +++ b/web/vendor/bootstrap-icons/telephone-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/telephone-forward-fill.svg b/web/vendor/bootstrap-icons/telephone-forward-fill.svg new file mode 100644 index 0000000..26fc35f --- /dev/null +++ b/web/vendor/bootstrap-icons/telephone-forward-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/telephone-forward.svg b/web/vendor/bootstrap-icons/telephone-forward.svg new file mode 100644 index 0000000..08c07bd --- /dev/null +++ b/web/vendor/bootstrap-icons/telephone-forward.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/telephone-inbound-fill.svg b/web/vendor/bootstrap-icons/telephone-inbound-fill.svg new file mode 100644 index 0000000..85434d0 --- /dev/null +++ b/web/vendor/bootstrap-icons/telephone-inbound-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/telephone-inbound.svg b/web/vendor/bootstrap-icons/telephone-inbound.svg new file mode 100644 index 0000000..8ec20a6 --- /dev/null +++ b/web/vendor/bootstrap-icons/telephone-inbound.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/telephone-minus-fill.svg b/web/vendor/bootstrap-icons/telephone-minus-fill.svg new file mode 100644 index 0000000..7b2fe9d --- /dev/null +++ b/web/vendor/bootstrap-icons/telephone-minus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/telephone-minus.svg b/web/vendor/bootstrap-icons/telephone-minus.svg new file mode 100644 index 0000000..6ebc50e --- /dev/null +++ b/web/vendor/bootstrap-icons/telephone-minus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/telephone-outbound-fill.svg b/web/vendor/bootstrap-icons/telephone-outbound-fill.svg new file mode 100644 index 0000000..0a18bda --- /dev/null +++ b/web/vendor/bootstrap-icons/telephone-outbound-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/telephone-outbound.svg b/web/vendor/bootstrap-icons/telephone-outbound.svg new file mode 100644 index 0000000..566eb46 --- /dev/null +++ b/web/vendor/bootstrap-icons/telephone-outbound.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/telephone-plus-fill.svg b/web/vendor/bootstrap-icons/telephone-plus-fill.svg new file mode 100644 index 0000000..b02874f --- /dev/null +++ b/web/vendor/bootstrap-icons/telephone-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/telephone-plus.svg b/web/vendor/bootstrap-icons/telephone-plus.svg new file mode 100644 index 0000000..787e0c6 --- /dev/null +++ b/web/vendor/bootstrap-icons/telephone-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/telephone-x-fill.svg b/web/vendor/bootstrap-icons/telephone-x-fill.svg new file mode 100644 index 0000000..5410e16 --- /dev/null +++ b/web/vendor/bootstrap-icons/telephone-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/telephone-x.svg b/web/vendor/bootstrap-icons/telephone-x.svg new file mode 100644 index 0000000..3f483a1 --- /dev/null +++ b/web/vendor/bootstrap-icons/telephone-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/telephone.svg b/web/vendor/bootstrap-icons/telephone.svg new file mode 100644 index 0000000..679e8a9 --- /dev/null +++ b/web/vendor/bootstrap-icons/telephone.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tencent-qq.svg b/web/vendor/bootstrap-icons/tencent-qq.svg new file mode 100644 index 0000000..0d5cd23 --- /dev/null +++ b/web/vendor/bootstrap-icons/tencent-qq.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/terminal-dash.svg b/web/vendor/bootstrap-icons/terminal-dash.svg new file mode 100644 index 0000000..9f46e8e --- /dev/null +++ b/web/vendor/bootstrap-icons/terminal-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/terminal-fill.svg b/web/vendor/bootstrap-icons/terminal-fill.svg new file mode 100644 index 0000000..fabd075 --- /dev/null +++ b/web/vendor/bootstrap-icons/terminal-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/terminal-plus.svg b/web/vendor/bootstrap-icons/terminal-plus.svg new file mode 100644 index 0000000..32c6432 --- /dev/null +++ b/web/vendor/bootstrap-icons/terminal-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/terminal-split.svg b/web/vendor/bootstrap-icons/terminal-split.svg new file mode 100644 index 0000000..a378c37 --- /dev/null +++ b/web/vendor/bootstrap-icons/terminal-split.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/terminal-x.svg b/web/vendor/bootstrap-icons/terminal-x.svg new file mode 100644 index 0000000..aa59e7f --- /dev/null +++ b/web/vendor/bootstrap-icons/terminal-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/terminal.svg b/web/vendor/bootstrap-icons/terminal.svg new file mode 100644 index 0000000..44aef95 --- /dev/null +++ b/web/vendor/bootstrap-icons/terminal.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/text-center.svg b/web/vendor/bootstrap-icons/text-center.svg new file mode 100644 index 0000000..12d9e29 --- /dev/null +++ b/web/vendor/bootstrap-icons/text-center.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/text-indent-left.svg b/web/vendor/bootstrap-icons/text-indent-left.svg new file mode 100644 index 0000000..5a607af --- /dev/null +++ b/web/vendor/bootstrap-icons/text-indent-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/text-indent-right.svg b/web/vendor/bootstrap-icons/text-indent-right.svg new file mode 100644 index 0000000..de91d9e --- /dev/null +++ b/web/vendor/bootstrap-icons/text-indent-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/text-left.svg b/web/vendor/bootstrap-icons/text-left.svg new file mode 100644 index 0000000..36ae0d3 --- /dev/null +++ b/web/vendor/bootstrap-icons/text-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/text-paragraph.svg b/web/vendor/bootstrap-icons/text-paragraph.svg new file mode 100644 index 0000000..035a1c8 --- /dev/null +++ b/web/vendor/bootstrap-icons/text-paragraph.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/text-right.svg b/web/vendor/bootstrap-icons/text-right.svg new file mode 100644 index 0000000..98178e7 --- /dev/null +++ b/web/vendor/bootstrap-icons/text-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/text-wrap.svg b/web/vendor/bootstrap-icons/text-wrap.svg new file mode 100644 index 0000000..4c732d6 --- /dev/null +++ b/web/vendor/bootstrap-icons/text-wrap.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/textarea-resize.svg b/web/vendor/bootstrap-icons/textarea-resize.svg new file mode 100644 index 0000000..6401320 --- /dev/null +++ b/web/vendor/bootstrap-icons/textarea-resize.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/textarea-t.svg b/web/vendor/bootstrap-icons/textarea-t.svg new file mode 100644 index 0000000..145cbb7 --- /dev/null +++ b/web/vendor/bootstrap-icons/textarea-t.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/textarea.svg b/web/vendor/bootstrap-icons/textarea.svg new file mode 100644 index 0000000..176ca25 --- /dev/null +++ b/web/vendor/bootstrap-icons/textarea.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/thermometer-half.svg b/web/vendor/bootstrap-icons/thermometer-half.svg new file mode 100644 index 0000000..018eab1 --- /dev/null +++ b/web/vendor/bootstrap-icons/thermometer-half.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/thermometer-high.svg b/web/vendor/bootstrap-icons/thermometer-high.svg new file mode 100644 index 0000000..22e77d1 --- /dev/null +++ b/web/vendor/bootstrap-icons/thermometer-high.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/thermometer-low.svg b/web/vendor/bootstrap-icons/thermometer-low.svg new file mode 100644 index 0000000..1f0f5e1 --- /dev/null +++ b/web/vendor/bootstrap-icons/thermometer-low.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/thermometer-snow.svg b/web/vendor/bootstrap-icons/thermometer-snow.svg new file mode 100644 index 0000000..df7c1d1 --- /dev/null +++ b/web/vendor/bootstrap-icons/thermometer-snow.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/thermometer-sun.svg b/web/vendor/bootstrap-icons/thermometer-sun.svg new file mode 100644 index 0000000..c453dee --- /dev/null +++ b/web/vendor/bootstrap-icons/thermometer-sun.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/thermometer.svg b/web/vendor/bootstrap-icons/thermometer.svg new file mode 100644 index 0000000..8a5529b --- /dev/null +++ b/web/vendor/bootstrap-icons/thermometer.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/threads-fill.svg b/web/vendor/bootstrap-icons/threads-fill.svg new file mode 100644 index 0000000..b19666d --- /dev/null +++ b/web/vendor/bootstrap-icons/threads-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/threads.svg b/web/vendor/bootstrap-icons/threads.svg new file mode 100644 index 0000000..13c9e7a --- /dev/null +++ b/web/vendor/bootstrap-icons/threads.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/three-dots-vertical.svg b/web/vendor/bootstrap-icons/three-dots-vertical.svg new file mode 100644 index 0000000..f5ef7d4 --- /dev/null +++ b/web/vendor/bootstrap-icons/three-dots-vertical.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/three-dots.svg b/web/vendor/bootstrap-icons/three-dots.svg new file mode 100644 index 0000000..4706f52 --- /dev/null +++ b/web/vendor/bootstrap-icons/three-dots.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/thunderbolt-fill.svg b/web/vendor/bootstrap-icons/thunderbolt-fill.svg new file mode 100644 index 0000000..1faea43 --- /dev/null +++ b/web/vendor/bootstrap-icons/thunderbolt-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/thunderbolt.svg b/web/vendor/bootstrap-icons/thunderbolt.svg new file mode 100644 index 0000000..3655659 --- /dev/null +++ b/web/vendor/bootstrap-icons/thunderbolt.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ticket-detailed-fill.svg b/web/vendor/bootstrap-icons/ticket-detailed-fill.svg new file mode 100644 index 0000000..cd7a3a7 --- /dev/null +++ b/web/vendor/bootstrap-icons/ticket-detailed-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ticket-detailed.svg b/web/vendor/bootstrap-icons/ticket-detailed.svg new file mode 100644 index 0000000..cf32e88 --- /dev/null +++ b/web/vendor/bootstrap-icons/ticket-detailed.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ticket-fill.svg b/web/vendor/bootstrap-icons/ticket-fill.svg new file mode 100644 index 0000000..01e9108 --- /dev/null +++ b/web/vendor/bootstrap-icons/ticket-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ticket-perforated-fill.svg b/web/vendor/bootstrap-icons/ticket-perforated-fill.svg new file mode 100644 index 0000000..38c18dc --- /dev/null +++ b/web/vendor/bootstrap-icons/ticket-perforated-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ticket-perforated.svg b/web/vendor/bootstrap-icons/ticket-perforated.svg new file mode 100644 index 0000000..da44537 --- /dev/null +++ b/web/vendor/bootstrap-icons/ticket-perforated.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ticket.svg b/web/vendor/bootstrap-icons/ticket.svg new file mode 100644 index 0000000..eb813a1 --- /dev/null +++ b/web/vendor/bootstrap-icons/ticket.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tiktok.svg b/web/vendor/bootstrap-icons/tiktok.svg new file mode 100644 index 0000000..04c6679 --- /dev/null +++ b/web/vendor/bootstrap-icons/tiktok.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/toggle-off.svg b/web/vendor/bootstrap-icons/toggle-off.svg new file mode 100644 index 0000000..e1e89ad --- /dev/null +++ b/web/vendor/bootstrap-icons/toggle-off.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/toggle-on.svg b/web/vendor/bootstrap-icons/toggle-on.svg new file mode 100644 index 0000000..7cd6eb3 --- /dev/null +++ b/web/vendor/bootstrap-icons/toggle-on.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/toggle2-off.svg b/web/vendor/bootstrap-icons/toggle2-off.svg new file mode 100644 index 0000000..61739ce --- /dev/null +++ b/web/vendor/bootstrap-icons/toggle2-off.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/toggle2-on.svg b/web/vendor/bootstrap-icons/toggle2-on.svg new file mode 100644 index 0000000..d752ce8 --- /dev/null +++ b/web/vendor/bootstrap-icons/toggle2-on.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/toggles.svg b/web/vendor/bootstrap-icons/toggles.svg new file mode 100644 index 0000000..659c185 --- /dev/null +++ b/web/vendor/bootstrap-icons/toggles.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/toggles2.svg b/web/vendor/bootstrap-icons/toggles2.svg new file mode 100644 index 0000000..2f90344 --- /dev/null +++ b/web/vendor/bootstrap-icons/toggles2.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tools.svg b/web/vendor/bootstrap-icons/tools.svg new file mode 100644 index 0000000..f6efdcc --- /dev/null +++ b/web/vendor/bootstrap-icons/tools.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tornado.svg b/web/vendor/bootstrap-icons/tornado.svg new file mode 100644 index 0000000..2a6397c --- /dev/null +++ b/web/vendor/bootstrap-icons/tornado.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/train-freight-front-fill.svg b/web/vendor/bootstrap-icons/train-freight-front-fill.svg new file mode 100644 index 0000000..e272051 --- /dev/null +++ b/web/vendor/bootstrap-icons/train-freight-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/train-freight-front.svg b/web/vendor/bootstrap-icons/train-freight-front.svg new file mode 100644 index 0000000..097c960 --- /dev/null +++ b/web/vendor/bootstrap-icons/train-freight-front.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/train-front-fill.svg b/web/vendor/bootstrap-icons/train-front-fill.svg new file mode 100644 index 0000000..4acad08 --- /dev/null +++ b/web/vendor/bootstrap-icons/train-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/train-front.svg b/web/vendor/bootstrap-icons/train-front.svg new file mode 100644 index 0000000..81ce139 --- /dev/null +++ b/web/vendor/bootstrap-icons/train-front.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/train-lightrail-front-fill.svg b/web/vendor/bootstrap-icons/train-lightrail-front-fill.svg new file mode 100644 index 0000000..7bd87fb --- /dev/null +++ b/web/vendor/bootstrap-icons/train-lightrail-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/train-lightrail-front.svg b/web/vendor/bootstrap-icons/train-lightrail-front.svg new file mode 100644 index 0000000..d7aa87f --- /dev/null +++ b/web/vendor/bootstrap-icons/train-lightrail-front.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/translate.svg b/web/vendor/bootstrap-icons/translate.svg new file mode 100644 index 0000000..2e0754e --- /dev/null +++ b/web/vendor/bootstrap-icons/translate.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/transparency.svg b/web/vendor/bootstrap-icons/transparency.svg new file mode 100644 index 0000000..289a4b9 --- /dev/null +++ b/web/vendor/bootstrap-icons/transparency.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/trash-fill.svg b/web/vendor/bootstrap-icons/trash-fill.svg new file mode 100644 index 0000000..b67453a --- /dev/null +++ b/web/vendor/bootstrap-icons/trash-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/trash.svg b/web/vendor/bootstrap-icons/trash.svg new file mode 100644 index 0000000..3020264 --- /dev/null +++ b/web/vendor/bootstrap-icons/trash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/trash2-fill.svg b/web/vendor/bootstrap-icons/trash2-fill.svg new file mode 100644 index 0000000..fb1d90d --- /dev/null +++ b/web/vendor/bootstrap-icons/trash2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/trash2.svg b/web/vendor/bootstrap-icons/trash2.svg new file mode 100644 index 0000000..0cabe8d --- /dev/null +++ b/web/vendor/bootstrap-icons/trash2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/trash3-fill.svg b/web/vendor/bootstrap-icons/trash3-fill.svg new file mode 100644 index 0000000..42fbfc5 --- /dev/null +++ b/web/vendor/bootstrap-icons/trash3-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/trash3.svg b/web/vendor/bootstrap-icons/trash3.svg new file mode 100644 index 0000000..5194bf0 --- /dev/null +++ b/web/vendor/bootstrap-icons/trash3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tree-fill.svg b/web/vendor/bootstrap-icons/tree-fill.svg new file mode 100644 index 0000000..d00e733 --- /dev/null +++ b/web/vendor/bootstrap-icons/tree-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tree.svg b/web/vendor/bootstrap-icons/tree.svg new file mode 100644 index 0000000..17a5efe --- /dev/null +++ b/web/vendor/bootstrap-icons/tree.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/trello.svg b/web/vendor/bootstrap-icons/trello.svg new file mode 100644 index 0000000..bd88732 --- /dev/null +++ b/web/vendor/bootstrap-icons/trello.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/triangle-fill.svg b/web/vendor/bootstrap-icons/triangle-fill.svg new file mode 100644 index 0000000..474c8bb --- /dev/null +++ b/web/vendor/bootstrap-icons/triangle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/triangle-half.svg b/web/vendor/bootstrap-icons/triangle-half.svg new file mode 100644 index 0000000..a495ca0 --- /dev/null +++ b/web/vendor/bootstrap-icons/triangle-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/triangle.svg b/web/vendor/bootstrap-icons/triangle.svg new file mode 100644 index 0000000..95a6a9b --- /dev/null +++ b/web/vendor/bootstrap-icons/triangle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/trophy-fill.svg b/web/vendor/bootstrap-icons/trophy-fill.svg new file mode 100644 index 0000000..f469737 --- /dev/null +++ b/web/vendor/bootstrap-icons/trophy-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/trophy.svg b/web/vendor/bootstrap-icons/trophy.svg new file mode 100644 index 0000000..ae13957 --- /dev/null +++ b/web/vendor/bootstrap-icons/trophy.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tropical-storm.svg b/web/vendor/bootstrap-icons/tropical-storm.svg new file mode 100644 index 0000000..9eb3354 --- /dev/null +++ b/web/vendor/bootstrap-icons/tropical-storm.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/truck-flatbed.svg b/web/vendor/bootstrap-icons/truck-flatbed.svg new file mode 100644 index 0000000..4b38155 --- /dev/null +++ b/web/vendor/bootstrap-icons/truck-flatbed.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/truck-front-fill.svg b/web/vendor/bootstrap-icons/truck-front-fill.svg new file mode 100644 index 0000000..39f72d0 --- /dev/null +++ b/web/vendor/bootstrap-icons/truck-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/truck-front.svg b/web/vendor/bootstrap-icons/truck-front.svg new file mode 100644 index 0000000..d805db5 --- /dev/null +++ b/web/vendor/bootstrap-icons/truck-front.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/truck.svg b/web/vendor/bootstrap-icons/truck.svg new file mode 100644 index 0000000..72c5439 --- /dev/null +++ b/web/vendor/bootstrap-icons/truck.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tsunami.svg b/web/vendor/bootstrap-icons/tsunami.svg new file mode 100644 index 0000000..be5f9be --- /dev/null +++ b/web/vendor/bootstrap-icons/tsunami.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tux.svg b/web/vendor/bootstrap-icons/tux.svg new file mode 100644 index 0000000..6a3242c --- /dev/null +++ b/web/vendor/bootstrap-icons/tux.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tv-fill.svg b/web/vendor/bootstrap-icons/tv-fill.svg new file mode 100644 index 0000000..483c9fd --- /dev/null +++ b/web/vendor/bootstrap-icons/tv-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/tv.svg b/web/vendor/bootstrap-icons/tv.svg new file mode 100644 index 0000000..fa8b3c1 --- /dev/null +++ b/web/vendor/bootstrap-icons/tv.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/twitch.svg b/web/vendor/bootstrap-icons/twitch.svg new file mode 100644 index 0000000..b2c8ff5 --- /dev/null +++ b/web/vendor/bootstrap-icons/twitch.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/twitter-x.svg b/web/vendor/bootstrap-icons/twitter-x.svg new file mode 100644 index 0000000..2fafcc2 --- /dev/null +++ b/web/vendor/bootstrap-icons/twitter-x.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/twitter.svg b/web/vendor/bootstrap-icons/twitter.svg new file mode 100644 index 0000000..3001352 --- /dev/null +++ b/web/vendor/bootstrap-icons/twitter.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/type-bold.svg b/web/vendor/bootstrap-icons/type-bold.svg new file mode 100644 index 0000000..0814a2e --- /dev/null +++ b/web/vendor/bootstrap-icons/type-bold.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/type-h1.svg b/web/vendor/bootstrap-icons/type-h1.svg new file mode 100644 index 0000000..0df41f6 --- /dev/null +++ b/web/vendor/bootstrap-icons/type-h1.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/type-h2.svg b/web/vendor/bootstrap-icons/type-h2.svg new file mode 100644 index 0000000..03379ed --- /dev/null +++ b/web/vendor/bootstrap-icons/type-h2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/type-h3.svg b/web/vendor/bootstrap-icons/type-h3.svg new file mode 100644 index 0000000..97de531 --- /dev/null +++ b/web/vendor/bootstrap-icons/type-h3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/type-h4.svg b/web/vendor/bootstrap-icons/type-h4.svg new file mode 100644 index 0000000..a7ddc81 --- /dev/null +++ b/web/vendor/bootstrap-icons/type-h4.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/type-h5.svg b/web/vendor/bootstrap-icons/type-h5.svg new file mode 100644 index 0000000..776bfa3 --- /dev/null +++ b/web/vendor/bootstrap-icons/type-h5.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/type-h6.svg b/web/vendor/bootstrap-icons/type-h6.svg new file mode 100644 index 0000000..9267192 --- /dev/null +++ b/web/vendor/bootstrap-icons/type-h6.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/type-italic.svg b/web/vendor/bootstrap-icons/type-italic.svg new file mode 100644 index 0000000..3ac6b09 --- /dev/null +++ b/web/vendor/bootstrap-icons/type-italic.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/type-strikethrough.svg b/web/vendor/bootstrap-icons/type-strikethrough.svg new file mode 100644 index 0000000..c64eba3 --- /dev/null +++ b/web/vendor/bootstrap-icons/type-strikethrough.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/type-underline.svg b/web/vendor/bootstrap-icons/type-underline.svg new file mode 100644 index 0000000..1c0b6c4 --- /dev/null +++ b/web/vendor/bootstrap-icons/type-underline.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/type.svg b/web/vendor/bootstrap-icons/type.svg new file mode 100644 index 0000000..8c1fde1 --- /dev/null +++ b/web/vendor/bootstrap-icons/type.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/typescript.svg b/web/vendor/bootstrap-icons/typescript.svg new file mode 100644 index 0000000..12429d8 --- /dev/null +++ b/web/vendor/bootstrap-icons/typescript.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ubuntu.svg b/web/vendor/bootstrap-icons/ubuntu.svg new file mode 100644 index 0000000..89c8830 --- /dev/null +++ b/web/vendor/bootstrap-icons/ubuntu.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ui-checks-grid.svg b/web/vendor/bootstrap-icons/ui-checks-grid.svg new file mode 100644 index 0000000..e5d1ed9 --- /dev/null +++ b/web/vendor/bootstrap-icons/ui-checks-grid.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ui-checks.svg b/web/vendor/bootstrap-icons/ui-checks.svg new file mode 100644 index 0000000..5d02869 --- /dev/null +++ b/web/vendor/bootstrap-icons/ui-checks.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ui-radios-grid.svg b/web/vendor/bootstrap-icons/ui-radios-grid.svg new file mode 100644 index 0000000..9f9aae0 --- /dev/null +++ b/web/vendor/bootstrap-icons/ui-radios-grid.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/ui-radios.svg b/web/vendor/bootstrap-icons/ui-radios.svg new file mode 100644 index 0000000..9165340 --- /dev/null +++ b/web/vendor/bootstrap-icons/ui-radios.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/umbrella-fill.svg b/web/vendor/bootstrap-icons/umbrella-fill.svg new file mode 100644 index 0000000..3efaf13 --- /dev/null +++ b/web/vendor/bootstrap-icons/umbrella-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/umbrella.svg b/web/vendor/bootstrap-icons/umbrella.svg new file mode 100644 index 0000000..f7b698c --- /dev/null +++ b/web/vendor/bootstrap-icons/umbrella.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/unindent.svg b/web/vendor/bootstrap-icons/unindent.svg new file mode 100644 index 0000000..9e68255 --- /dev/null +++ b/web/vendor/bootstrap-icons/unindent.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/union.svg b/web/vendor/bootstrap-icons/union.svg new file mode 100644 index 0000000..ba23f54 --- /dev/null +++ b/web/vendor/bootstrap-icons/union.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/unity.svg b/web/vendor/bootstrap-icons/unity.svg new file mode 100644 index 0000000..8b84508 --- /dev/null +++ b/web/vendor/bootstrap-icons/unity.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/universal-access-circle.svg b/web/vendor/bootstrap-icons/universal-access-circle.svg new file mode 100644 index 0000000..e5ea936 --- /dev/null +++ b/web/vendor/bootstrap-icons/universal-access-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/universal-access.svg b/web/vendor/bootstrap-icons/universal-access.svg new file mode 100644 index 0000000..0d0d6ef --- /dev/null +++ b/web/vendor/bootstrap-icons/universal-access.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/unlock-fill.svg b/web/vendor/bootstrap-icons/unlock-fill.svg new file mode 100644 index 0000000..c130330 --- /dev/null +++ b/web/vendor/bootstrap-icons/unlock-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/unlock.svg b/web/vendor/bootstrap-icons/unlock.svg new file mode 100644 index 0000000..73625c2 --- /dev/null +++ b/web/vendor/bootstrap-icons/unlock.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/unlock2-fill.svg b/web/vendor/bootstrap-icons/unlock2-fill.svg new file mode 100644 index 0000000..1d8ef92 --- /dev/null +++ b/web/vendor/bootstrap-icons/unlock2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/unlock2.svg b/web/vendor/bootstrap-icons/unlock2.svg new file mode 100644 index 0000000..0815a16 --- /dev/null +++ b/web/vendor/bootstrap-icons/unlock2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/upc-scan.svg b/web/vendor/bootstrap-icons/upc-scan.svg new file mode 100644 index 0000000..1a89554 --- /dev/null +++ b/web/vendor/bootstrap-icons/upc-scan.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/upc.svg b/web/vendor/bootstrap-icons/upc.svg new file mode 100644 index 0000000..785297d --- /dev/null +++ b/web/vendor/bootstrap-icons/upc.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/upload.svg b/web/vendor/bootstrap-icons/upload.svg new file mode 100644 index 0000000..9a4a363 --- /dev/null +++ b/web/vendor/bootstrap-icons/upload.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/usb-c-fill.svg b/web/vendor/bootstrap-icons/usb-c-fill.svg new file mode 100644 index 0000000..759eee2 --- /dev/null +++ b/web/vendor/bootstrap-icons/usb-c-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/usb-c.svg b/web/vendor/bootstrap-icons/usb-c.svg new file mode 100644 index 0000000..1198332 --- /dev/null +++ b/web/vendor/bootstrap-icons/usb-c.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/usb-drive-fill.svg b/web/vendor/bootstrap-icons/usb-drive-fill.svg new file mode 100644 index 0000000..2f656ee --- /dev/null +++ b/web/vendor/bootstrap-icons/usb-drive-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/usb-drive.svg b/web/vendor/bootstrap-icons/usb-drive.svg new file mode 100644 index 0000000..739051d --- /dev/null +++ b/web/vendor/bootstrap-icons/usb-drive.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/usb-fill.svg b/web/vendor/bootstrap-icons/usb-fill.svg new file mode 100644 index 0000000..a3b17fa --- /dev/null +++ b/web/vendor/bootstrap-icons/usb-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/usb-micro-fill.svg b/web/vendor/bootstrap-icons/usb-micro-fill.svg new file mode 100644 index 0000000..1469a9b --- /dev/null +++ b/web/vendor/bootstrap-icons/usb-micro-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/usb-micro.svg b/web/vendor/bootstrap-icons/usb-micro.svg new file mode 100644 index 0000000..ece7da7 --- /dev/null +++ b/web/vendor/bootstrap-icons/usb-micro.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/usb-mini-fill.svg b/web/vendor/bootstrap-icons/usb-mini-fill.svg new file mode 100644 index 0000000..3ab0747 --- /dev/null +++ b/web/vendor/bootstrap-icons/usb-mini-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/usb-mini.svg b/web/vendor/bootstrap-icons/usb-mini.svg new file mode 100644 index 0000000..f095b67 --- /dev/null +++ b/web/vendor/bootstrap-icons/usb-mini.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/usb-plug-fill.svg b/web/vendor/bootstrap-icons/usb-plug-fill.svg new file mode 100644 index 0000000..d1dc518 --- /dev/null +++ b/web/vendor/bootstrap-icons/usb-plug-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/usb-plug.svg b/web/vendor/bootstrap-icons/usb-plug.svg new file mode 100644 index 0000000..f3d7220 --- /dev/null +++ b/web/vendor/bootstrap-icons/usb-plug.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/usb-symbol.svg b/web/vendor/bootstrap-icons/usb-symbol.svg new file mode 100644 index 0000000..457f93f --- /dev/null +++ b/web/vendor/bootstrap-icons/usb-symbol.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/usb.svg b/web/vendor/bootstrap-icons/usb.svg new file mode 100644 index 0000000..737bef5 --- /dev/null +++ b/web/vendor/bootstrap-icons/usb.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/valentine.svg b/web/vendor/bootstrap-icons/valentine.svg new file mode 100644 index 0000000..7b8f0a3 --- /dev/null +++ b/web/vendor/bootstrap-icons/valentine.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/valentine2.svg b/web/vendor/bootstrap-icons/valentine2.svg new file mode 100644 index 0000000..6d95a2d --- /dev/null +++ b/web/vendor/bootstrap-icons/valentine2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/vector-pen.svg b/web/vendor/bootstrap-icons/vector-pen.svg new file mode 100644 index 0000000..60115b7 --- /dev/null +++ b/web/vendor/bootstrap-icons/vector-pen.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/view-list.svg b/web/vendor/bootstrap-icons/view-list.svg new file mode 100644 index 0000000..9211543 --- /dev/null +++ b/web/vendor/bootstrap-icons/view-list.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/view-stacked.svg b/web/vendor/bootstrap-icons/view-stacked.svg new file mode 100644 index 0000000..84b5ccf --- /dev/null +++ b/web/vendor/bootstrap-icons/view-stacked.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/vignette.svg b/web/vendor/bootstrap-icons/vignette.svg new file mode 100644 index 0000000..d179290 --- /dev/null +++ b/web/vendor/bootstrap-icons/vignette.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/vimeo.svg b/web/vendor/bootstrap-icons/vimeo.svg new file mode 100644 index 0000000..6b8e4b5 --- /dev/null +++ b/web/vendor/bootstrap-icons/vimeo.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/vinyl-fill.svg b/web/vendor/bootstrap-icons/vinyl-fill.svg new file mode 100644 index 0000000..546d7bb --- /dev/null +++ b/web/vendor/bootstrap-icons/vinyl-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/vinyl.svg b/web/vendor/bootstrap-icons/vinyl.svg new file mode 100644 index 0000000..63647e5 --- /dev/null +++ b/web/vendor/bootstrap-icons/vinyl.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/virus.svg b/web/vendor/bootstrap-icons/virus.svg new file mode 100644 index 0000000..fd291a5 --- /dev/null +++ b/web/vendor/bootstrap-icons/virus.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/virus2.svg b/web/vendor/bootstrap-icons/virus2.svg new file mode 100644 index 0000000..53f44e9 --- /dev/null +++ b/web/vendor/bootstrap-icons/virus2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/voicemail.svg b/web/vendor/bootstrap-icons/voicemail.svg new file mode 100644 index 0000000..ba22eb1 --- /dev/null +++ b/web/vendor/bootstrap-icons/voicemail.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/volume-down-fill.svg b/web/vendor/bootstrap-icons/volume-down-fill.svg new file mode 100644 index 0000000..681d349 --- /dev/null +++ b/web/vendor/bootstrap-icons/volume-down-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/volume-down.svg b/web/vendor/bootstrap-icons/volume-down.svg new file mode 100644 index 0000000..3ca7e6a --- /dev/null +++ b/web/vendor/bootstrap-icons/volume-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/volume-mute-fill.svg b/web/vendor/bootstrap-icons/volume-mute-fill.svg new file mode 100644 index 0000000..148628c --- /dev/null +++ b/web/vendor/bootstrap-icons/volume-mute-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/volume-mute.svg b/web/vendor/bootstrap-icons/volume-mute.svg new file mode 100644 index 0000000..d06d3dc --- /dev/null +++ b/web/vendor/bootstrap-icons/volume-mute.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/volume-off-fill.svg b/web/vendor/bootstrap-icons/volume-off-fill.svg new file mode 100644 index 0000000..315110a --- /dev/null +++ b/web/vendor/bootstrap-icons/volume-off-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/volume-off.svg b/web/vendor/bootstrap-icons/volume-off.svg new file mode 100644 index 0000000..e5f82cc --- /dev/null +++ b/web/vendor/bootstrap-icons/volume-off.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/volume-up-fill.svg b/web/vendor/bootstrap-icons/volume-up-fill.svg new file mode 100644 index 0000000..0f94073 --- /dev/null +++ b/web/vendor/bootstrap-icons/volume-up-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/volume-up.svg b/web/vendor/bootstrap-icons/volume-up.svg new file mode 100644 index 0000000..6347f42 --- /dev/null +++ b/web/vendor/bootstrap-icons/volume-up.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/vr.svg b/web/vendor/bootstrap-icons/vr.svg new file mode 100644 index 0000000..5ad5438 --- /dev/null +++ b/web/vendor/bootstrap-icons/vr.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/wallet-fill.svg b/web/vendor/bootstrap-icons/wallet-fill.svg new file mode 100644 index 0000000..ee1c27d --- /dev/null +++ b/web/vendor/bootstrap-icons/wallet-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/wallet.svg b/web/vendor/bootstrap-icons/wallet.svg new file mode 100644 index 0000000..6c9d247 --- /dev/null +++ b/web/vendor/bootstrap-icons/wallet.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/wallet2.svg b/web/vendor/bootstrap-icons/wallet2.svg new file mode 100644 index 0000000..b127b0e --- /dev/null +++ b/web/vendor/bootstrap-icons/wallet2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/watch.svg b/web/vendor/bootstrap-icons/watch.svg new file mode 100644 index 0000000..542d4d8 --- /dev/null +++ b/web/vendor/bootstrap-icons/watch.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/water.svg b/web/vendor/bootstrap-icons/water.svg new file mode 100644 index 0000000..666653b --- /dev/null +++ b/web/vendor/bootstrap-icons/water.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/webcam-fill.svg b/web/vendor/bootstrap-icons/webcam-fill.svg new file mode 100644 index 0000000..e8db7ba --- /dev/null +++ b/web/vendor/bootstrap-icons/webcam-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/webcam.svg b/web/vendor/bootstrap-icons/webcam.svg new file mode 100644 index 0000000..0d23803 --- /dev/null +++ b/web/vendor/bootstrap-icons/webcam.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/wechat.svg b/web/vendor/bootstrap-icons/wechat.svg new file mode 100644 index 0000000..3bc67dd --- /dev/null +++ b/web/vendor/bootstrap-icons/wechat.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/whatsapp.svg b/web/vendor/bootstrap-icons/whatsapp.svg new file mode 100644 index 0000000..5cde6f7 --- /dev/null +++ b/web/vendor/bootstrap-icons/whatsapp.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/wifi-1.svg b/web/vendor/bootstrap-icons/wifi-1.svg new file mode 100644 index 0000000..5f3d340 --- /dev/null +++ b/web/vendor/bootstrap-icons/wifi-1.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/wifi-2.svg b/web/vendor/bootstrap-icons/wifi-2.svg new file mode 100644 index 0000000..09d26c2 --- /dev/null +++ b/web/vendor/bootstrap-icons/wifi-2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/wifi-off.svg b/web/vendor/bootstrap-icons/wifi-off.svg new file mode 100644 index 0000000..2f5e61f --- /dev/null +++ b/web/vendor/bootstrap-icons/wifi-off.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/wifi.svg b/web/vendor/bootstrap-icons/wifi.svg new file mode 100644 index 0000000..773e027 --- /dev/null +++ b/web/vendor/bootstrap-icons/wifi.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/wikipedia.svg b/web/vendor/bootstrap-icons/wikipedia.svg new file mode 100644 index 0000000..11f2fc6 --- /dev/null +++ b/web/vendor/bootstrap-icons/wikipedia.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/wind.svg b/web/vendor/bootstrap-icons/wind.svg new file mode 100644 index 0000000..2ac05cd --- /dev/null +++ b/web/vendor/bootstrap-icons/wind.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/window-dash.svg b/web/vendor/bootstrap-icons/window-dash.svg new file mode 100644 index 0000000..5e157af --- /dev/null +++ b/web/vendor/bootstrap-icons/window-dash.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/window-desktop.svg b/web/vendor/bootstrap-icons/window-desktop.svg new file mode 100644 index 0000000..fa17523 --- /dev/null +++ b/web/vendor/bootstrap-icons/window-desktop.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/window-dock.svg b/web/vendor/bootstrap-icons/window-dock.svg new file mode 100644 index 0000000..41cdf69 --- /dev/null +++ b/web/vendor/bootstrap-icons/window-dock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/window-fullscreen.svg b/web/vendor/bootstrap-icons/window-fullscreen.svg new file mode 100644 index 0000000..421c4c5 --- /dev/null +++ b/web/vendor/bootstrap-icons/window-fullscreen.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/window-plus.svg b/web/vendor/bootstrap-icons/window-plus.svg new file mode 100644 index 0000000..e24ce0c --- /dev/null +++ b/web/vendor/bootstrap-icons/window-plus.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/window-sidebar.svg b/web/vendor/bootstrap-icons/window-sidebar.svg new file mode 100644 index 0000000..d020d13 --- /dev/null +++ b/web/vendor/bootstrap-icons/window-sidebar.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/window-split.svg b/web/vendor/bootstrap-icons/window-split.svg new file mode 100644 index 0000000..96bdd24 --- /dev/null +++ b/web/vendor/bootstrap-icons/window-split.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/window-stack.svg b/web/vendor/bootstrap-icons/window-stack.svg new file mode 100644 index 0000000..8862976 --- /dev/null +++ b/web/vendor/bootstrap-icons/window-stack.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/window-x.svg b/web/vendor/bootstrap-icons/window-x.svg new file mode 100644 index 0000000..c45e078 --- /dev/null +++ b/web/vendor/bootstrap-icons/window-x.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/window.svg b/web/vendor/bootstrap-icons/window.svg new file mode 100644 index 0000000..9bd2a2a --- /dev/null +++ b/web/vendor/bootstrap-icons/window.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/windows.svg b/web/vendor/bootstrap-icons/windows.svg new file mode 100644 index 0000000..af3b18c --- /dev/null +++ b/web/vendor/bootstrap-icons/windows.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/wordpress.svg b/web/vendor/bootstrap-icons/wordpress.svg new file mode 100644 index 0000000..7d5808c --- /dev/null +++ b/web/vendor/bootstrap-icons/wordpress.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/wrench-adjustable-circle-fill.svg b/web/vendor/bootstrap-icons/wrench-adjustable-circle-fill.svg new file mode 100644 index 0000000..33156c7 --- /dev/null +++ b/web/vendor/bootstrap-icons/wrench-adjustable-circle-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/wrench-adjustable-circle.svg b/web/vendor/bootstrap-icons/wrench-adjustable-circle.svg new file mode 100644 index 0000000..381fb30 --- /dev/null +++ b/web/vendor/bootstrap-icons/wrench-adjustable-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/wrench-adjustable.svg b/web/vendor/bootstrap-icons/wrench-adjustable.svg new file mode 100644 index 0000000..e7456d7 --- /dev/null +++ b/web/vendor/bootstrap-icons/wrench-adjustable.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/wrench.svg b/web/vendor/bootstrap-icons/wrench.svg new file mode 100644 index 0000000..806cca0 --- /dev/null +++ b/web/vendor/bootstrap-icons/wrench.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/x-circle-fill.svg b/web/vendor/bootstrap-icons/x-circle-fill.svg new file mode 100644 index 0000000..4070fb3 --- /dev/null +++ b/web/vendor/bootstrap-icons/x-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/x-circle.svg b/web/vendor/bootstrap-icons/x-circle.svg new file mode 100644 index 0000000..0e8c641 --- /dev/null +++ b/web/vendor/bootstrap-icons/x-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/x-diamond-fill.svg b/web/vendor/bootstrap-icons/x-diamond-fill.svg new file mode 100644 index 0000000..6ec461a --- /dev/null +++ b/web/vendor/bootstrap-icons/x-diamond-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/x-diamond.svg b/web/vendor/bootstrap-icons/x-diamond.svg new file mode 100644 index 0000000..b93295e --- /dev/null +++ b/web/vendor/bootstrap-icons/x-diamond.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/x-lg.svg b/web/vendor/bootstrap-icons/x-lg.svg new file mode 100644 index 0000000..b689cbb --- /dev/null +++ b/web/vendor/bootstrap-icons/x-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/x-octagon-fill.svg b/web/vendor/bootstrap-icons/x-octagon-fill.svg new file mode 100644 index 0000000..dd9fc6a --- /dev/null +++ b/web/vendor/bootstrap-icons/x-octagon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/x-octagon.svg b/web/vendor/bootstrap-icons/x-octagon.svg new file mode 100644 index 0000000..181a39f --- /dev/null +++ b/web/vendor/bootstrap-icons/x-octagon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/x-square-fill.svg b/web/vendor/bootstrap-icons/x-square-fill.svg new file mode 100644 index 0000000..5499578 --- /dev/null +++ b/web/vendor/bootstrap-icons/x-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/x-square.svg b/web/vendor/bootstrap-icons/x-square.svg new file mode 100644 index 0000000..eb62b61 --- /dev/null +++ b/web/vendor/bootstrap-icons/x-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/x.svg b/web/vendor/bootstrap-icons/x.svg new file mode 100644 index 0000000..fdcc4e8 --- /dev/null +++ b/web/vendor/bootstrap-icons/x.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/xbox.svg b/web/vendor/bootstrap-icons/xbox.svg new file mode 100644 index 0000000..c0672b2 --- /dev/null +++ b/web/vendor/bootstrap-icons/xbox.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/yelp.svg b/web/vendor/bootstrap-icons/yelp.svg new file mode 100644 index 0000000..76e8884 --- /dev/null +++ b/web/vendor/bootstrap-icons/yelp.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/yin-yang.svg b/web/vendor/bootstrap-icons/yin-yang.svg new file mode 100644 index 0000000..1f50275 --- /dev/null +++ b/web/vendor/bootstrap-icons/yin-yang.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/youtube.svg b/web/vendor/bootstrap-icons/youtube.svg new file mode 100644 index 0000000..3c9c0be --- /dev/null +++ b/web/vendor/bootstrap-icons/youtube.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/zoom-in.svg b/web/vendor/bootstrap-icons/zoom-in.svg new file mode 100644 index 0000000..438e9bc --- /dev/null +++ b/web/vendor/bootstrap-icons/zoom-in.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/bootstrap-icons/zoom-out.svg b/web/vendor/bootstrap-icons/zoom-out.svg new file mode 100644 index 0000000..8be9f29 --- /dev/null +++ b/web/vendor/bootstrap-icons/zoom-out.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/vendor/editorjs/editorjs.mjs b/web/vendor/editorjs/editorjs.mjs new file mode 100644 index 0000000..a7c80b7 --- /dev/null +++ b/web/vendor/editorjs/editorjs.mjs @@ -0,0 +1,11208 @@ +(function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode(".ce-hint--align-start{text-align:left}.ce-hint--align-center{text-align:center}.ce-hint__description{opacity:.6;margin-top:3px}")),document.head.appendChild(e)}}catch(t){console.error("vite-plugin-css-injected-by-js",t)}})(); +var Ce = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : typeof global < "u" ? global : typeof self < "u" ? self : {}; +function Ke(n) { + return n && n.__esModule && Object.prototype.hasOwnProperty.call(n, "default") ? n.default : n; +} +function Xn(n) { + if (n.__esModule) + return n; + var e = n.default; + if (typeof e == "function") { + var t = function o() { + return this instanceof o ? Reflect.construct(e, arguments, this.constructor) : e.apply(this, arguments); + }; + t.prototype = e.prototype; + } else + t = {}; + return Object.defineProperty(t, "__esModule", { value: !0 }), Object.keys(n).forEach(function(o) { + var i = Object.getOwnPropertyDescriptor(n, o); + Object.defineProperty(t, o, i.get ? i : { + enumerable: !0, + get: function() { + return n[o]; + } + }); + }), t; +} +function ot() { +} +Object.assign(ot, { + default: ot, + register: ot, + revert: function() { + }, + __esModule: !0 +}); +Element.prototype.matches || (Element.prototype.matches = Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector || function(n) { + const e = (this.document || this.ownerDocument).querySelectorAll(n); + let t = e.length; + for (; --t >= 0 && e.item(t) !== this; ) + ; + return t > -1; +}); +Element.prototype.closest || (Element.prototype.closest = function(n) { + let e = this; + if (!document.documentElement.contains(e)) + return null; + do { + if (e.matches(n)) + return e; + e = e.parentElement || e.parentNode; + } while (e !== null); + return null; +}); +Element.prototype.prepend || (Element.prototype.prepend = function(e) { + const t = document.createDocumentFragment(); + Array.isArray(e) || (e = [e]), e.forEach((o) => { + const i = o instanceof Node; + t.appendChild(i ? o : document.createTextNode(o)); + }), this.insertBefore(t, this.firstChild); +}); +Element.prototype.scrollIntoViewIfNeeded || (Element.prototype.scrollIntoViewIfNeeded = function(n) { + n = arguments.length === 0 ? !0 : !!n; + const e = this.parentNode, t = window.getComputedStyle(e, null), o = parseInt(t.getPropertyValue("border-top-width")), i = parseInt(t.getPropertyValue("border-left-width")), s = this.offsetTop - e.offsetTop < e.scrollTop, r = this.offsetTop - e.offsetTop + this.clientHeight - o > e.scrollTop + e.clientHeight, a = this.offsetLeft - e.offsetLeft < e.scrollLeft, l = this.offsetLeft - e.offsetLeft + this.clientWidth - i > e.scrollLeft + e.clientWidth, c = s && !r; + (s || r) && n && (e.scrollTop = this.offsetTop - e.offsetTop - e.clientHeight / 2 - o + this.clientHeight / 2), (a || l) && n && (e.scrollLeft = this.offsetLeft - e.offsetLeft - e.clientWidth / 2 - i + this.clientWidth / 2), (s || r || a || l) && !n && this.scrollIntoView(c); +}); +window.requestIdleCallback = window.requestIdleCallback || function(n) { + const e = Date.now(); + return setTimeout(function() { + n({ + didTimeout: !1, + timeRemaining: function() { + return Math.max(0, 50 - (Date.now() - e)); + } + }); + }, 1); +}; +window.cancelIdleCallback = window.cancelIdleCallback || function(n) { + clearTimeout(n); +}; +let Vn = (n = 21) => crypto.getRandomValues(new Uint8Array(n)).reduce((e, t) => (t &= 63, t < 36 ? e += t.toString(36) : t < 62 ? e += (t - 26).toString(36).toUpperCase() : t > 62 ? e += "-" : e += "_", e), ""); +var Lo = /* @__PURE__ */ ((n) => (n.VERBOSE = "VERBOSE", n.INFO = "INFO", n.WARN = "WARN", n.ERROR = "ERROR", n))(Lo || {}); +const y = { + BACKSPACE: 8, + TAB: 9, + ENTER: 13, + SHIFT: 16, + CTRL: 17, + ALT: 18, + ESC: 27, + SPACE: 32, + LEFT: 37, + UP: 38, + DOWN: 40, + RIGHT: 39, + DELETE: 46, + META: 91, + SLASH: 191 +}, qn = { + LEFT: 0, + WHEEL: 1, + RIGHT: 2, + BACKWARD: 3, + FORWARD: 4 +}; +function Ie(n, e, t = "log", o, i = "color: inherit") { + if (!("console" in window) || !window.console[t]) + return; + const s = ["info", "log", "warn", "error"].includes(t), r = []; + switch (Ie.logLevel) { + case "ERROR": + if (t !== "error") + return; + break; + case "WARN": + if (!["error", "warn"].includes(t)) + return; + break; + case "INFO": + if (!s || n) + return; + break; + } + o && r.push(o); + const a = "Editor.js 2.31.1", l = `line-height: 1em; + color: #006FEA; + display: inline-block; + font-size: 11px; + line-height: 1em; + background-color: #fff; + padding: 4px 9px; + border-radius: 30px; + border: 1px solid rgba(56, 138, 229, 0.16); + margin: 4px 5px 4px 0;`; + n && (s ? (r.unshift(l, i), e = `%c${a}%c ${e}`) : e = `( ${a} )${e}`); + try { + s ? o ? console[t](`${e} %o`, ...r) : console[t](e, ...r) : console[t](e); + } catch { + } +} +Ie.logLevel = "VERBOSE"; +function Zn(n) { + Ie.logLevel = n; +} +const S = Ie.bind(window, !1), X = Ie.bind(window, !0); +function le(n) { + return Object.prototype.toString.call(n).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); +} +function A(n) { + return le(n) === "function" || le(n) === "asyncfunction"; +} +function D(n) { + return le(n) === "object"; +} +function te(n) { + return le(n) === "string"; +} +function Gn(n) { + return le(n) === "boolean"; +} +function yo(n) { + return le(n) === "number"; +} +function wo(n) { + return le(n) === "undefined"; +} +function V(n) { + return n ? Object.keys(n).length === 0 && n.constructor === Object : !0; +} +function Po(n) { + return n > 47 && n < 58 || // number keys + n === 32 || n === 13 || // Space bar & return key(s) + n === 229 || // processing key input for certain languages — Chinese, Japanese, etc. + n > 64 && n < 91 || // letter keys + n > 95 && n < 112 || // Numpad keys + n > 185 && n < 193 || // ;=,-./` (in order) + n > 218 && n < 223; +} +async function Qn(n, e = () => { +}, t = () => { +}) { + async function o(i, s, r) { + try { + await i.function(i.data), await s(wo(i.data) ? {} : i.data); + } catch { + r(wo(i.data) ? {} : i.data); + } + } + return n.reduce(async (i, s) => (await i, o(s, e, t)), Promise.resolve()); +} +function No(n) { + return Array.prototype.slice.call(n); +} +function Fe(n, e) { + return function() { + const t = this, o = arguments; + window.setTimeout(() => n.apply(t, o), e); + }; +} +function Jn(n) { + return n.name.split(".").pop(); +} +function ei(n) { + return /^[-\w]+\/([-+\w]+|\*)$/.test(n); +} +function Eo(n, e, t) { + let o; + return (...i) => { + const s = this, r = () => { + o = null, t || n.apply(s, i); + }, a = t && !o; + window.clearTimeout(o), o = window.setTimeout(r, e), a && n.apply(s, i); + }; +} +function dt(n, e, t = void 0) { + let o, i, s, r = null, a = 0; + t || (t = {}); + const l = function() { + a = t.leading === !1 ? 0 : Date.now(), r = null, s = n.apply(o, i), r || (o = i = null); + }; + return function() { + const c = Date.now(); + !a && t.leading === !1 && (a = c); + const d = e - (c - a); + return o = this, i = arguments, d <= 0 || d > e ? (r && (clearTimeout(r), r = null), a = c, s = n.apply(o, i), r || (o = i = null)) : !r && t.trailing !== !1 && (r = setTimeout(l, d)), s; + }; +} +function ti() { + const n = { + win: !1, + mac: !1, + x11: !1, + linux: !1 + }, e = Object.keys(n).find((t) => window.navigator.appVersion.toLowerCase().indexOf(t) !== -1); + return e && (n[e] = !0), n; +} +function je(n) { + return n[0].toUpperCase() + n.slice(1); +} +function ut(n, ...e) { + if (!e.length) + return n; + const t = e.shift(); + if (D(n) && D(t)) + for (const o in t) + D(t[o]) ? (n[o] || Object.assign(n, { [o]: {} }), ut(n[o], t[o])) : Object.assign(n, { [o]: t[o] }); + return ut(n, ...e); +} +function vt(n) { + const e = ti(); + return n = n.replace(/shift/gi, "⇧").replace(/backspace/gi, "⌫").replace(/enter/gi, "⏎").replace(/up/gi, "↑").replace(/left/gi, "→").replace(/down/gi, "↓").replace(/right/gi, "←").replace(/escape/gi, "⎋").replace(/insert/gi, "Ins").replace(/delete/gi, "␡").replace(/\+/gi, " + "), e.mac ? n = n.replace(/ctrl|cmd/gi, "⌘").replace(/alt/gi, "⌥") : n = n.replace(/cmd/gi, "Ctrl").replace(/windows/gi, "WIN"), n; +} +function oi(n) { + try { + return new URL(n).href; + } catch { + } + return n.substring(0, 2) === "//" ? window.location.protocol + n : window.location.origin + n; +} +function ni() { + return Vn(10); +} +function ii(n) { + window.open(n, "_blank"); +} +function si(n = "") { + return `${n}${Math.floor(Math.random() * 1e8).toString(16)}`; +} +function ht(n, e, t) { + const o = `«${e}» is deprecated and will be removed in the next major release. Please use the «${t}» instead.`; + n && X(o, "warn"); +} +function me(n, e, t) { + const o = t.value ? "value" : "get", i = t[o], s = `#${e}Cache`; + if (t[o] = function(...r) { + return this[s] === void 0 && (this[s] = i.apply(this, ...r)), this[s]; + }, o === "get" && t.set) { + const r = t.set; + t.set = function(a) { + delete n[s], r.apply(this, a); + }; + } + return t; +} +const Ro = 650; +function be() { + return window.matchMedia(`(max-width: ${Ro}px)`).matches; +} +const pt = typeof window < "u" && window.navigator && window.navigator.platform && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === "MacIntel" && window.navigator.maxTouchPoints > 1); +function ri(n, e) { + const t = Array.isArray(n) || D(n), o = Array.isArray(e) || D(e); + return t || o ? JSON.stringify(n) === JSON.stringify(e) : n === e; +} +class u { + /** + * Check if passed tag has no closed tag + * + * @param {HTMLElement} tag - element to check + * @returns {boolean} + */ + static isSingleTag(e) { + return e.tagName && [ + "AREA", + "BASE", + "BR", + "COL", + "COMMAND", + "EMBED", + "HR", + "IMG", + "INPUT", + "KEYGEN", + "LINK", + "META", + "PARAM", + "SOURCE", + "TRACK", + "WBR" + ].includes(e.tagName); + } + /** + * Check if element is BR or WBR + * + * @param {HTMLElement} element - element to check + * @returns {boolean} + */ + static isLineBreakTag(e) { + return e && e.tagName && [ + "BR", + "WBR" + ].includes(e.tagName); + } + /** + * Helper for making Elements with class name and attributes + * + * @param {string} tagName - new Element tag name + * @param {string[]|string} [classNames] - list or name of CSS class name(s) + * @param {object} [attributes] - any attributes + * @returns {HTMLElement} + */ + static make(e, t = null, o = {}) { + const i = document.createElement(e); + if (Array.isArray(t)) { + const s = t.filter((r) => r !== void 0); + i.classList.add(...s); + } else + t && i.classList.add(t); + for (const s in o) + Object.prototype.hasOwnProperty.call(o, s) && (i[s] = o[s]); + return i; + } + /** + * Creates Text Node with the passed content + * + * @param {string} content - text content + * @returns {Text} + */ + static text(e) { + return document.createTextNode(e); + } + /** + * Append one or several elements to the parent + * + * @param {Element|DocumentFragment} parent - where to append + * @param {Element|Element[]|DocumentFragment|Text|Text[]} elements - element or elements list + */ + static append(e, t) { + Array.isArray(t) ? t.forEach((o) => e.appendChild(o)) : e.appendChild(t); + } + /** + * Append element or a couple to the beginning of the parent elements + * + * @param {Element} parent - where to append + * @param {Element|Element[]} elements - element or elements list + */ + static prepend(e, t) { + Array.isArray(t) ? (t = t.reverse(), t.forEach((o) => e.prepend(o))) : e.prepend(t); + } + /** + * Swap two elements in parent + * + * @param {HTMLElement} el1 - from + * @param {HTMLElement} el2 - to + * @deprecated + */ + static swap(e, t) { + const o = document.createElement("div"), i = e.parentNode; + i.insertBefore(o, e), i.insertBefore(e, t), i.insertBefore(t, o), i.removeChild(o); + } + /** + * Selector Decorator + * + * Returns first match + * + * @param {Element} el - element we searching inside. Default - DOM Document + * @param {string} selector - searching string + * @returns {Element} + */ + static find(e = document, t) { + return e.querySelector(t); + } + /** + * Get Element by Id + * + * @param {string} id - id to find + * @returns {HTMLElement | null} + */ + static get(e) { + return document.getElementById(e); + } + /** + * Selector Decorator. + * + * Returns all matches + * + * @param {Element|Document} el - element we searching inside. Default - DOM Document + * @param {string} selector - searching string + * @returns {NodeList} + */ + static findAll(e = document, t) { + return e.querySelectorAll(t); + } + /** + * Returns CSS selector for all text inputs + */ + static get allInputsSelector() { + return "[contenteditable=true], textarea, input:not([type]), " + ["text", "password", "email", "number", "search", "tel", "url"].map((t) => `input[type="${t}"]`).join(", "); + } + /** + * Find all contenteditable, textarea and editable input elements passed holder contains + * + * @param holder - element where to find inputs + */ + static findAllInputs(e) { + return No(e.querySelectorAll(u.allInputsSelector)).reduce((t, o) => u.isNativeInput(o) || u.containsOnlyInlineElements(o) ? [...t, o] : [...t, ...u.getDeepestBlockElements(o)], []); + } + /** + * Search for deepest node which is Leaf. + * Leaf is the vertex that doesn't have any child nodes + * + * @description Method recursively goes throw the all Node until it finds the Leaf + * @param {Node} node - root Node. From this vertex we start Deep-first search + * {@link https://en.wikipedia.org/wiki/Depth-first_search} + * @param {boolean} [atLast] - find last text node + * @returns - it can be text Node or Element Node, so that caret will able to work with it + * Can return null if node is Document or DocumentFragment, or node is not attached to the DOM + */ + static getDeepestNode(e, t = !1) { + const o = t ? "lastChild" : "firstChild", i = t ? "previousSibling" : "nextSibling"; + if (e && e.nodeType === Node.ELEMENT_NODE && e[o]) { + let s = e[o]; + if (u.isSingleTag(s) && !u.isNativeInput(s) && !u.isLineBreakTag(s)) + if (s[i]) + s = s[i]; + else if (s.parentNode[i]) + s = s.parentNode[i]; + else + return s.parentNode; + return this.getDeepestNode(s, t); + } + return e; + } + /** + * Check if object is DOM node + * + * @param {*} node - object to check + * @returns {boolean} + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + static isElement(e) { + return yo(e) ? !1 : e && e.nodeType && e.nodeType === Node.ELEMENT_NODE; + } + /** + * Check if object is DocumentFragment node + * + * @param {object} node - object to check + * @returns {boolean} + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + static isFragment(e) { + return yo(e) ? !1 : e && e.nodeType && e.nodeType === Node.DOCUMENT_FRAGMENT_NODE; + } + /** + * Check if passed element is contenteditable + * + * @param {HTMLElement} element - html element to check + * @returns {boolean} + */ + static isContentEditable(e) { + return e.contentEditable === "true"; + } + /** + * Checks target if it is native input + * + * @param {*} target - HTML element or string + * @returns {boolean} + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + static isNativeInput(e) { + const t = [ + "INPUT", + "TEXTAREA" + ]; + return e && e.tagName ? t.includes(e.tagName) : !1; + } + /** + * Checks if we can set caret + * + * @param {HTMLElement} target - target to check + * @returns {boolean} + */ + static canSetCaret(e) { + let t = !0; + if (u.isNativeInput(e)) + switch (e.type) { + case "file": + case "checkbox": + case "radio": + case "hidden": + case "submit": + case "button": + case "image": + case "reset": + t = !1; + break; + } + else + t = u.isContentEditable(e); + return t; + } + /** + * Checks node if it is empty + * + * @description Method checks simple Node without any childs for emptiness + * If you have Node with 2 or more children id depth, you better use {@link Dom#isEmpty} method + * @param {Node} node - node to check + * @param {string} [ignoreChars] - char or substring to treat as empty + * @returns {boolean} true if it is empty + */ + static isNodeEmpty(e, t) { + let o; + return this.isSingleTag(e) && !this.isLineBreakTag(e) ? !1 : (this.isElement(e) && this.isNativeInput(e) ? o = e.value : o = e.textContent.replace("​", ""), t && (o = o.replace(new RegExp(t, "g"), "")), o.length === 0); + } + /** + * checks node if it is doesn't have any child nodes + * + * @param {Node} node - node to check + * @returns {boolean} + */ + static isLeaf(e) { + return e ? e.childNodes.length === 0 : !1; + } + /** + * breadth-first search (BFS) + * {@link https://en.wikipedia.org/wiki/Breadth-first_search} + * + * @description Pushes to stack all DOM leafs and checks for emptiness + * @param {Node} node - node to check + * @param {string} [ignoreChars] - char or substring to treat as empty + * @returns {boolean} + */ + static isEmpty(e, t) { + const o = [e]; + for (; o.length > 0; ) + if (e = o.shift(), !!e) { + if (this.isLeaf(e) && !this.isNodeEmpty(e, t)) + return !1; + e.childNodes && o.push(...Array.from(e.childNodes)); + } + return !0; + } + /** + * Check if string contains html elements + * + * @param {string} str - string to check + * @returns {boolean} + */ + static isHTMLString(e) { + const t = u.make("div"); + return t.innerHTML = e, t.childElementCount > 0; + } + /** + * Return length of node`s text content + * + * @param {Node} node - node with content + * @returns {number} + */ + static getContentLength(e) { + return u.isNativeInput(e) ? e.value.length : e.nodeType === Node.TEXT_NODE ? e.length : e.textContent.length; + } + /** + * Return array of names of block html elements + * + * @returns {string[]} + */ + static get blockElements() { + return [ + "address", + "article", + "aside", + "blockquote", + "canvas", + "div", + "dl", + "dt", + "fieldset", + "figcaption", + "figure", + "footer", + "form", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "header", + "hgroup", + "hr", + "li", + "main", + "nav", + "noscript", + "ol", + "output", + "p", + "pre", + "ruby", + "section", + "table", + "tbody", + "thead", + "tr", + "tfoot", + "ul", + "video" + ]; + } + /** + * Check if passed content includes only inline elements + * + * @param {string|HTMLElement} data - element or html string + * @returns {boolean} + */ + static containsOnlyInlineElements(e) { + let t; + te(e) ? (t = document.createElement("div"), t.innerHTML = e) : t = e; + const o = (i) => !u.blockElements.includes(i.tagName.toLowerCase()) && Array.from(i.children).every(o); + return Array.from(t.children).every(o); + } + /** + * Find and return all block elements in the passed parent (including subtree) + * + * @param {HTMLElement} parent - root element + * @returns {HTMLElement[]} + */ + static getDeepestBlockElements(e) { + return u.containsOnlyInlineElements(e) ? [e] : Array.from(e.children).reduce((t, o) => [...t, ...u.getDeepestBlockElements(o)], []); + } + /** + * Helper for get holder from {string} or return HTMLElement + * + * @param {string | HTMLElement} element - holder's id or holder's HTML Element + * @returns {HTMLElement} + */ + static getHolder(e) { + return te(e) ? document.getElementById(e) : e; + } + /** + * Returns true if element is anchor (is A tag) + * + * @param {Element} element - element to check + * @returns {boolean} + */ + static isAnchor(e) { + return e.tagName.toLowerCase() === "a"; + } + /** + * Return element's offset related to the document + * + * @todo handle case when editor initialized in scrollable popup + * @param el - element to compute offset + */ + static offset(e) { + const t = e.getBoundingClientRect(), o = window.pageXOffset || document.documentElement.scrollLeft, i = window.pageYOffset || document.documentElement.scrollTop, s = t.top + i, r = t.left + o; + return { + top: s, + left: r, + bottom: s + t.height, + right: r + t.width + }; + } + /** + * Find text node and offset by total content offset + * + * @param {Node} root - root node to start search from + * @param {number} totalOffset - offset relative to the root node content + * @returns {{node: Node | null, offset: number}} - node and offset inside node + */ + static getNodeByOffset(e, t) { + let o = 0, i = null; + const s = document.createTreeWalker( + e, + NodeFilter.SHOW_TEXT, + null + ); + let r = s.nextNode(); + for (; r; ) { + const c = r.textContent, d = c === null ? 0 : c.length; + if (i = r, o + d >= t) + break; + o += d, r = s.nextNode(); + } + if (!i) + return { + node: null, + offset: 0 + }; + const a = i.textContent; + if (a === null || a.length === 0) + return { + node: null, + offset: 0 + }; + const l = Math.min(t - o, a.length); + return { + node: i, + offset: l + }; + } +} +function ai(n) { + return !/[^\t\n\r ]/.test(n); +} +function li(n) { + const e = window.getComputedStyle(n), t = parseFloat(e.fontSize), o = parseFloat(e.lineHeight) || t * 1.2, i = parseFloat(e.paddingTop), s = parseFloat(e.borderTopWidth), r = parseFloat(e.marginTop), a = t * 0.8, l = (o - t) / 2; + return r + s + i + l + a; +} +function Do(n) { + n.dataset.empty = u.isEmpty(n) ? "true" : "false"; +} +const ci = { + blockTunes: { + toggler: { + "Click to tune": "", + "or drag to move": "" + } + }, + inlineToolbar: { + converter: { + "Convert to": "" + } + }, + toolbar: { + toolbox: { + Add: "" + } + }, + popover: { + Filter: "", + "Nothing found": "", + "Convert to": "" + } +}, di = { + Text: "", + Link: "", + Bold: "", + Italic: "" +}, ui = { + link: { + "Add a link": "" + }, + stub: { + "The block can not be displayed correctly.": "" + } +}, hi = { + delete: { + Delete: "", + "Click to delete": "" + }, + moveUp: { + "Move up": "" + }, + moveDown: { + "Move down": "" + } +}, Fo = { + ui: ci, + toolNames: di, + tools: ui, + blockTunes: hi +}, jo = class he { + /** + * Type-safe translation for internal UI texts: + * Perform translation of the string by namespace and a key + * + * @example I18n.ui(I18nInternalNS.ui.blockTunes.toggler, 'Click to tune') + * @param internalNamespace - path to translated string in dictionary + * @param dictKey - dictionary key. Better to use default locale original text + */ + static ui(e, t) { + return he._t(e, t); + } + /** + * Translate for external strings that is not presented in default dictionary. + * For example, for user-specified tool names + * + * @param namespace - path to translated string in dictionary + * @param dictKey - dictionary key. Better to use default locale original text + */ + static t(e, t) { + return he._t(e, t); + } + /** + * Adjust module for using external dictionary + * + * @param dictionary - new messages list to override default + */ + static setDictionary(e) { + he.currentDictionary = e; + } + /** + * Perform translation both for internal and external namespaces + * If there is no translation found, returns passed key as a translated message + * + * @param namespace - path to translated string in dictionary + * @param dictKey - dictionary key. Better to use default locale original text + */ + static _t(e, t) { + const o = he.getNamespace(e); + return !o || !o[t] ? t : o[t]; + } + /** + * Find messages section by namespace path + * + * @param namespace - path to section + */ + static getNamespace(e) { + return e.split(".").reduce((o, i) => !o || !Object.keys(o).length ? {} : o[i], he.currentDictionary); + } +}; +jo.currentDictionary = Fo; +let z = jo; +class Ho extends Error { +} +class Oe { + constructor() { + this.subscribers = {}; + } + /** + * Subscribe any event on callback + * + * @param eventName - event name + * @param callback - subscriber + */ + on(e, t) { + e in this.subscribers || (this.subscribers[e] = []), this.subscribers[e].push(t); + } + /** + * Subscribe any event on callback. Callback will be called once and be removed from subscribers array after call. + * + * @param eventName - event name + * @param callback - subscriber + */ + once(e, t) { + e in this.subscribers || (this.subscribers[e] = []); + const o = (i) => { + const s = t(i), r = this.subscribers[e].indexOf(o); + return r !== -1 && this.subscribers[e].splice(r, 1), s; + }; + this.subscribers[e].push(o); + } + /** + * Emit callbacks with passed data + * + * @param eventName - event name + * @param data - subscribers get this data when they were fired + */ + emit(e, t) { + V(this.subscribers) || !this.subscribers[e] || this.subscribers[e].reduce((o, i) => { + const s = i(o); + return s !== void 0 ? s : o; + }, t); + } + /** + * Unsubscribe callback from event + * + * @param eventName - event name + * @param callback - event handler + */ + off(e, t) { + if (this.subscribers[e] === void 0) { + console.warn(`EventDispatcher .off(): there is no subscribers for event "${e.toString()}". Probably, .off() called before .on()`); + return; + } + for (let o = 0; o < this.subscribers[e].length; o++) + if (this.subscribers[e][o] === t) { + delete this.subscribers[e][o]; + break; + } + } + /** + * Destroyer + * clears subscribers list + */ + destroy() { + this.subscribers = {}; + } +} +function J(n) { + Object.setPrototypeOf(this, { + /** + * Block id + * + * @returns {string} + */ + get id() { + return n.id; + }, + /** + * Tool name + * + * @returns {string} + */ + get name() { + return n.name; + }, + /** + * Tool config passed on Editor's initialization + * + * @returns {ToolConfig} + */ + get config() { + return n.config; + }, + /** + * .ce-block element, that wraps plugin contents + * + * @returns {HTMLElement} + */ + get holder() { + return n.holder; + }, + /** + * True if Block content is empty + * + * @returns {boolean} + */ + get isEmpty() { + return n.isEmpty; + }, + /** + * True if Block is selected with Cross-Block selection + * + * @returns {boolean} + */ + get selected() { + return n.selected; + }, + /** + * Set Block's stretch state + * + * @param {boolean} state — state to set + */ + set stretched(t) { + n.stretched = t; + }, + /** + * True if Block is stretched + * + * @returns {boolean} + */ + get stretched() { + return n.stretched; + }, + /** + * True if Block has inputs to be focused + */ + get focusable() { + return n.focusable; + }, + /** + * Call Tool method with errors handler under-the-hood + * + * @param {string} methodName - method to call + * @param {object} param - object with parameters + * @returns {unknown} + */ + call(t, o) { + return n.call(t, o); + }, + /** + * Save Block content + * + * @returns {Promise} + */ + save() { + return n.save(); + }, + /** + * Validate Block data + * + * @param {BlockToolData} data - data to validate + * @returns {Promise} + */ + validate(t) { + return n.validate(t); + }, + /** + * Allows to say Editor that Block was changed. Used to manually trigger Editor's 'onChange' callback + * Can be useful for block changes invisible for editor core. + */ + dispatchChange() { + n.dispatchChange(); + }, + /** + * Tool could specify several entries to be displayed at the Toolbox (for example, "Heading 1", "Heading 2", "Heading 3") + * This method returns the entry that is related to the Block (depended on the Block data) + */ + getActiveToolboxEntry() { + return n.getActiveToolboxEntry(); + } + }); +} +class _e { + constructor() { + this.allListeners = []; + } + /** + * Assigns event listener on element and returns unique identifier + * + * @param {EventTarget} element - DOM element that needs to be listened + * @param {string} eventType - event type + * @param {Function} handler - method that will be fired on event + * @param {boolean|AddEventListenerOptions} options - useCapture or {capture, passive, once} + */ + on(e, t, o, i = !1) { + const s = si("l"), r = { + id: s, + element: e, + eventType: t, + handler: o, + options: i + }; + if (!this.findOne(e, t, o)) + return this.allListeners.push(r), e.addEventListener(t, o, i), s; + } + /** + * Removes event listener from element + * + * @param {EventTarget} element - DOM element that we removing listener + * @param {string} eventType - event type + * @param {Function} handler - remove handler, if element listens several handlers on the same event type + * @param {boolean|AddEventListenerOptions} options - useCapture or {capture, passive, once} + */ + off(e, t, o, i) { + const s = this.findAll(e, t, o); + s.forEach((r, a) => { + const l = this.allListeners.indexOf(s[a]); + l > -1 && (this.allListeners.splice(l, 1), r.element.removeEventListener(r.eventType, r.handler, r.options)); + }); + } + /** + * Removes listener by id + * + * @param {string} id - listener identifier + */ + offById(e) { + const t = this.findById(e); + t && t.element.removeEventListener(t.eventType, t.handler, t.options); + } + /** + * Finds and returns first listener by passed params + * + * @param {EventTarget} element - event target + * @param {string} [eventType] - event type + * @param {Function} [handler] - event handler + * @returns {ListenerData|null} + */ + findOne(e, t, o) { + const i = this.findAll(e, t, o); + return i.length > 0 ? i[0] : null; + } + /** + * Return all stored listeners by passed params + * + * @param {EventTarget} element - event target + * @param {string} eventType - event type + * @param {Function} handler - event handler + * @returns {ListenerData[]} + */ + findAll(e, t, o) { + let i; + const s = e ? this.findByEventTarget(e) : []; + return e && t && o ? i = s.filter((r) => r.eventType === t && r.handler === o) : e && t ? i = s.filter((r) => r.eventType === t) : i = s, i; + } + /** + * Removes all listeners + */ + removeAll() { + this.allListeners.map((e) => { + e.element.removeEventListener(e.eventType, e.handler, e.options); + }), this.allListeners = []; + } + /** + * Module cleanup on destruction + */ + destroy() { + this.removeAll(); + } + /** + * Search method: looks for listener by passed element + * + * @param {EventTarget} element - searching element + * @returns {Array} listeners that found on element + */ + findByEventTarget(e) { + return this.allListeners.filter((t) => { + if (t.element === e) + return t; + }); + } + /** + * Search method: looks for listener by passed event type + * + * @param {string} eventType - event type + * @returns {ListenerData[]} listeners that found on element + */ + findByType(e) { + return this.allListeners.filter((t) => { + if (t.eventType === e) + return t; + }); + } + /** + * Search method: looks for listener by passed handler + * + * @param {Function} handler - event handler + * @returns {ListenerData[]} listeners that found on element + */ + findByHandler(e) { + return this.allListeners.filter((t) => { + if (t.handler === e) + return t; + }); + } + /** + * Returns listener data found by id + * + * @param {string} id - listener identifier + * @returns {ListenerData} + */ + findById(e) { + return this.allListeners.find((t) => t.id === e); + } +} +class E { + /** + * @class + * @param options - Module options + * @param options.config - Module config + * @param options.eventsDispatcher - Common event bus + */ + constructor({ config: e, eventsDispatcher: t }) { + if (this.nodes = {}, this.listeners = new _e(), this.readOnlyMutableListeners = { + /** + * Assigns event listener on DOM element and pushes into special array that might be removed + * + * @param {EventTarget} element - DOM Element + * @param {string} eventType - Event name + * @param {Function} handler - Event handler + * @param {boolean|AddEventListenerOptions} options - Listening options + */ + on: (o, i, s, r = !1) => { + this.mutableListenerIds.push( + this.listeners.on(o, i, s, r) + ); + }, + /** + * Clears all mutable listeners + */ + clearAll: () => { + for (const o of this.mutableListenerIds) + this.listeners.offById(o); + this.mutableListenerIds = []; + } + }, this.mutableListenerIds = [], new.target === E) + throw new TypeError("Constructors for abstract class Module are not allowed."); + this.config = e, this.eventsDispatcher = t; + } + /** + * Editor modules setter + * + * @param {EditorModules} Editor - Editor's Modules + */ + set state(e) { + this.Editor = e; + } + /** + * Remove memorized nodes + */ + removeAllNodes() { + for (const e in this.nodes) { + const t = this.nodes[e]; + t instanceof HTMLElement && t.remove(); + } + } + /** + * Returns true if current direction is RTL (Right-To-Left) + */ + get isRtl() { + return this.config.i18n.direction === "rtl"; + } +} +class b { + constructor() { + this.instance = null, this.selection = null, this.savedSelectionRange = null, this.isFakeBackgroundEnabled = !1, this.commandBackground = "backColor", this.commandRemoveFormat = "removeFormat"; + } + /** + * Editor styles + * + * @returns {{editorWrapper: string, editorZone: string}} + */ + static get CSS() { + return { + editorWrapper: "codex-editor", + editorZone: "codex-editor__redactor" + }; + } + /** + * Returns selected anchor + * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorNode} + * + * @returns {Node|null} + */ + static get anchorNode() { + const e = window.getSelection(); + return e ? e.anchorNode : null; + } + /** + * Returns selected anchor element + * + * @returns {Element|null} + */ + static get anchorElement() { + const e = window.getSelection(); + if (!e) + return null; + const t = e.anchorNode; + return t ? u.isElement(t) ? t : t.parentElement : null; + } + /** + * Returns selection offset according to the anchor node + * {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorOffset} + * + * @returns {number|null} + */ + static get anchorOffset() { + const e = window.getSelection(); + return e ? e.anchorOffset : null; + } + /** + * Is current selection range collapsed + * + * @returns {boolean|null} + */ + static get isCollapsed() { + const e = window.getSelection(); + return e ? e.isCollapsed : null; + } + /** + * Check current selection if it is at Editor's zone + * + * @returns {boolean} + */ + static get isAtEditor() { + return this.isSelectionAtEditor(b.get()); + } + /** + * Check if passed selection is at Editor's zone + * + * @param selection - Selection object to check + */ + static isSelectionAtEditor(e) { + if (!e) + return !1; + let t = e.anchorNode || e.focusNode; + t && t.nodeType === Node.TEXT_NODE && (t = t.parentNode); + let o = null; + return t && t instanceof Element && (o = t.closest(`.${b.CSS.editorZone}`)), o ? o.nodeType === Node.ELEMENT_NODE : !1; + } + /** + * Check if passed range at Editor zone + * + * @param range - range to check + */ + static isRangeAtEditor(e) { + if (!e) + return; + let t = e.startContainer; + t && t.nodeType === Node.TEXT_NODE && (t = t.parentNode); + let o = null; + return t && t instanceof Element && (o = t.closest(`.${b.CSS.editorZone}`)), o ? o.nodeType === Node.ELEMENT_NODE : !1; + } + /** + * Methods return boolean that true if selection exists on the page + */ + static get isSelectionExists() { + return !!b.get().anchorNode; + } + /** + * Return first range + * + * @returns {Range|null} + */ + static get range() { + return this.getRangeFromSelection(this.get()); + } + /** + * Returns range from passed Selection object + * + * @param selection - Selection object to get Range from + */ + static getRangeFromSelection(e) { + return e && e.rangeCount ? e.getRangeAt(0) : null; + } + /** + * Calculates position and size of selected text + * + * @returns {DOMRect | ClientRect} + */ + static get rect() { + let e = document.selection, t, o = { + x: 0, + y: 0, + width: 0, + height: 0 + }; + if (e && e.type !== "Control") + return e = e, t = e.createRange(), o.x = t.boundingLeft, o.y = t.boundingTop, o.width = t.boundingWidth, o.height = t.boundingHeight, o; + if (!window.getSelection) + return S("Method window.getSelection is not supported", "warn"), o; + if (e = window.getSelection(), e.rangeCount === null || isNaN(e.rangeCount)) + return S("Method SelectionUtils.rangeCount is not supported", "warn"), o; + if (e.rangeCount === 0) + return o; + if (t = e.getRangeAt(0).cloneRange(), t.getBoundingClientRect && (o = t.getBoundingClientRect()), o.x === 0 && o.y === 0) { + const i = document.createElement("span"); + if (i.getBoundingClientRect) { + i.appendChild(document.createTextNode("​")), t.insertNode(i), o = i.getBoundingClientRect(); + const s = i.parentNode; + s.removeChild(i), s.normalize(); + } + } + return o; + } + /** + * Returns selected text as String + * + * @returns {string} + */ + static get text() { + return window.getSelection ? window.getSelection().toString() : ""; + } + /** + * Returns window SelectionUtils + * {@link https://developer.mozilla.org/ru/docs/Web/API/Window/getSelection} + * + * @returns {Selection} + */ + static get() { + return window.getSelection(); + } + /** + * Set focus to contenteditable or native input element + * + * @param element - element where to set focus + * @param offset - offset of cursor + */ + static setCursor(e, t = 0) { + const o = document.createRange(), i = window.getSelection(); + return u.isNativeInput(e) ? u.canSetCaret(e) ? (e.focus(), e.selectionStart = e.selectionEnd = t, e.getBoundingClientRect()) : void 0 : (o.setStart(e, t), o.setEnd(e, t), i.removeAllRanges(), i.addRange(o), o.getBoundingClientRect()); + } + /** + * Check if current range exists and belongs to container + * + * @param container - where range should be + */ + static isRangeInsideContainer(e) { + const t = b.range; + return t === null ? !1 : e.contains(t.startContainer); + } + /** + * Adds fake cursor to the current range + */ + static addFakeCursor() { + const e = b.range; + if (e === null) + return; + const t = u.make("span", "codex-editor__fake-cursor"); + t.dataset.mutationFree = "true", e.collapse(), e.insertNode(t); + } + /** + * Check if passed element contains a fake cursor + * + * @param el - where to check + */ + static isFakeCursorInsideContainer(e) { + return u.find(e, ".codex-editor__fake-cursor") !== null; + } + /** + * Removes fake cursor from a container + * + * @param container - container to look for + */ + static removeFakeCursor(e = document.body) { + const t = u.find(e, ".codex-editor__fake-cursor"); + t && t.remove(); + } + /** + * Removes fake background + */ + removeFakeBackground() { + this.isFakeBackgroundEnabled && (this.isFakeBackgroundEnabled = !1, document.execCommand(this.commandRemoveFormat)); + } + /** + * Sets fake background + */ + setFakeBackground() { + document.execCommand(this.commandBackground, !1, "#a8d6ff"), this.isFakeBackgroundEnabled = !0; + } + /** + * Save SelectionUtils's range + */ + save() { + this.savedSelectionRange = b.range; + } + /** + * Restore saved SelectionUtils's range + */ + restore() { + if (!this.savedSelectionRange) + return; + const e = window.getSelection(); + e.removeAllRanges(), e.addRange(this.savedSelectionRange); + } + /** + * Clears saved selection + */ + clearSaved() { + this.savedSelectionRange = null; + } + /** + * Collapse current selection + */ + collapseToEnd() { + const e = window.getSelection(), t = document.createRange(); + t.selectNodeContents(e.focusNode), t.collapse(!1), e.removeAllRanges(), e.addRange(t); + } + /** + * Looks ahead to find passed tag from current selection + * + * @param {string} tagName - tag to found + * @param {string} [className] - tag's class name + * @param {number} [searchDepth] - count of tags that can be included. For better performance. + * @returns {HTMLElement|null} + */ + findParentTag(e, t, o = 10) { + const i = window.getSelection(); + let s = null; + return !i || !i.anchorNode || !i.focusNode ? null : ([ + /** the Node in which the selection begins */ + i.anchorNode, + /** the Node in which the selection ends */ + i.focusNode + ].forEach((a) => { + let l = o; + for (; l > 0 && a.parentNode && !(a.tagName === e && (s = a, t && a.classList && !a.classList.contains(t) && (s = null), s)); ) + a = a.parentNode, l--; + }), s); + } + /** + * Expands selection range to the passed parent node + * + * @param {HTMLElement} element - element which contents should be selected + */ + expandToTag(e) { + const t = window.getSelection(); + t.removeAllRanges(); + const o = document.createRange(); + o.selectNodeContents(e), t.addRange(o); + } +} +function pi(n, e) { + const { type: t, target: o, addedNodes: i, removedNodes: s } = n; + return n.type === "attributes" && n.attributeName === "data-empty" ? !1 : !!(e.contains(o) || t === "childList" && (Array.from(i).some((l) => l === e) || Array.from(s).some((l) => l === e))); +} +const ft = "redactor dom changed", $o = "block changed", zo = "fake cursor is about to be toggled", Uo = "fake cursor have been set", Te = "editor mobile layout toggled"; +function gt(n, e) { + if (!n.conversionConfig) + return !1; + const t = n.conversionConfig[e]; + return A(t) || te(t); +} +function He(n, e) { + return gt(n.tool, e); +} +function Wo(n, e) { + return Object.entries(n).some(([t, o]) => e[t] && ri(e[t], o)); +} +async function Yo(n, e) { + const o = (await n.save()).data, i = e.find((s) => s.name === n.name); + return i !== void 0 && !gt(i, "export") ? [] : e.reduce((s, r) => { + if (!gt(r, "import") || r.toolbox === void 0) + return s; + const a = r.toolbox.filter((l) => { + if (V(l) || l.icon === void 0) + return !1; + if (l.data !== void 0) { + if (Wo(l.data, o)) + return !1; + } else if (r.name === n.name) + return !1; + return !0; + }); + return s.push({ + ...r, + toolbox: a + }), s; + }, []); +} +function xo(n, e) { + return n.mergeable ? n.name === e.name ? !0 : He(e, "export") && He(n, "import") : !1; +} +function fi(n, e) { + const t = e == null ? void 0 : e.export; + return A(t) ? t(n) : te(t) ? n[t] : (t !== void 0 && S("Conversion «export» property must be a string or function. String means key of saved data object to export. Function should export processed string to export."), ""); +} +function Bo(n, e, t) { + const o = e == null ? void 0 : e.import; + return A(o) ? o(n, t) : te(o) ? { + [o]: n + } : (o !== void 0 && S("Conversion «import» property must be a string or function. String means key of tool data to import. Function accepts a imported string and return composed tool data."), {}); +} +var _ = /* @__PURE__ */ ((n) => (n.Default = "default", n.Separator = "separator", n.Html = "html", n))(_ || {}), ee = /* @__PURE__ */ ((n) => (n.APPEND_CALLBACK = "appendCallback", n.RENDERED = "rendered", n.MOVED = "moved", n.UPDATED = "updated", n.REMOVED = "removed", n.ON_PASTE = "onPaste", n))(ee || {}); +class R extends Oe { + /** + * @param options - block constructor options + * @param [options.id] - block's id. Will be generated if omitted. + * @param options.data - Tool's initial data + * @param options.tool — block's tool + * @param options.api - Editor API module for pass it to the Block Tunes + * @param options.readOnly - Read-Only flag + * @param [eventBus] - Editor common event bus. Allows to subscribe on some Editor events. Could be omitted when "virtual" Block is created. See BlocksAPI@composeBlockData. + */ + constructor({ + id: e = ni(), + data: t, + tool: o, + readOnly: i, + tunesData: s + }, r) { + super(), this.cachedInputs = [], this.toolRenderedElement = null, this.tunesInstances = /* @__PURE__ */ new Map(), this.defaultTunesInstances = /* @__PURE__ */ new Map(), this.unavailableTunesData = {}, this.inputIndex = 0, this.editorEventBus = null, this.handleFocus = () => { + this.dropInputsCache(), this.updateCurrentInput(); + }, this.didMutated = (a = void 0) => { + const l = a === void 0, c = a instanceof InputEvent; + !l && !c && this.detectToolRootChange(a); + let d; + l || c ? d = !0 : d = !(a.length > 0 && a.every((p) => { + const { addedNodes: g, removedNodes: f, target: v } = p; + return [ + ...Array.from(g), + ...Array.from(f), + v + ].some((T) => (u.isElement(T) || (T = T.parentElement), T && T.closest('[data-mutation-free="true"]') !== null)); + })), d && (this.dropInputsCache(), this.updateCurrentInput(), this.toggleInputsEmptyMark(), this.call( + "updated" + /* UPDATED */ + ), this.emit("didMutated", this)); + }, this.name = o.name, this.id = e, this.settings = o.settings, this.config = o.settings.config || {}, this.editorEventBus = r || null, this.blockAPI = new J(this), this.tool = o, this.toolInstance = o.create(t, this.blockAPI, i), this.tunes = o.tunes, this.composeTunes(s), this.holder = this.compose(), window.requestIdleCallback(() => { + this.watchBlockMutations(), this.addInputEvents(), this.toggleInputsEmptyMark(); + }); + } + /** + * CSS classes for the Block + * + * @returns {{wrapper: string, content: string}} + */ + static get CSS() { + return { + wrapper: "ce-block", + wrapperStretched: "ce-block--stretched", + content: "ce-block__content", + selected: "ce-block--selected", + dropTarget: "ce-block--drop-target" + }; + } + /** + * Find and return all editable elements (contenteditable and native inputs) in the Tool HTML + */ + get inputs() { + if (this.cachedInputs.length !== 0) + return this.cachedInputs; + const e = u.findAllInputs(this.holder); + return this.inputIndex > e.length - 1 && (this.inputIndex = e.length - 1), this.cachedInputs = e, e; + } + /** + * Return current Tool`s input + * If Block doesn't contain inputs, return undefined + */ + get currentInput() { + return this.inputs[this.inputIndex]; + } + /** + * Set input index to the passed element + * + * @param element - HTML Element to set as current input + */ + set currentInput(e) { + const t = this.inputs.findIndex((o) => o === e || o.contains(e)); + t !== -1 && (this.inputIndex = t); + } + /** + * Return first Tool`s input + * If Block doesn't contain inputs, return undefined + */ + get firstInput() { + return this.inputs[0]; + } + /** + * Return first Tool`s input + * If Block doesn't contain inputs, return undefined + */ + get lastInput() { + const e = this.inputs; + return e[e.length - 1]; + } + /** + * Return next Tool`s input or undefined if it doesn't exist + * If Block doesn't contain inputs, return undefined + */ + get nextInput() { + return this.inputs[this.inputIndex + 1]; + } + /** + * Return previous Tool`s input or undefined if it doesn't exist + * If Block doesn't contain inputs, return undefined + */ + get previousInput() { + return this.inputs[this.inputIndex - 1]; + } + /** + * Get Block's JSON data + * + * @returns {object} + */ + get data() { + return this.save().then((e) => e && !V(e.data) ? e.data : {}); + } + /** + * Returns tool's sanitizer config + * + * @returns {object} + */ + get sanitize() { + return this.tool.sanitizeConfig; + } + /** + * is block mergeable + * We plugin have merge function then we call it mergeable + * + * @returns {boolean} + */ + get mergeable() { + return A(this.toolInstance.merge); + } + /** + * If Block contains inputs, it is focusable + */ + get focusable() { + return this.inputs.length !== 0; + } + /** + * Check block for emptiness + * + * @returns {boolean} + */ + get isEmpty() { + const e = u.isEmpty(this.pluginsContent, "/"), t = !this.hasMedia; + return e && t; + } + /** + * Check if block has a media content such as images, iframe and other + * + * @returns {boolean} + */ + get hasMedia() { + const e = [ + "img", + "iframe", + "video", + "audio", + "source", + "input", + "textarea", + "twitterwidget" + ]; + return !!this.holder.querySelector(e.join(",")); + } + /** + * Set selected state + * We don't need to mark Block as Selected when it is empty + * + * @param {boolean} state - 'true' to select, 'false' to remove selection + */ + set selected(e) { + var i, s; + this.holder.classList.toggle(R.CSS.selected, e); + const t = e === !0 && b.isRangeInsideContainer(this.holder), o = e === !1 && b.isFakeCursorInsideContainer(this.holder); + (t || o) && ((i = this.editorEventBus) == null || i.emit(zo, { state: e }), t ? b.addFakeCursor() : b.removeFakeCursor(this.holder), (s = this.editorEventBus) == null || s.emit(Uo, { state: e })); + } + /** + * Returns True if it is Selected + * + * @returns {boolean} + */ + get selected() { + return this.holder.classList.contains(R.CSS.selected); + } + /** + * Set stretched state + * + * @param {boolean} state - 'true' to enable, 'false' to disable stretched state + */ + set stretched(e) { + this.holder.classList.toggle(R.CSS.wrapperStretched, e); + } + /** + * Return Block's stretched state + * + * @returns {boolean} + */ + get stretched() { + return this.holder.classList.contains(R.CSS.wrapperStretched); + } + /** + * Toggle drop target state + * + * @param {boolean} state - 'true' if block is drop target, false otherwise + */ + set dropTarget(e) { + this.holder.classList.toggle(R.CSS.dropTarget, e); + } + /** + * Returns Plugins content + * + * @returns {HTMLElement} + */ + get pluginsContent() { + return this.toolRenderedElement; + } + /** + * Calls Tool's method + * + * Method checks tool property {MethodName}. Fires method with passes params If it is instance of Function + * + * @param {string} methodName - method to call + * @param {object} params - method argument + */ + call(e, t) { + if (A(this.toolInstance[e])) { + e === "appendCallback" && S( + "`appendCallback` hook is deprecated and will be removed in the next major release. Use `rendered` hook instead", + "warn" + ); + try { + this.toolInstance[e].call(this.toolInstance, t); + } catch (o) { + S(`Error during '${e}' call: ${o.message}`, "error"); + } + } + } + /** + * Call plugins merge method + * + * @param {BlockToolData} data - data to merge + */ + async mergeWith(e) { + await this.toolInstance.merge(e); + } + /** + * Extracts data from Block + * Groups Tool's save processing time + * + * @returns {object} + */ + async save() { + const e = await this.toolInstance.save(this.pluginsContent), t = this.unavailableTunesData; + [ + ...this.tunesInstances.entries(), + ...this.defaultTunesInstances.entries() + ].forEach(([s, r]) => { + if (A(r.save)) + try { + t[s] = r.save(); + } catch (a) { + S(`Tune ${r.constructor.name} save method throws an Error %o`, "warn", a); + } + }); + const o = window.performance.now(); + let i; + return Promise.resolve(e).then((s) => (i = window.performance.now(), { + id: this.id, + tool: this.name, + data: s, + tunes: t, + time: i - o + })).catch((s) => { + S(`Saving process for ${this.name} tool failed due to the ${s}`, "log", "red"); + }); + } + /** + * Uses Tool's validation method to check the correctness of output data + * Tool's validation method is optional + * + * @description Method returns true|false whether data passed the validation or not + * @param {BlockToolData} data - data to validate + * @returns {Promise} valid + */ + async validate(e) { + let t = !0; + return this.toolInstance.validate instanceof Function && (t = await this.toolInstance.validate(e)), t; + } + /** + * Returns data to render in Block Tunes menu. + * Splits block tunes into 2 groups: block specific tunes and common tunes + */ + getTunes() { + const e = [], t = [], o = typeof this.toolInstance.renderSettings == "function" ? this.toolInstance.renderSettings() : []; + return u.isElement(o) ? e.push({ + type: _.Html, + element: o + }) : Array.isArray(o) ? e.push(...o) : e.push(o), [ + ...this.tunesInstances.values(), + ...this.defaultTunesInstances.values() + ].map((s) => s.render()).forEach((s) => { + u.isElement(s) ? t.push({ + type: _.Html, + element: s + }) : Array.isArray(s) ? t.push(...s) : t.push(s); + }), { + toolTunes: e, + commonTunes: t + }; + } + /** + * Update current input index with selection anchor node + */ + updateCurrentInput() { + this.currentInput = u.isNativeInput(document.activeElement) || !b.anchorNode ? document.activeElement : b.anchorNode; + } + /** + * Allows to say Editor that Block was changed. Used to manually trigger Editor's 'onChange' callback + * Can be useful for block changes invisible for editor core. + */ + dispatchChange() { + this.didMutated(); + } + /** + * Call Tool instance destroy method + */ + destroy() { + this.unwatchBlockMutations(), this.removeInputEvents(), super.destroy(), A(this.toolInstance.destroy) && this.toolInstance.destroy(); + } + /** + * Tool could specify several entries to be displayed at the Toolbox (for example, "Heading 1", "Heading 2", "Heading 3") + * This method returns the entry that is related to the Block (depended on the Block data) + */ + async getActiveToolboxEntry() { + const e = this.tool.toolbox; + if (e.length === 1) + return Promise.resolve(this.tool.toolbox[0]); + const t = await this.data, o = e; + return o == null ? void 0 : o.find((i) => Wo(i.data, t)); + } + /** + * Exports Block data as string using conversion config + */ + async exportDataAsString() { + const e = await this.data; + return fi(e, this.tool.conversionConfig); + } + /** + * Make default Block wrappers and put Tool`s content there + * + * @returns {HTMLDivElement} + */ + compose() { + const e = u.make("div", R.CSS.wrapper), t = u.make("div", R.CSS.content), o = this.toolInstance.render(); + e.dataset.id = this.id, this.toolRenderedElement = o, t.appendChild(this.toolRenderedElement); + let i = t; + return [...this.tunesInstances.values(), ...this.defaultTunesInstances.values()].forEach((s) => { + if (A(s.wrap)) + try { + i = s.wrap(i); + } catch (r) { + S(`Tune ${s.constructor.name} wrap method throws an Error %o`, "warn", r); + } + }), e.appendChild(i), e; + } + /** + * Instantiate Block Tunes + * + * @param tunesData - current Block tunes data + * @private + */ + composeTunes(e) { + Array.from(this.tunes.values()).forEach((t) => { + (t.isInternal ? this.defaultTunesInstances : this.tunesInstances).set(t.name, t.create(e[t.name], this.blockAPI)); + }), Object.entries(e).forEach(([t, o]) => { + this.tunesInstances.has(t) || (this.unavailableTunesData[t] = o); + }); + } + /** + * Adds focus event listeners to all inputs and contenteditable + */ + addInputEvents() { + this.inputs.forEach((e) => { + e.addEventListener("focus", this.handleFocus), u.isNativeInput(e) && e.addEventListener("input", this.didMutated); + }); + } + /** + * removes focus event listeners from all inputs and contenteditable + */ + removeInputEvents() { + this.inputs.forEach((e) => { + e.removeEventListener("focus", this.handleFocus), u.isNativeInput(e) && e.removeEventListener("input", this.didMutated); + }); + } + /** + * Listen common editor Dom Changed event and detect mutations related to the Block + */ + watchBlockMutations() { + var e; + this.redactorDomChangedCallback = (t) => { + const { mutations: o } = t; + o.some((s) => pi(s, this.toolRenderedElement)) && this.didMutated(o); + }, (e = this.editorEventBus) == null || e.on(ft, this.redactorDomChangedCallback); + } + /** + * Remove redactor dom change event listener + */ + unwatchBlockMutations() { + var e; + (e = this.editorEventBus) == null || e.off(ft, this.redactorDomChangedCallback); + } + /** + * Sometimes Tool can replace own main element, for example H2 -> H4 or UL -> OL + * We need to detect such changes and update a link to tools main element with the new one + * + * @param mutations - records of block content mutations + */ + detectToolRootChange(e) { + e.forEach((t) => { + if (Array.from(t.removedNodes).includes(this.toolRenderedElement)) { + const i = t.addedNodes[t.addedNodes.length - 1]; + this.toolRenderedElement = i; + } + }); + } + /** + * Clears inputs cached value + */ + dropInputsCache() { + this.cachedInputs = []; + } + /** + * Mark inputs with 'data-empty' attribute with the empty state + */ + toggleInputsEmptyMark() { + this.inputs.forEach(Do); + } +} +class gi extends E { + constructor() { + super(...arguments), this.insert = (e = this.config.defaultBlock, t = {}, o = {}, i, s, r, a) => { + const l = this.Editor.BlockManager.insert({ + id: a, + tool: e, + data: t, + index: i, + needToFocus: s, + replace: r + }); + return new J(l); + }, this.composeBlockData = async (e) => { + const t = this.Editor.Tools.blockTools.get(e); + return new R({ + tool: t, + api: this.Editor.API, + readOnly: !0, + data: {}, + tunesData: {} + }).data; + }, this.update = async (e, t, o) => { + const { BlockManager: i } = this.Editor, s = i.getBlockById(e); + if (s === void 0) + throw new Error(`Block with id "${e}" not found`); + const r = await i.update(s, t, o); + return new J(r); + }, this.convert = async (e, t, o) => { + var h, p; + const { BlockManager: i, Tools: s } = this.Editor, r = i.getBlockById(e); + if (!r) + throw new Error(`Block with id "${e}" not found`); + const a = s.blockTools.get(r.name), l = s.blockTools.get(t); + if (!l) + throw new Error(`Block Tool with type "${t}" not found`); + const c = ((h = a == null ? void 0 : a.conversionConfig) == null ? void 0 : h.export) !== void 0, d = ((p = l.conversionConfig) == null ? void 0 : p.import) !== void 0; + if (c && d) { + const g = await i.convert(r, t, o); + return new J(g); + } else { + const g = [ + c ? !1 : je(r.name), + d ? !1 : je(t) + ].filter(Boolean).join(" and "); + throw new Error(`Conversion from "${r.name}" to "${t}" is not possible. ${g} tool(s) should provide a "conversionConfig"`); + } + }, this.insertMany = (e, t = this.Editor.BlockManager.blocks.length - 1) => { + this.validateIndex(t); + const o = e.map(({ id: i, type: s, data: r }) => this.Editor.BlockManager.composeBlock({ + id: i, + tool: s || this.config.defaultBlock, + data: r + })); + return this.Editor.BlockManager.insertMany(o, t), o.map((i) => new J(i)); + }; + } + /** + * Available methods + * + * @returns {Blocks} + */ + get methods() { + return { + clear: () => this.clear(), + render: (e) => this.render(e), + renderFromHTML: (e) => this.renderFromHTML(e), + delete: (e) => this.delete(e), + swap: (e, t) => this.swap(e, t), + move: (e, t) => this.move(e, t), + getBlockByIndex: (e) => this.getBlockByIndex(e), + getById: (e) => this.getById(e), + getCurrentBlockIndex: () => this.getCurrentBlockIndex(), + getBlockIndex: (e) => this.getBlockIndex(e), + getBlocksCount: () => this.getBlocksCount(), + getBlockByElement: (e) => this.getBlockByElement(e), + stretchBlock: (e, t = !0) => this.stretchBlock(e, t), + insertNewBlock: () => this.insertNewBlock(), + insert: this.insert, + insertMany: this.insertMany, + update: this.update, + composeBlockData: this.composeBlockData, + convert: this.convert + }; + } + /** + * Returns Blocks count + * + * @returns {number} + */ + getBlocksCount() { + return this.Editor.BlockManager.blocks.length; + } + /** + * Returns current block index + * + * @returns {number} + */ + getCurrentBlockIndex() { + return this.Editor.BlockManager.currentBlockIndex; + } + /** + * Returns the index of Block by id; + * + * @param id - block id + */ + getBlockIndex(e) { + const t = this.Editor.BlockManager.getBlockById(e); + if (!t) { + X("There is no block with id `" + e + "`", "warn"); + return; + } + return this.Editor.BlockManager.getBlockIndex(t); + } + /** + * Returns BlockAPI object by Block index + * + * @param {number} index - index to get + */ + getBlockByIndex(e) { + const t = this.Editor.BlockManager.getBlockByIndex(e); + if (t === void 0) { + X("There is no block at index `" + e + "`", "warn"); + return; + } + return new J(t); + } + /** + * Returns BlockAPI object by Block id + * + * @param id - id of block to get + */ + getById(e) { + const t = this.Editor.BlockManager.getBlockById(e); + return t === void 0 ? (X("There is no block with id `" + e + "`", "warn"), null) : new J(t); + } + /** + * Get Block API object by any child html element + * + * @param element - html element to get Block by + */ + getBlockByElement(e) { + const t = this.Editor.BlockManager.getBlock(e); + if (t === void 0) { + X("There is no block corresponding to element `" + e + "`", "warn"); + return; + } + return new J(t); + } + /** + * Call Block Manager method that swap Blocks + * + * @param {number} fromIndex - position of first Block + * @param {number} toIndex - position of second Block + * @deprecated — use 'move' instead + */ + swap(e, t) { + S( + "`blocks.swap()` method is deprecated and will be removed in the next major release. Use `block.move()` method instead", + "info" + ), this.Editor.BlockManager.swap(e, t); + } + /** + * Move block from one index to another + * + * @param {number} toIndex - index to move to + * @param {number} fromIndex - index to move from + */ + move(e, t) { + this.Editor.BlockManager.move(e, t); + } + /** + * Deletes Block + * + * @param {number} blockIndex - index of Block to delete + */ + delete(e = this.Editor.BlockManager.currentBlockIndex) { + try { + const t = this.Editor.BlockManager.getBlockByIndex(e); + this.Editor.BlockManager.removeBlock(t); + } catch (t) { + X(t, "warn"); + return; + } + this.Editor.BlockManager.blocks.length === 0 && this.Editor.BlockManager.insert(), this.Editor.BlockManager.currentBlock && this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock, this.Editor.Caret.positions.END), this.Editor.Toolbar.close(); + } + /** + * Clear Editor's area + */ + async clear() { + await this.Editor.BlockManager.clear(!0), this.Editor.InlineToolbar.close(); + } + /** + * Fills Editor with Blocks data + * + * @param {OutputData} data — Saved Editor data + */ + async render(e) { + if (e === void 0 || e.blocks === void 0) + throw new Error("Incorrect data passed to the render() method"); + this.Editor.ModificationsObserver.disable(), await this.Editor.BlockManager.clear(), await this.Editor.Renderer.render(e.blocks), this.Editor.ModificationsObserver.enable(); + } + /** + * Render passed HTML string + * + * @param {string} data - HTML string to render + * @returns {Promise} + */ + async renderFromHTML(e) { + return await this.Editor.BlockManager.clear(), this.Editor.Paste.processText(e, !0); + } + /** + * Stretch Block's content + * + * @param {number} index - index of Block to stretch + * @param {boolean} status - true to enable, false to disable + * @deprecated Use BlockAPI interface to stretch Blocks + */ + stretchBlock(e, t = !0) { + ht( + !0, + "blocks.stretchBlock()", + "BlockAPI" + ); + const o = this.Editor.BlockManager.getBlockByIndex(e); + o && (o.stretched = t); + } + /** + * Insert new Block + * After set caret to this Block + * + * @todo remove in 3.0.0 + * @deprecated with insert() method + */ + insertNewBlock() { + S("Method blocks.insertNewBlock() is deprecated and it will be removed in the next major release. Use blocks.insert() instead.", "warn"), this.insert(); + } + /** + * Validated block index and throws an error if it's invalid + * + * @param index - index to validate + */ + validateIndex(e) { + if (typeof e != "number") + throw new Error("Index should be a number"); + if (e < 0) + throw new Error("Index should be greater than or equal to 0"); + if (e === null) + throw new Error("Index should be greater than or equal to 0"); + } +} +function mi(n, e) { + return typeof n == "number" ? e.BlockManager.getBlockByIndex(n) : typeof n == "string" ? e.BlockManager.getBlockById(n) : e.BlockManager.getBlockById(n.id); +} +class bi extends E { + constructor() { + super(...arguments), this.setToFirstBlock = (e = this.Editor.Caret.positions.DEFAULT, t = 0) => this.Editor.BlockManager.firstBlock ? (this.Editor.Caret.setToBlock(this.Editor.BlockManager.firstBlock, e, t), !0) : !1, this.setToLastBlock = (e = this.Editor.Caret.positions.DEFAULT, t = 0) => this.Editor.BlockManager.lastBlock ? (this.Editor.Caret.setToBlock(this.Editor.BlockManager.lastBlock, e, t), !0) : !1, this.setToPreviousBlock = (e = this.Editor.Caret.positions.DEFAULT, t = 0) => this.Editor.BlockManager.previousBlock ? (this.Editor.Caret.setToBlock(this.Editor.BlockManager.previousBlock, e, t), !0) : !1, this.setToNextBlock = (e = this.Editor.Caret.positions.DEFAULT, t = 0) => this.Editor.BlockManager.nextBlock ? (this.Editor.Caret.setToBlock(this.Editor.BlockManager.nextBlock, e, t), !0) : !1, this.setToBlock = (e, t = this.Editor.Caret.positions.DEFAULT, o = 0) => { + const i = mi(e, this.Editor); + return i === void 0 ? !1 : (this.Editor.Caret.setToBlock(i, t, o), !0); + }, this.focus = (e = !1) => e ? this.setToLastBlock(this.Editor.Caret.positions.END) : this.setToFirstBlock(this.Editor.Caret.positions.START); + } + /** + * Available methods + * + * @returns {Caret} + */ + get methods() { + return { + setToFirstBlock: this.setToFirstBlock, + setToLastBlock: this.setToLastBlock, + setToPreviousBlock: this.setToPreviousBlock, + setToNextBlock: this.setToNextBlock, + setToBlock: this.setToBlock, + focus: this.focus + }; + } +} +class vi extends E { + /** + * Available methods + * + * @returns {Events} + */ + get methods() { + return { + emit: (e, t) => this.emit(e, t), + off: (e, t) => this.off(e, t), + on: (e, t) => this.on(e, t) + }; + } + /** + * Subscribe on Events + * + * @param {string} eventName - event name to subscribe + * @param {Function} callback - event handler + */ + on(e, t) { + this.eventsDispatcher.on(e, t); + } + /** + * Emit event with data + * + * @param {string} eventName - event to emit + * @param {object} data - event's data + */ + emit(e, t) { + this.eventsDispatcher.emit(e, t); + } + /** + * Unsubscribe from Event + * + * @param {string} eventName - event to unsubscribe + * @param {Function} callback - event handler + */ + off(e, t) { + this.eventsDispatcher.off(e, t); + } +} +class kt extends E { + /** + * Return namespace section for tool or block tune + * + * @param toolName - tool name + * @param isTune - is tool a block tune + */ + static getNamespace(e, t) { + return t ? `blockTunes.${e}` : `tools.${e}`; + } + /** + * Return I18n API methods with global dictionary access + */ + get methods() { + return { + t: () => { + X("I18n.t() method can be accessed only from Tools", "warn"); + } + }; + } + /** + * Return I18n API methods with tool namespaced dictionary + * + * @param toolName - tool name + * @param isTune - is tool a block tune + */ + getMethodsForTool(e, t) { + return Object.assign( + this.methods, + { + t: (o) => z.t(kt.getNamespace(e, t), o) + } + ); + } +} +class ki extends E { + /** + * Editor.js Core API modules + */ + get methods() { + return { + blocks: this.Editor.BlocksAPI.methods, + caret: this.Editor.CaretAPI.methods, + tools: this.Editor.ToolsAPI.methods, + events: this.Editor.EventsAPI.methods, + listeners: this.Editor.ListenersAPI.methods, + notifier: this.Editor.NotifierAPI.methods, + sanitizer: this.Editor.SanitizerAPI.methods, + saver: this.Editor.SaverAPI.methods, + selection: this.Editor.SelectionAPI.methods, + styles: this.Editor.StylesAPI.classes, + toolbar: this.Editor.ToolbarAPI.methods, + inlineToolbar: this.Editor.InlineToolbarAPI.methods, + tooltip: this.Editor.TooltipAPI.methods, + i18n: this.Editor.I18nAPI.methods, + readOnly: this.Editor.ReadOnlyAPI.methods, + ui: this.Editor.UiAPI.methods + }; + } + /** + * Returns Editor.js Core API methods for passed tool + * + * @param toolName - tool name + * @param isTune - is tool a block tune + */ + getMethodsForTool(e, t) { + return Object.assign( + this.methods, + { + i18n: this.Editor.I18nAPI.getMethodsForTool(e, t) + } + ); + } +} +class yi extends E { + /** + * Available methods + * + * @returns {InlineToolbar} + */ + get methods() { + return { + close: () => this.close(), + open: () => this.open() + }; + } + /** + * Open Inline Toolbar + */ + open() { + this.Editor.InlineToolbar.tryToShow(); + } + /** + * Close Inline Toolbar + */ + close() { + this.Editor.InlineToolbar.close(); + } +} +class wi extends E { + /** + * Available methods + * + * @returns {Listeners} + */ + get methods() { + return { + on: (e, t, o, i) => this.on(e, t, o, i), + off: (e, t, o, i) => this.off(e, t, o, i), + offById: (e) => this.offById(e) + }; + } + /** + * Ads a DOM event listener. Return it's id. + * + * @param {HTMLElement} element - Element to set handler to + * @param {string} eventType - event type + * @param {() => void} handler - event handler + * @param {boolean} useCapture - capture event or not + */ + on(e, t, o, i) { + return this.listeners.on(e, t, o, i); + } + /** + * Removes DOM listener from element + * + * @param {Element} element - Element to remove handler from + * @param eventType - event type + * @param handler - event handler + * @param {boolean} useCapture - capture event or not + */ + off(e, t, o, i) { + this.listeners.off(e, t, o, i); + } + /** + * Removes DOM listener by the listener id + * + * @param id - id of the listener to remove + */ + offById(e) { + this.listeners.offById(e); + } +} +var Ko = { exports: {} }; +(function(n, e) { + (function(t, o) { + n.exports = o(); + })(window, function() { + return function(t) { + var o = {}; + function i(s) { + if (o[s]) + return o[s].exports; + var r = o[s] = { i: s, l: !1, exports: {} }; + return t[s].call(r.exports, r, r.exports, i), r.l = !0, r.exports; + } + return i.m = t, i.c = o, i.d = function(s, r, a) { + i.o(s, r) || Object.defineProperty(s, r, { enumerable: !0, get: a }); + }, i.r = function(s) { + typeof Symbol < "u" && Symbol.toStringTag && Object.defineProperty(s, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(s, "__esModule", { value: !0 }); + }, i.t = function(s, r) { + if (1 & r && (s = i(s)), 8 & r || 4 & r && typeof s == "object" && s && s.__esModule) + return s; + var a = /* @__PURE__ */ Object.create(null); + if (i.r(a), Object.defineProperty(a, "default", { enumerable: !0, value: s }), 2 & r && typeof s != "string") + for (var l in s) + i.d(a, l, (function(c) { + return s[c]; + }).bind(null, l)); + return a; + }, i.n = function(s) { + var r = s && s.__esModule ? function() { + return s.default; + } : function() { + return s; + }; + return i.d(r, "a", r), r; + }, i.o = function(s, r) { + return Object.prototype.hasOwnProperty.call(s, r); + }, i.p = "/", i(i.s = 0); + }([function(t, o, i) { + i(1), /*! + * Codex JavaScript Notification module + * https://github.com/codex-team/js-notifier + */ + t.exports = function() { + var s = i(6), r = "cdx-notify--bounce-in", a = null; + return { show: function(l) { + if (l.message) { + (function() { + if (a) + return !0; + a = s.getWrapper(), document.body.appendChild(a); + })(); + var c = null, d = l.time || 8e3; + switch (l.type) { + case "confirm": + c = s.confirm(l); + break; + case "prompt": + c = s.prompt(l); + break; + default: + c = s.alert(l), window.setTimeout(function() { + c.remove(); + }, d); + } + a.appendChild(c), c.classList.add(r); + } + } }; + }(); + }, function(t, o, i) { + var s = i(2); + typeof s == "string" && (s = [[t.i, s, ""]]); + var r = { hmr: !0, transform: void 0, insertInto: void 0 }; + i(4)(s, r), s.locals && (t.exports = s.locals); + }, function(t, o, i) { + (t.exports = i(3)(!1)).push([t.i, `.cdx-notify--error{background:#fffbfb!important}.cdx-notify--error::before{background:#fb5d5d!important}.cdx-notify__input{max-width:130px;padding:5px 10px;background:#f7f7f7;border:0;border-radius:3px;font-size:13px;color:#656b7c;outline:0}.cdx-notify__input:-ms-input-placeholder{color:#656b7c}.cdx-notify__input::placeholder{color:#656b7c}.cdx-notify__input:focus:-ms-input-placeholder{color:rgba(101,107,124,.3)}.cdx-notify__input:focus::placeholder{color:rgba(101,107,124,.3)}.cdx-notify__button{border:none;border-radius:3px;font-size:13px;padding:5px 10px;cursor:pointer}.cdx-notify__button:last-child{margin-left:10px}.cdx-notify__button--cancel{background:#f2f5f7;box-shadow:0 2px 1px 0 rgba(16,19,29,0);color:#656b7c}.cdx-notify__button--cancel:hover{background:#eee}.cdx-notify__button--confirm{background:#34c992;box-shadow:0 1px 1px 0 rgba(18,49,35,.05);color:#fff}.cdx-notify__button--confirm:hover{background:#33b082}.cdx-notify__btns-wrapper{display:-ms-flexbox;display:flex;-ms-flex-flow:row nowrap;flex-flow:row nowrap;margin-top:5px}.cdx-notify__cross{position:absolute;top:5px;right:5px;width:10px;height:10px;padding:5px;opacity:.54;cursor:pointer}.cdx-notify__cross::after,.cdx-notify__cross::before{content:'';position:absolute;left:9px;top:5px;height:12px;width:2px;background:#575d67}.cdx-notify__cross::before{transform:rotate(-45deg)}.cdx-notify__cross::after{transform:rotate(45deg)}.cdx-notify__cross:hover{opacity:1}.cdx-notifies{position:fixed;z-index:2;bottom:20px;left:20px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",sans-serif}.cdx-notify{position:relative;width:220px;margin-top:15px;padding:13px 16px;background:#fff;box-shadow:0 11px 17px 0 rgba(23,32,61,.13);border-radius:5px;font-size:14px;line-height:1.4em;word-wrap:break-word}.cdx-notify::before{content:'';position:absolute;display:block;top:0;left:0;width:3px;height:calc(100% - 6px);margin:3px;border-radius:5px;background:0 0}@keyframes bounceIn{0%{opacity:0;transform:scale(.3)}50%{opacity:1;transform:scale(1.05)}70%{transform:scale(.9)}100%{transform:scale(1)}}.cdx-notify--bounce-in{animation-name:bounceIn;animation-duration:.6s;animation-iteration-count:1}.cdx-notify--success{background:#fafffe!important}.cdx-notify--success::before{background:#41ffb1!important}`, ""]); + }, function(t, o) { + t.exports = function(i) { + var s = []; + return s.toString = function() { + return this.map(function(r) { + var a = function(l, c) { + var d = l[1] || "", h = l[3]; + if (!h) + return d; + if (c && typeof btoa == "function") { + var p = (f = h, "/*# sourceMappingURL=data:application/json;charset=utf-8;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(f)))) + " */"), g = h.sources.map(function(v) { + return "/*# sourceURL=" + h.sourceRoot + v + " */"; + }); + return [d].concat(g).concat([p]).join(` +`); + } + var f; + return [d].join(` +`); + }(r, i); + return r[2] ? "@media " + r[2] + "{" + a + "}" : a; + }).join(""); + }, s.i = function(r, a) { + typeof r == "string" && (r = [[null, r, ""]]); + for (var l = {}, c = 0; c < this.length; c++) { + var d = this[c][0]; + typeof d == "number" && (l[d] = !0); + } + for (c = 0; c < r.length; c++) { + var h = r[c]; + typeof h[0] == "number" && l[h[0]] || (a && !h[2] ? h[2] = a : a && (h[2] = "(" + h[2] + ") and (" + a + ")"), s.push(h)); + } + }, s; + }; + }, function(t, o, i) { + var s, r, a = {}, l = (s = function() { + return window && document && document.all && !window.atob; + }, function() { + return r === void 0 && (r = s.apply(this, arguments)), r; + }), c = function(k) { + var m = {}; + return function(w) { + if (typeof w == "function") + return w(); + if (m[w] === void 0) { + var x = (function(I) { + return document.querySelector(I); + }).call(this, w); + if (window.HTMLIFrameElement && x instanceof window.HTMLIFrameElement) + try { + x = x.contentDocument.head; + } catch { + x = null; + } + m[w] = x; + } + return m[w]; + }; + }(), d = null, h = 0, p = [], g = i(5); + function f(k, m) { + for (var w = 0; w < k.length; w++) { + var x = k[w], I = a[x.id]; + if (I) { + I.refs++; + for (var C = 0; C < I.parts.length; C++) + I.parts[C](x.parts[C]); + for (; C < x.parts.length; C++) + I.parts.push(F(x.parts[C], m)); + } else { + var N = []; + for (C = 0; C < x.parts.length; C++) + N.push(F(x.parts[C], m)); + a[x.id] = { id: x.id, refs: 1, parts: N }; + } + } + } + function v(k, m) { + for (var w = [], x = {}, I = 0; I < k.length; I++) { + var C = k[I], N = m.base ? C[0] + m.base : C[0], B = { css: C[1], media: C[2], sourceMap: C[3] }; + x[N] ? x[N].parts.push(B) : w.push(x[N] = { id: N, parts: [B] }); + } + return w; + } + function O(k, m) { + var w = c(k.insertInto); + if (!w) + throw new Error("Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid."); + var x = p[p.length - 1]; + if (k.insertAt === "top") + x ? x.nextSibling ? w.insertBefore(m, x.nextSibling) : w.appendChild(m) : w.insertBefore(m, w.firstChild), p.push(m); + else if (k.insertAt === "bottom") + w.appendChild(m); + else { + if (typeof k.insertAt != "object" || !k.insertAt.before) + throw new Error(`[Style Loader] + + Invalid value for parameter 'insertAt' ('options.insertAt') found. + Must be 'top', 'bottom', or Object. + (https://github.com/webpack-contrib/style-loader#insertat) +`); + var I = c(k.insertInto + " " + k.insertAt.before); + w.insertBefore(m, I); + } + } + function T(k) { + if (k.parentNode === null) + return !1; + k.parentNode.removeChild(k); + var m = p.indexOf(k); + m >= 0 && p.splice(m, 1); + } + function M(k) { + var m = document.createElement("style"); + return k.attrs.type === void 0 && (k.attrs.type = "text/css"), q(m, k.attrs), O(k, m), m; + } + function q(k, m) { + Object.keys(m).forEach(function(w) { + k.setAttribute(w, m[w]); + }); + } + function F(k, m) { + var w, x, I, C; + if (m.transform && k.css) { + if (!(C = m.transform(k.css))) + return function() { + }; + k.css = C; + } + if (m.singleton) { + var N = h++; + w = d || (d = M(m)), x = ie.bind(null, w, N, !1), I = ie.bind(null, w, N, !0); + } else + k.sourceMap && typeof URL == "function" && typeof URL.createObjectURL == "function" && typeof URL.revokeObjectURL == "function" && typeof Blob == "function" && typeof btoa == "function" ? (w = function(B) { + var W = document.createElement("link"); + return B.attrs.type === void 0 && (B.attrs.type = "text/css"), B.attrs.rel = "stylesheet", q(W, B.attrs), O(B, W), W; + }(m), x = (function(B, W, ve) { + var se = ve.css, tt = ve.sourceMap, Yn = W.convertToAbsoluteUrls === void 0 && tt; + (W.convertToAbsoluteUrls || Yn) && (se = g(se)), tt && (se += ` +/*# sourceMappingURL=data:application/json;base64,` + btoa(unescape(encodeURIComponent(JSON.stringify(tt)))) + " */"); + var Kn = new Blob([se], { type: "text/css" }), ko = B.href; + B.href = URL.createObjectURL(Kn), ko && URL.revokeObjectURL(ko); + }).bind(null, w, m), I = function() { + T(w), w.href && URL.revokeObjectURL(w.href); + }) : (w = M(m), x = (function(B, W) { + var ve = W.css, se = W.media; + if (se && B.setAttribute("media", se), B.styleSheet) + B.styleSheet.cssText = ve; + else { + for (; B.firstChild; ) + B.removeChild(B.firstChild); + B.appendChild(document.createTextNode(ve)); + } + }).bind(null, w), I = function() { + T(w); + }); + return x(k), function(B) { + if (B) { + if (B.css === k.css && B.media === k.media && B.sourceMap === k.sourceMap) + return; + x(k = B); + } else + I(); + }; + } + t.exports = function(k, m) { + if (typeof DEBUG < "u" && DEBUG && typeof document != "object") + throw new Error("The style-loader cannot be used in a non-browser environment"); + (m = m || {}).attrs = typeof m.attrs == "object" ? m.attrs : {}, m.singleton || typeof m.singleton == "boolean" || (m.singleton = l()), m.insertInto || (m.insertInto = "head"), m.insertAt || (m.insertAt = "bottom"); + var w = v(k, m); + return f(w, m), function(x) { + for (var I = [], C = 0; C < w.length; C++) { + var N = w[C]; + (B = a[N.id]).refs--, I.push(B); + } + for (x && f(v(x, m), m), C = 0; C < I.length; C++) { + var B; + if ((B = I[C]).refs === 0) { + for (var W = 0; W < B.parts.length; W++) + B.parts[W](); + delete a[B.id]; + } + } + }; + }; + var H, Q = (H = [], function(k, m) { + return H[k] = m, H.filter(Boolean).join(` +`); + }); + function ie(k, m, w, x) { + var I = w ? "" : x.css; + if (k.styleSheet) + k.styleSheet.cssText = Q(m, I); + else { + var C = document.createTextNode(I), N = k.childNodes; + N[m] && k.removeChild(N[m]), N.length ? k.insertBefore(C, N[m]) : k.appendChild(C); + } + } + }, function(t, o) { + t.exports = function(i) { + var s = typeof window < "u" && window.location; + if (!s) + throw new Error("fixUrls requires window.location"); + if (!i || typeof i != "string") + return i; + var r = s.protocol + "//" + s.host, a = r + s.pathname.replace(/\/[^\/]*$/, "/"); + return i.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi, function(l, c) { + var d, h = c.trim().replace(/^"(.*)"$/, function(p, g) { + return g; + }).replace(/^'(.*)'$/, function(p, g) { + return g; + }); + return /^(#|data:|http:\/\/|https:\/\/|file:\/\/\/|\s*$)/i.test(h) ? l : (d = h.indexOf("//") === 0 ? h : h.indexOf("/") === 0 ? r + h : a + h.replace(/^\.\//, ""), "url(" + JSON.stringify(d) + ")"); + }); + }; + }, function(t, o, i) { + var s, r, a, l, c, d, h, p, g; + t.exports = (s = "cdx-notifies", r = "cdx-notify", a = "cdx-notify__cross", l = "cdx-notify__button--confirm", c = "cdx-notify__button--cancel", d = "cdx-notify__input", h = "cdx-notify__button", p = "cdx-notify__btns-wrapper", { alert: g = function(f) { + var v = document.createElement("DIV"), O = document.createElement("DIV"), T = f.message, M = f.style; + return v.classList.add(r), M && v.classList.add(r + "--" + M), v.innerHTML = T, O.classList.add(a), O.addEventListener("click", v.remove.bind(v)), v.appendChild(O), v; + }, confirm: function(f) { + var v = g(f), O = document.createElement("div"), T = document.createElement("button"), M = document.createElement("button"), q = v.querySelector("." + a), F = f.cancelHandler, H = f.okHandler; + return O.classList.add(p), T.innerHTML = f.okText || "Confirm", M.innerHTML = f.cancelText || "Cancel", T.classList.add(h), M.classList.add(h), T.classList.add(l), M.classList.add(c), F && typeof F == "function" && (M.addEventListener("click", F), q.addEventListener("click", F)), H && typeof H == "function" && T.addEventListener("click", H), T.addEventListener("click", v.remove.bind(v)), M.addEventListener("click", v.remove.bind(v)), O.appendChild(T), O.appendChild(M), v.appendChild(O), v; + }, prompt: function(f) { + var v = g(f), O = document.createElement("div"), T = document.createElement("button"), M = document.createElement("input"), q = v.querySelector("." + a), F = f.cancelHandler, H = f.okHandler; + return O.classList.add(p), T.innerHTML = f.okText || "Ok", T.classList.add(h), T.classList.add(l), M.classList.add(d), f.placeholder && M.setAttribute("placeholder", f.placeholder), f.default && (M.value = f.default), f.inputType && (M.type = f.inputType), F && typeof F == "function" && q.addEventListener("click", F), H && typeof H == "function" && T.addEventListener("click", function() { + H(M.value); + }), T.addEventListener("click", v.remove.bind(v)), O.appendChild(M), O.appendChild(T), v.appendChild(O), v; + }, getWrapper: function() { + var f = document.createElement("DIV"); + return f.classList.add(s), f; + } }); + }]); + }); +})(Ko); +var Ei = Ko.exports; +const xi = /* @__PURE__ */ Ke(Ei); +class Bi { + /** + * Show web notification + * + * @param {NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions} options - notification options + */ + show(e) { + xi.show(e); + } +} +class Ci extends E { + /** + * @param moduleConfiguration - Module Configuration + * @param moduleConfiguration.config - Editor's config + * @param moduleConfiguration.eventsDispatcher - Editor's event dispatcher + */ + constructor({ config: e, eventsDispatcher: t }) { + super({ + config: e, + eventsDispatcher: t + }), this.notifier = new Bi(); + } + /** + * Available methods + */ + get methods() { + return { + show: (e) => this.show(e) + }; + } + /** + * Show notification + * + * @param {NotifierOptions} options - message option + */ + show(e) { + return this.notifier.show(e); + } +} +class Ti extends E { + /** + * Available methods + */ + get methods() { + const e = () => this.isEnabled; + return { + toggle: (t) => this.toggle(t), + get isEnabled() { + return e(); + } + }; + } + /** + * Set or toggle read-only state + * + * @param {boolean|undefined} state - set or toggle state + * @returns {boolean} current value + */ + toggle(e) { + return this.Editor.ReadOnly.toggle(e); + } + /** + * Returns current read-only state + */ + get isEnabled() { + return this.Editor.ReadOnly.isEnabled; + } +} +var Xo = { exports: {} }; +(function(n, e) { + (function(t, o) { + n.exports = o(); + })(Ce, function() { + function t(h) { + var p = h.tags, g = Object.keys(p), f = g.map(function(v) { + return typeof p[v]; + }).every(function(v) { + return v === "object" || v === "boolean" || v === "function"; + }); + if (!f) + throw new Error("The configuration was invalid"); + this.config = h; + } + var o = ["P", "LI", "TD", "TH", "DIV", "H1", "H2", "H3", "H4", "H5", "H6", "PRE"]; + function i(h) { + return o.indexOf(h.nodeName) !== -1; + } + var s = ["A", "B", "STRONG", "I", "EM", "SUB", "SUP", "U", "STRIKE"]; + function r(h) { + return s.indexOf(h.nodeName) !== -1; + } + t.prototype.clean = function(h) { + const p = document.implementation.createHTMLDocument(), g = p.createElement("div"); + return g.innerHTML = h, this._sanitize(p, g), g.innerHTML; + }, t.prototype._sanitize = function(h, p) { + var g = a(h, p), f = g.firstChild(); + if (f) + do { + if (f.nodeType === Node.TEXT_NODE) + if (f.data.trim() === "" && (f.previousElementSibling && i(f.previousElementSibling) || f.nextElementSibling && i(f.nextElementSibling))) { + p.removeChild(f), this._sanitize(h, p); + break; + } else + continue; + if (f.nodeType === Node.COMMENT_NODE) { + p.removeChild(f), this._sanitize(h, p); + break; + } + var v = r(f), O; + v && (O = Array.prototype.some.call(f.childNodes, i)); + var T = !!p.parentNode, M = i(p) && i(f) && T, q = f.nodeName.toLowerCase(), F = l(this.config, q, f), H = v && O; + if (H || c(f, F) || !this.config.keepNestedBlockElements && M) { + if (!(f.nodeName === "SCRIPT" || f.nodeName === "STYLE")) + for (; f.childNodes.length > 0; ) + p.insertBefore(f.childNodes[0], f); + p.removeChild(f), this._sanitize(h, p); + break; + } + for (var Q = 0; Q < f.attributes.length; Q += 1) { + var ie = f.attributes[Q]; + d(ie, F, f) && (f.removeAttribute(ie.name), Q = Q - 1); + } + this._sanitize(h, f); + } while (f = g.nextSibling()); + }; + function a(h, p) { + return h.createTreeWalker( + p, + NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT, + null, + !1 + ); + } + function l(h, p, g) { + return typeof h.tags[p] == "function" ? h.tags[p](g) : h.tags[p]; + } + function c(h, p) { + return typeof p > "u" ? !0 : typeof p == "boolean" ? !p : !1; + } + function d(h, p, g) { + var f = h.name.toLowerCase(); + return p === !0 ? !1 : typeof p[f] == "function" ? !p[f](h.value, g) : typeof p[f] > "u" || p[f] === !1 ? !0 : typeof p[f] == "string" ? p[f] !== h.value : !1; + } + return t; + }); +})(Xo); +var Si = Xo.exports; +const Ii = /* @__PURE__ */ Ke(Si); +function yt(n, e) { + return n.map((t) => { + const o = A(e) ? e(t.tool) : e; + return V(o) || (t.data = wt(t.data, o)), t; + }); +} +function Z(n, e = {}) { + const t = { + tags: e + }; + return new Ii(t).clean(n); +} +function wt(n, e) { + return Array.isArray(n) ? Oi(n, e) : D(n) ? _i(n, e) : te(n) ? Mi(n, e) : n; +} +function Oi(n, e) { + return n.map((t) => wt(t, e)); +} +function _i(n, e) { + const t = {}; + for (const o in n) { + if (!Object.prototype.hasOwnProperty.call(n, o)) + continue; + const i = n[o], s = Ai(e[o]) ? e[o] : e; + t[o] = wt(i, s); + } + return t; +} +function Mi(n, e) { + return D(e) ? Z(n, e) : e === !1 ? Z(n, {}) : n; +} +function Ai(n) { + return D(n) || Gn(n) || A(n); +} +class Li extends E { + /** + * Available methods + * + * @returns {SanitizerConfig} + */ + get methods() { + return { + clean: (e, t) => this.clean(e, t) + }; + } + /** + * Perform sanitizing of a string + * + * @param {string} taintString - what to sanitize + * @param {SanitizerConfig} config - sanitizer config + * @returns {string} + */ + clean(e, t) { + return Z(e, t); + } +} +class Pi extends E { + /** + * Available methods + * + * @returns {Saver} + */ + get methods() { + return { + save: () => this.save() + }; + } + /** + * Return Editor's data + * + * @returns {OutputData} + */ + save() { + const e = "Editor's content can not be saved in read-only mode"; + return this.Editor.ReadOnly.isEnabled ? (X(e, "warn"), Promise.reject(new Error(e))) : this.Editor.Saver.save(); + } +} +class Ni extends E { + constructor() { + super(...arguments), this.selectionUtils = new b(); + } + /** + * Available methods + * + * @returns {SelectionAPIInterface} + */ + get methods() { + return { + findParentTag: (e, t) => this.findParentTag(e, t), + expandToTag: (e) => this.expandToTag(e), + save: () => this.selectionUtils.save(), + restore: () => this.selectionUtils.restore(), + setFakeBackground: () => this.selectionUtils.setFakeBackground(), + removeFakeBackground: () => this.selectionUtils.removeFakeBackground() + }; + } + /** + * Looks ahead from selection and find passed tag with class name + * + * @param {string} tagName - tag to find + * @param {string} className - tag's class name + * @returns {HTMLElement|null} + */ + findParentTag(e, t) { + return this.selectionUtils.findParentTag(e, t); + } + /** + * Expand selection to passed tag + * + * @param {HTMLElement} node - tag that should contain selection + */ + expandToTag(e) { + this.selectionUtils.expandToTag(e); + } +} +class Ri extends E { + /** + * Available methods + */ + get methods() { + return { + getBlockTools: () => Array.from(this.Editor.Tools.blockTools.values()) + }; + } +} +class Di extends E { + /** + * Exported classes + */ + get classes() { + return { + /** + * Base Block styles + */ + block: "cdx-block", + /** + * Inline Tools styles + */ + inlineToolButton: "ce-inline-tool", + inlineToolButtonActive: "ce-inline-tool--active", + /** + * UI elements + */ + input: "cdx-input", + loader: "cdx-loader", + button: "cdx-button", + /** + * Settings styles + */ + settingsButton: "cdx-settings-button", + settingsButtonActive: "cdx-settings-button--active" + }; + } +} +class Fi extends E { + /** + * Available methods + * + * @returns {Toolbar} + */ + get methods() { + return { + close: () => this.close(), + open: () => this.open(), + toggleBlockSettings: (e) => this.toggleBlockSettings(e), + toggleToolbox: (e) => this.toggleToolbox(e) + }; + } + /** + * Open toolbar + */ + open() { + this.Editor.Toolbar.moveAndOpen(); + } + /** + * Close toolbar and all included elements + */ + close() { + this.Editor.Toolbar.close(); + } + /** + * Toggles Block Setting of the current block + * + * @param {boolean} openingState — opening state of Block Setting + */ + toggleBlockSettings(e) { + if (this.Editor.BlockManager.currentBlockIndex === -1) { + X("Could't toggle the Toolbar because there is no block selected ", "warn"); + return; + } + e ?? !this.Editor.BlockSettings.opened ? (this.Editor.Toolbar.moveAndOpen(), this.Editor.BlockSettings.open()) : this.Editor.BlockSettings.close(); + } + /** + * Open toolbox + * + * @param {boolean} openingState - Opening state of toolbox + */ + toggleToolbox(e) { + if (this.Editor.BlockManager.currentBlockIndex === -1) { + X("Could't toggle the Toolbox because there is no block selected ", "warn"); + return; + } + e ?? !this.Editor.Toolbar.toolbox.opened ? (this.Editor.Toolbar.moveAndOpen(), this.Editor.Toolbar.toolbox.open()) : this.Editor.Toolbar.toolbox.close(); + } +} +var Vo = { exports: {} }; +/*! + * CodeX.Tooltips + * + * @version 1.0.5 + * + * @licence MIT + * @author CodeX + * + * + */ +(function(n, e) { + (function(t, o) { + n.exports = o(); + })(window, function() { + return function(t) { + var o = {}; + function i(s) { + if (o[s]) + return o[s].exports; + var r = o[s] = { i: s, l: !1, exports: {} }; + return t[s].call(r.exports, r, r.exports, i), r.l = !0, r.exports; + } + return i.m = t, i.c = o, i.d = function(s, r, a) { + i.o(s, r) || Object.defineProperty(s, r, { enumerable: !0, get: a }); + }, i.r = function(s) { + typeof Symbol < "u" && Symbol.toStringTag && Object.defineProperty(s, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(s, "__esModule", { value: !0 }); + }, i.t = function(s, r) { + if (1 & r && (s = i(s)), 8 & r || 4 & r && typeof s == "object" && s && s.__esModule) + return s; + var a = /* @__PURE__ */ Object.create(null); + if (i.r(a), Object.defineProperty(a, "default", { enumerable: !0, value: s }), 2 & r && typeof s != "string") + for (var l in s) + i.d(a, l, (function(c) { + return s[c]; + }).bind(null, l)); + return a; + }, i.n = function(s) { + var r = s && s.__esModule ? function() { + return s.default; + } : function() { + return s; + }; + return i.d(r, "a", r), r; + }, i.o = function(s, r) { + return Object.prototype.hasOwnProperty.call(s, r); + }, i.p = "", i(i.s = 0); + }([function(t, o, i) { + t.exports = i(1); + }, function(t, o, i) { + i.r(o), i.d(o, "default", function() { + return s; + }); + class s { + constructor() { + this.nodes = { wrapper: null, content: null }, this.showed = !1, this.offsetTop = 10, this.offsetLeft = 10, this.offsetRight = 10, this.hidingDelay = 0, this.handleWindowScroll = () => { + this.showed && this.hide(!0); + }, this.loadStyles(), this.prepare(), window.addEventListener("scroll", this.handleWindowScroll, { passive: !0 }); + } + get CSS() { + return { tooltip: "ct", tooltipContent: "ct__content", tooltipShown: "ct--shown", placement: { left: "ct--left", bottom: "ct--bottom", right: "ct--right", top: "ct--top" } }; + } + show(a, l, c) { + this.nodes.wrapper || this.prepare(), this.hidingTimeout && clearTimeout(this.hidingTimeout); + const d = Object.assign({ placement: "bottom", marginTop: 0, marginLeft: 0, marginRight: 0, marginBottom: 0, delay: 70, hidingDelay: 0 }, c); + if (d.hidingDelay && (this.hidingDelay = d.hidingDelay), this.nodes.content.innerHTML = "", typeof l == "string") + this.nodes.content.appendChild(document.createTextNode(l)); + else { + if (!(l instanceof Node)) + throw Error("[CodeX Tooltip] Wrong type of «content» passed. It should be an instance of Node or String. But " + typeof l + " given."); + this.nodes.content.appendChild(l); + } + switch (this.nodes.wrapper.classList.remove(...Object.values(this.CSS.placement)), d.placement) { + case "top": + this.placeTop(a, d); + break; + case "left": + this.placeLeft(a, d); + break; + case "right": + this.placeRight(a, d); + break; + case "bottom": + default: + this.placeBottom(a, d); + } + d && d.delay ? this.showingTimeout = setTimeout(() => { + this.nodes.wrapper.classList.add(this.CSS.tooltipShown), this.showed = !0; + }, d.delay) : (this.nodes.wrapper.classList.add(this.CSS.tooltipShown), this.showed = !0); + } + hide(a = !1) { + if (this.hidingDelay && !a) + return this.hidingTimeout && clearTimeout(this.hidingTimeout), void (this.hidingTimeout = setTimeout(() => { + this.hide(!0); + }, this.hidingDelay)); + this.nodes.wrapper.classList.remove(this.CSS.tooltipShown), this.showed = !1, this.showingTimeout && clearTimeout(this.showingTimeout); + } + onHover(a, l, c) { + a.addEventListener("mouseenter", () => { + this.show(a, l, c); + }), a.addEventListener("mouseleave", () => { + this.hide(); + }); + } + destroy() { + this.nodes.wrapper.remove(), window.removeEventListener("scroll", this.handleWindowScroll); + } + prepare() { + this.nodes.wrapper = this.make("div", this.CSS.tooltip), this.nodes.content = this.make("div", this.CSS.tooltipContent), this.append(this.nodes.wrapper, this.nodes.content), this.append(document.body, this.nodes.wrapper); + } + loadStyles() { + const a = "codex-tooltips-style"; + if (document.getElementById(a)) + return; + const l = i(2), c = this.make("style", null, { textContent: l.toString(), id: a }); + this.prepend(document.head, c); + } + placeBottom(a, l) { + const c = a.getBoundingClientRect(), d = c.left + a.clientWidth / 2 - this.nodes.wrapper.offsetWidth / 2, h = c.bottom + window.pageYOffset + this.offsetTop + l.marginTop; + this.applyPlacement("bottom", d, h); + } + placeTop(a, l) { + const c = a.getBoundingClientRect(), d = c.left + a.clientWidth / 2 - this.nodes.wrapper.offsetWidth / 2, h = c.top + window.pageYOffset - this.nodes.wrapper.clientHeight - this.offsetTop; + this.applyPlacement("top", d, h); + } + placeLeft(a, l) { + const c = a.getBoundingClientRect(), d = c.left - this.nodes.wrapper.offsetWidth - this.offsetLeft - l.marginLeft, h = c.top + window.pageYOffset + a.clientHeight / 2 - this.nodes.wrapper.offsetHeight / 2; + this.applyPlacement("left", d, h); + } + placeRight(a, l) { + const c = a.getBoundingClientRect(), d = c.right + this.offsetRight + l.marginRight, h = c.top + window.pageYOffset + a.clientHeight / 2 - this.nodes.wrapper.offsetHeight / 2; + this.applyPlacement("right", d, h); + } + applyPlacement(a, l, c) { + this.nodes.wrapper.classList.add(this.CSS.placement[a]), this.nodes.wrapper.style.left = l + "px", this.nodes.wrapper.style.top = c + "px"; + } + make(a, l = null, c = {}) { + const d = document.createElement(a); + Array.isArray(l) ? d.classList.add(...l) : l && d.classList.add(l); + for (const h in c) + c.hasOwnProperty(h) && (d[h] = c[h]); + return d; + } + append(a, l) { + Array.isArray(l) ? l.forEach((c) => a.appendChild(c)) : a.appendChild(l); + } + prepend(a, l) { + Array.isArray(l) ? (l = l.reverse()).forEach((c) => a.prepend(c)) : a.prepend(l); + } + } + }, function(t, o) { + t.exports = `.ct{z-index:999;opacity:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none;-webkit-transition:opacity 50ms ease-in,-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,transform 70ms cubic-bezier(.215,.61,.355,1),-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);will-change:opacity,top,left;-webkit-box-shadow:0 8px 12px 0 rgba(29,32,43,.17),0 4px 5px -3px rgba(5,6,12,.49);box-shadow:0 8px 12px 0 rgba(29,32,43,.17),0 4px 5px -3px rgba(5,6,12,.49);border-radius:9px}.ct,.ct:before{position:absolute;top:0;left:0}.ct:before{content:"";bottom:0;right:0;background-color:#1d202b;z-index:-1;border-radius:4px}@supports(-webkit-mask-box-image:url("")){.ct:before{border-radius:0;-webkit-mask-box-image:url('data:image/svg+xml;charset=utf-8,') 48% 41% 37.9% 53.3%}}@media (--mobile){.ct{display:none}}.ct__content{padding:6px 10px;color:#cdd1e0;font-size:12px;text-align:center;letter-spacing:.02em;line-height:1em}.ct:after{content:"";width:8px;height:8px;position:absolute;background-color:#1d202b;z-index:-1}.ct--bottom{-webkit-transform:translateY(5px);transform:translateY(5px)}.ct--bottom:after{top:-3px;left:50%;-webkit-transform:translateX(-50%) rotate(-45deg);transform:translateX(-50%) rotate(-45deg)}.ct--top{-webkit-transform:translateY(-5px);transform:translateY(-5px)}.ct--top:after{top:auto;bottom:-3px;left:50%;-webkit-transform:translateX(-50%) rotate(-45deg);transform:translateX(-50%) rotate(-45deg)}.ct--left{-webkit-transform:translateX(-5px);transform:translateX(-5px)}.ct--left:after{top:50%;left:auto;right:0;-webkit-transform:translate(41.6%,-50%) rotate(-45deg);transform:translate(41.6%,-50%) rotate(-45deg)}.ct--right{-webkit-transform:translateX(5px);transform:translateX(5px)}.ct--right:after{top:50%;left:0;-webkit-transform:translate(-41.6%,-50%) rotate(-45deg);transform:translate(-41.6%,-50%) rotate(-45deg)}.ct--shown{opacity:1;-webkit-transform:none;transform:none}`; + }]).default; + }); +})(Vo); +var ji = Vo.exports; +const Hi = /* @__PURE__ */ Ke(ji); +let U = null; +function Et() { + U || (U = new Hi()); +} +function $i(n, e, t) { + Et(), U == null || U.show(n, e, t); +} +function $e(n = !1) { + Et(), U == null || U.hide(n); +} +function ze(n, e, t) { + Et(), U == null || U.onHover(n, e, t); +} +function zi() { + U == null || U.destroy(), U = null; +} +class Ui extends E { + /** + * @class + * @param moduleConfiguration - Module Configuration + * @param moduleConfiguration.config - Editor's config + * @param moduleConfiguration.eventsDispatcher - Editor's event dispatcher + */ + constructor({ config: e, eventsDispatcher: t }) { + super({ + config: e, + eventsDispatcher: t + }); + } + /** + * Available methods + */ + get methods() { + return { + show: (e, t, o) => this.show(e, t, o), + hide: () => this.hide(), + onHover: (e, t, o) => this.onHover(e, t, o) + }; + } + /** + * Method show tooltip on element with passed HTML content + * + * @param {HTMLElement} element - element on which tooltip should be shown + * @param {TooltipContent} content - tooltip content + * @param {TooltipOptions} options - tooltip options + */ + show(e, t, o) { + $i(e, t, o); + } + /** + * Method hides tooltip on HTML page + */ + hide() { + $e(); + } + /** + * Decorator for showing Tooltip by mouseenter/mouseleave + * + * @param {HTMLElement} element - element on which tooltip should be shown + * @param {TooltipContent} content - tooltip content + * @param {TooltipOptions} options - tooltip options + */ + onHover(e, t, o) { + ze(e, t, o); + } +} +class Wi extends E { + /** + * Available methods / getters + */ + get methods() { + return { + nodes: this.editorNodes + /** + * There can be added some UI methods, like toggleThinMode() etc + */ + }; + } + /** + * Exported classes + */ + get editorNodes() { + return { + /** + * Top-level editor instance wrapper + */ + wrapper: this.Editor.UI.nodes.wrapper, + /** + * Element that holds all the Blocks + */ + redactor: this.Editor.UI.nodes.redactor + }; + } +} +function qo(n, e) { + const t = {}; + return Object.entries(n).forEach(([o, i]) => { + if (D(i)) { + const s = e ? `${e}.${o}` : o; + Object.values(i).every((a) => te(a)) ? t[o] = s : t[o] = qo(i, s); + return; + } + t[o] = i; + }), t; +} +const K = qo(Fo); +function Yi(n, e) { + const t = {}; + return Object.keys(n).forEach((o) => { + const i = e[o]; + i !== void 0 ? t[i] = n[o] : t[o] = n[o]; + }), t; +} +const Zo = class Ee { + /** + * @param {HTMLElement[]} nodeList — the list of iterable HTML-items + * @param {string} focusedCssClass - user-provided CSS-class that will be set in flipping process + */ + constructor(e, t) { + this.cursor = -1, this.items = [], this.items = e || [], this.focusedCssClass = t; + } + /** + * Returns Focused button Node + * + * @returns {HTMLElement} + */ + get currentItem() { + return this.cursor === -1 ? null : this.items[this.cursor]; + } + /** + * Sets cursor to specified position + * + * @param cursorPosition - new cursor position + */ + setCursor(e) { + e < this.items.length && e >= -1 && (this.dropCursor(), this.cursor = e, this.items[this.cursor].classList.add(this.focusedCssClass)); + } + /** + * Sets items. Can be used when iterable items changed dynamically + * + * @param {HTMLElement[]} nodeList - nodes to iterate + */ + setItems(e) { + this.items = e; + } + /** + * Sets cursor next to the current + */ + next() { + this.cursor = this.leafNodesAndReturnIndex(Ee.directions.RIGHT); + } + /** + * Sets cursor before current + */ + previous() { + this.cursor = this.leafNodesAndReturnIndex(Ee.directions.LEFT); + } + /** + * Sets cursor to the default position and removes CSS-class from previously focused item + */ + dropCursor() { + this.cursor !== -1 && (this.items[this.cursor].classList.remove(this.focusedCssClass), this.cursor = -1); + } + /** + * Leafs nodes inside the target list from active element + * + * @param {string} direction - leaf direction. Can be 'left' or 'right' + * @returns {number} index of focused node + */ + leafNodesAndReturnIndex(e) { + if (this.items.length === 0) + return this.cursor; + let t = this.cursor; + return t === -1 ? t = e === Ee.directions.RIGHT ? -1 : 0 : this.items[t].classList.remove(this.focusedCssClass), e === Ee.directions.RIGHT ? t = (t + 1) % this.items.length : t = (this.items.length + t - 1) % this.items.length, u.canSetCaret(this.items[t]) && Fe(() => b.setCursor(this.items[t]), 50)(), this.items[t].classList.add(this.focusedCssClass), t; + } +}; +Zo.directions = { + RIGHT: "right", + LEFT: "left" +}; +let ke = Zo; +class ce { + /** + * @param options - different constructing settings + */ + constructor(e) { + this.iterator = null, this.activated = !1, this.flipCallbacks = [], this.onKeyDown = (t) => { + if (!(!this.isEventReadyForHandling(t) || t.shiftKey === !0)) + switch (ce.usedKeys.includes(t.keyCode) && t.preventDefault(), t.keyCode) { + case y.TAB: + this.handleTabPress(t); + break; + case y.LEFT: + case y.UP: + this.flipLeft(); + break; + case y.RIGHT: + case y.DOWN: + this.flipRight(); + break; + case y.ENTER: + this.handleEnterPress(t); + break; + } + }, this.iterator = new ke(e.items, e.focusedItemClass), this.activateCallback = e.activateCallback, this.allowedKeys = e.allowedKeys || ce.usedKeys; + } + /** + * True if flipper is currently activated + */ + get isActivated() { + return this.activated; + } + /** + * Array of keys (codes) that is handled by Flipper + * Used to: + * - preventDefault only for this keys, not all keydowns (@see constructor) + * - to skip external behaviours only for these keys, when filler is activated (@see BlockEvents@arrowRightAndDown) + */ + static get usedKeys() { + return [ + y.TAB, + y.LEFT, + y.RIGHT, + y.ENTER, + y.UP, + y.DOWN + ]; + } + /** + * Active tab/arrows handling by flipper + * + * @param items - Some modules (like, InlineToolbar, BlockSettings) might refresh buttons dynamically + * @param cursorPosition - index of the item that should be focused once flipper is activated + */ + activate(e, t) { + this.activated = !0, e && this.iterator.setItems(e), t !== void 0 && this.iterator.setCursor(t), document.addEventListener("keydown", this.onKeyDown, !0); + } + /** + * Disable tab/arrows handling by flipper + */ + deactivate() { + this.activated = !1, this.dropCursor(), document.removeEventListener("keydown", this.onKeyDown); + } + /** + * Focus first item + */ + focusFirst() { + this.dropCursor(), this.flipRight(); + } + /** + * Focuses previous flipper iterator item + */ + flipLeft() { + this.iterator.previous(), this.flipCallback(); + } + /** + * Focuses next flipper iterator item + */ + flipRight() { + this.iterator.next(), this.flipCallback(); + } + /** + * Return true if some button is focused + */ + hasFocus() { + return !!this.iterator.currentItem; + } + /** + * Registeres function that should be executed on each navigation action + * + * @param cb - function to execute + */ + onFlip(e) { + this.flipCallbacks.push(e); + } + /** + * Unregisteres function that is executed on each navigation action + * + * @param cb - function to stop executing + */ + removeOnFlip(e) { + this.flipCallbacks = this.flipCallbacks.filter((t) => t !== e); + } + /** + * Drops flipper's iterator cursor + * + * @see DomIterator#dropCursor + */ + dropCursor() { + this.iterator.dropCursor(); + } + /** + * This function is fired before handling flipper keycodes + * The result of this function defines if it is need to be handled or not + * + * @param {KeyboardEvent} event - keydown keyboard event + * @returns {boolean} + */ + isEventReadyForHandling(e) { + return this.activated && this.allowedKeys.includes(e.keyCode); + } + /** + * When flipper is activated tab press will leaf the items + * + * @param {KeyboardEvent} event - tab keydown event + */ + handleTabPress(e) { + switch (e.shiftKey ? ke.directions.LEFT : ke.directions.RIGHT) { + case ke.directions.RIGHT: + this.flipRight(); + break; + case ke.directions.LEFT: + this.flipLeft(); + break; + } + } + /** + * Enter press will click current item if flipper is activated + * + * @param {KeyboardEvent} event - enter keydown event + */ + handleEnterPress(e) { + this.activated && (this.iterator.currentItem && (e.stopPropagation(), e.preventDefault(), this.iterator.currentItem.click()), A(this.activateCallback) && this.activateCallback(this.iterator.currentItem)); + } + /** + * Fired after flipping in any direction + */ + flipCallback() { + this.iterator.currentItem && this.iterator.currentItem.scrollIntoViewIfNeeded(), this.flipCallbacks.forEach((e) => e()); + } +} +const Ki = '', Xi = '', Vi = '', qi = '', Zi = '', Gi = '', Qi = '', Ji = '', Co = '', es = '', ts = '', Go = '', os = '', ns = '', is = '', ss = "__", rs = "--"; +function ne(n) { + return (e, t) => [[n, e].filter((i) => !!i).join(ss), t].filter((i) => !!i).join(rs); +} +const ye = ne("ce-hint"), we = { + root: ye(), + alignedStart: ye(null, "align-left"), + alignedCenter: ye(null, "align-center"), + title: ye("title"), + description: ye("description") +}; +class as { + /** + * Constructs the hint content instance + * + * @param params - hint content parameters + */ + constructor(e) { + this.nodes = { + root: u.make("div", [we.root, e.alignment === "center" ? we.alignedCenter : we.alignedStart]), + title: u.make("div", we.title, { textContent: e.title }) + }, this.nodes.root.appendChild(this.nodes.title), e.description !== void 0 && (this.nodes.description = u.make("div", we.description, { textContent: e.description }), this.nodes.root.appendChild(this.nodes.description)); + } + /** + * Returns the root element of the hint content + */ + getElement() { + return this.nodes.root; + } +} +class xt { + /** + * Constructs the instance + * + * @param params - instance parameters + */ + constructor(e) { + this.params = e; + } + /** + * Item name if exists + */ + get name() { + if (this.params !== void 0 && "name" in this.params) + return this.params.name; + } + /** + * Destroys the instance + */ + destroy() { + $e(); + } + /** + * Called when children popover is opened (if exists) + */ + onChildrenOpen() { + var e; + this.params !== void 0 && "children" in this.params && typeof ((e = this.params.children) == null ? void 0 : e.onOpen) == "function" && this.params.children.onOpen(); + } + /** + * Called when children popover is closed (if exists) + */ + onChildrenClose() { + var e; + this.params !== void 0 && "children" in this.params && typeof ((e = this.params.children) == null ? void 0 : e.onClose) == "function" && this.params.children.onClose(); + } + /** + * Called on popover item click + */ + handleClick() { + var e, t; + this.params !== void 0 && "onActivate" in this.params && ((t = (e = this.params).onActivate) == null || t.call(e, this.params)); + } + /** + * Adds hint to the item element if hint data is provided + * + * @param itemElement - popover item root element to add hint to + * @param hintData - hint data + */ + addHint(e, t) { + const o = new as(t); + ze(e, o.getElement(), { + placement: t.position, + hidingDelay: 100 + }); + } + /** + * Returns item children that are represented as popover items + */ + get children() { + var e; + return this.params !== void 0 && "children" in this.params && ((e = this.params.children) == null ? void 0 : e.items) !== void 0 ? this.params.children.items : []; + } + /** + * Returns true if item has any type of children + */ + get hasChildren() { + return this.children.length > 0; + } + /** + * Returns true if item children should be open instantly after popover is opened and not on item click/hover + */ + get isChildrenOpen() { + var e; + return this.params !== void 0 && "children" in this.params && ((e = this.params.children) == null ? void 0 : e.isOpen) === !0; + } + /** + * True if item children items should be navigatable via keyboard + */ + get isChildrenFlippable() { + var e; + return !(this.params === void 0 || !("children" in this.params) || ((e = this.params.children) == null ? void 0 : e.isFlippable) === !1); + } + /** + * Returns true if item has children that should be searchable + */ + get isChildrenSearchable() { + var e; + return this.params !== void 0 && "children" in this.params && ((e = this.params.children) == null ? void 0 : e.searchable) === !0; + } + /** + * True if popover should close once item is activated + */ + get closeOnActivate() { + return this.params !== void 0 && "closeOnActivate" in this.params && this.params.closeOnActivate; + } + /** + * True if item is active + */ + get isActive() { + return this.params === void 0 || !("isActive" in this.params) ? !1 : typeof this.params.isActive == "function" ? this.params.isActive() : this.params.isActive === !0; + } +} +const Y = ne("ce-popover-item"), L = { + container: Y(), + active: Y(null, "active"), + disabled: Y(null, "disabled"), + focused: Y(null, "focused"), + hidden: Y(null, "hidden"), + confirmationState: Y(null, "confirmation"), + noHover: Y(null, "no-hover"), + noFocus: Y(null, "no-focus"), + title: Y("title"), + secondaryTitle: Y("secondary-title"), + icon: Y("icon"), + iconTool: Y("icon", "tool"), + iconChevronRight: Y("icon", "chevron-right"), + wobbleAnimation: ne("wobble")() +}; +class re extends xt { + /** + * Constructs popover item instance + * + * @param params - popover item construction params + * @param renderParams - popover item render params. + * The parameters that are not set by user via popover api but rather depend on technical implementation + */ + constructor(e, t) { + super(e), this.params = e, this.nodes = { + root: null, + icon: null + }, this.confirmationState = null, this.removeSpecialFocusBehavior = () => { + var o; + (o = this.nodes.root) == null || o.classList.remove(L.noFocus); + }, this.removeSpecialHoverBehavior = () => { + var o; + (o = this.nodes.root) == null || o.classList.remove(L.noHover); + }, this.onErrorAnimationEnd = () => { + var o, i; + (o = this.nodes.icon) == null || o.classList.remove(L.wobbleAnimation), (i = this.nodes.icon) == null || i.removeEventListener("animationend", this.onErrorAnimationEnd); + }, this.nodes.root = this.make(e, t); + } + /** + * True if item is disabled and hence not clickable + */ + get isDisabled() { + return this.params.isDisabled === !0; + } + /** + * Exposes popover item toggle parameter + */ + get toggle() { + return this.params.toggle; + } + /** + * Item title + */ + get title() { + return this.params.title; + } + /** + * True if confirmation state is enabled for popover item + */ + get isConfirmationStateEnabled() { + return this.confirmationState !== null; + } + /** + * True if item is focused in keyboard navigation process + */ + get isFocused() { + return this.nodes.root === null ? !1 : this.nodes.root.classList.contains(L.focused); + } + /** + * Returns popover item root element + */ + getElement() { + return this.nodes.root; + } + /** + * Called on popover item click + */ + handleClick() { + if (this.isConfirmationStateEnabled && this.confirmationState !== null) { + this.activateOrEnableConfirmationMode(this.confirmationState); + return; + } + this.activateOrEnableConfirmationMode(this.params); + } + /** + * Toggles item active state + * + * @param isActive - true if item should strictly should become active + */ + toggleActive(e) { + var t; + (t = this.nodes.root) == null || t.classList.toggle(L.active, e); + } + /** + * Toggles item hidden state + * + * @param isHidden - true if item should be hidden + */ + toggleHidden(e) { + var t; + (t = this.nodes.root) == null || t.classList.toggle(L.hidden, e); + } + /** + * Resets popover item to its original state + */ + reset() { + this.isConfirmationStateEnabled && this.disableConfirmationMode(); + } + /** + * Method called once item becomes focused during keyboard navigation + */ + onFocus() { + this.disableSpecialHoverAndFocusBehavior(); + } + /** + * Constructs HTML element corresponding to popover item params + * + * @param params - item construction params + * @param renderParams - popover item render params + */ + make(e, t) { + var s, r; + const o = (t == null ? void 0 : t.wrapperTag) || "div", i = u.make(o, L.container, { + type: o === "button" ? "button" : void 0 + }); + return e.name && (i.dataset.itemName = e.name), this.nodes.icon = u.make("div", [L.icon, L.iconTool], { + innerHTML: e.icon || Qi + }), i.appendChild(this.nodes.icon), e.title !== void 0 && i.appendChild(u.make("div", L.title, { + innerHTML: e.title || "" + })), e.secondaryLabel && i.appendChild(u.make("div", L.secondaryTitle, { + textContent: e.secondaryLabel + })), this.hasChildren && i.appendChild(u.make("div", [L.icon, L.iconChevronRight], { + innerHTML: qi + })), this.isActive && i.classList.add(L.active), e.isDisabled && i.classList.add(L.disabled), e.hint !== void 0 && ((s = t == null ? void 0 : t.hint) == null ? void 0 : s.enabled) !== !1 && this.addHint(i, { + ...e.hint, + position: ((r = t == null ? void 0 : t.hint) == null ? void 0 : r.position) || "right" + }), i; + } + /** + * Activates confirmation mode for the item. + * + * @param newState - new popover item params that should be applied + */ + enableConfirmationMode(e) { + if (this.nodes.root === null) + return; + const t = { + ...this.params, + ...e, + confirmation: "confirmation" in e ? e.confirmation : void 0 + }, o = this.make(t); + this.nodes.root.innerHTML = o.innerHTML, this.nodes.root.classList.add(L.confirmationState), this.confirmationState = e, this.enableSpecialHoverAndFocusBehavior(); + } + /** + * Returns item to its original state + */ + disableConfirmationMode() { + if (this.nodes.root === null) + return; + const e = this.make(this.params); + this.nodes.root.innerHTML = e.innerHTML, this.nodes.root.classList.remove(L.confirmationState), this.confirmationState = null, this.disableSpecialHoverAndFocusBehavior(); + } + /** + * Enables special focus and hover behavior for item in confirmation state. + * This is needed to prevent item from being highlighted as hovered/focused just after click. + */ + enableSpecialHoverAndFocusBehavior() { + var e, t, o; + (e = this.nodes.root) == null || e.classList.add(L.noHover), (t = this.nodes.root) == null || t.classList.add(L.noFocus), (o = this.nodes.root) == null || o.addEventListener("mouseleave", this.removeSpecialHoverBehavior, { once: !0 }); + } + /** + * Disables special focus and hover behavior + */ + disableSpecialHoverAndFocusBehavior() { + var e; + this.removeSpecialFocusBehavior(), this.removeSpecialHoverBehavior(), (e = this.nodes.root) == null || e.removeEventListener("mouseleave", this.removeSpecialHoverBehavior); + } + /** + * Executes item's onActivate callback if the item has no confirmation configured + * + * @param item - item to activate or bring to confirmation mode + */ + activateOrEnableConfirmationMode(e) { + var t; + if (!("confirmation" in e) || e.confirmation === void 0) + try { + (t = e.onActivate) == null || t.call(e, e), this.disableConfirmationMode(); + } catch { + this.animateError(); + } + else + this.enableConfirmationMode(e.confirmation); + } + /** + * Animates item which symbolizes that error occured while executing 'onActivate()' callback + */ + animateError() { + var e, t, o; + (e = this.nodes.icon) != null && e.classList.contains(L.wobbleAnimation) || ((t = this.nodes.icon) == null || t.classList.add(L.wobbleAnimation), (o = this.nodes.icon) == null || o.addEventListener("animationend", this.onErrorAnimationEnd)); + } +} +const nt = ne("ce-popover-item-separator"), it = { + container: nt(), + line: nt("line"), + hidden: nt(null, "hidden") +}; +class Qo extends xt { + /** + * Constructs the instance + */ + constructor() { + super(), this.nodes = { + root: u.make("div", it.container), + line: u.make("div", it.line) + }, this.nodes.root.appendChild(this.nodes.line); + } + /** + * Returns popover separator root element + */ + getElement() { + return this.nodes.root; + } + /** + * Toggles item hidden state + * + * @param isHidden - true if item should be hidden + */ + toggleHidden(e) { + var t; + (t = this.nodes.root) == null || t.classList.toggle(it.hidden, e); + } +} +var G = /* @__PURE__ */ ((n) => (n.Closed = "closed", n.ClosedOnActivate = "closed-on-activate", n))(G || {}); +const $ = ne("ce-popover"), P = { + popover: $(), + popoverContainer: $("container"), + popoverOpenTop: $(null, "open-top"), + popoverOpenLeft: $(null, "open-left"), + popoverOpened: $(null, "opened"), + search: $("search"), + nothingFoundMessage: $("nothing-found-message"), + nothingFoundMessageDisplayed: $("nothing-found-message", "displayed"), + items: $("items"), + overlay: $("overlay"), + overlayHidden: $("overlay", "hidden"), + popoverNested: $(null, "nested"), + getPopoverNestedClass: (n) => $(null, `nested-level-${n.toString()}`), + popoverInline: $(null, "inline"), + popoverHeader: $("header") +}; +var fe = /* @__PURE__ */ ((n) => (n.NestingLevel = "--nesting-level", n.PopoverHeight = "--popover-height", n.InlinePopoverWidth = "--inline-popover-width", n.TriggerItemLeft = "--trigger-item-left", n.TriggerItemTop = "--trigger-item-top", n))(fe || {}); +const To = ne("ce-popover-item-html"), So = { + root: To(), + hidden: To(null, "hidden") +}; +class Se extends xt { + /** + * Constructs the instance + * + * @param params – instance parameters + * @param renderParams – popover item render params. + * The parameters that are not set by user via popover api but rather depend on technical implementation + */ + constructor(e, t) { + var o, i; + super(e), this.nodes = { + root: u.make("div", So.root) + }, this.nodes.root.appendChild(e.element), e.name && (this.nodes.root.dataset.itemName = e.name), e.hint !== void 0 && ((o = t == null ? void 0 : t.hint) == null ? void 0 : o.enabled) !== !1 && this.addHint(this.nodes.root, { + ...e.hint, + position: ((i = t == null ? void 0 : t.hint) == null ? void 0 : i.position) || "right" + }); + } + /** + * Returns popover item root element + */ + getElement() { + return this.nodes.root; + } + /** + * Toggles item hidden state + * + * @param isHidden - true if item should be hidden + */ + toggleHidden(e) { + var t; + (t = this.nodes.root) == null || t.classList.toggle(So.hidden, e); + } + /** + * Returns list of buttons and inputs inside custom content + */ + getControls() { + const e = this.nodes.root.querySelectorAll( + `button, ${u.allInputsSelector}` + ); + return Array.from(e); + } +} +class Jo extends Oe { + /** + * Constructs the instance + * + * @param params - popover construction params + * @param itemsRenderParams - popover item render params. + * The parameters that are not set by user via popover api but rather depend on technical implementation + */ + constructor(e, t = {}) { + super(), this.params = e, this.itemsRenderParams = t, this.listeners = new _e(), this.messages = { + nothingFound: "Nothing found", + search: "Search" + }, this.items = this.buildItems(e.items), e.messages && (this.messages = { + ...this.messages, + ...e.messages + }), this.nodes = {}, this.nodes.popoverContainer = u.make("div", [P.popoverContainer]), this.nodes.nothingFoundMessage = u.make("div", [P.nothingFoundMessage], { + textContent: this.messages.nothingFound + }), this.nodes.popoverContainer.appendChild(this.nodes.nothingFoundMessage), this.nodes.items = u.make("div", [P.items]), this.items.forEach((o) => { + const i = o.getElement(); + i !== null && this.nodes.items.appendChild(i); + }), this.nodes.popoverContainer.appendChild(this.nodes.items), this.listeners.on(this.nodes.popoverContainer, "click", (o) => this.handleClick(o)), this.nodes.popover = u.make("div", [ + P.popover, + this.params.class + ]), this.nodes.popover.appendChild(this.nodes.popoverContainer); + } + /** + * List of default popover items that are searchable and may have confirmation state + */ + get itemsDefault() { + return this.items.filter((e) => e instanceof re); + } + /** + * Returns HTML element corresponding to the popover + */ + getElement() { + return this.nodes.popover; + } + /** + * Open popover + */ + show() { + this.nodes.popover.classList.add(P.popoverOpened), this.search !== void 0 && this.search.focus(); + } + /** + * Closes popover + */ + hide() { + this.nodes.popover.classList.remove(P.popoverOpened), this.nodes.popover.classList.remove(P.popoverOpenTop), this.itemsDefault.forEach((e) => e.reset()), this.search !== void 0 && this.search.clear(), this.emit(G.Closed); + } + /** + * Clears memory + */ + destroy() { + var e; + this.items.forEach((t) => t.destroy()), this.nodes.popover.remove(), this.listeners.removeAll(), (e = this.search) == null || e.destroy(); + } + /** + * Looks for the item by name and imitates click on it + * + * @param name - name of the item to activate + */ + activateItemByName(e) { + const t = this.items.find((o) => o.name === e); + this.handleItemClick(t); + } + /** + * Factory method for creating popover items + * + * @param items - list of items params + */ + buildItems(e) { + return e.map((t) => { + switch (t.type) { + case _.Separator: + return new Qo(); + case _.Html: + return new Se(t, this.itemsRenderParams[_.Html]); + default: + return new re(t, this.itemsRenderParams[_.Default]); + } + }); + } + /** + * Retrieves popover item that is the target of the specified event + * + * @param event - event to retrieve popover item from + */ + getTargetItem(e) { + return this.items.filter((t) => t instanceof re || t instanceof Se).find((t) => { + const o = t.getElement(); + return o === null ? !1 : e.composedPath().includes(o); + }); + } + /** + * Handles popover item click + * + * @param item - item to handle click of + */ + handleItemClick(e) { + if (!("isDisabled" in e && e.isDisabled)) { + if (e.hasChildren) { + this.showNestedItems(e), "handleClick" in e && typeof e.handleClick == "function" && e.handleClick(); + return; + } + this.itemsDefault.filter((t) => t !== e).forEach((t) => t.reset()), "handleClick" in e && typeof e.handleClick == "function" && e.handleClick(), this.toggleItemActivenessIfNeeded(e), e.closeOnActivate && (this.hide(), this.emit(G.ClosedOnActivate)); + } + } + /** + * Handles clicks inside popover + * + * @param event - item to handle click of + */ + handleClick(e) { + const t = this.getTargetItem(e); + t !== void 0 && this.handleItemClick(t); + } + /** + * - Toggles item active state, if clicked popover item has property 'toggle' set to true. + * + * - Performs radiobutton-like behavior if the item has property 'toggle' set to string key. + * (All the other items with the same key get inactive, and the item gets active) + * + * @param clickedItem - popover item that was clicked + */ + toggleItemActivenessIfNeeded(e) { + if (e instanceof re && (e.toggle === !0 && e.toggleActive(), typeof e.toggle == "string")) { + const t = this.itemsDefault.filter((o) => o.toggle === e.toggle); + if (t.length === 1) { + e.toggleActive(); + return; + } + t.forEach((o) => { + o.toggleActive(o === e); + }); + } + } +} +var Ue = /* @__PURE__ */ ((n) => (n.Search = "search", n))(Ue || {}); +const st = ne("cdx-search-field"), rt = { + wrapper: st(), + icon: st("icon"), + input: st("input") +}; +class ls extends Oe { + /** + * @param options - available config + * @param options.items - searchable items list + * @param options.placeholder - input placeholder + */ + constructor({ items: e, placeholder: t }) { + super(), this.listeners = new _e(), this.items = e, this.wrapper = u.make("div", rt.wrapper); + const o = u.make("div", rt.icon, { + innerHTML: os + }); + this.input = u.make("input", rt.input, { + placeholder: t, + /** + * Used to prevent focusing on the input by Tab key + * (Popover in the Toolbar lays below the blocks, + * so Tab in the last block will focus this hidden input if this property is not set) + */ + tabIndex: -1 + }), this.wrapper.appendChild(o), this.wrapper.appendChild(this.input), this.listeners.on(this.input, "input", () => { + this.searchQuery = this.input.value, this.emit(Ue.Search, { + query: this.searchQuery, + items: this.foundItems + }); + }); + } + /** + * Returns search field element + */ + getElement() { + return this.wrapper; + } + /** + * Sets focus to the input + */ + focus() { + this.input.focus(); + } + /** + * Clears search query and results + */ + clear() { + this.input.value = "", this.searchQuery = "", this.emit(Ue.Search, { + query: "", + items: this.foundItems + }); + } + /** + * Clears memory + */ + destroy() { + this.listeners.removeAll(); + } + /** + * Returns list of found items for the current search query + */ + get foundItems() { + return this.items.filter((e) => this.checkItem(e)); + } + /** + * Contains logic for checking whether passed item conforms the search query + * + * @param item - item to be checked + */ + checkItem(e) { + var i, s; + const t = ((i = e.title) == null ? void 0 : i.toLowerCase()) || "", o = (s = this.searchQuery) == null ? void 0 : s.toLowerCase(); + return o !== void 0 ? t.includes(o) : !1; + } +} +var cs = Object.defineProperty, ds = Object.getOwnPropertyDescriptor, us = (n, e, t, o) => { + for (var i = o > 1 ? void 0 : o ? ds(e, t) : e, s = n.length - 1, r; s >= 0; s--) + (r = n[s]) && (i = (o ? r(e, t, i) : r(i)) || i); + return o && i && cs(e, t, i), i; +}; +const en = class tn extends Jo { + /** + * Construct the instance + * + * @param params - popover params + * @param itemsRenderParams – popover item render params. + * The parameters that are not set by user via popover api but rather depend on technical implementation + */ + constructor(e, t) { + super(e, t), this.nestingLevel = 0, this.nestedPopoverTriggerItem = null, this.previouslyHoveredItem = null, this.scopeElement = document.body, this.hide = () => { + var o; + super.hide(), this.destroyNestedPopoverIfExists(), (o = this.flipper) == null || o.deactivate(), this.previouslyHoveredItem = null; + }, this.onFlip = () => { + const o = this.itemsDefault.find((i) => i.isFocused); + o == null || o.onFocus(); + }, this.onSearch = (o) => { + var a; + const i = o.query === "", s = o.items.length === 0; + this.items.forEach((l) => { + let c = !1; + l instanceof re ? c = !o.items.includes(l) : (l instanceof Qo || l instanceof Se) && (c = s || !i), l.toggleHidden(c); + }), this.toggleNothingFoundMessage(s); + const r = o.query === "" ? this.flippableElements : o.items.map((l) => l.getElement()); + (a = this.flipper) != null && a.isActivated && (this.flipper.deactivate(), this.flipper.activate(r)); + }, e.nestingLevel !== void 0 && (this.nestingLevel = e.nestingLevel), this.nestingLevel > 0 && this.nodes.popover.classList.add(P.popoverNested), e.scopeElement !== void 0 && (this.scopeElement = e.scopeElement), this.nodes.popoverContainer !== null && this.listeners.on(this.nodes.popoverContainer, "mouseover", (o) => this.handleHover(o)), e.searchable && this.addSearch(), e.flippable !== !1 && (this.flipper = new ce({ + items: this.flippableElements, + focusedItemClass: L.focused, + allowedKeys: [ + y.TAB, + y.UP, + y.DOWN, + y.ENTER + ] + }), this.flipper.onFlip(this.onFlip)); + } + /** + * Returns true if some item inside popover is focused + */ + hasFocus() { + return this.flipper === void 0 ? !1 : this.flipper.hasFocus(); + } + /** + * Scroll position inside items container of the popover + */ + get scrollTop() { + return this.nodes.items === null ? 0 : this.nodes.items.scrollTop; + } + /** + * Returns visible element offset top + */ + get offsetTop() { + return this.nodes.popoverContainer === null ? 0 : this.nodes.popoverContainer.offsetTop; + } + /** + * Open popover + */ + show() { + var e; + this.nodes.popover.style.setProperty(fe.PopoverHeight, this.size.height + "px"), this.shouldOpenBottom || this.nodes.popover.classList.add(P.popoverOpenTop), this.shouldOpenRight || this.nodes.popover.classList.add(P.popoverOpenLeft), super.show(), (e = this.flipper) == null || e.activate(this.flippableElements); + } + /** + * Clears memory + */ + destroy() { + this.hide(), super.destroy(); + } + /** + * Handles displaying nested items for the item. + * + * @param item – item to show nested popover for + */ + showNestedItems(e) { + this.nestedPopover !== null && this.nestedPopover !== void 0 || (this.nestedPopoverTriggerItem = e, this.showNestedPopoverForItem(e)); + } + /** + * Handles hover events inside popover items container + * + * @param event - hover event data + */ + handleHover(e) { + const t = this.getTargetItem(e); + t !== void 0 && this.previouslyHoveredItem !== t && (this.destroyNestedPopoverIfExists(), this.previouslyHoveredItem = t, t.hasChildren && this.showNestedPopoverForItem(t)); + } + /** + * Sets CSS variable with position of item near which nested popover should be displayed. + * Is used for correct positioning of the nested popover + * + * @param nestedPopoverEl - nested popover element + * @param item – item near which nested popover should be displayed + */ + setTriggerItemPosition(e, t) { + const o = t.getElement(), i = (o ? o.offsetTop : 0) - this.scrollTop, s = this.offsetTop + i; + e.style.setProperty(fe.TriggerItemTop, s + "px"); + } + /** + * Destroys existing nested popover + */ + destroyNestedPopoverIfExists() { + var e, t; + this.nestedPopover === void 0 || this.nestedPopover === null || (this.nestedPopover.off(G.ClosedOnActivate, this.hide), this.nestedPopover.hide(), this.nestedPopover.destroy(), this.nestedPopover.getElement().remove(), this.nestedPopover = null, (e = this.flipper) == null || e.activate(this.flippableElements), (t = this.nestedPopoverTriggerItem) == null || t.onChildrenClose()); + } + /** + * Creates and displays nested popover for specified item. + * Is used only on desktop + * + * @param item - item to display nested popover by + */ + showNestedPopoverForItem(e) { + var o; + this.nestedPopover = new tn({ + searchable: e.isChildrenSearchable, + items: e.children, + nestingLevel: this.nestingLevel + 1, + flippable: e.isChildrenFlippable, + messages: this.messages + }), e.onChildrenOpen(), this.nestedPopover.on(G.ClosedOnActivate, this.hide); + const t = this.nestedPopover.getElement(); + return this.nodes.popover.appendChild(t), this.setTriggerItemPosition(t, e), t.style.setProperty(fe.NestingLevel, this.nestedPopover.nestingLevel.toString()), this.nestedPopover.show(), (o = this.flipper) == null || o.deactivate(), this.nestedPopover; + } + /** + * Checks if popover should be opened bottom. + * It should happen when there is enough space below or not enough space above + */ + get shouldOpenBottom() { + if (this.nodes.popover === void 0 || this.nodes.popover === null) + return !1; + const e = this.nodes.popoverContainer.getBoundingClientRect(), t = this.scopeElement.getBoundingClientRect(), o = this.size.height, i = e.top + o, s = e.top - o, r = Math.min(window.innerHeight, t.bottom); + return s < t.top || i <= r; + } + /** + * Checks if popover should be opened left. + * It should happen when there is enough space in the right or not enough space in the left + */ + get shouldOpenRight() { + if (this.nodes.popover === void 0 || this.nodes.popover === null) + return !1; + const e = this.nodes.popover.getBoundingClientRect(), t = this.scopeElement.getBoundingClientRect(), o = this.size.width, i = e.right + o, s = e.left - o, r = Math.min(window.innerWidth, t.right); + return s < t.left || i <= r; + } + get size() { + var i; + const e = { + height: 0, + width: 0 + }; + if (this.nodes.popover === null) + return e; + const t = this.nodes.popover.cloneNode(!0); + t.style.visibility = "hidden", t.style.position = "absolute", t.style.top = "-1000px", t.classList.add(P.popoverOpened), (i = t.querySelector("." + P.popoverNested)) == null || i.remove(), document.body.appendChild(t); + const o = t.querySelector("." + P.popoverContainer); + return e.height = o.offsetHeight, e.width = o.offsetWidth, t.remove(), e; + } + /** + * Returns list of elements available for keyboard navigation. + */ + get flippableElements() { + return this.items.map((t) => { + if (t instanceof re) + return t.getElement(); + if (t instanceof Se) + return t.getControls(); + }).flat().filter((t) => t != null); + } + /** + * Adds search to the popover + */ + addSearch() { + this.search = new ls({ + items: this.itemsDefault, + placeholder: this.messages.search + }), this.search.on(Ue.Search, this.onSearch); + const e = this.search.getElement(); + e.classList.add(P.search), this.nodes.popoverContainer.insertBefore(e, this.nodes.popoverContainer.firstChild); + } + /** + * Toggles nothing found message visibility + * + * @param isDisplayed - true if the message should be displayed + */ + toggleNothingFoundMessage(e) { + this.nodes.nothingFoundMessage.classList.toggle(P.nothingFoundMessageDisplayed, e); + } +}; +us([ + me +], en.prototype, "size", 1); +let Bt = en; +class hs extends Bt { + /** + * Constructs the instance + * + * @param params - instance parameters + */ + constructor(e) { + const t = !be(); + super( + { + ...e, + class: P.popoverInline + }, + { + [_.Default]: { + /** + * We use button instead of div here to fix bug associated with focus loss (which leads to selection change) on click in safari + * + * @todo figure out better way to solve the issue + */ + wrapperTag: "button", + hint: { + position: "top", + alignment: "center", + enabled: t + } + }, + [_.Html]: { + hint: { + position: "top", + alignment: "center", + enabled: t + } + } + } + ), this.items.forEach((o) => { + !(o instanceof re) && !(o instanceof Se) || o.hasChildren && o.isChildrenOpen && this.showNestedItems(o); + }); + } + /** + * Returns visible element offset top + */ + get offsetLeft() { + return this.nodes.popoverContainer === null ? 0 : this.nodes.popoverContainer.offsetLeft; + } + /** + * Open popover + */ + show() { + this.nestingLevel === 0 && this.nodes.popover.style.setProperty( + fe.InlinePopoverWidth, + this.size.width + "px" + ), super.show(); + } + /** + * Disable hover event handling. + * Overrides parent's class behavior + */ + handleHover() { + } + /** + * Sets CSS variable with position of item near which nested popover should be displayed. + * Is used to position nested popover right below clicked item + * + * @param nestedPopoverEl - nested popover element + * @param item – item near which nested popover should be displayed + */ + setTriggerItemPosition(e, t) { + const o = t.getElement(), i = o ? o.offsetLeft : 0, s = this.offsetLeft + i; + e.style.setProperty( + fe.TriggerItemLeft, + s + "px" + ); + } + /** + * Handles displaying nested items for the item. + * Overriding in order to add toggling behaviour + * + * @param item – item to toggle nested popover for + */ + showNestedItems(e) { + if (this.nestedPopoverTriggerItem === e) { + this.destroyNestedPopoverIfExists(), this.nestedPopoverTriggerItem = null; + return; + } + super.showNestedItems(e); + } + /** + * Creates and displays nested popover for specified item. + * Is used only on desktop + * + * @param item - item to display nested popover by + */ + showNestedPopoverForItem(e) { + const t = super.showNestedPopoverForItem(e); + return t.getElement().classList.add(P.getPopoverNestedClass(t.nestingLevel)), t; + } + /** + * Overrides default item click handling. + * Helps to close nested popover once other item is clicked. + * + * @param item - clicked item + */ + handleItemClick(e) { + var t; + e !== this.nestedPopoverTriggerItem && ((t = this.nestedPopoverTriggerItem) == null || t.handleClick(), super.destroyNestedPopoverIfExists()), super.handleItemClick(e); + } +} +const on = class xe { + constructor() { + this.scrollPosition = null; + } + /** + * Locks body element scroll + */ + lock() { + pt ? this.lockHard() : document.body.classList.add(xe.CSS.scrollLocked); + } + /** + * Unlocks body element scroll + */ + unlock() { + pt ? this.unlockHard() : document.body.classList.remove(xe.CSS.scrollLocked); + } + /** + * Locks scroll in a hard way (via setting fixed position to body element) + */ + lockHard() { + this.scrollPosition = window.pageYOffset, document.documentElement.style.setProperty( + "--window-scroll-offset", + `${this.scrollPosition}px` + ), document.body.classList.add(xe.CSS.scrollLockedHard); + } + /** + * Unlocks hard scroll lock + */ + unlockHard() { + document.body.classList.remove(xe.CSS.scrollLockedHard), this.scrollPosition !== null && window.scrollTo(0, this.scrollPosition), this.scrollPosition = null; + } +}; +on.CSS = { + scrollLocked: "ce-scroll-locked", + scrollLockedHard: "ce-scroll-locked--hard" +}; +let ps = on; +const at = ne("ce-popover-header"), lt = { + root: at(), + text: at("text"), + backButton: at("back-button") +}; +class fs { + /** + * Constructs the instance + * + * @param params - popover header params + */ + constructor({ text: e, onBackButtonClick: t }) { + this.listeners = new _e(), this.text = e, this.onBackButtonClick = t, this.nodes = { + root: u.make("div", [lt.root]), + backButton: u.make("button", [lt.backButton]), + text: u.make("div", [lt.text]) + }, this.nodes.backButton.innerHTML = Vi, this.nodes.root.appendChild(this.nodes.backButton), this.listeners.on(this.nodes.backButton, "click", this.onBackButtonClick), this.nodes.text.innerText = this.text, this.nodes.root.appendChild(this.nodes.text); + } + /** + * Returns popover header root html element + */ + getElement() { + return this.nodes.root; + } + /** + * Destroys the instance + */ + destroy() { + this.nodes.root.remove(), this.listeners.destroy(); + } +} +class gs { + constructor() { + this.history = []; + } + /** + * Push new popover state + * + * @param state - new state + */ + push(e) { + this.history.push(e); + } + /** + * Pop last popover state + */ + pop() { + return this.history.pop(); + } + /** + * Title retrieved from the current state + */ + get currentTitle() { + return this.history.length === 0 ? "" : this.history[this.history.length - 1].title; + } + /** + * Items list retrieved from the current state + */ + get currentItems() { + return this.history.length === 0 ? [] : this.history[this.history.length - 1].items; + } + /** + * Returns history to initial popover state + */ + reset() { + for (; this.history.length > 1; ) + this.pop(); + } +} +class nn extends Jo { + /** + * Construct the instance + * + * @param params - popover params + */ + constructor(e) { + super(e, { + [_.Default]: { + hint: { + enabled: !1 + } + }, + [_.Html]: { + hint: { + enabled: !1 + } + } + }), this.scrollLocker = new ps(), this.history = new gs(), this.isHidden = !0, this.nodes.overlay = u.make("div", [P.overlay, P.overlayHidden]), this.nodes.popover.insertBefore(this.nodes.overlay, this.nodes.popover.firstChild), this.listeners.on(this.nodes.overlay, "click", () => { + this.hide(); + }), this.history.push({ items: e.items }); + } + /** + * Open popover + */ + show() { + this.nodes.overlay.classList.remove(P.overlayHidden), super.show(), this.scrollLocker.lock(), this.isHidden = !1; + } + /** + * Closes popover + */ + hide() { + this.isHidden || (super.hide(), this.nodes.overlay.classList.add(P.overlayHidden), this.scrollLocker.unlock(), this.history.reset(), this.isHidden = !0); + } + /** + * Clears memory + */ + destroy() { + super.destroy(), this.scrollLocker.unlock(); + } + /** + * Handles displaying nested items for the item + * + * @param item – item to show nested popover for + */ + showNestedItems(e) { + this.updateItemsAndHeader(e.children, e.title), this.history.push({ + title: e.title, + items: e.children + }); + } + /** + * Removes rendered popover items and header and displays new ones + * + * @param items - new popover items + * @param title - new popover header text + */ + updateItemsAndHeader(e, t) { + if (this.header !== null && this.header !== void 0 && (this.header.destroy(), this.header = null), t !== void 0) { + this.header = new fs({ + text: t, + onBackButtonClick: () => { + this.history.pop(), this.updateItemsAndHeader(this.history.currentItems, this.history.currentTitle); + } + }); + const o = this.header.getElement(); + o !== null && this.nodes.popoverContainer.insertBefore(o, this.nodes.popoverContainer.firstChild); + } + this.items.forEach((o) => { + var i; + return (i = o.getElement()) == null ? void 0 : i.remove(); + }), this.items = this.buildItems(e), this.items.forEach((o) => { + var s; + const i = o.getElement(); + i !== null && ((s = this.nodes.items) == null || s.appendChild(i)); + }); + } +} +class ms extends E { + constructor() { + super(...arguments), this.opened = !1, this.hasMobileLayoutToggleListener = !1, this.selection = new b(), this.popover = null, this.close = () => { + this.opened && (this.opened = !1, b.isAtEditor || this.selection.restore(), this.selection.clearSaved(), !this.Editor.CrossBlockSelection.isCrossBlockSelectionStarted && this.Editor.BlockManager.currentBlock && this.Editor.BlockSelection.unselectBlock(this.Editor.BlockManager.currentBlock), this.eventsDispatcher.emit(this.events.closed), this.popover && (this.popover.off(G.Closed, this.onPopoverClose), this.popover.destroy(), this.popover.getElement().remove(), this.popover = null)); + }, this.onPopoverClose = () => { + this.close(); + }; + } + /** + * Module Events + */ + get events() { + return { + opened: "block-settings-opened", + closed: "block-settings-closed" + }; + } + /** + * Block Settings CSS + */ + get CSS() { + return { + settings: "ce-settings" + }; + } + /** + * Getter for inner popover's flipper instance + * + * @todo remove once BlockSettings becomes standalone non-module class + */ + get flipper() { + var e; + if (this.popover !== null) + return "flipper" in this.popover ? (e = this.popover) == null ? void 0 : e.flipper : void 0; + } + /** + * Panel with block settings with 2 sections: + * - Tool's Settings + * - Default Settings [Move, Remove, etc] + */ + make() { + this.nodes.wrapper = u.make("div", [this.CSS.settings]), this.eventsDispatcher.on(Te, this.close), this.hasMobileLayoutToggleListener = !0; + } + /** + * Destroys module + */ + destroy() { + this.removeAllNodes(), this.listeners.destroy(), this.hasMobileLayoutToggleListener && (this.eventsDispatcher.off(Te, this.close), this.hasMobileLayoutToggleListener = !1); + } + /** + * Open Block Settings pane + * + * @param targetBlock - near which Block we should open BlockSettings + */ + async open(e = this.Editor.BlockManager.currentBlock) { + var s; + this.opened = !0, this.selection.save(), this.Editor.BlockSelection.selectBlock(e), this.Editor.BlockSelection.clearCache(); + const { toolTunes: t, commonTunes: o } = e.getTunes(); + this.eventsDispatcher.emit(this.events.opened); + const i = be() ? nn : Bt; + this.popover = new i({ + searchable: !0, + items: await this.getTunesItems(e, o, t), + scopeElement: this.Editor.API.methods.ui.nodes.redactor, + messages: { + nothingFound: z.ui(K.ui.popover, "Nothing found"), + search: z.ui(K.ui.popover, "Filter") + } + }), this.popover.on(G.Closed, this.onPopoverClose), (s = this.nodes.wrapper) == null || s.append(this.popover.getElement()), this.popover.show(); + } + /** + * Returns root block settings element + */ + getElement() { + return this.nodes.wrapper; + } + /** + * Returns list of items to be displayed in block tunes menu. + * Merges tool specific tunes, conversion menu and common tunes in one list in predefined order + * + * @param currentBlock – block we are about to open block tunes for + * @param commonTunes – common tunes + * @param toolTunes - tool specific tunes + */ + async getTunesItems(e, t, o) { + const i = []; + o !== void 0 && o.length > 0 && (i.push(...o), i.push({ + type: _.Separator + })); + const s = Array.from(this.Editor.Tools.blockTools.values()), a = (await Yo(e, s)).reduce((l, c) => (c.toolbox.forEach((d) => { + l.push({ + icon: d.icon, + title: z.t(K.toolNames, d.title), + name: c.name, + closeOnActivate: !0, + onActivate: async () => { + const { BlockManager: h, Caret: p, Toolbar: g } = this.Editor, f = await h.convert(e, c.name, d.data); + g.close(), p.setToBlock(f, p.positions.END); + } + }); + }), l), []); + return a.length > 0 && (i.push({ + icon: Go, + name: "convert-to", + title: z.ui(K.ui.popover, "Convert to"), + children: { + searchable: !0, + items: a + } + }), i.push({ + type: _.Separator + })), i.push(...t), i.map((l) => this.resolveTuneAliases(l)); + } + /** + * Resolves aliases in tunes menu items + * + * @param item - item with resolved aliases + */ + resolveTuneAliases(e) { + if (e.type === _.Separator || e.type === _.Html) + return e; + const t = Yi(e, { label: "title" }); + return e.confirmation && (t.confirmation = this.resolveTuneAliases(e.confirmation)), t; + } +} +var sn = { exports: {} }; +/*! + * Library for handling keyboard shortcuts + * @copyright CodeX (https://codex.so) + * @license MIT + * @author CodeX (https://codex.so) + * @version 1.2.0 + */ +(function(n, e) { + (function(t, o) { + n.exports = o(); + })(window, function() { + return function(t) { + var o = {}; + function i(s) { + if (o[s]) + return o[s].exports; + var r = o[s] = { i: s, l: !1, exports: {} }; + return t[s].call(r.exports, r, r.exports, i), r.l = !0, r.exports; + } + return i.m = t, i.c = o, i.d = function(s, r, a) { + i.o(s, r) || Object.defineProperty(s, r, { enumerable: !0, get: a }); + }, i.r = function(s) { + typeof Symbol < "u" && Symbol.toStringTag && Object.defineProperty(s, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(s, "__esModule", { value: !0 }); + }, i.t = function(s, r) { + if (1 & r && (s = i(s)), 8 & r || 4 & r && typeof s == "object" && s && s.__esModule) + return s; + var a = /* @__PURE__ */ Object.create(null); + if (i.r(a), Object.defineProperty(a, "default", { enumerable: !0, value: s }), 2 & r && typeof s != "string") + for (var l in s) + i.d(a, l, (function(c) { + return s[c]; + }).bind(null, l)); + return a; + }, i.n = function(s) { + var r = s && s.__esModule ? function() { + return s.default; + } : function() { + return s; + }; + return i.d(r, "a", r), r; + }, i.o = function(s, r) { + return Object.prototype.hasOwnProperty.call(s, r); + }, i.p = "", i(i.s = 0); + }([function(t, o, i) { + function s(l, c) { + for (var d = 0; d < c.length; d++) { + var h = c[d]; + h.enumerable = h.enumerable || !1, h.configurable = !0, "value" in h && (h.writable = !0), Object.defineProperty(l, h.key, h); + } + } + function r(l, c, d) { + return c && s(l.prototype, c), d && s(l, d), l; + } + i.r(o); + var a = function() { + function l(c) { + var d = this; + (function(h, p) { + if (!(h instanceof p)) + throw new TypeError("Cannot call a class as a function"); + })(this, l), this.commands = {}, this.keys = {}, this.name = c.name, this.parseShortcutName(c.name), this.element = c.on, this.callback = c.callback, this.executeShortcut = function(h) { + d.execute(h); + }, this.element.addEventListener("keydown", this.executeShortcut, !1); + } + return r(l, null, [{ key: "supportedCommands", get: function() { + return { SHIFT: ["SHIFT"], CMD: ["CMD", "CONTROL", "COMMAND", "WINDOWS", "CTRL"], ALT: ["ALT", "OPTION"] }; + } }, { key: "keyCodes", get: function() { + return { 0: 48, 1: 49, 2: 50, 3: 51, 4: 52, 5: 53, 6: 54, 7: 55, 8: 56, 9: 57, A: 65, B: 66, C: 67, D: 68, E: 69, F: 70, G: 71, H: 72, I: 73, J: 74, K: 75, L: 76, M: 77, N: 78, O: 79, P: 80, Q: 81, R: 82, S: 83, T: 84, U: 85, V: 86, W: 87, X: 88, Y: 89, Z: 90, BACKSPACE: 8, ENTER: 13, ESCAPE: 27, LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40, INSERT: 45, DELETE: 46, ".": 190 }; + } }]), r(l, [{ key: "parseShortcutName", value: function(c) { + c = c.split("+"); + for (var d = 0; d < c.length; d++) { + c[d] = c[d].toUpperCase(); + var h = !1; + for (var p in l.supportedCommands) + if (l.supportedCommands[p].includes(c[d])) { + h = this.commands[p] = !0; + break; + } + h || (this.keys[c[d]] = !0); + } + for (var g in l.supportedCommands) + this.commands[g] || (this.commands[g] = !1); + } }, { key: "execute", value: function(c) { + var d, h = { CMD: c.ctrlKey || c.metaKey, SHIFT: c.shiftKey, ALT: c.altKey }, p = !0; + for (d in this.commands) + this.commands[d] !== h[d] && (p = !1); + var g, f = !0; + for (g in this.keys) + f = f && c.keyCode === l.keyCodes[g]; + p && f && this.callback(c); + } }, { key: "remove", value: function() { + this.element.removeEventListener("keydown", this.executeShortcut); + } }]), l; + }(); + o.default = a; + }]).default; + }); +})(sn); +var bs = sn.exports; +const vs = /* @__PURE__ */ Ke(bs); +class ks { + constructor() { + this.registeredShortcuts = /* @__PURE__ */ new Map(); + } + /** + * Register shortcut + * + * @param shortcut - shortcut options + */ + add(e) { + if (this.findShortcut(e.on, e.name)) + throw Error( + `Shortcut ${e.name} is already registered for ${e.on}. Please remove it before add a new handler.` + ); + const o = new vs({ + name: e.name, + on: e.on, + callback: e.handler + }), i = this.registeredShortcuts.get(e.on) || []; + this.registeredShortcuts.set(e.on, [...i, o]); + } + /** + * Remove shortcut + * + * @param element - Element shortcut is set for + * @param name - shortcut name + */ + remove(e, t) { + const o = this.findShortcut(e, t); + if (!o) + return; + o.remove(); + const s = this.registeredShortcuts.get(e).filter((r) => r !== o); + if (s.length === 0) { + this.registeredShortcuts.delete(e); + return; + } + this.registeredShortcuts.set(e, s); + } + /** + * Get Shortcut instance if exist + * + * @param element - Element shorcut is set for + * @param shortcut - shortcut name + * @returns {number} index - shortcut index if exist + */ + findShortcut(e, t) { + return (this.registeredShortcuts.get(e) || []).find(({ name: i }) => i === t); + } +} +const ge = new ks(); +var ys = Object.defineProperty, ws = Object.getOwnPropertyDescriptor, rn = (n, e, t, o) => { + for (var i = o > 1 ? void 0 : o ? ws(e, t) : e, s = n.length - 1, r; s >= 0; s--) + (r = n[s]) && (i = (o ? r(e, t, i) : r(i)) || i); + return o && i && ys(e, t, i), i; +}, Le = /* @__PURE__ */ ((n) => (n.Opened = "toolbox-opened", n.Closed = "toolbox-closed", n.BlockAdded = "toolbox-block-added", n))(Le || {}); +const Ct = class an extends Oe { + /** + * Toolbox constructor + * + * @param options - available parameters + * @param options.api - Editor API methods + * @param options.tools - Tools available to check whether some of them should be displayed at the Toolbox or not + */ + constructor({ api: e, tools: t, i18nLabels: o }) { + super(), this.opened = !1, this.listeners = new _e(), this.popover = null, this.handleMobileLayoutToggle = () => { + this.destroyPopover(), this.initPopover(); + }, this.onPopoverClose = () => { + this.opened = !1, this.emit( + "toolbox-closed" + /* Closed */ + ); + }, this.api = e, this.tools = t, this.i18nLabels = o, this.enableShortcuts(), this.nodes = { + toolbox: u.make("div", an.CSS.toolbox) + }, this.initPopover(), this.api.events.on(Te, this.handleMobileLayoutToggle); + } + /** + * Returns True if Toolbox is Empty and nothing to show + * + * @returns {boolean} + */ + get isEmpty() { + return this.toolsToBeDisplayed.length === 0; + } + /** + * CSS styles + */ + static get CSS() { + return { + toolbox: "ce-toolbox" + }; + } + /** + * Returns root block settings element + */ + getElement() { + return this.nodes.toolbox; + } + /** + * Returns true if the Toolbox has the Flipper activated and the Flipper has selected button + */ + hasFocus() { + if (this.popover !== null) + return "hasFocus" in this.popover ? this.popover.hasFocus() : void 0; + } + /** + * Destroy Module + */ + destroy() { + var e; + super.destroy(), this.nodes && this.nodes.toolbox && this.nodes.toolbox.remove(), this.removeAllShortcuts(), (e = this.popover) == null || e.off(G.Closed, this.onPopoverClose), this.listeners.destroy(), this.api.events.off(Te, this.handleMobileLayoutToggle); + } + /** + * Toolbox Tool's button click handler + * + * @param toolName - tool type to be activated + * @param blockDataOverrides - Block data predefined by the activated Toolbox item + */ + toolButtonActivated(e, t) { + this.insertNewBlock(e, t); + } + /** + * Open Toolbox with Tools + */ + open() { + var e; + this.isEmpty || ((e = this.popover) == null || e.show(), this.opened = !0, this.emit( + "toolbox-opened" + /* Opened */ + )); + } + /** + * Close Toolbox + */ + close() { + var e; + (e = this.popover) == null || e.hide(), this.opened = !1, this.emit( + "toolbox-closed" + /* Closed */ + ); + } + /** + * Close Toolbox + */ + toggle() { + this.opened ? this.close() : this.open(); + } + /** + * Creates toolbox popover and appends it inside wrapper element + */ + initPopover() { + var t; + const e = be() ? nn : Bt; + this.popover = new e({ + scopeElement: this.api.ui.nodes.redactor, + searchable: !0, + messages: { + nothingFound: this.i18nLabels.nothingFound, + search: this.i18nLabels.filter + }, + items: this.toolboxItemsToBeDisplayed + }), this.popover.on(G.Closed, this.onPopoverClose), (t = this.nodes.toolbox) == null || t.append(this.popover.getElement()); + } + /** + * Destroys popover instance and removes it from DOM + */ + destroyPopover() { + this.popover !== null && (this.popover.hide(), this.popover.off(G.Closed, this.onPopoverClose), this.popover.destroy(), this.popover = null), this.nodes.toolbox !== null && (this.nodes.toolbox.innerHTML = ""); + } + get toolsToBeDisplayed() { + const e = []; + return this.tools.forEach((t) => { + t.toolbox && e.push(t); + }), e; + } + get toolboxItemsToBeDisplayed() { + const e = (t, o, i = !0) => ({ + icon: t.icon, + title: z.t(K.toolNames, t.title || je(o.name)), + name: o.name, + onActivate: () => { + this.toolButtonActivated(o.name, t.data); + }, + secondaryLabel: o.shortcut && i ? vt(o.shortcut) : "" + }); + return this.toolsToBeDisplayed.reduce((t, o) => (Array.isArray(o.toolbox) ? o.toolbox.forEach((i, s) => { + t.push(e(i, o, s === 0)); + }) : o.toolbox !== void 0 && t.push(e(o.toolbox, o)), t), []); + } + /** + * Iterate all tools and enable theirs shortcuts if specified + */ + enableShortcuts() { + this.toolsToBeDisplayed.forEach((e) => { + const t = e.shortcut; + t && this.enableShortcutForTool(e.name, t); + }); + } + /** + * Enable shortcut Block Tool implemented shortcut + * + * @param {string} toolName - Tool name + * @param {string} shortcut - shortcut according to the ShortcutData Module format + */ + enableShortcutForTool(e, t) { + ge.add({ + name: t, + on: this.api.ui.nodes.redactor, + handler: async (o) => { + o.preventDefault(); + const i = this.api.blocks.getCurrentBlockIndex(), s = this.api.blocks.getBlockByIndex(i); + if (s) + try { + const r = await this.api.blocks.convert(s.id, e); + this.api.caret.setToBlock(r, "end"); + return; + } catch { + } + this.insertNewBlock(e); + } + }); + } + /** + * Removes all added shortcuts + * Fired when the Read-Only mode is activated + */ + removeAllShortcuts() { + this.toolsToBeDisplayed.forEach((e) => { + const t = e.shortcut; + t && ge.remove(this.api.ui.nodes.redactor, t); + }); + } + /** + * Inserts new block + * Can be called when button clicked on Toolbox or by ShortcutData + * + * @param {string} toolName - Tool name + * @param blockDataOverrides - predefined Block data + */ + async insertNewBlock(e, t) { + const o = this.api.blocks.getCurrentBlockIndex(), i = this.api.blocks.getBlockByIndex(o); + if (!i) + return; + const s = i.isEmpty ? o : o + 1; + let r; + if (t) { + const l = await this.api.blocks.composeBlockData(e); + r = Object.assign(l, t); + } + const a = this.api.blocks.insert( + e, + r, + void 0, + s, + void 0, + i.isEmpty + ); + a.call(ee.APPEND_CALLBACK), this.api.caret.setToBlock(s), this.emit("toolbox-block-added", { + block: a + }), this.api.toolbar.close(); + } +}; +rn([ + me +], Ct.prototype, "toolsToBeDisplayed", 1); +rn([ + me +], Ct.prototype, "toolboxItemsToBeDisplayed", 1); +let Es = Ct; +const ln = "block hovered"; +async function xs(n, e) { + const t = navigator.keyboard; + if (!t) + return e; + try { + return (await t.getLayoutMap()).get(n) || e; + } catch (o) { + return console.error(o), e; + } +} +class Bs extends E { + /** + * @class + * @param moduleConfiguration - Module Configuration + * @param moduleConfiguration.config - Editor's config + * @param moduleConfiguration.eventsDispatcher - Editor's event dispatcher + */ + constructor({ config: e, eventsDispatcher: t }) { + super({ + config: e, + eventsDispatcher: t + }), this.toolboxInstance = null; + } + /** + * CSS styles + * + * @returns {object} + */ + get CSS() { + return { + toolbar: "ce-toolbar", + content: "ce-toolbar__content", + actions: "ce-toolbar__actions", + actionsOpened: "ce-toolbar__actions--opened", + toolbarOpened: "ce-toolbar--opened", + openedToolboxHolderModifier: "codex-editor--toolbox-opened", + plusButton: "ce-toolbar__plus", + plusButtonShortcut: "ce-toolbar__plus-shortcut", + settingsToggler: "ce-toolbar__settings-btn", + settingsTogglerHidden: "ce-toolbar__settings-btn--hidden" + }; + } + /** + * Returns the Toolbar opening state + * + * @returns {boolean} + */ + get opened() { + return this.nodes.wrapper.classList.contains(this.CSS.toolbarOpened); + } + /** + * Public interface for accessing the Toolbox + */ + get toolbox() { + var e; + return { + opened: (e = this.toolboxInstance) == null ? void 0 : e.opened, + close: () => { + var t; + (t = this.toolboxInstance) == null || t.close(); + }, + open: () => { + if (this.toolboxInstance === null) { + S("toolbox.open() called before initialization is finished", "warn"); + return; + } + this.Editor.BlockManager.currentBlock = this.hoveredBlock, this.toolboxInstance.open(); + }, + toggle: () => { + if (this.toolboxInstance === null) { + S("toolbox.toggle() called before initialization is finished", "warn"); + return; + } + this.toolboxInstance.toggle(); + }, + hasFocus: () => { + var t; + return (t = this.toolboxInstance) == null ? void 0 : t.hasFocus(); + } + }; + } + /** + * Block actions appearance manipulations + */ + get blockActions() { + return { + hide: () => { + this.nodes.actions.classList.remove(this.CSS.actionsOpened); + }, + show: () => { + this.nodes.actions.classList.add(this.CSS.actionsOpened); + } + }; + } + /** + * Methods for working with Block Tunes toggler + */ + get blockTunesToggler() { + return { + hide: () => this.nodes.settingsToggler.classList.add(this.CSS.settingsTogglerHidden), + show: () => this.nodes.settingsToggler.classList.remove(this.CSS.settingsTogglerHidden) + }; + } + /** + * Toggles read-only mode + * + * @param {boolean} readOnlyEnabled - read-only mode + */ + toggleReadOnly(e) { + e ? (this.destroy(), this.Editor.BlockSettings.destroy(), this.disableModuleBindings()) : window.requestIdleCallback(() => { + this.drawUI(), this.enableModuleBindings(); + }, { timeout: 2e3 }); + } + /** + * Move Toolbar to the passed (or current) Block + * + * @param block - block to move Toolbar near it + */ + moveAndOpen(e = this.Editor.BlockManager.currentBlock) { + if (this.toolboxInstance === null) { + S("Can't open Toolbar since Editor initialization is not finished yet", "warn"); + return; + } + if (this.toolboxInstance.opened && this.toolboxInstance.close(), this.Editor.BlockSettings.opened && this.Editor.BlockSettings.close(), !e) + return; + this.hoveredBlock = e; + const t = e.holder, { isMobile: o } = this.Editor.UI; + let i; + const s = 20, r = e.firstInput, a = t.getBoundingClientRect(), l = r !== void 0 ? r.getBoundingClientRect() : null, c = l !== null ? l.top - a.top : null, d = c !== null ? c > s : void 0; + if (o) + i = t.offsetTop + t.offsetHeight; + else if (r === void 0 || d) { + const h = parseInt(window.getComputedStyle(e.pluginsContent).paddingTop); + i = t.offsetTop + h; + } else { + const h = li(r), p = parseInt(window.getComputedStyle(this.nodes.plusButton).height, 10), g = 8; + i = t.offsetTop + h - p + g + c; + } + this.nodes.wrapper.style.top = `${Math.floor(i)}px`, this.Editor.BlockManager.blocks.length === 1 && e.isEmpty ? this.blockTunesToggler.hide() : this.blockTunesToggler.show(), this.open(); + } + /** + * Close the Toolbar + */ + close() { + var e, t; + this.Editor.ReadOnly.isEnabled || ((e = this.nodes.wrapper) == null || e.classList.remove(this.CSS.toolbarOpened), this.blockActions.hide(), (t = this.toolboxInstance) == null || t.close(), this.Editor.BlockSettings.close(), this.reset()); + } + /** + * Reset the Toolbar position to prevent DOM height growth, for example after blocks deletion + */ + reset() { + this.nodes.wrapper.style.top = "unset"; + } + /** + * Open Toolbar with Plus Button and Actions + * + * @param {boolean} withBlockActions - by default, Toolbar opens with Block Actions. + * This flag allows to open Toolbar without Actions. + */ + open(e = !0) { + this.nodes.wrapper.classList.add(this.CSS.toolbarOpened), e ? this.blockActions.show() : this.blockActions.hide(); + } + /** + * Draws Toolbar elements + */ + async make() { + this.nodes.wrapper = u.make("div", this.CSS.toolbar), ["content", "actions"].forEach((s) => { + this.nodes[s] = u.make("div", this.CSS[s]); + }), u.append(this.nodes.wrapper, this.nodes.content), u.append(this.nodes.content, this.nodes.actions), this.nodes.plusButton = u.make("div", this.CSS.plusButton, { + innerHTML: ts + }), u.append(this.nodes.actions, this.nodes.plusButton), this.readOnlyMutableListeners.on(this.nodes.plusButton, "click", () => { + $e(!0), this.plusButtonClicked(); + }, !1); + const e = u.make("div"); + e.appendChild(document.createTextNode(z.ui(K.ui.toolbar.toolbox, "Add"))), e.appendChild(u.make("div", this.CSS.plusButtonShortcut, { + textContent: "/" + })), ze(this.nodes.plusButton, e, { + hidingDelay: 400 + }), this.nodes.settingsToggler = u.make("span", this.CSS.settingsToggler, { + innerHTML: es + }), u.append(this.nodes.actions, this.nodes.settingsToggler); + const t = u.make("div"), o = u.text(z.ui(K.ui.blockTunes.toggler, "Click to tune")), i = await xs("Slash", "/"); + t.appendChild(o), t.appendChild(u.make("div", this.CSS.plusButtonShortcut, { + textContent: vt(`CMD + ${i}`) + })), ze(this.nodes.settingsToggler, t, { + hidingDelay: 400 + }), u.append(this.nodes.actions, this.makeToolbox()), u.append(this.nodes.actions, this.Editor.BlockSettings.getElement()), u.append(this.Editor.UI.nodes.wrapper, this.nodes.wrapper); + } + /** + * Creates the Toolbox instance and return it's rendered element + */ + makeToolbox() { + return this.toolboxInstance = new Es({ + api: this.Editor.API.methods, + tools: this.Editor.Tools.blockTools, + i18nLabels: { + filter: z.ui(K.ui.popover, "Filter"), + nothingFound: z.ui(K.ui.popover, "Nothing found") + } + }), this.toolboxInstance.on(Le.Opened, () => { + this.Editor.UI.nodes.wrapper.classList.add(this.CSS.openedToolboxHolderModifier); + }), this.toolboxInstance.on(Le.Closed, () => { + this.Editor.UI.nodes.wrapper.classList.remove(this.CSS.openedToolboxHolderModifier); + }), this.toolboxInstance.on(Le.BlockAdded, ({ block: e }) => { + const { BlockManager: t, Caret: o } = this.Editor, i = t.getBlockById(e.id); + i.inputs.length === 0 && (i === t.lastBlock ? (t.insertAtEnd(), o.setToBlock(t.lastBlock)) : o.setToBlock(t.nextBlock)); + }), this.toolboxInstance.getElement(); + } + /** + * Handler for Plus Button + */ + plusButtonClicked() { + var e; + this.Editor.BlockManager.currentBlock = this.hoveredBlock, (e = this.toolboxInstance) == null || e.toggle(); + } + /** + * Enable bindings + */ + enableModuleBindings() { + this.readOnlyMutableListeners.on(this.nodes.settingsToggler, "mousedown", (e) => { + var t; + e.stopPropagation(), this.settingsTogglerClicked(), (t = this.toolboxInstance) != null && t.opened && this.toolboxInstance.close(), $e(!0); + }, !0), be() || this.eventsDispatcher.on(ln, (e) => { + var t; + this.Editor.BlockSettings.opened || (t = this.toolboxInstance) != null && t.opened || this.moveAndOpen(e.block); + }); + } + /** + * Disable bindings + */ + disableModuleBindings() { + this.readOnlyMutableListeners.clearAll(); + } + /** + * Clicks on the Block Settings toggler + */ + settingsTogglerClicked() { + this.Editor.BlockManager.currentBlock = this.hoveredBlock, this.Editor.BlockSettings.opened ? this.Editor.BlockSettings.close() : this.Editor.BlockSettings.open(this.hoveredBlock); + } + /** + * Draws Toolbar UI + * + * Toolbar contains BlockSettings and Toolbox. + * That's why at first we draw its components and then Toolbar itself + * + * Steps: + * - Make Toolbar dependent components like BlockSettings, Toolbox and so on + * - Make itself and append dependent nodes to itself + * + */ + drawUI() { + this.Editor.BlockSettings.make(), this.make(); + } + /** + * Removes all created and saved HTMLElements + * It is used in Read-Only mode + */ + destroy() { + this.removeAllNodes(), this.toolboxInstance && this.toolboxInstance.destroy(); + } +} +var ae = /* @__PURE__ */ ((n) => (n[n.Block = 0] = "Block", n[n.Inline = 1] = "Inline", n[n.Tune = 2] = "Tune", n))(ae || {}), Pe = /* @__PURE__ */ ((n) => (n.Shortcut = "shortcut", n.Toolbox = "toolbox", n.EnabledInlineTools = "inlineToolbar", n.EnabledBlockTunes = "tunes", n.Config = "config", n))(Pe || {}), cn = /* @__PURE__ */ ((n) => (n.Shortcut = "shortcut", n.SanitizeConfig = "sanitize", n))(cn || {}), pe = /* @__PURE__ */ ((n) => (n.IsEnabledLineBreaks = "enableLineBreaks", n.Toolbox = "toolbox", n.ConversionConfig = "conversionConfig", n.IsReadOnlySupported = "isReadOnlySupported", n.PasteConfig = "pasteConfig", n))(pe || {}), We = /* @__PURE__ */ ((n) => (n.IsInline = "isInline", n.Title = "title", n.IsReadOnlySupported = "isReadOnlySupported", n))(We || {}), mt = /* @__PURE__ */ ((n) => (n.IsTune = "isTune", n))(mt || {}); +class Tt { + /** + * @class + * @param {ConstructorOptions} options - Constructor options + */ + constructor({ + name: e, + constructable: t, + config: o, + api: i, + isDefault: s, + isInternal: r = !1, + defaultPlaceholder: a + }) { + this.api = i, this.name = e, this.constructable = t, this.config = o, this.isDefault = s, this.isInternal = r, this.defaultPlaceholder = a; + } + /** + * Returns Tool user configuration + */ + get settings() { + const e = this.config.config || {}; + return this.isDefault && !("placeholder" in e) && this.defaultPlaceholder && (e.placeholder = this.defaultPlaceholder), e; + } + /** + * Calls Tool's reset method + */ + reset() { + if (A(this.constructable.reset)) + return this.constructable.reset(); + } + /** + * Calls Tool's prepare method + */ + prepare() { + if (A(this.constructable.prepare)) + return this.constructable.prepare({ + toolName: this.name, + config: this.settings + }); + } + /** + * Returns shortcut for Tool (internal or specified by user) + */ + get shortcut() { + const e = this.constructable.shortcut; + return this.config.shortcut || e; + } + /** + * Returns Tool's sanitizer configuration + */ + get sanitizeConfig() { + return this.constructable.sanitize || {}; + } + /** + * Returns true if Tools is inline + */ + isInline() { + return this.type === ae.Inline; + } + /** + * Returns true if Tools is block + */ + isBlock() { + return this.type === ae.Block; + } + /** + * Returns true if Tools is tune + */ + isTune() { + return this.type === ae.Tune; + } +} +class Cs extends E { + /** + * @param moduleConfiguration - Module Configuration + * @param moduleConfiguration.config - Editor's config + * @param moduleConfiguration.eventsDispatcher - Editor's event dispatcher + */ + constructor({ config: e, eventsDispatcher: t }) { + super({ + config: e, + eventsDispatcher: t + }), this.CSS = { + inlineToolbar: "ce-inline-toolbar" + }, this.opened = !1, this.popover = null, this.toolbarVerticalMargin = be() ? 20 : 6, this.tools = /* @__PURE__ */ new Map(), window.requestIdleCallback(() => { + this.make(); + }, { timeout: 2e3 }); + } + /** + * Moving / appearance + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + /** + * Shows Inline Toolbar if something is selected + * + * @param [needToClose] - pass true to close toolbar if it is not allowed. + * Avoid to use it just for closing IT, better call .close() clearly. + */ + async tryToShow(e = !1) { + e && this.close(), this.allowedToShow() && (await this.open(), this.Editor.Toolbar.close()); + } + /** + * Hides Inline Toolbar + */ + close() { + var e, t; + if (this.opened) { + for (const [o, i] of this.tools) { + const s = this.getToolShortcut(o.name); + s !== void 0 && ge.remove(this.Editor.UI.nodes.redactor, s), A(i.clear) && i.clear(); + } + this.tools = /* @__PURE__ */ new Map(), this.reset(), this.opened = !1, (e = this.popover) == null || e.hide(), (t = this.popover) == null || t.destroy(), this.popover = null; + } + } + /** + * Check if node is contained by Inline Toolbar + * + * @param {Node} node — node to check + */ + containsNode(e) { + return this.nodes.wrapper === void 0 ? !1 : this.nodes.wrapper.contains(e); + } + /** + * Removes UI and its components + */ + destroy() { + var e; + this.removeAllNodes(), (e = this.popover) == null || e.destroy(), this.popover = null; + } + /** + * Making DOM + */ + make() { + this.nodes.wrapper = u.make("div", [ + this.CSS.inlineToolbar, + ...this.isRtl ? [this.Editor.UI.CSS.editorRtlFix] : [] + ]), u.append(this.Editor.UI.nodes.wrapper, this.nodes.wrapper); + } + /** + * Shows Inline Toolbar + */ + async open() { + var t; + if (this.opened) + return; + this.opened = !0, this.popover !== null && this.popover.destroy(), this.createToolsInstances(); + const e = await this.getPopoverItems(); + this.popover = new hs({ + items: e, + scopeElement: this.Editor.API.methods.ui.nodes.redactor, + messages: { + nothingFound: z.ui(K.ui.popover, "Nothing found"), + search: z.ui(K.ui.popover, "Filter") + } + }), this.move(this.popover.size.width), (t = this.nodes.wrapper) == null || t.append(this.popover.getElement()), this.popover.show(); + } + /** + * Move Toolbar to the selected text + * + * @param popoverWidth - width of the toolbar popover + */ + move(e) { + const t = b.rect, o = this.Editor.UI.nodes.wrapper.getBoundingClientRect(), i = { + x: t.x - o.x, + y: t.y + t.height - // + window.scrollY + o.top + this.toolbarVerticalMargin + }; + i.x + e + o.x > this.Editor.UI.contentRect.right && (i.x = this.Editor.UI.contentRect.right - e - o.x), this.nodes.wrapper.style.left = Math.floor(i.x) + "px", this.nodes.wrapper.style.top = Math.floor(i.y) + "px"; + } + /** + * Clear orientation classes and reset position + */ + reset() { + this.nodes.wrapper.style.left = "0", this.nodes.wrapper.style.top = "0"; + } + /** + * Need to show Inline Toolbar or not + */ + allowedToShow() { + const e = ["IMG", "INPUT"], t = b.get(), o = b.text; + if (!t || !t.anchorNode || t.isCollapsed || o.length < 1) + return !1; + const i = u.isElement(t.anchorNode) ? t.anchorNode : t.anchorNode.parentElement; + if (i === null || t !== null && e.includes(i.tagName)) + return !1; + const s = this.Editor.BlockManager.getBlock(t.anchorNode); + return !s || this.getTools().some((c) => s.tool.inlineTools.has(c.name)) === !1 ? !1 : i.closest("[contenteditable]") !== null; + } + /** + * Working with Tools + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + /** + * Returns tools that are available for current block + * + * Used to check if Inline Toolbar could be shown + * and to render tools in the Inline Toolbar + */ + getTools() { + const e = this.Editor.BlockManager.currentBlock; + return e ? Array.from(e.tool.inlineTools.values()).filter((o) => !(this.Editor.ReadOnly.isEnabled && o.isReadOnlySupported !== !0)) : []; + } + /** + * Constructs tools instances and saves them to this.tools + */ + createToolsInstances() { + this.tools = /* @__PURE__ */ new Map(), this.getTools().forEach((t) => { + const o = t.create(); + this.tools.set(t, o); + }); + } + /** + * Returns Popover Items for tools segregated by their appearance type: regular items and custom html elements. + */ + async getPopoverItems() { + const e = []; + let t = 0; + for (const [o, i] of this.tools) { + const s = await i.render(), r = this.getToolShortcut(o.name); + if (r !== void 0) + try { + this.enableShortcuts(o.name, r); + } catch { + } + const a = r !== void 0 ? vt(r) : void 0, l = z.t( + K.toolNames, + o.title || je(o.name) + ); + [s].flat().forEach((c) => { + var h, p; + const d = { + name: o.name, + onActivate: () => { + this.toolClicked(i); + }, + hint: { + title: l, + description: a + } + }; + if (u.isElement(c)) { + const g = { + ...d, + element: c, + type: _.Html + }; + if (A(i.renderActions)) { + const f = i.renderActions(); + g.children = { + isOpen: (h = i.checkState) == null ? void 0 : h.call(i, b.get()), + /** Disable keyboard navigation in actions, as it might conflict with enter press handling */ + isFlippable: !1, + items: [ + { + type: _.Html, + element: f + } + ] + }; + } else + (p = i.checkState) == null || p.call(i, b.get()); + e.push(g); + } else if (c.type === _.Html) + e.push({ + ...d, + ...c, + type: _.Html + }); + else if (c.type === _.Separator) + e.push({ + type: _.Separator + }); + else { + const g = { + ...d, + ...c, + type: _.Default + }; + "children" in g && t !== 0 && e.push({ + type: _.Separator + }), e.push(g), "children" in g && t < this.tools.size - 1 && e.push({ + type: _.Separator + }); + } + }), t++; + } + return e; + } + /** + * Get shortcut name for tool + * + * @param toolName — Tool name + */ + getToolShortcut(e) { + const { Tools: t } = this.Editor, o = t.inlineTools.get(e), i = t.internal.inlineTools; + return Array.from(i.keys()).includes(e) ? this.inlineTools[e][cn.Shortcut] : o == null ? void 0 : o.shortcut; + } + /** + * Enable Tool shortcut with Editor Shortcuts Module + * + * @param toolName - tool name + * @param shortcut - shortcut according to the ShortcutData Module format + */ + enableShortcuts(e, t) { + ge.add({ + name: t, + handler: (o) => { + var s; + const { currentBlock: i } = this.Editor.BlockManager; + i && i.tool.enabledInlineTools && (o.preventDefault(), (s = this.popover) == null || s.activateItemByName(e)); + }, + /** + * We need to bind shortcut to the document to make it work in read-only mode + */ + on: document + }); + } + /** + * Inline Tool button clicks + * + * @param tool - Tool's instance + */ + toolClicked(e) { + var o; + const t = b.range; + (o = e.surround) == null || o.call(e, t), this.checkToolsState(); + } + /** + * Check Tools` state by selection + */ + checkToolsState() { + var e; + (e = this.tools) == null || e.forEach((t) => { + var o; + (o = t.checkState) == null || o.call(t, b.get()); + }); + } + /** + * Get inline tools tools + * Tools that has isInline is true + */ + get inlineTools() { + const e = {}; + return Array.from(this.Editor.Tools.inlineTools.entries()).forEach(([t, o]) => { + e[t] = o.create(); + }), e; + } +} +function dn() { + const n = window.getSelection(); + if (n === null) + return [null, 0]; + let e = n.focusNode, t = n.focusOffset; + return e === null ? [null, 0] : (e.nodeType !== Node.TEXT_NODE && e.childNodes.length > 0 && (e.childNodes[t] ? (e = e.childNodes[t], t = 0) : (e = e.childNodes[t - 1], t = e.textContent.length)), [e, t]); +} +function un(n, e, t, o) { + const i = document.createRange(); + o === "left" ? (i.setStart(n, 0), i.setEnd(e, t)) : (i.setStart(e, t), i.setEnd(n, n.childNodes.length)); + const s = i.cloneContents(), r = document.createElement("div"); + r.appendChild(s); + const a = r.textContent || ""; + return ai(a); +} +function Ne(n) { + const e = u.getDeepestNode(n); + if (e === null || u.isEmpty(n)) + return !0; + if (u.isNativeInput(e)) + return e.selectionEnd === 0; + if (u.isEmpty(n)) + return !0; + const [t, o] = dn(); + return t === null ? !1 : un(n, t, o, "left"); +} +function Re(n) { + const e = u.getDeepestNode(n, !0); + if (e === null) + return !0; + if (u.isNativeInput(e)) + return e.selectionEnd === e.value.length; + const [t, o] = dn(); + return t === null ? !1 : un(n, t, o, "right"); +} +var hn = {}, St = {}, Xe = {}, de = {}, It = {}, Ot = {}; +Object.defineProperty(Ot, "__esModule", { value: !0 }); +Ot.allInputsSelector = Ts; +function Ts() { + var n = ["text", "password", "email", "number", "search", "tel", "url"]; + return "[contenteditable=true], textarea, input:not([type]), " + n.map(function(e) { + return 'input[type="'.concat(e, '"]'); + }).join(", "); +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.allInputsSelector = void 0; + var e = Ot; + Object.defineProperty(n, "allInputsSelector", { enumerable: !0, get: function() { + return e.allInputsSelector; + } }); +})(It); +var ue = {}, _t = {}; +Object.defineProperty(_t, "__esModule", { value: !0 }); +_t.isNativeInput = Ss; +function Ss(n) { + var e = [ + "INPUT", + "TEXTAREA" + ]; + return n && n.tagName ? e.includes(n.tagName) : !1; +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.isNativeInput = void 0; + var e = _t; + Object.defineProperty(n, "isNativeInput", { enumerable: !0, get: function() { + return e.isNativeInput; + } }); +})(ue); +var pn = {}, Mt = {}; +Object.defineProperty(Mt, "__esModule", { value: !0 }); +Mt.append = Is; +function Is(n, e) { + Array.isArray(e) ? e.forEach(function(t) { + n.appendChild(t); + }) : n.appendChild(e); +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.append = void 0; + var e = Mt; + Object.defineProperty(n, "append", { enumerable: !0, get: function() { + return e.append; + } }); +})(pn); +var At = {}, Lt = {}; +Object.defineProperty(Lt, "__esModule", { value: !0 }); +Lt.blockElements = Os; +function Os() { + return [ + "address", + "article", + "aside", + "blockquote", + "canvas", + "div", + "dl", + "dt", + "fieldset", + "figcaption", + "figure", + "footer", + "form", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "header", + "hgroup", + "hr", + "li", + "main", + "nav", + "noscript", + "ol", + "output", + "p", + "pre", + "ruby", + "section", + "table", + "tbody", + "thead", + "tr", + "tfoot", + "ul", + "video" + ]; +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.blockElements = void 0; + var e = Lt; + Object.defineProperty(n, "blockElements", { enumerable: !0, get: function() { + return e.blockElements; + } }); +})(At); +var fn = {}, Pt = {}; +Object.defineProperty(Pt, "__esModule", { value: !0 }); +Pt.calculateBaseline = _s; +function _s(n) { + var e = window.getComputedStyle(n), t = parseFloat(e.fontSize), o = parseFloat(e.lineHeight) || t * 1.2, i = parseFloat(e.paddingTop), s = parseFloat(e.borderTopWidth), r = parseFloat(e.marginTop), a = t * 0.8, l = (o - t) / 2, c = r + s + i + l + a; + return c; +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.calculateBaseline = void 0; + var e = Pt; + Object.defineProperty(n, "calculateBaseline", { enumerable: !0, get: function() { + return e.calculateBaseline; + } }); +})(fn); +var gn = {}, Nt = {}, Rt = {}, Dt = {}; +Object.defineProperty(Dt, "__esModule", { value: !0 }); +Dt.isContentEditable = Ms; +function Ms(n) { + return n.contentEditable === "true"; +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.isContentEditable = void 0; + var e = Dt; + Object.defineProperty(n, "isContentEditable", { enumerable: !0, get: function() { + return e.isContentEditable; + } }); +})(Rt); +Object.defineProperty(Nt, "__esModule", { value: !0 }); +Nt.canSetCaret = Ps; +var As = ue, Ls = Rt; +function Ps(n) { + var e = !0; + if ((0, As.isNativeInput)(n)) + switch (n.type) { + case "file": + case "checkbox": + case "radio": + case "hidden": + case "submit": + case "button": + case "image": + case "reset": + e = !1; + break; + } + else + e = (0, Ls.isContentEditable)(n); + return e; +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.canSetCaret = void 0; + var e = Nt; + Object.defineProperty(n, "canSetCaret", { enumerable: !0, get: function() { + return e.canSetCaret; + } }); +})(gn); +var Ve = {}, Ft = {}; +function Ns(n, e, t) { + const o = t.value !== void 0 ? "value" : "get", i = t[o], s = `#${e}Cache`; + if (t[o] = function(...r) { + return this[s] === void 0 && (this[s] = i.apply(this, r)), this[s]; + }, o === "get" && t.set) { + const r = t.set; + t.set = function(a) { + delete n[s], r.apply(this, a); + }; + } + return t; +} +function mn() { + const n = { + win: !1, + mac: !1, + x11: !1, + linux: !1 + }, e = Object.keys(n).find((t) => window.navigator.appVersion.toLowerCase().indexOf(t) !== -1); + return e !== void 0 && (n[e] = !0), n; +} +function jt(n) { + return n != null && n !== "" && (typeof n != "object" || Object.keys(n).length > 0); +} +function Rs(n) { + return !jt(n); +} +const Ds = () => typeof window < "u" && window.navigator !== null && jt(window.navigator.platform) && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === "MacIntel" && window.navigator.maxTouchPoints > 1); +function Fs(n) { + const e = mn(); + return n = n.replace(/shift/gi, "⇧").replace(/backspace/gi, "⌫").replace(/enter/gi, "⏎").replace(/up/gi, "↑").replace(/left/gi, "→").replace(/down/gi, "↓").replace(/right/gi, "←").replace(/escape/gi, "⎋").replace(/insert/gi, "Ins").replace(/delete/gi, "␡").replace(/\+/gi, "+"), e.mac ? n = n.replace(/ctrl|cmd/gi, "⌘").replace(/alt/gi, "⌥") : n = n.replace(/cmd/gi, "Ctrl").replace(/windows/gi, "WIN"), n; +} +function js(n) { + return n[0].toUpperCase() + n.slice(1); +} +function Hs(n) { + const e = document.createElement("div"); + e.style.position = "absolute", e.style.left = "-999px", e.style.bottom = "-999px", e.innerHTML = n, document.body.appendChild(e); + const t = window.getSelection(), o = document.createRange(); + if (o.selectNode(e), t === null) + throw new Error("Cannot copy text to clipboard"); + t.removeAllRanges(), t.addRange(o), document.execCommand("copy"), document.body.removeChild(e); +} +function $s(n, e, t) { + let o; + return (...i) => { + const s = this, r = () => { + o = void 0, t !== !0 && n.apply(s, i); + }, a = t === !0 && o !== void 0; + window.clearTimeout(o), o = window.setTimeout(r, e), a && n.apply(s, i); + }; +} +function oe(n) { + return Object.prototype.toString.call(n).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); +} +function zs(n) { + return oe(n) === "boolean"; +} +function bn(n) { + return oe(n) === "function" || oe(n) === "asyncfunction"; +} +function Us(n) { + return bn(n) && /^\s*class\s+/.test(n.toString()); +} +function Ws(n) { + return oe(n) === "number"; +} +function De(n) { + return oe(n) === "object"; +} +function Ys(n) { + return Promise.resolve(n) === n; +} +function Ks(n) { + return oe(n) === "string"; +} +function Xs(n) { + return oe(n) === "undefined"; +} +function bt(n, ...e) { + if (!e.length) + return n; + const t = e.shift(); + if (De(n) && De(t)) + for (const o in t) + De(t[o]) ? (n[o] === void 0 && Object.assign(n, { [o]: {} }), bt(n[o], t[o])) : Object.assign(n, { [o]: t[o] }); + return bt(n, ...e); +} +function Vs(n, e, t) { + const o = `«${e}» is deprecated and will be removed in the next major release. Please use the «${t}» instead.`; + n && console.warn(o); +} +function qs(n) { + try { + return new URL(n).href; + } catch { + } + return n.substring(0, 2) === "//" ? window.location.protocol + n : window.location.origin + n; +} +function Zs(n) { + return n > 47 && n < 58 || n === 32 || n === 13 || n === 229 || n > 64 && n < 91 || n > 95 && n < 112 || n > 185 && n < 193 || n > 218 && n < 223; +} +const Gs = { + BACKSPACE: 8, + TAB: 9, + ENTER: 13, + SHIFT: 16, + CTRL: 17, + ALT: 18, + ESC: 27, + SPACE: 32, + LEFT: 37, + UP: 38, + DOWN: 40, + RIGHT: 39, + DELETE: 46, + META: 91, + SLASH: 191 +}, Qs = { + LEFT: 0, + WHEEL: 1, + RIGHT: 2, + BACKWARD: 3, + FORWARD: 4 +}; +let Js = class { + constructor() { + this.completed = Promise.resolve(); + } + /** + * Add new promise to queue + * @param operation - promise should be added to queue + */ + add(e) { + return new Promise((t, o) => { + this.completed = this.completed.then(e).then(t).catch(o); + }); + } +}; +function er(n, e, t = void 0) { + let o, i, s, r = null, a = 0; + t || (t = {}); + const l = function() { + a = t.leading === !1 ? 0 : Date.now(), r = null, s = n.apply(o, i), r === null && (o = i = null); + }; + return function() { + const c = Date.now(); + !a && t.leading === !1 && (a = c); + const d = e - (c - a); + return o = this, i = arguments, d <= 0 || d > e ? (r && (clearTimeout(r), r = null), a = c, s = n.apply(o, i), r === null && (o = i = null)) : !r && t.trailing !== !1 && (r = setTimeout(l, d)), s; + }; +} +const tr = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ + __proto__: null, + PromiseQueue: Js, + beautifyShortcut: Fs, + cacheable: Ns, + capitalize: js, + copyTextToClipboard: Hs, + debounce: $s, + deepMerge: bt, + deprecationAssert: Vs, + getUserOS: mn, + getValidUrl: qs, + isBoolean: zs, + isClass: Us, + isEmpty: Rs, + isFunction: bn, + isIosDevice: Ds, + isNumber: Ws, + isObject: De, + isPrintableKey: Zs, + isPromise: Ys, + isString: Ks, + isUndefined: Xs, + keyCodes: Gs, + mouseButtons: Qs, + notEmpty: jt, + throttle: er, + typeOf: oe +}, Symbol.toStringTag, { value: "Module" })), Ht = /* @__PURE__ */ Xn(tr); +Object.defineProperty(Ft, "__esModule", { value: !0 }); +Ft.containsOnlyInlineElements = ir; +var or = Ht, nr = At; +function ir(n) { + var e; + (0, or.isString)(n) ? (e = document.createElement("div"), e.innerHTML = n) : e = n; + var t = function(o) { + return !(0, nr.blockElements)().includes(o.tagName.toLowerCase()) && Array.from(o.children).every(t); + }; + return Array.from(e.children).every(t); +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.containsOnlyInlineElements = void 0; + var e = Ft; + Object.defineProperty(n, "containsOnlyInlineElements", { enumerable: !0, get: function() { + return e.containsOnlyInlineElements; + } }); +})(Ve); +var vn = {}, $t = {}, qe = {}, zt = {}; +Object.defineProperty(zt, "__esModule", { value: !0 }); +zt.make = sr; +function sr(n, e, t) { + var o; + e === void 0 && (e = null), t === void 0 && (t = {}); + var i = document.createElement(n); + if (Array.isArray(e)) { + var s = e.filter(function(a) { + return a !== void 0; + }); + (o = i.classList).add.apply(o, s); + } else + e !== null && i.classList.add(e); + for (var r in t) + Object.prototype.hasOwnProperty.call(t, r) && (i[r] = t[r]); + return i; +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.make = void 0; + var e = zt; + Object.defineProperty(n, "make", { enumerable: !0, get: function() { + return e.make; + } }); +})(qe); +Object.defineProperty($t, "__esModule", { value: !0 }); +$t.fragmentToString = ar; +var rr = qe; +function ar(n) { + var e = (0, rr.make)("div"); + return e.appendChild(n), e.innerHTML; +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.fragmentToString = void 0; + var e = $t; + Object.defineProperty(n, "fragmentToString", { enumerable: !0, get: function() { + return e.fragmentToString; + } }); +})(vn); +var kn = {}, Ut = {}; +Object.defineProperty(Ut, "__esModule", { value: !0 }); +Ut.getContentLength = cr; +var lr = ue; +function cr(n) { + var e, t; + return (0, lr.isNativeInput)(n) ? n.value.length : n.nodeType === Node.TEXT_NODE ? n.length : (t = (e = n.textContent) === null || e === void 0 ? void 0 : e.length) !== null && t !== void 0 ? t : 0; +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.getContentLength = void 0; + var e = Ut; + Object.defineProperty(n, "getContentLength", { enumerable: !0, get: function() { + return e.getContentLength; + } }); +})(kn); +var Wt = {}, Yt = {}, Io = Ce && Ce.__spreadArray || function(n, e, t) { + if (t || arguments.length === 2) + for (var o = 0, i = e.length, s; o < i; o++) + (s || !(o in e)) && (s || (s = Array.prototype.slice.call(e, 0, o)), s[o] = e[o]); + return n.concat(s || Array.prototype.slice.call(e)); +}; +Object.defineProperty(Yt, "__esModule", { value: !0 }); +Yt.getDeepestBlockElements = yn; +var dr = Ve; +function yn(n) { + return (0, dr.containsOnlyInlineElements)(n) ? [n] : Array.from(n.children).reduce(function(e, t) { + return Io(Io([], e, !0), yn(t), !0); + }, []); +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.getDeepestBlockElements = void 0; + var e = Yt; + Object.defineProperty(n, "getDeepestBlockElements", { enumerable: !0, get: function() { + return e.getDeepestBlockElements; + } }); +})(Wt); +var wn = {}, Kt = {}, Ze = {}, Xt = {}; +Object.defineProperty(Xt, "__esModule", { value: !0 }); +Xt.isLineBreakTag = ur; +function ur(n) { + return [ + "BR", + "WBR" + ].includes(n.tagName); +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.isLineBreakTag = void 0; + var e = Xt; + Object.defineProperty(n, "isLineBreakTag", { enumerable: !0, get: function() { + return e.isLineBreakTag; + } }); +})(Ze); +var Ge = {}, Vt = {}; +Object.defineProperty(Vt, "__esModule", { value: !0 }); +Vt.isSingleTag = hr; +function hr(n) { + return [ + "AREA", + "BASE", + "BR", + "COL", + "COMMAND", + "EMBED", + "HR", + "IMG", + "INPUT", + "KEYGEN", + "LINK", + "META", + "PARAM", + "SOURCE", + "TRACK", + "WBR" + ].includes(n.tagName); +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.isSingleTag = void 0; + var e = Vt; + Object.defineProperty(n, "isSingleTag", { enumerable: !0, get: function() { + return e.isSingleTag; + } }); +})(Ge); +Object.defineProperty(Kt, "__esModule", { value: !0 }); +Kt.getDeepestNode = En; +var pr = ue, fr = Ze, gr = Ge; +function En(n, e) { + e === void 0 && (e = !1); + var t = e ? "lastChild" : "firstChild", o = e ? "previousSibling" : "nextSibling"; + if (n.nodeType === Node.ELEMENT_NODE && n[t]) { + var i = n[t]; + if ((0, gr.isSingleTag)(i) && !(0, pr.isNativeInput)(i) && !(0, fr.isLineBreakTag)(i)) + if (i[o]) + i = i[o]; + else if (i.parentNode !== null && i.parentNode[o]) + i = i.parentNode[o]; + else + return i.parentNode; + return En(i, e); + } + return n; +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.getDeepestNode = void 0; + var e = Kt; + Object.defineProperty(n, "getDeepestNode", { enumerable: !0, get: function() { + return e.getDeepestNode; + } }); +})(wn); +var xn = {}, qt = {}, Me = Ce && Ce.__spreadArray || function(n, e, t) { + if (t || arguments.length === 2) + for (var o = 0, i = e.length, s; o < i; o++) + (s || !(o in e)) && (s || (s = Array.prototype.slice.call(e, 0, o)), s[o] = e[o]); + return n.concat(s || Array.prototype.slice.call(e)); +}; +Object.defineProperty(qt, "__esModule", { value: !0 }); +qt.findAllInputs = yr; +var mr = Ve, br = Wt, vr = It, kr = ue; +function yr(n) { + return Array.from(n.querySelectorAll((0, vr.allInputsSelector)())).reduce(function(e, t) { + return (0, kr.isNativeInput)(t) || (0, mr.containsOnlyInlineElements)(t) ? Me(Me([], e, !0), [t], !1) : Me(Me([], e, !0), (0, br.getDeepestBlockElements)(t), !0); + }, []); +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.findAllInputs = void 0; + var e = qt; + Object.defineProperty(n, "findAllInputs", { enumerable: !0, get: function() { + return e.findAllInputs; + } }); +})(xn); +var Bn = {}, Zt = {}; +Object.defineProperty(Zt, "__esModule", { value: !0 }); +Zt.isCollapsedWhitespaces = wr; +function wr(n) { + return !/[^\t\n\r ]/.test(n); +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.isCollapsedWhitespaces = void 0; + var e = Zt; + Object.defineProperty(n, "isCollapsedWhitespaces", { enumerable: !0, get: function() { + return e.isCollapsedWhitespaces; + } }); +})(Bn); +var Gt = {}, Qt = {}; +Object.defineProperty(Qt, "__esModule", { value: !0 }); +Qt.isElement = xr; +var Er = Ht; +function xr(n) { + return (0, Er.isNumber)(n) ? !1 : !!n && !!n.nodeType && n.nodeType === Node.ELEMENT_NODE; +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.isElement = void 0; + var e = Qt; + Object.defineProperty(n, "isElement", { enumerable: !0, get: function() { + return e.isElement; + } }); +})(Gt); +var Cn = {}, Jt = {}, eo = {}, to = {}; +Object.defineProperty(to, "__esModule", { value: !0 }); +to.isLeaf = Br; +function Br(n) { + return n === null ? !1 : n.childNodes.length === 0; +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.isLeaf = void 0; + var e = to; + Object.defineProperty(n, "isLeaf", { enumerable: !0, get: function() { + return e.isLeaf; + } }); +})(eo); +var oo = {}, no = {}; +Object.defineProperty(no, "__esModule", { value: !0 }); +no.isNodeEmpty = Or; +var Cr = Ze, Tr = Gt, Sr = ue, Ir = Ge; +function Or(n, e) { + var t = ""; + return (0, Ir.isSingleTag)(n) && !(0, Cr.isLineBreakTag)(n) ? !1 : ((0, Tr.isElement)(n) && (0, Sr.isNativeInput)(n) ? t = n.value : n.textContent !== null && (t = n.textContent.replace("​", "")), e !== void 0 && (t = t.replace(new RegExp(e, "g"), "")), t.trim().length === 0); +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.isNodeEmpty = void 0; + var e = no; + Object.defineProperty(n, "isNodeEmpty", { enumerable: !0, get: function() { + return e.isNodeEmpty; + } }); +})(oo); +Object.defineProperty(Jt, "__esModule", { value: !0 }); +Jt.isEmpty = Ar; +var _r = eo, Mr = oo; +function Ar(n, e) { + n.normalize(); + for (var t = [n]; t.length > 0; ) { + var o = t.shift(); + if (o) { + if (n = o, (0, _r.isLeaf)(n) && !(0, Mr.isNodeEmpty)(n, e)) + return !1; + t.push.apply(t, Array.from(n.childNodes)); + } + } + return !0; +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.isEmpty = void 0; + var e = Jt; + Object.defineProperty(n, "isEmpty", { enumerable: !0, get: function() { + return e.isEmpty; + } }); +})(Cn); +var Tn = {}, io = {}; +Object.defineProperty(io, "__esModule", { value: !0 }); +io.isFragment = Pr; +var Lr = Ht; +function Pr(n) { + return (0, Lr.isNumber)(n) ? !1 : !!n && !!n.nodeType && n.nodeType === Node.DOCUMENT_FRAGMENT_NODE; +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.isFragment = void 0; + var e = io; + Object.defineProperty(n, "isFragment", { enumerable: !0, get: function() { + return e.isFragment; + } }); +})(Tn); +var Sn = {}, so = {}; +Object.defineProperty(so, "__esModule", { value: !0 }); +so.isHTMLString = Rr; +var Nr = qe; +function Rr(n) { + var e = (0, Nr.make)("div"); + return e.innerHTML = n, e.childElementCount > 0; +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.isHTMLString = void 0; + var e = so; + Object.defineProperty(n, "isHTMLString", { enumerable: !0, get: function() { + return e.isHTMLString; + } }); +})(Sn); +var In = {}, ro = {}; +Object.defineProperty(ro, "__esModule", { value: !0 }); +ro.offset = Dr; +function Dr(n) { + var e = n.getBoundingClientRect(), t = window.pageXOffset || document.documentElement.scrollLeft, o = window.pageYOffset || document.documentElement.scrollTop, i = e.top + o, s = e.left + t; + return { + top: i, + left: s, + bottom: i + e.height, + right: s + e.width + }; +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.offset = void 0; + var e = ro; + Object.defineProperty(n, "offset", { enumerable: !0, get: function() { + return e.offset; + } }); +})(In); +var On = {}, ao = {}; +Object.defineProperty(ao, "__esModule", { value: !0 }); +ao.prepend = Fr; +function Fr(n, e) { + Array.isArray(e) ? (e = e.reverse(), e.forEach(function(t) { + return n.prepend(t); + })) : n.prepend(e); +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.prepend = void 0; + var e = ao; + Object.defineProperty(n, "prepend", { enumerable: !0, get: function() { + return e.prepend; + } }); +})(On); +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.prepend = n.offset = n.make = n.isLineBreakTag = n.isSingleTag = n.isNodeEmpty = n.isLeaf = n.isHTMLString = n.isFragment = n.isEmpty = n.isElement = n.isContentEditable = n.isCollapsedWhitespaces = n.findAllInputs = n.isNativeInput = n.allInputsSelector = n.getDeepestNode = n.getDeepestBlockElements = n.getContentLength = n.fragmentToString = n.containsOnlyInlineElements = n.canSetCaret = n.calculateBaseline = n.blockElements = n.append = void 0; + var e = It; + Object.defineProperty(n, "allInputsSelector", { enumerable: !0, get: function() { + return e.allInputsSelector; + } }); + var t = ue; + Object.defineProperty(n, "isNativeInput", { enumerable: !0, get: function() { + return t.isNativeInput; + } }); + var o = pn; + Object.defineProperty(n, "append", { enumerable: !0, get: function() { + return o.append; + } }); + var i = At; + Object.defineProperty(n, "blockElements", { enumerable: !0, get: function() { + return i.blockElements; + } }); + var s = fn; + Object.defineProperty(n, "calculateBaseline", { enumerable: !0, get: function() { + return s.calculateBaseline; + } }); + var r = gn; + Object.defineProperty(n, "canSetCaret", { enumerable: !0, get: function() { + return r.canSetCaret; + } }); + var a = Ve; + Object.defineProperty(n, "containsOnlyInlineElements", { enumerable: !0, get: function() { + return a.containsOnlyInlineElements; + } }); + var l = vn; + Object.defineProperty(n, "fragmentToString", { enumerable: !0, get: function() { + return l.fragmentToString; + } }); + var c = kn; + Object.defineProperty(n, "getContentLength", { enumerable: !0, get: function() { + return c.getContentLength; + } }); + var d = Wt; + Object.defineProperty(n, "getDeepestBlockElements", { enumerable: !0, get: function() { + return d.getDeepestBlockElements; + } }); + var h = wn; + Object.defineProperty(n, "getDeepestNode", { enumerable: !0, get: function() { + return h.getDeepestNode; + } }); + var p = xn; + Object.defineProperty(n, "findAllInputs", { enumerable: !0, get: function() { + return p.findAllInputs; + } }); + var g = Bn; + Object.defineProperty(n, "isCollapsedWhitespaces", { enumerable: !0, get: function() { + return g.isCollapsedWhitespaces; + } }); + var f = Rt; + Object.defineProperty(n, "isContentEditable", { enumerable: !0, get: function() { + return f.isContentEditable; + } }); + var v = Gt; + Object.defineProperty(n, "isElement", { enumerable: !0, get: function() { + return v.isElement; + } }); + var O = Cn; + Object.defineProperty(n, "isEmpty", { enumerable: !0, get: function() { + return O.isEmpty; + } }); + var T = Tn; + Object.defineProperty(n, "isFragment", { enumerable: !0, get: function() { + return T.isFragment; + } }); + var M = Sn; + Object.defineProperty(n, "isHTMLString", { enumerable: !0, get: function() { + return M.isHTMLString; + } }); + var q = eo; + Object.defineProperty(n, "isLeaf", { enumerable: !0, get: function() { + return q.isLeaf; + } }); + var F = oo; + Object.defineProperty(n, "isNodeEmpty", { enumerable: !0, get: function() { + return F.isNodeEmpty; + } }); + var H = Ze; + Object.defineProperty(n, "isLineBreakTag", { enumerable: !0, get: function() { + return H.isLineBreakTag; + } }); + var Q = Ge; + Object.defineProperty(n, "isSingleTag", { enumerable: !0, get: function() { + return Q.isSingleTag; + } }); + var ie = qe; + Object.defineProperty(n, "make", { enumerable: !0, get: function() { + return ie.make; + } }); + var k = In; + Object.defineProperty(n, "offset", { enumerable: !0, get: function() { + return k.offset; + } }); + var m = On; + Object.defineProperty(n, "prepend", { enumerable: !0, get: function() { + return m.prepend; + } }); +})(de); +var Qe = {}; +Object.defineProperty(Qe, "__esModule", { value: !0 }); +Qe.getContenteditableSlice = Hr; +var jr = de; +function Hr(n, e, t, o, i) { + var s; + i === void 0 && (i = !1); + var r = document.createRange(); + if (o === "left" ? (r.setStart(n, 0), r.setEnd(e, t)) : (r.setStart(e, t), r.setEnd(n, n.childNodes.length)), i === !0) { + var a = r.extractContents(); + return (0, jr.fragmentToString)(a); + } + var l = r.cloneContents(), c = document.createElement("div"); + c.appendChild(l); + var d = (s = c.textContent) !== null && s !== void 0 ? s : ""; + return d; +} +Object.defineProperty(Xe, "__esModule", { value: !0 }); +Xe.checkContenteditableSliceForEmptiness = Ur; +var $r = de, zr = Qe; +function Ur(n, e, t, o) { + var i = (0, zr.getContenteditableSlice)(n, e, t, o); + return (0, $r.isCollapsedWhitespaces)(i); +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.checkContenteditableSliceForEmptiness = void 0; + var e = Xe; + Object.defineProperty(n, "checkContenteditableSliceForEmptiness", { enumerable: !0, get: function() { + return e.checkContenteditableSliceForEmptiness; + } }); +})(St); +var _n = {}; +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.getContenteditableSlice = void 0; + var e = Qe; + Object.defineProperty(n, "getContenteditableSlice", { enumerable: !0, get: function() { + return e.getContenteditableSlice; + } }); +})(_n); +var Mn = {}, lo = {}; +Object.defineProperty(lo, "__esModule", { value: !0 }); +lo.focus = Yr; +var Wr = de; +function Yr(n, e) { + var t, o; + if (e === void 0 && (e = !0), (0, Wr.isNativeInput)(n)) { + n.focus(); + var i = e ? 0 : n.value.length; + n.setSelectionRange(i, i); + } else { + var s = document.createRange(), r = window.getSelection(); + if (!r) + return; + var a = function(p) { + var g = document.createTextNode(""); + p.appendChild(g), s.setStart(g, 0), s.setEnd(g, 0); + }, l = function(p) { + return p != null; + }, c = n.childNodes, d = e ? c[0] : c[c.length - 1]; + if (l(d)) { + for (; l(d) && d.nodeType !== Node.TEXT_NODE; ) + d = e ? d.firstChild : d.lastChild; + if (l(d) && d.nodeType === Node.TEXT_NODE) { + var h = (o = (t = d.textContent) === null || t === void 0 ? void 0 : t.length) !== null && o !== void 0 ? o : 0, i = e ? 0 : h; + s.setStart(d, i), s.setEnd(d, i); + } else + a(n); + } else + a(n); + r.removeAllRanges(), r.addRange(s); + } +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.focus = void 0; + var e = lo; + Object.defineProperty(n, "focus", { enumerable: !0, get: function() { + return e.focus; + } }); +})(Mn); +var co = {}, Je = {}; +Object.defineProperty(Je, "__esModule", { value: !0 }); +Je.getCaretNodeAndOffset = Kr; +function Kr() { + var n = window.getSelection(); + if (n === null) + return [null, 0]; + var e = n.focusNode, t = n.focusOffset; + return e === null ? [null, 0] : (e.nodeType !== Node.TEXT_NODE && e.childNodes.length > 0 && (e.childNodes[t] !== void 0 ? (e = e.childNodes[t], t = 0) : (e = e.childNodes[t - 1], e.textContent !== null && (t = e.textContent.length))), [e, t]); +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.getCaretNodeAndOffset = void 0; + var e = Je; + Object.defineProperty(n, "getCaretNodeAndOffset", { enumerable: !0, get: function() { + return e.getCaretNodeAndOffset; + } }); +})(co); +var An = {}, et = {}; +Object.defineProperty(et, "__esModule", { value: !0 }); +et.getRange = Xr; +function Xr() { + var n = window.getSelection(); + return n && n.rangeCount ? n.getRangeAt(0) : null; +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.getRange = void 0; + var e = et; + Object.defineProperty(n, "getRange", { enumerable: !0, get: function() { + return e.getRange; + } }); +})(An); +var Ln = {}, uo = {}; +Object.defineProperty(uo, "__esModule", { value: !0 }); +uo.isCaretAtEndOfInput = Zr; +var Oo = de, Vr = co, qr = St; +function Zr(n) { + var e = (0, Oo.getDeepestNode)(n, !0); + if (e === null) + return !0; + if ((0, Oo.isNativeInput)(e)) + return e.selectionEnd === e.value.length; + var t = (0, Vr.getCaretNodeAndOffset)(), o = t[0], i = t[1]; + return o === null ? !1 : (0, qr.checkContenteditableSliceForEmptiness)(n, o, i, "right"); +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.isCaretAtEndOfInput = void 0; + var e = uo; + Object.defineProperty(n, "isCaretAtEndOfInput", { enumerable: !0, get: function() { + return e.isCaretAtEndOfInput; + } }); +})(Ln); +var Pn = {}, ho = {}; +Object.defineProperty(ho, "__esModule", { value: !0 }); +ho.isCaretAtStartOfInput = Jr; +var Ae = de, Gr = Je, Qr = Xe; +function Jr(n) { + var e = (0, Ae.getDeepestNode)(n); + if (e === null || (0, Ae.isEmpty)(n)) + return !0; + if ((0, Ae.isNativeInput)(e)) + return e.selectionEnd === 0; + if ((0, Ae.isEmpty)(n)) + return !0; + var t = (0, Gr.getCaretNodeAndOffset)(), o = t[0], i = t[1]; + return o === null ? !1 : (0, Qr.checkContenteditableSliceForEmptiness)(n, o, i, "left"); +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.isCaretAtStartOfInput = void 0; + var e = ho; + Object.defineProperty(n, "isCaretAtStartOfInput", { enumerable: !0, get: function() { + return e.isCaretAtStartOfInput; + } }); +})(Pn); +var Nn = {}, po = {}; +Object.defineProperty(po, "__esModule", { value: !0 }); +po.save = oa; +var ea = de, ta = et; +function oa() { + var n = (0, ta.getRange)(), e = (0, ea.make)("span"); + if (e.id = "cursor", e.hidden = !0, !!n) + return n.insertNode(e), function() { + var o = window.getSelection(); + o && (n.setStartAfter(e), n.setEndAfter(e), o.removeAllRanges(), o.addRange(n), setTimeout(function() { + e.remove(); + }, 150)); + }; +} +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.save = void 0; + var e = po; + Object.defineProperty(n, "save", { enumerable: !0, get: function() { + return e.save; + } }); +})(Nn); +(function(n) { + Object.defineProperty(n, "__esModule", { value: !0 }), n.save = n.isCaretAtStartOfInput = n.isCaretAtEndOfInput = n.getRange = n.getCaretNodeAndOffset = n.focus = n.getContenteditableSlice = n.checkContenteditableSliceForEmptiness = void 0; + var e = St; + Object.defineProperty(n, "checkContenteditableSliceForEmptiness", { enumerable: !0, get: function() { + return e.checkContenteditableSliceForEmptiness; + } }); + var t = _n; + Object.defineProperty(n, "getContenteditableSlice", { enumerable: !0, get: function() { + return t.getContenteditableSlice; + } }); + var o = Mn; + Object.defineProperty(n, "focus", { enumerable: !0, get: function() { + return o.focus; + } }); + var i = co; + Object.defineProperty(n, "getCaretNodeAndOffset", { enumerable: !0, get: function() { + return i.getCaretNodeAndOffset; + } }); + var s = An; + Object.defineProperty(n, "getRange", { enumerable: !0, get: function() { + return s.getRange; + } }); + var r = Ln; + Object.defineProperty(n, "isCaretAtEndOfInput", { enumerable: !0, get: function() { + return r.isCaretAtEndOfInput; + } }); + var a = Pn; + Object.defineProperty(n, "isCaretAtStartOfInput", { enumerable: !0, get: function() { + return a.isCaretAtStartOfInput; + } }); + var l = Nn; + Object.defineProperty(n, "save", { enumerable: !0, get: function() { + return l.save; + } }); +})(hn); +class na extends E { + /** + * All keydowns on Block + * + * @param {KeyboardEvent} event - keydown + */ + keydown(e) { + switch (this.beforeKeydownProcessing(e), e.keyCode) { + case y.BACKSPACE: + this.backspace(e); + break; + case y.DELETE: + this.delete(e); + break; + case y.ENTER: + this.enter(e); + break; + case y.DOWN: + case y.RIGHT: + this.arrowRightAndDown(e); + break; + case y.UP: + case y.LEFT: + this.arrowLeftAndUp(e); + break; + case y.TAB: + this.tabPressed(e); + break; + } + e.key === "/" && !e.ctrlKey && !e.metaKey && this.slashPressed(e), e.code === "Slash" && (e.ctrlKey || e.metaKey) && (e.preventDefault(), this.commandSlashPressed()); + } + /** + * Fires on keydown before event processing + * + * @param {KeyboardEvent} event - keydown + */ + beforeKeydownProcessing(e) { + this.needToolbarClosing(e) && Po(e.keyCode) && (this.Editor.Toolbar.close(), e.ctrlKey || e.metaKey || e.altKey || e.shiftKey || this.Editor.BlockSelection.clearSelection(e)); + } + /** + * Key up on Block: + * - shows Inline Toolbar if something selected + * - shows conversion toolbar with 85% of block selection + * + * @param {KeyboardEvent} event - keyup event + */ + keyup(e) { + e.shiftKey || this.Editor.UI.checkEmptiness(); + } + /** + * Add drop target styles + * + * @param {DragEvent} event - drag over event + */ + dragOver(e) { + const t = this.Editor.BlockManager.getBlockByChildNode(e.target); + t.dropTarget = !0; + } + /** + * Remove drop target style + * + * @param {DragEvent} event - drag leave event + */ + dragLeave(e) { + const t = this.Editor.BlockManager.getBlockByChildNode(e.target); + t.dropTarget = !1; + } + /** + * Copying selected blocks + * Before putting to the clipboard we sanitize all blocks and then copy to the clipboard + * + * @param {ClipboardEvent} event - clipboard event + */ + handleCommandC(e) { + const { BlockSelection: t } = this.Editor; + t.anyBlockSelected && t.copySelectedBlocks(e); + } + /** + * Copy and Delete selected Blocks + * + * @param {ClipboardEvent} event - clipboard event + */ + handleCommandX(e) { + const { BlockSelection: t, BlockManager: o, Caret: i } = this.Editor; + t.anyBlockSelected && t.copySelectedBlocks(e).then(() => { + const s = o.removeSelectedBlocks(), r = o.insertDefaultBlockAtIndex(s, !0); + i.setToBlock(r, i.positions.START), t.clearSelection(e); + }); + } + /** + * Tab pressed inside a Block. + * + * @param {KeyboardEvent} event - keydown + */ + tabPressed(e) { + const { InlineToolbar: t, Caret: o } = this.Editor; + if (t.opened) + return; + (e.shiftKey ? o.navigatePrevious(!0) : o.navigateNext(!0)) && e.preventDefault(); + } + /** + * '/' + 'command' keydown inside a Block + */ + commandSlashPressed() { + this.Editor.BlockSelection.selectedBlocks.length > 1 || this.activateBlockSettings(); + } + /** + * '/' keydown inside a Block + * + * @param event - keydown + */ + slashPressed(e) { + !this.Editor.UI.nodes.wrapper.contains(e.target) || !this.Editor.BlockManager.currentBlock.isEmpty || (e.preventDefault(), this.Editor.Caret.insertContentAtCaretPosition("/"), this.activateToolbox()); + } + /** + * ENTER pressed on block + * + * @param {KeyboardEvent} event - keydown + */ + enter(e) { + const { BlockManager: t, UI: o } = this.Editor, i = t.currentBlock; + if (i === void 0 || i.tool.isLineBreaksEnabled || o.someToolbarOpened && o.someFlipperButtonFocused || e.shiftKey && !pt) + return; + let s = i; + i.currentInput !== void 0 && Ne(i.currentInput) && !i.hasMedia ? this.Editor.BlockManager.insertDefaultBlockAtIndex(this.Editor.BlockManager.currentBlockIndex) : i.currentInput && Re(i.currentInput) ? s = this.Editor.BlockManager.insertDefaultBlockAtIndex(this.Editor.BlockManager.currentBlockIndex + 1) : s = this.Editor.BlockManager.split(), this.Editor.Caret.setToBlock(s), this.Editor.Toolbar.moveAndOpen(s), e.preventDefault(); + } + /** + * Handle backspace keydown on Block + * + * @param {KeyboardEvent} event - keydown + */ + backspace(e) { + const { BlockManager: t, Caret: o } = this.Editor, { currentBlock: i, previousBlock: s } = t; + if (i === void 0 || !b.isCollapsed || !i.currentInput || !Ne(i.currentInput)) + return; + if (e.preventDefault(), this.Editor.Toolbar.close(), !(i.currentInput === i.firstInput)) { + o.navigatePrevious(); + return; + } + if (s === null) + return; + if (s.isEmpty) { + t.removeBlock(s); + return; + } + if (i.isEmpty) { + t.removeBlock(i); + const l = t.currentBlock; + o.setToBlock(l, o.positions.END); + return; + } + xo(s, i) ? this.mergeBlocks(s, i) : o.setToBlock(s, o.positions.END); + } + /** + * Handles delete keydown on Block + * Removes char after the caret. + * If caret is at the end of the block, merge next block with current + * + * @param {KeyboardEvent} event - keydown + */ + delete(e) { + const { BlockManager: t, Caret: o } = this.Editor, { currentBlock: i, nextBlock: s } = t; + if (!b.isCollapsed || !Re(i.currentInput)) + return; + if (e.preventDefault(), this.Editor.Toolbar.close(), !(i.currentInput === i.lastInput)) { + o.navigateNext(); + return; + } + if (s === null) + return; + if (s.isEmpty) { + t.removeBlock(s); + return; + } + if (i.isEmpty) { + t.removeBlock(i), o.setToBlock(s, o.positions.START); + return; + } + xo(i, s) ? this.mergeBlocks(i, s) : o.setToBlock(s, o.positions.START); + } + /** + * Merge passed Blocks + * + * @param targetBlock - to which Block we want to merge + * @param blockToMerge - what Block we want to merge + */ + mergeBlocks(e, t) { + const { BlockManager: o, Toolbar: i } = this.Editor; + e.lastInput !== void 0 && (hn.focus(e.lastInput, !1), o.mergeBlocks(e, t).then(() => { + i.close(); + })); + } + /** + * Handle right and down keyboard keys + * + * @param {KeyboardEvent} event - keyboard event + */ + arrowRightAndDown(e) { + const t = ce.usedKeys.includes(e.keyCode) && (!e.shiftKey || e.keyCode === y.TAB); + if (this.Editor.UI.someToolbarOpened && t) + return; + this.Editor.Toolbar.close(); + const { currentBlock: o } = this.Editor.BlockManager, s = ((o == null ? void 0 : o.currentInput) !== void 0 ? Re(o.currentInput) : void 0) || this.Editor.BlockSelection.anyBlockSelected; + if (e.shiftKey && e.keyCode === y.DOWN && s) { + this.Editor.CrossBlockSelection.toggleBlockSelectedState(); + return; + } + if (e.keyCode === y.DOWN || e.keyCode === y.RIGHT && !this.isRtl ? this.Editor.Caret.navigateNext() : this.Editor.Caret.navigatePrevious()) { + e.preventDefault(); + return; + } + Fe(() => { + this.Editor.BlockManager.currentBlock && this.Editor.BlockManager.currentBlock.updateCurrentInput(); + }, 20)(), this.Editor.BlockSelection.clearSelection(e); + } + /** + * Handle left and up keyboard keys + * + * @param {KeyboardEvent} event - keyboard event + */ + arrowLeftAndUp(e) { + if (this.Editor.UI.someToolbarOpened) { + if (ce.usedKeys.includes(e.keyCode) && (!e.shiftKey || e.keyCode === y.TAB)) + return; + this.Editor.UI.closeAllToolbars(); + } + this.Editor.Toolbar.close(); + const { currentBlock: t } = this.Editor.BlockManager, i = ((t == null ? void 0 : t.currentInput) !== void 0 ? Ne(t.currentInput) : void 0) || this.Editor.BlockSelection.anyBlockSelected; + if (e.shiftKey && e.keyCode === y.UP && i) { + this.Editor.CrossBlockSelection.toggleBlockSelectedState(!1); + return; + } + if (e.keyCode === y.UP || e.keyCode === y.LEFT && !this.isRtl ? this.Editor.Caret.navigatePrevious() : this.Editor.Caret.navigateNext()) { + e.preventDefault(); + return; + } + Fe(() => { + this.Editor.BlockManager.currentBlock && this.Editor.BlockManager.currentBlock.updateCurrentInput(); + }, 20)(), this.Editor.BlockSelection.clearSelection(e); + } + /** + * Cases when we need to close Toolbar + * + * @param {KeyboardEvent} event - keyboard event + */ + needToolbarClosing(e) { + const t = e.keyCode === y.ENTER && this.Editor.Toolbar.toolbox.opened, o = e.keyCode === y.ENTER && this.Editor.BlockSettings.opened, i = e.keyCode === y.ENTER && this.Editor.InlineToolbar.opened, s = e.keyCode === y.TAB; + return !(e.shiftKey || s || t || o || i); + } + /** + * If Toolbox is not open, then just open it and show plus button + */ + activateToolbox() { + this.Editor.Toolbar.opened || this.Editor.Toolbar.moveAndOpen(), this.Editor.Toolbar.toolbox.open(); + } + /** + * Open Toolbar and show BlockSettings before flipping Tools + */ + activateBlockSettings() { + this.Editor.Toolbar.opened || this.Editor.Toolbar.moveAndOpen(), this.Editor.BlockSettings.opened || this.Editor.BlockSettings.open(); + } +} +class ct { + /** + * @class + * @param {HTMLElement} workingArea — editor`s working node + */ + constructor(e) { + this.blocks = [], this.workingArea = e; + } + /** + * Get length of Block instances array + * + * @returns {number} + */ + get length() { + return this.blocks.length; + } + /** + * Get Block instances array + * + * @returns {Block[]} + */ + get array() { + return this.blocks; + } + /** + * Get blocks html elements array + * + * @returns {HTMLElement[]} + */ + get nodes() { + return No(this.workingArea.children); + } + /** + * Proxy trap to implement array-like setter + * + * @example + * blocks[0] = new Block(...) + * @param {Blocks} instance — Blocks instance + * @param {PropertyKey} property — block index or any Blocks class property key to set + * @param {Block} value — value to set + * @returns {boolean} + */ + static set(e, t, o) { + return isNaN(Number(t)) ? (Reflect.set(e, t, o), !0) : (e.insert(+t, o), !0); + } + /** + * Proxy trap to implement array-like getter + * + * @param {Blocks} instance — Blocks instance + * @param {PropertyKey} property — Blocks class property key + * @returns {Block|*} + */ + static get(e, t) { + return isNaN(Number(t)) ? Reflect.get(e, t) : e.get(+t); + } + /** + * Push new Block to the blocks array and append it to working area + * + * @param {Block} block - Block to add + */ + push(e) { + this.blocks.push(e), this.insertToDOM(e); + } + /** + * Swaps blocks with indexes first and second + * + * @param {number} first - first block index + * @param {number} second - second block index + * @deprecated — use 'move' instead + */ + swap(e, t) { + const o = this.blocks[t]; + u.swap(this.blocks[e].holder, o.holder), this.blocks[t] = this.blocks[e], this.blocks[e] = o; + } + /** + * Move a block from one to another index + * + * @param {number} toIndex - new index of the block + * @param {number} fromIndex - block to move + */ + move(e, t) { + const o = this.blocks.splice(t, 1)[0], i = e - 1, s = Math.max(0, i), r = this.blocks[s]; + e > 0 ? this.insertToDOM(o, "afterend", r) : this.insertToDOM(o, "beforebegin", r), this.blocks.splice(e, 0, o); + const a = this.composeBlockEvent("move", { + fromIndex: t, + toIndex: e + }); + o.call(ee.MOVED, a); + } + /** + * Insert new Block at passed index + * + * @param {number} index — index to insert Block + * @param {Block} block — Block to insert + * @param {boolean} replace — it true, replace block on given index + */ + insert(e, t, o = !1) { + if (!this.length) { + this.push(t); + return; + } + e > this.length && (e = this.length), o && (this.blocks[e].holder.remove(), this.blocks[e].call(ee.REMOVED)); + const i = o ? 1 : 0; + if (this.blocks.splice(e, i, t), e > 0) { + const s = this.blocks[e - 1]; + this.insertToDOM(t, "afterend", s); + } else { + const s = this.blocks[e + 1]; + s ? this.insertToDOM(t, "beforebegin", s) : this.insertToDOM(t); + } + } + /** + * Replaces block under passed index with passed block + * + * @param index - index of existed block + * @param block - new block + */ + replace(e, t) { + if (this.blocks[e] === void 0) + throw Error("Incorrect index"); + this.blocks[e].holder.replaceWith(t.holder), this.blocks[e] = t; + } + /** + * Inserts several blocks at once + * + * @param blocks - blocks to insert + * @param index - index to insert blocks at + */ + insertMany(e, t) { + const o = new DocumentFragment(); + for (const i of e) + o.appendChild(i.holder); + if (this.length > 0) { + if (t > 0) { + const i = Math.min(t - 1, this.length - 1); + this.blocks[i].holder.after(o); + } else + t === 0 && this.workingArea.prepend(o); + this.blocks.splice(t, 0, ...e); + } else + this.blocks.push(...e), this.workingArea.appendChild(o); + e.forEach((i) => i.call(ee.RENDERED)); + } + /** + * Remove block + * + * @param {number} index - index of Block to remove + */ + remove(e) { + isNaN(e) && (e = this.length - 1), this.blocks[e].holder.remove(), this.blocks[e].call(ee.REMOVED), this.blocks.splice(e, 1); + } + /** + * Remove all blocks + */ + removeAll() { + this.workingArea.innerHTML = "", this.blocks.forEach((e) => e.call(ee.REMOVED)), this.blocks.length = 0; + } + /** + * Insert Block after passed target + * + * @todo decide if this method is necessary + * @param {Block} targetBlock — target after which Block should be inserted + * @param {Block} newBlock — Block to insert + */ + insertAfter(e, t) { + const o = this.blocks.indexOf(e); + this.insert(o + 1, t); + } + /** + * Get Block by index + * + * @param {number} index — Block index + * @returns {Block} + */ + get(e) { + return this.blocks[e]; + } + /** + * Return index of passed Block + * + * @param {Block} block - Block to find + * @returns {number} + */ + indexOf(e) { + return this.blocks.indexOf(e); + } + /** + * Insert new Block into DOM + * + * @param {Block} block - Block to insert + * @param {InsertPosition} position — insert position (if set, will use insertAdjacentElement) + * @param {Block} target — Block related to position + */ + insertToDOM(e, t, o) { + t ? o.holder.insertAdjacentElement(t, e.holder) : this.workingArea.appendChild(e.holder), e.call(ee.RENDERED); + } + /** + * Composes Block event with passed type and details + * + * @param {string} type - event type + * @param {object} detail - event detail + */ + composeBlockEvent(e, t) { + return new CustomEvent(e, { + detail: t + }); + } +} +const _o = "block-removed", Mo = "block-added", ia = "block-moved", Ao = "block-changed"; +class sa { + constructor() { + this.completed = Promise.resolve(); + } + /** + * Add new promise to queue + * + * @param operation - promise should be added to queue + */ + add(e) { + return new Promise((t, o) => { + this.completed = this.completed.then(e).then(t).catch(o); + }); + } +} +class ra extends E { + constructor() { + super(...arguments), this._currentBlockIndex = -1, this._blocks = null; + } + /** + * Returns current Block index + * + * @returns {number} + */ + get currentBlockIndex() { + return this._currentBlockIndex; + } + /** + * Set current Block index and fire Block lifecycle callbacks + * + * @param {number} newIndex - index of Block to set as current + */ + set currentBlockIndex(e) { + this._currentBlockIndex = e; + } + /** + * returns first Block + * + * @returns {Block} + */ + get firstBlock() { + return this._blocks[0]; + } + /** + * returns last Block + * + * @returns {Block} + */ + get lastBlock() { + return this._blocks[this._blocks.length - 1]; + } + /** + * Get current Block instance + * + * @returns {Block} + */ + get currentBlock() { + return this._blocks[this.currentBlockIndex]; + } + /** + * Set passed Block as a current + * + * @param block - block to set as a current + */ + set currentBlock(e) { + this.currentBlockIndex = this.getBlockIndex(e); + } + /** + * Returns next Block instance + * + * @returns {Block|null} + */ + get nextBlock() { + return this.currentBlockIndex === this._blocks.length - 1 ? null : this._blocks[this.currentBlockIndex + 1]; + } + /** + * Return first Block with inputs after current Block + * + * @returns {Block | undefined} + */ + get nextContentfulBlock() { + return this.blocks.slice(this.currentBlockIndex + 1).find((t) => !!t.inputs.length); + } + /** + * Return first Block with inputs before current Block + * + * @returns {Block | undefined} + */ + get previousContentfulBlock() { + return this.blocks.slice(0, this.currentBlockIndex).reverse().find((t) => !!t.inputs.length); + } + /** + * Returns previous Block instance + * + * @returns {Block|null} + */ + get previousBlock() { + return this.currentBlockIndex === 0 ? null : this._blocks[this.currentBlockIndex - 1]; + } + /** + * Get array of Block instances + * + * @returns {Block[]} {@link Blocks#array} + */ + get blocks() { + return this._blocks.array; + } + /** + * Check if each Block is empty + * + * @returns {boolean} + */ + get isEditorEmpty() { + return this.blocks.every((e) => e.isEmpty); + } + /** + * Should be called after Editor.UI preparation + * Define this._blocks property + */ + prepare() { + const e = new ct(this.Editor.UI.nodes.redactor); + this._blocks = new Proxy(e, { + set: ct.set, + get: ct.get + }), this.listeners.on( + document, + "copy", + (t) => this.Editor.BlockEvents.handleCommandC(t) + ); + } + /** + * Toggle read-only state + * + * If readOnly is true: + * - Unbind event handlers from created Blocks + * + * if readOnly is false: + * - Bind event handlers to all existing Blocks + * + * @param {boolean} readOnlyEnabled - "read only" state + */ + toggleReadOnly(e) { + e ? this.disableModuleBindings() : this.enableModuleBindings(); + } + /** + * Creates Block instance by tool name + * + * @param {object} options - block creation options + * @param {string} options.tool - tools passed in editor config {@link EditorConfig#tools} + * @param {string} [options.id] - unique id for this block + * @param {BlockToolData} [options.data] - constructor params + * @returns {Block} + */ + composeBlock({ + tool: e, + data: t = {}, + id: o = void 0, + tunes: i = {} + }) { + const s = this.Editor.ReadOnly.isEnabled, r = this.Editor.Tools.blockTools.get(e), a = new R({ + id: o, + data: t, + tool: r, + api: this.Editor.API, + readOnly: s, + tunesData: i + }, this.eventsDispatcher); + return s || window.requestIdleCallback(() => { + this.bindBlockEvents(a); + }, { timeout: 2e3 }), a; + } + /** + * Insert new block into _blocks + * + * @param {object} options - insert options + * @param {string} [options.id] - block's unique id + * @param {string} [options.tool] - plugin name, by default method inserts the default block type + * @param {object} [options.data] - plugin data + * @param {number} [options.index] - index where to insert new Block + * @param {boolean} [options.needToFocus] - flag shows if needed to update current Block index + * @param {boolean} [options.replace] - flag shows if block by passed index should be replaced with inserted one + * @returns {Block} + */ + insert({ + id: e = void 0, + tool: t = this.config.defaultBlock, + data: o = {}, + index: i, + needToFocus: s = !0, + replace: r = !1, + tunes: a = {} + } = {}) { + let l = i; + l === void 0 && (l = this.currentBlockIndex + (r ? 0 : 1)); + const c = this.composeBlock({ + id: e, + tool: t, + data: o, + tunes: a + }); + return r && this.blockDidMutated(_o, this.getBlockByIndex(l), { + index: l + }), this._blocks.insert(l, c, r), this.blockDidMutated(Mo, c, { + index: l + }), s ? this.currentBlockIndex = l : l <= this.currentBlockIndex && this.currentBlockIndex++, c; + } + /** + * Inserts several blocks at once + * + * @param blocks - blocks to insert + * @param index - index where to insert + */ + insertMany(e, t = 0) { + this._blocks.insertMany(e, t); + } + /** + * Update Block data. + * + * Currently we don't have an 'update' method in the Tools API, so we just create a new block with the same id and type + * Should not trigger 'block-removed' or 'block-added' events. + * + * If neither data nor tunes is provided, return the provided block instead. + * + * @param block - block to update + * @param data - (optional) new data + * @param tunes - (optional) tune data + */ + async update(e, t, o) { + if (!t && !o) + return e; + const i = await e.data, s = this.composeBlock({ + id: e.id, + tool: e.name, + data: Object.assign({}, i, t ?? {}), + tunes: o ?? e.tunes + }), r = this.getBlockIndex(e); + return this._blocks.replace(r, s), this.blockDidMutated(Ao, s, { + index: r + }), s; + } + /** + * Replace passed Block with the new one with specified Tool and data + * + * @param block - block to replace + * @param newTool - new Tool name + * @param data - new Tool data + */ + replace(e, t, o) { + const i = this.getBlockIndex(e); + return this.insert({ + tool: t, + data: o, + index: i, + replace: !0 + }); + } + /** + * Insert pasted content. Call onPaste callback after insert. + * + * @param {string} toolName - name of Tool to insert + * @param {PasteEvent} pasteEvent - pasted data + * @param {boolean} replace - should replace current block + */ + paste(e, t, o = !1) { + const i = this.insert({ + tool: e, + replace: o + }); + try { + window.requestIdleCallback(() => { + i.call(ee.ON_PASTE, t); + }); + } catch (s) { + S(`${e}: onPaste callback call is failed`, "error", s); + } + return i; + } + /** + * Insert new default block at passed index + * + * @param {number} index - index where Block should be inserted + * @param {boolean} needToFocus - if true, updates current Block index + * + * TODO: Remove method and use insert() with index instead (?) + * @returns {Block} inserted Block + */ + insertDefaultBlockAtIndex(e, t = !1) { + const o = this.composeBlock({ tool: this.config.defaultBlock }); + return this._blocks[e] = o, this.blockDidMutated(Mo, o, { + index: e + }), t ? this.currentBlockIndex = e : e <= this.currentBlockIndex && this.currentBlockIndex++, o; + } + /** + * Always inserts at the end + * + * @returns {Block} + */ + insertAtEnd() { + return this.currentBlockIndex = this.blocks.length - 1, this.insert(); + } + /** + * Merge two blocks + * + * @param {Block} targetBlock - previous block will be append to this block + * @param {Block} blockToMerge - block that will be merged with target block + * @returns {Promise} - the sequence that can be continued + */ + async mergeBlocks(e, t) { + let o; + if (e.name === t.name && e.mergeable) { + const i = await t.data; + if (V(i)) { + console.error("Could not merge Block. Failed to extract original Block data."); + return; + } + const [s] = yt([i], e.tool.sanitizeConfig); + o = s; + } else if (e.mergeable && He(t, "export") && He(e, "import")) { + const i = await t.exportDataAsString(), s = Z(i, e.tool.sanitizeConfig); + o = Bo(s, e.tool.conversionConfig); + } + o !== void 0 && (await e.mergeWith(o), this.removeBlock(t), this.currentBlockIndex = this._blocks.indexOf(e)); + } + /** + * Remove passed Block + * + * @param block - Block to remove + * @param addLastBlock - if true, adds new default block at the end. @todo remove this logic and use event-bus instead + */ + removeBlock(e, t = !0) { + return new Promise((o) => { + const i = this._blocks.indexOf(e); + if (!this.validateIndex(i)) + throw new Error("Can't find a Block to remove"); + this._blocks.remove(i), e.destroy(), this.blockDidMutated(_o, e, { + index: i + }), this.currentBlockIndex >= i && this.currentBlockIndex--, this.blocks.length ? i === 0 && (this.currentBlockIndex = 0) : (this.unsetCurrentBlock(), t && this.insert()), o(); + }); + } + /** + * Remove only selected Blocks + * and returns first Block index where started removing... + * + * @returns {number|undefined} + */ + removeSelectedBlocks() { + let e; + for (let t = this.blocks.length - 1; t >= 0; t--) + this.blocks[t].selected && (this.removeBlock(this.blocks[t]), e = t); + return e; + } + /** + * Attention! + * After removing insert the new default typed Block and focus on it + * Removes all blocks + */ + removeAllBlocks() { + for (let e = this.blocks.length - 1; e >= 0; e--) + this._blocks.remove(e); + this.unsetCurrentBlock(), this.insert(), this.currentBlock.firstInput.focus(); + } + /** + * Split current Block + * 1. Extract content from Caret position to the Block`s end + * 2. Insert a new Block below current one with extracted content + * + * @returns {Block} + */ + split() { + const e = this.Editor.Caret.extractFragmentFromCaretPosition(), t = u.make("div"); + t.appendChild(e); + const o = { + text: u.isEmpty(t) ? "" : t.innerHTML + }; + return this.insert({ data: o }); + } + /** + * Returns Block by passed index + * + * @param {number} index - index to get. -1 to get last + * @returns {Block} + */ + getBlockByIndex(e) { + return e === -1 && (e = this._blocks.length - 1), this._blocks[e]; + } + /** + * Returns an index for passed Block + * + * @param block - block to find index + */ + getBlockIndex(e) { + return this._blocks.indexOf(e); + } + /** + * Returns the Block by passed id + * + * @param id - id of block to get + * @returns {Block} + */ + getBlockById(e) { + return this._blocks.array.find((t) => t.id === e); + } + /** + * Get Block instance by html element + * + * @param {Node} element - html element to get Block by + */ + getBlock(e) { + u.isElement(e) || (e = e.parentNode); + const t = this._blocks.nodes, o = e.closest(`.${R.CSS.wrapper}`), i = t.indexOf(o); + if (i >= 0) + return this._blocks[i]; + } + /** + * 1) Find first-level Block from passed child Node + * 2) Mark it as current + * + * @param {Node} childNode - look ahead from this node. + * @returns {Block | undefined} can return undefined in case when the passed child note is not a part of the current editor instance + */ + setCurrentBlockByChildNode(e) { + u.isElement(e) || (e = e.parentNode); + const t = e.closest(`.${R.CSS.wrapper}`); + if (!t) + return; + const o = t.closest(`.${this.Editor.UI.CSS.editorWrapper}`); + if (o != null && o.isEqualNode(this.Editor.UI.nodes.wrapper)) + return this.currentBlockIndex = this._blocks.nodes.indexOf(t), this.currentBlock.updateCurrentInput(), this.currentBlock; + } + /** + * Return block which contents passed node + * + * @param {Node} childNode - node to get Block by + * @returns {Block} + */ + getBlockByChildNode(e) { + if (!e || !(e instanceof Node)) + return; + u.isElement(e) || (e = e.parentNode); + const t = e.closest(`.${R.CSS.wrapper}`); + return this.blocks.find((o) => o.holder === t); + } + /** + * Swap Blocks Position + * + * @param {number} fromIndex - index of first block + * @param {number} toIndex - index of second block + * @deprecated — use 'move' instead + */ + swap(e, t) { + this._blocks.swap(e, t), this.currentBlockIndex = t; + } + /** + * Move a block to a new index + * + * @param {number} toIndex - index where to move Block + * @param {number} fromIndex - index of Block to move + */ + move(e, t = this.currentBlockIndex) { + if (isNaN(e) || isNaN(t)) { + S("Warning during 'move' call: incorrect indices provided.", "warn"); + return; + } + if (!this.validateIndex(e) || !this.validateIndex(t)) { + S("Warning during 'move' call: indices cannot be lower than 0 or greater than the amount of blocks.", "warn"); + return; + } + this._blocks.move(e, t), this.currentBlockIndex = e, this.blockDidMutated(ia, this.currentBlock, { + fromIndex: t, + toIndex: e + }); + } + /** + * Converts passed Block to the new Tool + * Uses Conversion Config + * + * @param blockToConvert - Block that should be converted + * @param targetToolName - name of the Tool to convert to + * @param blockDataOverrides - optional new Block data overrides + */ + async convert(e, t, o) { + if (!await e.save()) + throw new Error("Could not convert Block. Failed to extract original Block data."); + const s = this.Editor.Tools.blockTools.get(t); + if (!s) + throw new Error(`Could not convert Block. Tool «${t}» not found.`); + const r = await e.exportDataAsString(), a = Z( + r, + s.sanitizeConfig + ); + let l = Bo(a, s.conversionConfig, s.settings); + return o && (l = Object.assign(l, o)), this.replace(e, s.name, l); + } + /** + * Sets current Block Index -1 which means unknown + * and clear highlights + */ + unsetCurrentBlock() { + this.currentBlockIndex = -1; + } + /** + * Clears Editor + * + * @param {boolean} needToAddDefaultBlock - 1) in internal calls (for example, in api.blocks.render) + * we don't need to add an empty default block + * 2) in api.blocks.clear we should add empty block + */ + async clear(e = !1) { + const t = new sa(); + [...this.blocks].forEach((i) => { + t.add(async () => { + await this.removeBlock(i, !1); + }); + }), await t.completed, this.unsetCurrentBlock(), e && this.insert(), this.Editor.UI.checkEmptiness(); + } + /** + * Cleans up all the block tools' resources + * This is called when editor is destroyed + */ + async destroy() { + await Promise.all(this.blocks.map((e) => e.destroy())); + } + /** + * Bind Block events + * + * @param {Block} block - Block to which event should be bound + */ + bindBlockEvents(e) { + const { BlockEvents: t } = this.Editor; + this.readOnlyMutableListeners.on(e.holder, "keydown", (o) => { + t.keydown(o); + }), this.readOnlyMutableListeners.on(e.holder, "keyup", (o) => { + t.keyup(o); + }), this.readOnlyMutableListeners.on(e.holder, "dragover", (o) => { + t.dragOver(o); + }), this.readOnlyMutableListeners.on(e.holder, "dragleave", (o) => { + t.dragLeave(o); + }), e.on("didMutated", (o) => this.blockDidMutated(Ao, o, { + index: this.getBlockIndex(o) + })); + } + /** + * Disable mutable handlers and bindings + */ + disableModuleBindings() { + this.readOnlyMutableListeners.clearAll(); + } + /** + * Enables all module handlers and bindings for all Blocks + */ + enableModuleBindings() { + this.readOnlyMutableListeners.on( + document, + "cut", + (e) => this.Editor.BlockEvents.handleCommandX(e) + ), this.blocks.forEach((e) => { + this.bindBlockEvents(e); + }); + } + /** + * Validates that the given index is not lower than 0 or higher than the amount of blocks + * + * @param {number} index - index of blocks array to validate + * @returns {boolean} + */ + validateIndex(e) { + return !(e < 0 || e >= this._blocks.length); + } + /** + * Block mutation callback + * + * @param mutationType - what happened with block + * @param block - mutated block + * @param detailData - additional data to pass with change event + */ + blockDidMutated(e, t, o) { + const i = new CustomEvent(e, { + detail: { + target: new J(t), + ...o + } + }); + return this.eventsDispatcher.emit($o, { + event: i + }), t; + } +} +class aa extends E { + constructor() { + super(...arguments), this.anyBlockSelectedCache = null, this.needToSelectAll = !1, this.nativeInputSelected = !1, this.readyToBlockSelection = !1; + } + /** + * Sanitizer Config + * + * @returns {SanitizerConfig} + */ + get sanitizerConfig() { + return { + p: {}, + h1: {}, + h2: {}, + h3: {}, + h4: {}, + h5: {}, + h6: {}, + ol: {}, + ul: {}, + li: {}, + br: !0, + img: { + src: !0, + width: !0, + height: !0 + }, + a: { + href: !0 + }, + b: {}, + i: {}, + u: {} + }; + } + /** + * Flag that identifies all Blocks selection + * + * @returns {boolean} + */ + get allBlocksSelected() { + const { BlockManager: e } = this.Editor; + return e.blocks.every((t) => t.selected === !0); + } + /** + * Set selected all blocks + * + * @param {boolean} state - state to set + */ + set allBlocksSelected(e) { + const { BlockManager: t } = this.Editor; + t.blocks.forEach((o) => { + o.selected = e; + }), this.clearCache(); + } + /** + * Flag that identifies any Block selection + * + * @returns {boolean} + */ + get anyBlockSelected() { + const { BlockManager: e } = this.Editor; + return this.anyBlockSelectedCache === null && (this.anyBlockSelectedCache = e.blocks.some((t) => t.selected === !0)), this.anyBlockSelectedCache; + } + /** + * Return selected Blocks array + * + * @returns {Block[]} + */ + get selectedBlocks() { + return this.Editor.BlockManager.blocks.filter((e) => e.selected); + } + /** + * Module Preparation + * Registers Shortcuts CMD+A and CMD+C + * to select all and copy them + */ + prepare() { + this.selection = new b(), ge.add({ + name: "CMD+A", + handler: (e) => { + const { BlockManager: t, ReadOnly: o } = this.Editor; + if (o.isEnabled) { + e.preventDefault(), this.selectAllBlocks(); + return; + } + t.currentBlock && this.handleCommandA(e); + }, + on: this.Editor.UI.nodes.redactor + }); + } + /** + * Toggle read-only state + * + * - Remove all ranges + * - Unselect all Blocks + */ + toggleReadOnly() { + b.get().removeAllRanges(), this.allBlocksSelected = !1; + } + /** + * Remove selection of Block + * + * @param {number?} index - Block index according to the BlockManager's indexes + */ + unSelectBlockByIndex(e) { + const { BlockManager: t } = this.Editor; + let o; + isNaN(e) ? o = t.currentBlock : o = t.getBlockByIndex(e), o.selected = !1, this.clearCache(); + } + /** + * Clear selection from Blocks + * + * @param {Event} reason - event caused clear of selection + * @param {boolean} restoreSelection - if true, restore saved selection + */ + clearSelection(e, t = !1) { + const { BlockManager: o, Caret: i, RectangleSelection: s } = this.Editor; + this.needToSelectAll = !1, this.nativeInputSelected = !1, this.readyToBlockSelection = !1; + const r = e && e instanceof KeyboardEvent, a = r && Po(e.keyCode); + if (this.anyBlockSelected && r && a && !b.isSelectionExists) { + const l = o.removeSelectedBlocks(); + o.insertDefaultBlockAtIndex(l, !0), i.setToBlock(o.currentBlock), Fe(() => { + const c = e.key; + i.insertContentAtCaretPosition(c.length > 1 ? "" : c); + }, 20)(); + } + if (this.Editor.CrossBlockSelection.clear(e), !this.anyBlockSelected || s.isRectActivated()) { + this.Editor.RectangleSelection.clearSelection(); + return; + } + t && this.selection.restore(), this.allBlocksSelected = !1; + } + /** + * Reduce each Block and copy its content + * + * @param {ClipboardEvent} e - copy/cut event + * @returns {Promise} + */ + copySelectedBlocks(e) { + e.preventDefault(); + const t = u.make("div"); + this.selectedBlocks.forEach((s) => { + const r = Z(s.holder.innerHTML, this.sanitizerConfig), a = u.make("p"); + a.innerHTML = r, t.appendChild(a); + }); + const o = Array.from(t.childNodes).map((s) => s.textContent).join(` + +`), i = t.innerHTML; + return e.clipboardData.setData("text/plain", o), e.clipboardData.setData("text/html", i), Promise.all(this.selectedBlocks.map((s) => s.save())).then((s) => { + try { + e.clipboardData.setData(this.Editor.Paste.MIME_TYPE, JSON.stringify(s)); + } catch { + } + }); + } + /** + * Select Block by its index + * + * @param {number?} index - Block index according to the BlockManager's indexes + */ + selectBlockByIndex(e) { + const { BlockManager: t } = this.Editor, o = t.getBlockByIndex(e); + o !== void 0 && this.selectBlock(o); + } + /** + * Select passed Block + * + * @param {Block} block - Block to select + */ + selectBlock(e) { + this.selection.save(), b.get().removeAllRanges(), e.selected = !0, this.clearCache(), this.Editor.InlineToolbar.close(); + } + /** + * Remove selection from passed Block + * + * @param {Block} block - Block to unselect + */ + unselectBlock(e) { + e.selected = !1, this.clearCache(); + } + /** + * Clear anyBlockSelected cache + */ + clearCache() { + this.anyBlockSelectedCache = null; + } + /** + * Module destruction + * De-registers Shortcut CMD+A + */ + destroy() { + ge.remove(this.Editor.UI.nodes.redactor, "CMD+A"); + } + /** + * First CMD+A selects all input content by native behaviour, + * next CMD+A keypress selects all blocks + * + * @param {KeyboardEvent} event - keyboard event + */ + handleCommandA(e) { + if (this.Editor.RectangleSelection.clearSelection(), u.isNativeInput(e.target) && !this.readyToBlockSelection) { + this.readyToBlockSelection = !0; + return; + } + const t = this.Editor.BlockManager.getBlock(e.target), o = t.inputs; + if (o.length > 1 && !this.readyToBlockSelection) { + this.readyToBlockSelection = !0; + return; + } + if (o.length === 1 && !this.needToSelectAll) { + this.needToSelectAll = !0; + return; + } + this.needToSelectAll ? (e.preventDefault(), this.selectAllBlocks(), this.needToSelectAll = !1, this.readyToBlockSelection = !1) : this.readyToBlockSelection && (e.preventDefault(), this.selectBlock(t), this.needToSelectAll = !0); + } + /** + * Select All Blocks + * Each Block has selected setter that makes Block copyable + */ + selectAllBlocks() { + this.selection.save(), b.get().removeAllRanges(), this.allBlocksSelected = !0, this.Editor.InlineToolbar.close(); + } +} +class Ye extends E { + /** + * Allowed caret positions in input + * + * @static + * @returns {{START: string, END: string, DEFAULT: string}} + */ + get positions() { + return { + START: "start", + END: "end", + DEFAULT: "default" + }; + } + /** + * Elements styles that can be useful for Caret Module + */ + static get CSS() { + return { + shadowCaret: "cdx-shadow-caret" + }; + } + /** + * Method gets Block instance and puts caret to the text node with offset + * There two ways that method applies caret position: + * - first found text node: sets at the beginning, but you can pass an offset + * - last found text node: sets at the end of the node. Also, you can customize the behaviour + * + * @param {Block} block - Block class + * @param {string} position - position where to set caret. + * If default - leave default behaviour and apply offset if it's passed + * @param {number} offset - caret offset regarding to the block content + */ + setToBlock(e, t = this.positions.DEFAULT, o = 0) { + var c; + const { BlockManager: i, BlockSelection: s } = this.Editor; + if (s.clearSelection(), !e.focusable) { + (c = window.getSelection()) == null || c.removeAllRanges(), s.selectBlock(e), i.currentBlock = e; + return; + } + let r; + switch (t) { + case this.positions.START: + r = e.firstInput; + break; + case this.positions.END: + r = e.lastInput; + break; + default: + r = e.currentInput; + } + if (!r) + return; + let a, l = o; + if (t === this.positions.START) + a = u.getDeepestNode(r, !1), l = 0; + else if (t === this.positions.END) + a = u.getDeepestNode(r, !0), l = u.getContentLength(a); + else { + const { node: d, offset: h } = u.getNodeByOffset(r, o); + d ? (a = d, l = h) : (a = u.getDeepestNode(r, !1), l = 0); + } + this.set(a, l), i.setCurrentBlockByChildNode(e.holder), i.currentBlock.currentInput = r; + } + /** + * Set caret to the current input of current Block. + * + * @param {HTMLElement} input - input where caret should be set + * @param {string} position - position of the caret. + * If default - leave default behaviour and apply offset if it's passed + * @param {number} offset - caret offset regarding to the text node + */ + setToInput(e, t = this.positions.DEFAULT, o = 0) { + const { currentBlock: i } = this.Editor.BlockManager, s = u.getDeepestNode(e); + switch (t) { + case this.positions.START: + this.set(s, 0); + break; + case this.positions.END: + this.set(s, u.getContentLength(s)); + break; + default: + o && this.set(s, o); + } + i.currentInput = e; + } + /** + * Creates Document Range and sets caret to the element with offset + * + * @param {HTMLElement} element - target node. + * @param {number} offset - offset + */ + set(e, t = 0) { + const { top: i, bottom: s } = b.setCursor(e, t), { innerHeight: r } = window; + i < 0 ? window.scrollBy(0, i - 30) : s > r && window.scrollBy(0, s - r + 30); + } + /** + * Set Caret to the last Block + * If last block is not empty, append another empty block + */ + setToTheLastBlock() { + const e = this.Editor.BlockManager.lastBlock; + if (e) + if (e.tool.isDefault && e.isEmpty) + this.setToBlock(e); + else { + const t = this.Editor.BlockManager.insertAtEnd(); + this.setToBlock(t); + } + } + /** + * Extract content fragment of current Block from Caret position to the end of the Block + */ + extractFragmentFromCaretPosition() { + const e = b.get(); + if (e.rangeCount) { + const t = e.getRangeAt(0), o = this.Editor.BlockManager.currentBlock.currentInput; + if (t.deleteContents(), o) + if (u.isNativeInput(o)) { + const i = o, s = document.createDocumentFragment(), r = i.value.substring(0, i.selectionStart), a = i.value.substring(i.selectionStart); + return s.textContent = a, i.value = r, s; + } else { + const i = t.cloneRange(); + return i.selectNodeContents(o), i.setStart(t.endContainer, t.endOffset), i.extractContents(); + } + } + } + /** + * Set's caret to the next Block or Tool`s input + * Before moving caret, we should check if caret position is at the end of Plugins node + * Using {@link Dom#getDeepestNode} to get a last node and match with current selection + * + * @param {boolean} force - pass true to skip check for caret position + */ + navigateNext(e = !1) { + const { BlockManager: t } = this.Editor, { currentBlock: o, nextBlock: i } = t; + if (o === void 0) + return !1; + const { nextInput: s, currentInput: r } = o, a = r !== void 0 ? Re(r) : void 0; + let l = i; + const c = e || a || !o.focusable; + if (s && c) + return this.setToInput(s, this.positions.START), !0; + if (l === null) { + if (o.tool.isDefault || !c) + return !1; + l = t.insertAtEnd(); + } + return c ? (this.setToBlock(l, this.positions.START), !0) : !1; + } + /** + * Set's caret to the previous Tool`s input or Block + * Before moving caret, we should check if caret position is start of the Plugins node + * Using {@link Dom#getDeepestNode} to get a last node and match with current selection + * + * @param {boolean} force - pass true to skip check for caret position + */ + navigatePrevious(e = !1) { + const { currentBlock: t, previousBlock: o } = this.Editor.BlockManager; + if (!t) + return !1; + const { previousInput: i, currentInput: s } = t, r = s !== void 0 ? Ne(s) : void 0, a = e || r || !t.focusable; + return i && a ? (this.setToInput(i, this.positions.END), !0) : o !== null && a ? (this.setToBlock(o, this.positions.END), !0) : !1; + } + /** + * Inserts shadow element after passed element where caret can be placed + * + * @param {Element} element - element after which shadow caret should be inserted + */ + createShadow(e) { + const t = document.createElement("span"); + t.classList.add(Ye.CSS.shadowCaret), e.insertAdjacentElement("beforeend", t); + } + /** + * Restores caret position + * + * @param {HTMLElement} element - element where caret should be restored + */ + restoreCaret(e) { + const t = e.querySelector(`.${Ye.CSS.shadowCaret}`); + if (!t) + return; + new b().expandToTag(t); + const i = document.createRange(); + i.selectNode(t), i.extractContents(); + } + /** + * Inserts passed content at caret position + * + * @param {string} content - content to insert + */ + insertContentAtCaretPosition(e) { + const t = document.createDocumentFragment(), o = document.createElement("div"), i = b.get(), s = b.range; + o.innerHTML = e, Array.from(o.childNodes).forEach((c) => t.appendChild(c)), t.childNodes.length === 0 && t.appendChild(new Text()); + const r = t.lastChild; + s.deleteContents(), s.insertNode(t); + const a = document.createRange(), l = r.nodeType === Node.TEXT_NODE ? r : r.firstChild; + l !== null && l.textContent !== null && a.setStart(l, l.textContent.length), i.removeAllRanges(), i.addRange(a); + } +} +class la extends E { + constructor() { + super(...arguments), this.onMouseUp = () => { + this.listeners.off(document, "mouseover", this.onMouseOver), this.listeners.off(document, "mouseup", this.onMouseUp); + }, this.onMouseOver = (e) => { + const { BlockManager: t, BlockSelection: o } = this.Editor; + if (e.relatedTarget === null && e.target === null) + return; + const i = t.getBlockByChildNode(e.relatedTarget) || this.lastSelectedBlock, s = t.getBlockByChildNode(e.target); + if (!(!i || !s) && s !== i) { + if (i === this.firstSelectedBlock) { + b.get().removeAllRanges(), i.selected = !0, s.selected = !0, o.clearCache(); + return; + } + if (s === this.firstSelectedBlock) { + i.selected = !1, s.selected = !1, o.clearCache(); + return; + } + this.Editor.InlineToolbar.close(), this.toggleBlocksSelectedState(i, s), this.lastSelectedBlock = s; + } + }; + } + /** + * Module preparation + * + * @returns {Promise} + */ + async prepare() { + this.listeners.on(document, "mousedown", (e) => { + this.enableCrossBlockSelection(e); + }); + } + /** + * Sets up listeners + * + * @param {MouseEvent} event - mouse down event + */ + watchSelection(e) { + if (e.button !== qn.LEFT) + return; + const { BlockManager: t } = this.Editor; + this.firstSelectedBlock = t.getBlock(e.target), this.lastSelectedBlock = this.firstSelectedBlock, this.listeners.on(document, "mouseover", this.onMouseOver), this.listeners.on(document, "mouseup", this.onMouseUp); + } + /** + * Return boolean is cross block selection started: + * there should be at least 2 selected blocks + */ + get isCrossBlockSelectionStarted() { + return !!this.firstSelectedBlock && !!this.lastSelectedBlock && this.firstSelectedBlock !== this.lastSelectedBlock; + } + /** + * Change selection state of the next Block + * Used for CBS via Shift + arrow keys + * + * @param {boolean} next - if true, toggle next block. Previous otherwise + */ + toggleBlockSelectedState(e = !0) { + const { BlockManager: t, BlockSelection: o } = this.Editor; + this.lastSelectedBlock || (this.lastSelectedBlock = this.firstSelectedBlock = t.currentBlock), this.firstSelectedBlock === this.lastSelectedBlock && (this.firstSelectedBlock.selected = !0, o.clearCache(), b.get().removeAllRanges()); + const i = t.blocks.indexOf(this.lastSelectedBlock) + (e ? 1 : -1), s = t.blocks[i]; + s && (this.lastSelectedBlock.selected !== s.selected ? (s.selected = !0, o.clearCache()) : (this.lastSelectedBlock.selected = !1, o.clearCache()), this.lastSelectedBlock = s, this.Editor.InlineToolbar.close(), s.holder.scrollIntoView({ + block: "nearest" + })); + } + /** + * Clear saved state + * + * @param {Event} reason - event caused clear of selection + */ + clear(e) { + const { BlockManager: t, BlockSelection: o, Caret: i } = this.Editor, s = t.blocks.indexOf(this.firstSelectedBlock), r = t.blocks.indexOf(this.lastSelectedBlock); + if (o.anyBlockSelected && s > -1 && r > -1 && e && e instanceof KeyboardEvent) + switch (e.keyCode) { + case y.DOWN: + case y.RIGHT: + i.setToBlock(t.blocks[Math.max(s, r)], i.positions.END); + break; + case y.UP: + case y.LEFT: + i.setToBlock(t.blocks[Math.min(s, r)], i.positions.START); + break; + default: + i.setToBlock(t.blocks[Math.max(s, r)], i.positions.END); + } + this.firstSelectedBlock = this.lastSelectedBlock = null; + } + /** + * Enables Cross Block Selection + * + * @param {MouseEvent} event - mouse down event + */ + enableCrossBlockSelection(e) { + const { UI: t } = this.Editor; + b.isCollapsed || this.Editor.BlockSelection.clearSelection(e), t.nodes.redactor.contains(e.target) ? this.watchSelection(e) : this.Editor.BlockSelection.clearSelection(e); + } + /** + * Change blocks selection state between passed two blocks. + * + * @param {Block} firstBlock - first block in range + * @param {Block} lastBlock - last block in range + */ + toggleBlocksSelectedState(e, t) { + const { BlockManager: o, BlockSelection: i } = this.Editor, s = o.blocks.indexOf(e), r = o.blocks.indexOf(t), a = e.selected !== t.selected; + for (let l = Math.min(s, r); l <= Math.max(s, r); l++) { + const c = o.blocks[l]; + c !== this.firstSelectedBlock && c !== (a ? e : t) && (o.blocks[l].selected = !o.blocks[l].selected, i.clearCache()); + } + } +} +class ca extends E { + constructor() { + super(...arguments), this.isStartedAtEditor = !1; + } + /** + * Toggle read-only state + * + * if state is true: + * - disable all drag-n-drop event handlers + * + * if state is false: + * - restore drag-n-drop event handlers + * + * @param {boolean} readOnlyEnabled - "read only" state + */ + toggleReadOnly(e) { + e ? this.disableModuleBindings() : this.enableModuleBindings(); + } + /** + * Add drag events listeners to editor zone + */ + enableModuleBindings() { + const { UI: e } = this.Editor; + this.readOnlyMutableListeners.on(e.nodes.holder, "drop", async (t) => { + await this.processDrop(t); + }, !0), this.readOnlyMutableListeners.on(e.nodes.holder, "dragstart", () => { + this.processDragStart(); + }), this.readOnlyMutableListeners.on(e.nodes.holder, "dragover", (t) => { + this.processDragOver(t); + }, !0); + } + /** + * Unbind drag-n-drop event handlers + */ + disableModuleBindings() { + this.readOnlyMutableListeners.clearAll(); + } + /** + * Handle drop event + * + * @param {DragEvent} dropEvent - drop event + */ + async processDrop(e) { + const { + BlockManager: t, + Paste: o, + Caret: i + } = this.Editor; + e.preventDefault(), t.blocks.forEach((r) => { + r.dropTarget = !1; + }), b.isAtEditor && !b.isCollapsed && this.isStartedAtEditor && document.execCommand("delete"), this.isStartedAtEditor = !1; + const s = t.setCurrentBlockByChildNode(e.target); + if (s) + this.Editor.Caret.setToBlock(s, i.positions.END); + else { + const r = t.setCurrentBlockByChildNode(t.lastBlock.holder); + this.Editor.Caret.setToBlock(r, i.positions.END); + } + await o.processDataTransfer(e.dataTransfer, !0); + } + /** + * Handle drag start event + */ + processDragStart() { + b.isAtEditor && !b.isCollapsed && (this.isStartedAtEditor = !0), this.Editor.InlineToolbar.close(); + } + /** + * @param {DragEvent} dragEvent - drag event + */ + processDragOver(e) { + e.preventDefault(); + } +} +const da = 180, ua = 400; +class ha extends E { + /** + * Prepare the module + * + * @param options - options used by the modification observer module + * @param options.config - Editor configuration object + * @param options.eventsDispatcher - common Editor event bus + */ + constructor({ config: e, eventsDispatcher: t }) { + super({ + config: e, + eventsDispatcher: t + }), this.disabled = !1, this.batchingTimeout = null, this.batchingOnChangeQueue = /* @__PURE__ */ new Map(), this.batchTime = ua, this.mutationObserver = new MutationObserver((o) => { + this.redactorChanged(o); + }), this.eventsDispatcher.on($o, (o) => { + this.particularBlockChanged(o.event); + }), this.eventsDispatcher.on(zo, () => { + this.disable(); + }), this.eventsDispatcher.on(Uo, () => { + this.enable(); + }); + } + /** + * Enables onChange event + */ + enable() { + this.mutationObserver.observe( + this.Editor.UI.nodes.redactor, + { + childList: !0, + subtree: !0, + characterData: !0, + attributes: !0 + } + ), this.disabled = !1; + } + /** + * Disables onChange event + */ + disable() { + this.mutationObserver.disconnect(), this.disabled = !0; + } + /** + * Call onChange event passed to Editor.js configuration + * + * @param event - some of our custom change events + */ + particularBlockChanged(e) { + this.disabled || !A(this.config.onChange) || (this.batchingOnChangeQueue.set(`block:${e.detail.target.id}:event:${e.type}`, e), this.batchingTimeout && clearTimeout(this.batchingTimeout), this.batchingTimeout = setTimeout(() => { + let t; + this.batchingOnChangeQueue.size === 1 ? t = this.batchingOnChangeQueue.values().next().value : t = Array.from(this.batchingOnChangeQueue.values()), this.config.onChange && this.config.onChange(this.Editor.API.methods, t), this.batchingOnChangeQueue.clear(); + }, this.batchTime)); + } + /** + * Fired on every blocks wrapper dom change + * + * @param mutations - mutations happened + */ + redactorChanged(e) { + this.eventsDispatcher.emit(ft, { + mutations: e + }); + } +} +const Rn = class Dn extends E { + constructor() { + super(...arguments), this.MIME_TYPE = "application/x-editor-js", this.toolsTags = {}, this.tagsByTool = {}, this.toolsPatterns = [], this.toolsFiles = {}, this.exceptionList = [], this.processTool = (e) => { + try { + const t = e.create({}, {}, !1); + if (e.pasteConfig === !1) { + this.exceptionList.push(e.name); + return; + } + if (!A(t.onPaste)) + return; + this.getTagsConfig(e), this.getFilesConfig(e), this.getPatternsConfig(e); + } catch (t) { + S( + `Paste handling for «${e.name}» Tool hasn't been set up because of the error`, + "warn", + t + ); + } + }, this.handlePasteEvent = async (e) => { + const { BlockManager: t, Toolbar: o } = this.Editor, i = t.setCurrentBlockByChildNode(e.target); + !i || this.isNativeBehaviour(e.target) && !e.clipboardData.types.includes("Files") || i && this.exceptionList.includes(i.name) || (e.preventDefault(), this.processDataTransfer(e.clipboardData), o.close()); + }; + } + /** + * Set onPaste callback and collect tools` paste configurations + */ + async prepare() { + this.processTools(); + } + /** + * Set read-only state + * + * @param {boolean} readOnlyEnabled - read only flag value + */ + toggleReadOnly(e) { + e ? this.unsetCallback() : this.setCallback(); + } + /** + * Handle pasted or dropped data transfer object + * + * @param {DataTransfer} dataTransfer - pasted or dropped data transfer object + * @param {boolean} isDragNDrop - true if data transfer comes from drag'n'drop events + */ + async processDataTransfer(e, t = !1) { + const { Tools: o } = this.Editor, i = e.types; + if ((i.includes ? i.includes("Files") : i.contains("Files")) && !V(this.toolsFiles)) { + await this.processFiles(e.files); + return; + } + const r = e.getData(this.MIME_TYPE), a = e.getData("text/plain"); + let l = e.getData("text/html"); + if (r) + try { + this.insertEditorJSData(JSON.parse(r)); + return; + } catch { + } + t && a.trim() && l.trim() && (l = "

    " + (l.trim() ? l : a) + "

    "); + const c = Object.keys(this.toolsTags).reduce((p, g) => (p[g.toLowerCase()] = this.toolsTags[g].sanitizationConfig ?? {}, p), {}), d = Object.assign({}, c, o.getAllInlineToolsSanitizeConfig(), { br: {} }), h = Z(l, d); + !h.trim() || h.trim() === a || !u.isHTMLString(h) ? await this.processText(a) : await this.processText(h, !0); + } + /** + * Process pasted text and divide them into Blocks + * + * @param {string} data - text to process. Can be HTML or plain. + * @param {boolean} isHTML - if passed string is HTML, this parameter should be true + */ + async processText(e, t = !1) { + const { Caret: o, BlockManager: i } = this.Editor, s = t ? this.processHTML(e) : this.processPlain(e); + if (!s.length) + return; + if (s.length === 1) { + s[0].isBlock ? this.processSingleBlock(s.pop()) : this.processInlinePaste(s.pop()); + return; + } + const a = i.currentBlock && i.currentBlock.tool.isDefault && i.currentBlock.isEmpty; + s.map( + async (l, c) => this.insertBlock(l, c === 0 && a) + ), i.currentBlock && o.setToBlock(i.currentBlock, o.positions.END); + } + /** + * Set onPaste callback handler + */ + setCallback() { + this.listeners.on(this.Editor.UI.nodes.holder, "paste", this.handlePasteEvent); + } + /** + * Unset onPaste callback handler + */ + unsetCallback() { + this.listeners.off(this.Editor.UI.nodes.holder, "paste", this.handlePasteEvent); + } + /** + * Get and process tool`s paste configs + */ + processTools() { + const e = this.Editor.Tools.blockTools; + Array.from(e.values()).forEach(this.processTool); + } + /** + * Get tags name list from either tag name or sanitization config. + * + * @param {string | object} tagOrSanitizeConfig - tag name or sanitize config object. + * @returns {string[]} array of tags. + */ + collectTagNames(e) { + return te(e) ? [e] : D(e) ? Object.keys(e) : []; + } + /** + * Get tags to substitute by Tool + * + * @param tool - BlockTool object + */ + getTagsConfig(e) { + if (e.pasteConfig === !1) + return; + const t = e.pasteConfig.tags || [], o = []; + t.forEach((i) => { + const s = this.collectTagNames(i); + o.push(...s), s.forEach((r) => { + if (Object.prototype.hasOwnProperty.call(this.toolsTags, r)) { + S( + `Paste handler for «${e.name}» Tool on «${r}» tag is skipped because it is already used by «${this.toolsTags[r].tool.name}» Tool.`, + "warn" + ); + return; + } + const a = D(i) ? i[r] : null; + this.toolsTags[r.toUpperCase()] = { + tool: e, + sanitizationConfig: a + }; + }); + }), this.tagsByTool[e.name] = o.map((i) => i.toUpperCase()); + } + /** + * Get files` types and extensions to substitute by Tool + * + * @param tool - BlockTool object + */ + getFilesConfig(e) { + if (e.pasteConfig === !1) + return; + const { files: t = {} } = e.pasteConfig; + let { extensions: o, mimeTypes: i } = t; + !o && !i || (o && !Array.isArray(o) && (S(`«extensions» property of the onDrop config for «${e.name}» Tool should be an array`), o = []), i && !Array.isArray(i) && (S(`«mimeTypes» property of the onDrop config for «${e.name}» Tool should be an array`), i = []), i && (i = i.filter((s) => ei(s) ? !0 : (S(`MIME type value «${s}» for the «${e.name}» Tool is not a valid MIME type`, "warn"), !1))), this.toolsFiles[e.name] = { + extensions: o || [], + mimeTypes: i || [] + }); + } + /** + * Get RegExp patterns to substitute by Tool + * + * @param tool - BlockTool object + */ + getPatternsConfig(e) { + e.pasteConfig === !1 || !e.pasteConfig.patterns || V(e.pasteConfig.patterns) || Object.entries(e.pasteConfig.patterns).forEach(([t, o]) => { + o instanceof RegExp || S( + `Pattern ${o} for «${e.name}» Tool is skipped because it should be a Regexp instance.`, + "warn" + ), this.toolsPatterns.push({ + key: t, + pattern: o, + tool: e + }); + }); + } + /** + * Check if browser behavior suits better + * + * @param {EventTarget} element - element where content has been pasted + * @returns {boolean} + */ + isNativeBehaviour(e) { + return u.isNativeInput(e); + } + /** + * Get files from data transfer object and insert related Tools + * + * @param {FileList} items - pasted or dropped items + */ + async processFiles(e) { + const { BlockManager: t } = this.Editor; + let o; + o = await Promise.all( + Array.from(e).map((r) => this.processFile(r)) + ), o = o.filter((r) => !!r); + const s = t.currentBlock.tool.isDefault && t.currentBlock.isEmpty; + o.forEach( + (r, a) => { + t.paste(r.type, r.event, a === 0 && s); + } + ); + } + /** + * Get information about file and find Tool to handle it + * + * @param {File} file - file to process + */ + async processFile(e) { + const t = Jn(e), o = Object.entries(this.toolsFiles).find(([r, { mimeTypes: a, extensions: l }]) => { + const [c, d] = e.type.split("/"), h = l.find((g) => g.toLowerCase() === t.toLowerCase()), p = a.find((g) => { + const [f, v] = g.split("/"); + return f === c && (v === d || v === "*"); + }); + return !!h || !!p; + }); + if (!o) + return; + const [i] = o; + return { + event: this.composePasteEvent("file", { + file: e + }), + type: i + }; + } + /** + * Split HTML string to blocks and return it as array of Block data + * + * @param {string} innerHTML - html string to process + * @returns {PasteData[]} + */ + processHTML(e) { + const { Tools: t } = this.Editor, o = u.make("DIV"); + return o.innerHTML = e, this.getNodes(o).map((s) => { + let r, a = t.defaultTool, l = !1; + switch (s.nodeType) { + case Node.DOCUMENT_FRAGMENT_NODE: + r = u.make("div"), r.appendChild(s); + break; + case Node.ELEMENT_NODE: + r = s, l = !0, this.toolsTags[r.tagName] && (a = this.toolsTags[r.tagName].tool); + break; + } + const { tags: c } = a.pasteConfig || { tags: [] }, d = c.reduce((g, f) => (this.collectTagNames(f).forEach((O) => { + const T = D(f) ? f[O] : null; + g[O.toLowerCase()] = T || {}; + }), g), {}), h = Object.assign({}, d, a.baseSanitizeConfig); + if (r.tagName.toLowerCase() === "table") { + const g = Z(r.outerHTML, h); + r = u.make("div", void 0, { + innerHTML: g + }).firstChild; + } else + r.innerHTML = Z(r.innerHTML, h); + const p = this.composePasteEvent("tag", { + data: r + }); + return { + content: r, + isBlock: l, + tool: a.name, + event: p + }; + }).filter((s) => { + const r = u.isEmpty(s.content), a = u.isSingleTag(s.content); + return !r || a; + }); + } + /** + * Split plain text by new line symbols and return it as array of Block data + * + * @param {string} plain - string to process + * @returns {PasteData[]} + */ + processPlain(e) { + const { defaultBlock: t } = this.config; + if (!e) + return []; + const o = t; + return e.split(/\r?\n/).filter((i) => i.trim()).map((i) => { + const s = u.make("div"); + s.textContent = i; + const r = this.composePasteEvent("tag", { + data: s + }); + return { + content: s, + tool: o, + isBlock: !1, + event: r + }; + }); + } + /** + * Process paste of single Block tool content + * + * @param {PasteData} dataToInsert - data of Block to insert + */ + async processSingleBlock(e) { + const { Caret: t, BlockManager: o } = this.Editor, { currentBlock: i } = o; + if (!i || e.tool !== i.name || !u.containsOnlyInlineElements(e.content.innerHTML)) { + this.insertBlock(e, (i == null ? void 0 : i.tool.isDefault) && i.isEmpty); + return; + } + t.insertContentAtCaretPosition(e.content.innerHTML); + } + /** + * Process paste to single Block: + * 1. Find patterns` matches + * 2. Insert new block if it is not the same type as current one + * 3. Just insert text if there is no substitutions + * + * @param {PasteData} dataToInsert - data of Block to insert + */ + async processInlinePaste(e) { + const { BlockManager: t, Caret: o } = this.Editor, { content: i } = e; + if (t.currentBlock && t.currentBlock.tool.isDefault && i.textContent.length < Dn.PATTERN_PROCESSING_MAX_LENGTH) { + const r = await this.processPattern(i.textContent); + if (r) { + const a = t.currentBlock && t.currentBlock.tool.isDefault && t.currentBlock.isEmpty, l = t.paste(r.tool, r.event, a); + o.setToBlock(l, o.positions.END); + return; + } + } + if (t.currentBlock && t.currentBlock.currentInput) { + const r = t.currentBlock.tool.baseSanitizeConfig; + document.execCommand( + "insertHTML", + !1, + Z(i.innerHTML, r) + ); + } else + this.insertBlock(e); + } + /** + * Get patterns` matches + * + * @param {string} text - text to process + * @returns {Promise<{event: PasteEvent, tool: string}>} + */ + async processPattern(e) { + const t = this.toolsPatterns.find((i) => { + const s = i.pattern.exec(e); + return s ? e === s.shift() : !1; + }); + return t ? { + event: this.composePasteEvent("pattern", { + key: t.key, + data: e + }), + tool: t.tool.name + } : void 0; + } + /** + * Insert pasted Block content to Editor + * + * @param {PasteData} data - data to insert + * @param {boolean} canReplaceCurrentBlock - if true and is current Block is empty, will replace current Block + * @returns {void} + */ + insertBlock(e, t = !1) { + const { BlockManager: o, Caret: i } = this.Editor, { currentBlock: s } = o; + let r; + if (t && s && s.isEmpty) { + r = o.paste(e.tool, e.event, !0), i.setToBlock(r, i.positions.END); + return; + } + r = o.paste(e.tool, e.event), i.setToBlock(r, i.positions.END); + } + /** + * Insert data passed as application/x-editor-js JSON + * + * @param {Array} blocks — Blocks' data to insert + * @returns {void} + */ + insertEditorJSData(e) { + const { BlockManager: t, Caret: o, Tools: i } = this.Editor; + yt( + e, + (r) => i.blockTools.get(r).sanitizeConfig + ).forEach(({ tool: r, data: a }, l) => { + let c = !1; + l === 0 && (c = t.currentBlock && t.currentBlock.tool.isDefault && t.currentBlock.isEmpty); + const d = t.insert({ + tool: r, + data: a, + replace: c + }); + o.setToBlock(d, o.positions.END); + }); + } + /** + * Fetch nodes from Element node + * + * @param {Node} node - current node + * @param {Node[]} nodes - processed nodes + * @param {Node} destNode - destination node + */ + processElementNode(e, t, o) { + const i = Object.keys(this.toolsTags), s = e, { tool: r } = this.toolsTags[s.tagName] || {}, a = this.tagsByTool[r == null ? void 0 : r.name] || [], l = i.includes(s.tagName), c = u.blockElements.includes(s.tagName.toLowerCase()), d = Array.from(s.children).some( + ({ tagName: p }) => i.includes(p) && !a.includes(p) + ), h = Array.from(s.children).some( + ({ tagName: p }) => u.blockElements.includes(p.toLowerCase()) + ); + if (!c && !l && !d) + return o.appendChild(s), [...t, o]; + if (l && !d || c && !h && !d) + return [...t, o, s]; + } + /** + * Recursively divide HTML string to two types of nodes: + * 1. Block element + * 2. Document Fragments contained text and markup tags like a, b, i etc. + * + * @param {Node} wrapper - wrapper of paster HTML content + * @returns {Node[]} + */ + getNodes(e) { + const t = Array.from(e.childNodes); + let o; + const i = (s, r) => { + if (u.isEmpty(r) && !u.isSingleTag(r)) + return s; + const a = s[s.length - 1]; + let l = new DocumentFragment(); + switch (a && u.isFragment(a) && (l = s.pop()), r.nodeType) { + case Node.ELEMENT_NODE: + if (o = this.processElementNode(r, s, l), o) + return o; + break; + case Node.TEXT_NODE: + return l.appendChild(r), [...s, l]; + default: + return [...s, l]; + } + return [...s, ...Array.from(r.childNodes).reduce(i, [])]; + }; + return t.reduce(i, []); + } + /** + * Compose paste event with passed type and detail + * + * @param {string} type - event type + * @param {PasteEventDetail} detail - event detail + */ + composePasteEvent(e, t) { + return new CustomEvent(e, { + detail: t + }); + } +}; +Rn.PATTERN_PROCESSING_MAX_LENGTH = 450; +let pa = Rn; +class fa extends E { + constructor() { + super(...arguments), this.toolsDontSupportReadOnly = [], this.readOnlyEnabled = !1; + } + /** + * Returns state of read only mode + */ + get isEnabled() { + return this.readOnlyEnabled; + } + /** + * Set initial state + */ + async prepare() { + const { Tools: e } = this.Editor, { blockTools: t } = e, o = []; + Array.from(t.entries()).forEach(([i, s]) => { + s.isReadOnlySupported || o.push(i); + }), this.toolsDontSupportReadOnly = o, this.config.readOnly && o.length > 0 && this.throwCriticalError(), this.toggle(this.config.readOnly, !0); + } + /** + * Set read-only mode or toggle current state + * Call all Modules `toggleReadOnly` method and re-render Editor + * + * @param state - (optional) read-only state or toggle + * @param isInitial - (optional) true when editor is initializing + */ + async toggle(e = !this.readOnlyEnabled, t = !1) { + e && this.toolsDontSupportReadOnly.length > 0 && this.throwCriticalError(); + const o = this.readOnlyEnabled; + this.readOnlyEnabled = e; + for (const s in this.Editor) + this.Editor[s].toggleReadOnly && this.Editor[s].toggleReadOnly(e); + if (o === e) + return this.readOnlyEnabled; + if (t) + return this.readOnlyEnabled; + this.Editor.ModificationsObserver.disable(); + const i = await this.Editor.Saver.save(); + return await this.Editor.BlockManager.clear(), await this.Editor.Renderer.render(i.blocks), this.Editor.ModificationsObserver.enable(), this.readOnlyEnabled; + } + /** + * Throws an error about tools which don't support read-only mode + */ + throwCriticalError() { + throw new Ho( + `To enable read-only mode all connected tools should support it. Tools ${this.toolsDontSupportReadOnly.join(", ")} don't support read-only mode.` + ); + } +} +class Be extends E { + constructor() { + super(...arguments), this.isRectSelectionActivated = !1, this.SCROLL_SPEED = 3, this.HEIGHT_OF_SCROLL_ZONE = 40, this.BOTTOM_SCROLL_ZONE = 1, this.TOP_SCROLL_ZONE = 2, this.MAIN_MOUSE_BUTTON = 0, this.mousedown = !1, this.isScrolling = !1, this.inScrollZone = null, this.startX = 0, this.startY = 0, this.mouseX = 0, this.mouseY = 0, this.stackOfSelected = [], this.listenerIds = []; + } + /** + * CSS classes for the Block + * + * @returns {{wrapper: string, content: string}} + */ + static get CSS() { + return { + overlay: "codex-editor-overlay", + overlayContainer: "codex-editor-overlay__container", + rect: "codex-editor-overlay__rectangle", + topScrollZone: "codex-editor-overlay__scroll-zone--top", + bottomScrollZone: "codex-editor-overlay__scroll-zone--bottom" + }; + } + /** + * Module Preparation + * Creating rect and hang handlers + */ + prepare() { + this.enableModuleBindings(); + } + /** + * Init rect params + * + * @param {number} pageX - X coord of mouse + * @param {number} pageY - Y coord of mouse + */ + startSelection(e, t) { + const o = document.elementFromPoint(e - window.pageXOffset, t - window.pageYOffset); + o.closest(`.${this.Editor.Toolbar.CSS.toolbar}`) || (this.Editor.BlockSelection.allBlocksSelected = !1, this.clearSelection(), this.stackOfSelected = []); + const s = [ + `.${R.CSS.content}`, + `.${this.Editor.Toolbar.CSS.toolbar}`, + `.${this.Editor.InlineToolbar.CSS.inlineToolbar}` + ], r = o.closest("." + this.Editor.UI.CSS.editorWrapper), a = s.some((l) => !!o.closest(l)); + !r || a || (this.mousedown = !0, this.startX = e, this.startY = t); + } + /** + * Clear all params to end selection + */ + endSelection() { + this.mousedown = !1, this.startX = 0, this.startY = 0, this.overlayRectangle.style.display = "none"; + } + /** + * is RectSelection Activated + */ + isRectActivated() { + return this.isRectSelectionActivated; + } + /** + * Mark that selection is end + */ + clearSelection() { + this.isRectSelectionActivated = !1; + } + /** + * Sets Module necessary event handlers + */ + enableModuleBindings() { + const { container: e } = this.genHTML(); + this.listeners.on(e, "mousedown", (t) => { + this.processMouseDown(t); + }, !1), this.listeners.on(document.body, "mousemove", dt((t) => { + this.processMouseMove(t); + }, 10), { + passive: !0 + }), this.listeners.on(document.body, "mouseleave", () => { + this.processMouseLeave(); + }), this.listeners.on(window, "scroll", dt((t) => { + this.processScroll(t); + }, 10), { + passive: !0 + }), this.listeners.on(document.body, "mouseup", () => { + this.processMouseUp(); + }, !1); + } + /** + * Handle mouse down events + * + * @param {MouseEvent} mouseEvent - mouse event payload + */ + processMouseDown(e) { + if (e.button !== this.MAIN_MOUSE_BUTTON) + return; + e.target.closest(u.allInputsSelector) !== null || this.startSelection(e.pageX, e.pageY); + } + /** + * Handle mouse move events + * + * @param {MouseEvent} mouseEvent - mouse event payload + */ + processMouseMove(e) { + this.changingRectangle(e), this.scrollByZones(e.clientY); + } + /** + * Handle mouse leave + */ + processMouseLeave() { + this.clearSelection(), this.endSelection(); + } + /** + * @param {MouseEvent} mouseEvent - mouse event payload + */ + processScroll(e) { + this.changingRectangle(e); + } + /** + * Handle mouse up + */ + processMouseUp() { + this.clearSelection(), this.endSelection(); + } + /** + * Scroll If mouse in scroll zone + * + * @param {number} clientY - Y coord of mouse + */ + scrollByZones(e) { + if (this.inScrollZone = null, e <= this.HEIGHT_OF_SCROLL_ZONE && (this.inScrollZone = this.TOP_SCROLL_ZONE), document.documentElement.clientHeight - e <= this.HEIGHT_OF_SCROLL_ZONE && (this.inScrollZone = this.BOTTOM_SCROLL_ZONE), !this.inScrollZone) { + this.isScrolling = !1; + return; + } + this.isScrolling || (this.scrollVertical(this.inScrollZone === this.TOP_SCROLL_ZONE ? -this.SCROLL_SPEED : this.SCROLL_SPEED), this.isScrolling = !0); + } + /** + * Generates required HTML elements + * + * @returns {Object} + */ + genHTML() { + const { UI: e } = this.Editor, t = e.nodes.holder.querySelector("." + e.CSS.editorWrapper), o = u.make("div", Be.CSS.overlay, {}), i = u.make("div", Be.CSS.overlayContainer, {}), s = u.make("div", Be.CSS.rect, {}); + return i.appendChild(s), o.appendChild(i), t.appendChild(o), this.overlayRectangle = s, { + container: t, + overlay: o + }; + } + /** + * Activates scrolling if blockSelection is active and mouse is in scroll zone + * + * @param {number} speed - speed of scrolling + */ + scrollVertical(e) { + if (!(this.inScrollZone && this.mousedown)) + return; + const t = window.pageYOffset; + window.scrollBy(0, e), this.mouseY += window.pageYOffset - t, setTimeout(() => { + this.scrollVertical(e); + }, 0); + } + /** + * Handles the change in the rectangle and its effect + * + * @param {MouseEvent} event - mouse event + */ + changingRectangle(e) { + if (!this.mousedown) + return; + e.pageY !== void 0 && (this.mouseX = e.pageX, this.mouseY = e.pageY); + const { rightPos: t, leftPos: o, index: i } = this.genInfoForMouseSelection(), s = this.startX > t && this.mouseX > t, r = this.startX < o && this.mouseX < o; + this.rectCrossesBlocks = !(s || r), this.isRectSelectionActivated || (this.rectCrossesBlocks = !1, this.isRectSelectionActivated = !0, this.shrinkRectangleToPoint(), this.overlayRectangle.style.display = "block"), this.updateRectangleSize(), this.Editor.Toolbar.close(), i !== void 0 && (this.trySelectNextBlock(i), this.inverseSelection(), b.get().removeAllRanges()); + } + /** + * Shrink rect to singular point + */ + shrinkRectangleToPoint() { + this.overlayRectangle.style.left = `${this.startX - window.pageXOffset}px`, this.overlayRectangle.style.top = `${this.startY - window.pageYOffset}px`, this.overlayRectangle.style.bottom = `calc(100% - ${this.startY - window.pageYOffset}px`, this.overlayRectangle.style.right = `calc(100% - ${this.startX - window.pageXOffset}px`; + } + /** + * Select or unselect all of blocks in array if rect is out or in selectable area + */ + inverseSelection() { + const t = this.Editor.BlockManager.getBlockByIndex(this.stackOfSelected[0]).selected; + if (this.rectCrossesBlocks && !t) + for (const o of this.stackOfSelected) + this.Editor.BlockSelection.selectBlockByIndex(o); + if (!this.rectCrossesBlocks && t) + for (const o of this.stackOfSelected) + this.Editor.BlockSelection.unSelectBlockByIndex(o); + } + /** + * Updates size of rectangle + */ + updateRectangleSize() { + this.mouseY >= this.startY ? (this.overlayRectangle.style.top = `${this.startY - window.pageYOffset}px`, this.overlayRectangle.style.bottom = `calc(100% - ${this.mouseY - window.pageYOffset}px`) : (this.overlayRectangle.style.bottom = `calc(100% - ${this.startY - window.pageYOffset}px`, this.overlayRectangle.style.top = `${this.mouseY - window.pageYOffset}px`), this.mouseX >= this.startX ? (this.overlayRectangle.style.left = `${this.startX - window.pageXOffset}px`, this.overlayRectangle.style.right = `calc(100% - ${this.mouseX - window.pageXOffset}px`) : (this.overlayRectangle.style.right = `calc(100% - ${this.startX - window.pageXOffset}px`, this.overlayRectangle.style.left = `${this.mouseX - window.pageXOffset}px`); + } + /** + * Collects information needed to determine the behavior of the rectangle + * + * @returns {object} index - index next Block, leftPos - start of left border of Block, rightPos - right border + */ + genInfoForMouseSelection() { + const t = document.body.offsetWidth / 2, o = this.mouseY - window.pageYOffset, i = document.elementFromPoint(t, o), s = this.Editor.BlockManager.getBlockByChildNode(i); + let r; + s !== void 0 && (r = this.Editor.BlockManager.blocks.findIndex((h) => h.holder === s.holder)); + const a = this.Editor.BlockManager.lastBlock.holder.querySelector("." + R.CSS.content), l = Number.parseInt(window.getComputedStyle(a).width, 10) / 2, c = t - l, d = t + l; + return { + index: r, + leftPos: c, + rightPos: d + }; + } + /** + * Select block with index index + * + * @param index - index of block in redactor + */ + addBlockInSelection(e) { + this.rectCrossesBlocks && this.Editor.BlockSelection.selectBlockByIndex(e), this.stackOfSelected.push(e); + } + /** + * Adds a block to the selection and determines which blocks should be selected + * + * @param {object} index - index of new block in the reactor + */ + trySelectNextBlock(e) { + const t = this.stackOfSelected[this.stackOfSelected.length - 1] === e, o = this.stackOfSelected.length, i = 1, s = -1, r = 0; + if (t) + return; + const a = this.stackOfSelected[o - 1] - this.stackOfSelected[o - 2] > 0; + let l = r; + o > 1 && (l = a ? i : s); + const c = e > this.stackOfSelected[o - 1] && l === i, d = e < this.stackOfSelected[o - 1] && l === s, p = !(c || d || l === r); + if (!p && (e > this.stackOfSelected[o - 1] || this.stackOfSelected[o - 1] === void 0)) { + let v = this.stackOfSelected[o - 1] + 1 || e; + for (v; v <= e; v++) + this.addBlockInSelection(v); + return; + } + if (!p && e < this.stackOfSelected[o - 1]) { + for (let v = this.stackOfSelected[o - 1] - 1; v >= e; v--) + this.addBlockInSelection(v); + return; + } + if (!p) + return; + let g = o - 1, f; + for (e > this.stackOfSelected[o - 1] ? f = () => e > this.stackOfSelected[g] : f = () => e < this.stackOfSelected[g]; f(); ) + this.rectCrossesBlocks && this.Editor.BlockSelection.unSelectBlockByIndex(this.stackOfSelected[g]), this.stackOfSelected.pop(), g--; + } +} +class ga extends E { + /** + * Renders passed blocks as one batch + * + * @param blocksData - blocks to render + */ + async render(e) { + return new Promise((t) => { + const { Tools: o, BlockManager: i } = this.Editor; + if (e.length === 0) + i.insert(); + else { + const s = e.map(({ type: r, data: a, tunes: l, id: c }) => { + o.available.has(r) === !1 && (X(`Tool «${r}» is not found. Check 'tools' property at the Editor.js config.`, "warn"), a = this.composeStubDataForTool(r, a, c), r = o.stubTool); + let d; + try { + d = i.composeBlock({ + id: c, + tool: r, + data: a, + tunes: l + }); + } catch (h) { + S(`Block «${r}» skipped because of plugins error`, "error", { + data: a, + error: h + }), a = this.composeStubDataForTool(r, a, c), r = o.stubTool, d = i.composeBlock({ + id: c, + tool: r, + data: a, + tunes: l + }); + } + return d; + }); + i.insertMany(s); + } + window.requestIdleCallback(() => { + t(); + }, { timeout: 2e3 }); + }); + } + /** + * Create data for the Stub Tool that will be used instead of unavailable tool + * + * @param tool - unavailable tool name to stub + * @param data - data of unavailable block + * @param [id] - id of unavailable block + */ + composeStubDataForTool(e, t, o) { + const { Tools: i } = this.Editor; + let s = e; + if (i.unavailable.has(e)) { + const r = i.unavailable.get(e).toolbox; + r !== void 0 && r[0].title !== void 0 && (s = r[0].title); + } + return { + savedData: { + id: o, + type: e, + data: t + }, + title: s + }; + } +} +class ma extends E { + /** + * Composes new chain of Promises to fire them alternatelly + * + * @returns {OutputData} + */ + async save() { + const { BlockManager: e, Tools: t } = this.Editor, o = e.blocks, i = []; + try { + o.forEach((a) => { + i.push(this.getSavedData(a)); + }); + const s = await Promise.all(i), r = await yt(s, (a) => t.blockTools.get(a).sanitizeConfig); + return this.makeOutput(r); + } catch (s) { + X("Saving failed due to the Error %o", "error", s); + } + } + /** + * Saves and validates + * + * @param {Block} block - Editor's Tool + * @returns {ValidatedData} - Tool's validated data + */ + async getSavedData(e) { + const t = await e.save(), o = t && await e.validate(t.data); + return { + ...t, + isValid: o + }; + } + /** + * Creates output object with saved data, time and version of editor + * + * @param {ValidatedData} allExtractedData - data extracted from Blocks + * @returns {OutputData} + */ + makeOutput(e) { + const t = []; + return e.forEach(({ id: o, tool: i, data: s, tunes: r, isValid: a }) => { + if (!a) { + S(`Block «${i}» skipped because saved data is invalid`); + return; + } + if (i === this.Editor.Tools.stubTool) { + t.push(s); + return; + } + const l = { + id: o, + type: i, + data: s, + ...!V(r) && { + tunes: r + } + }; + t.push(l); + }), { + time: +/* @__PURE__ */ new Date(), + blocks: t, + version: "2.31.1" + }; + } +} +(function() { + try { + if (typeof document < "u") { + var n = document.createElement("style"); + n.appendChild(document.createTextNode(".ce-paragraph{line-height:1.6em;outline:none}.ce-block:only-of-type .ce-paragraph[data-placeholder-active]:empty:before,.ce-block:only-of-type .ce-paragraph[data-placeholder-active][data-empty=true]:before{content:attr(data-placeholder-active)}.ce-paragraph p:first-of-type{margin-top:0}.ce-paragraph p:last-of-type{margin-bottom:0}")), document.head.appendChild(n); + } + } catch (e) { + console.error("vite-plugin-css-injected-by-js", e); + } +})(); +const ba = ''; +function va(n) { + const e = document.createElement("div"); + e.innerHTML = n.trim(); + const t = document.createDocumentFragment(); + return t.append(...Array.from(e.childNodes)), t; +} +/** + * Base Paragraph Block for the Editor.js. + * Represents a regular text block + * + * @author CodeX (team@codex.so) + * @copyright CodeX 2018 + * @license The MIT License (MIT) + */ +class fo { + /** + * Default placeholder for Paragraph Tool + * + * @returns {string} + * @class + */ + static get DEFAULT_PLACEHOLDER() { + return ""; + } + /** + * Render plugin`s main Element and fill it with saved data + * + * @param {object} params - constructor params + * @param {ParagraphData} params.data - previously saved data + * @param {ParagraphConfig} params.config - user config for Tool + * @param {object} params.api - editor.js api + * @param {boolean} readOnly - read only mode flag + */ + constructor({ data: e, config: t, api: o, readOnly: i }) { + this.api = o, this.readOnly = i, this._CSS = { + block: this.api.styles.block, + wrapper: "ce-paragraph" + }, this.readOnly || (this.onKeyUp = this.onKeyUp.bind(this)), this._placeholder = t.placeholder ? t.placeholder : fo.DEFAULT_PLACEHOLDER, this._data = e ?? {}, this._element = null, this._preserveBlank = t.preserveBlank ?? !1; + } + /** + * Check if text content is empty and set empty string to inner html. + * We need this because some browsers (e.g. Safari) insert
    into empty contenteditanle elements + * + * @param {KeyboardEvent} e - key up event + */ + onKeyUp(e) { + if (e.code !== "Backspace" && e.code !== "Delete" || !this._element) + return; + const { textContent: t } = this._element; + t === "" && (this._element.innerHTML = ""); + } + /** + * Create Tool's view + * + * @returns {HTMLDivElement} + * @private + */ + drawView() { + const e = document.createElement("DIV"); + return e.classList.add(this._CSS.wrapper, this._CSS.block), e.contentEditable = "false", e.dataset.placeholderActive = this.api.i18n.t(this._placeholder), this._data.text && (e.innerHTML = this._data.text), this.readOnly || (e.contentEditable = "true", e.addEventListener("keyup", this.onKeyUp)), e; + } + /** + * Return Tool's view + * + * @returns {HTMLDivElement} + */ + render() { + return this._element = this.drawView(), this._element; + } + /** + * Method that specified how to merge two Text blocks. + * Called by Editor.js by backspace at the beginning of the Block + * + * @param {ParagraphData} data + * @public + */ + merge(e) { + if (!this._element) + return; + this._data.text += e.text; + const t = va(e.text); + this._element.appendChild(t), this._element.normalize(); + } + /** + * Validate Paragraph block data: + * - check for emptiness + * + * @param {ParagraphData} savedData — data received after saving + * @returns {boolean} false if saved data is not correct, otherwise true + * @public + */ + validate(e) { + return !(e.text.trim() === "" && !this._preserveBlank); + } + /** + * Extract Tool's data from the view + * + * @param {HTMLDivElement} toolsContent - Paragraph tools rendered view + * @returns {ParagraphData} - saved data + * @public + */ + save(e) { + return { + text: e.innerHTML + }; + } + /** + * On paste callback fired from Editor. + * + * @param {HTMLPasteEvent} event - event with pasted data + */ + onPaste(e) { + const t = { + text: e.detail.data.innerHTML + }; + this._data = t, window.requestAnimationFrame(() => { + this._element && (this._element.innerHTML = this._data.text || ""); + }); + } + /** + * Enable Conversion Toolbar. Paragraph can be converted to/from other tools + * @returns {ConversionConfig} + */ + static get conversionConfig() { + return { + export: "text", + // to convert Paragraph to other block, use 'text' property of saved data + import: "text" + // to covert other block's exported string to Paragraph, fill 'text' property of tool data + }; + } + /** + * Sanitizer rules + * @returns {SanitizerConfig} - Edtior.js sanitizer config + */ + static get sanitize() { + return { + text: { + br: !0 + } + }; + } + /** + * Returns true to notify the core that read-only mode is supported + * + * @returns {boolean} + */ + static get isReadOnlySupported() { + return !0; + } + /** + * Used by Editor paste handling API. + * Provides configuration to handle P tags. + * + * @returns {PasteConfig} - Paragraph Paste Setting + */ + static get pasteConfig() { + return { + tags: ["P"] + }; + } + /** + * Icon and title for displaying at the Toolbox + * + * @returns {ToolboxConfig} - Paragraph Toolbox Setting + */ + static get toolbox() { + return { + icon: ba, + title: "Text" + }; + } +} +class go { + constructor() { + this.commandName = "bold"; + } + /** + * Sanitizer Rule + * Leave tags + * + * @returns {object} + */ + static get sanitize() { + return { + b: {} + }; + } + /** + * Create button for Inline Toolbar + */ + render() { + return { + icon: Ki, + name: "bold", + onActivate: () => { + document.execCommand(this.commandName); + }, + isActive: () => document.queryCommandState(this.commandName) + }; + } + /** + * Set a shortcut + * + * @returns {boolean} + */ + get shortcut() { + return "CMD+B"; + } +} +go.isInline = !0; +go.title = "Bold"; +class mo { + constructor() { + this.commandName = "italic", this.CSS = { + button: "ce-inline-tool", + buttonActive: "ce-inline-tool--active", + buttonModifier: "ce-inline-tool--italic" + }, this.nodes = { + button: null + }; + } + /** + * Sanitizer Rule + * Leave tags + * + * @returns {object} + */ + static get sanitize() { + return { + i: {} + }; + } + /** + * Create button for Inline Toolbar + */ + render() { + return this.nodes.button = document.createElement("button"), this.nodes.button.type = "button", this.nodes.button.classList.add(this.CSS.button, this.CSS.buttonModifier), this.nodes.button.innerHTML = Ji, this.nodes.button; + } + /** + * Wrap range with tag + */ + surround() { + document.execCommand(this.commandName); + } + /** + * Check selection and set activated state to button if there are tag + */ + checkState() { + const e = document.queryCommandState(this.commandName); + return this.nodes.button.classList.toggle(this.CSS.buttonActive, e), e; + } + /** + * Set a shortcut + */ + get shortcut() { + return "CMD+I"; + } +} +mo.isInline = !0; +mo.title = "Italic"; +class bo { + /** + * @param api - Editor.js API + */ + constructor({ api: e }) { + this.commandLink = "createLink", this.commandUnlink = "unlink", this.ENTER_KEY = 13, this.CSS = { + button: "ce-inline-tool", + buttonActive: "ce-inline-tool--active", + buttonModifier: "ce-inline-tool--link", + buttonUnlink: "ce-inline-tool--unlink", + input: "ce-inline-tool-input", + inputShowed: "ce-inline-tool-input--showed" + }, this.nodes = { + button: null, + input: null + }, this.inputOpened = !1, this.toolbar = e.toolbar, this.inlineToolbar = e.inlineToolbar, this.notifier = e.notifier, this.i18n = e.i18n, this.selection = new b(); + } + /** + * Sanitizer Rule + * Leave tags + * + * @returns {object} + */ + static get sanitize() { + return { + a: { + href: !0, + target: "_blank", + rel: "nofollow" + } + }; + } + /** + * Create button for Inline Toolbar + */ + render() { + return this.nodes.button = document.createElement("button"), this.nodes.button.type = "button", this.nodes.button.classList.add(this.CSS.button, this.CSS.buttonModifier), this.nodes.button.innerHTML = Co, this.nodes.button; + } + /** + * Input for the link + */ + renderActions() { + return this.nodes.input = document.createElement("input"), this.nodes.input.placeholder = this.i18n.t("Add a link"), this.nodes.input.enterKeyHint = "done", this.nodes.input.classList.add(this.CSS.input), this.nodes.input.addEventListener("keydown", (e) => { + e.keyCode === this.ENTER_KEY && this.enterPressed(e); + }), this.nodes.input; + } + /** + * Handle clicks on the Inline Toolbar icon + * + * @param {Range} range - range to wrap with link + */ + surround(e) { + if (e) { + this.inputOpened ? (this.selection.restore(), this.selection.removeFakeBackground()) : (this.selection.setFakeBackground(), this.selection.save()); + const t = this.selection.findParentTag("A"); + if (t) { + this.selection.expandToTag(t), this.unlink(), this.closeActions(), this.checkState(), this.toolbar.close(); + return; + } + } + this.toggleActions(); + } + /** + * Check selection and set activated state to button if there are tag + */ + checkState() { + const e = this.selection.findParentTag("A"); + if (e) { + this.nodes.button.innerHTML = ns, this.nodes.button.classList.add(this.CSS.buttonUnlink), this.nodes.button.classList.add(this.CSS.buttonActive), this.openActions(); + const t = e.getAttribute("href"); + this.nodes.input.value = t !== "null" ? t : "", this.selection.save(); + } else + this.nodes.button.innerHTML = Co, this.nodes.button.classList.remove(this.CSS.buttonUnlink), this.nodes.button.classList.remove(this.CSS.buttonActive); + return !!e; + } + /** + * Function called with Inline Toolbar closing + */ + clear() { + this.closeActions(); + } + /** + * Set a shortcut + */ + get shortcut() { + return "CMD+K"; + } + /** + * Show/close link input + */ + toggleActions() { + this.inputOpened ? this.closeActions(!1) : this.openActions(!0); + } + /** + * @param {boolean} needFocus - on link creation we need to focus input. On editing - nope. + */ + openActions(e = !1) { + this.nodes.input.classList.add(this.CSS.inputShowed), e && this.nodes.input.focus(), this.inputOpened = !0; + } + /** + * Close input + * + * @param {boolean} clearSavedSelection — we don't need to clear saved selection + * on toggle-clicks on the icon of opened Toolbar + */ + closeActions(e = !0) { + if (this.selection.isFakeBackgroundEnabled) { + const t = new b(); + t.save(), this.selection.restore(), this.selection.removeFakeBackground(), t.restore(); + } + this.nodes.input.classList.remove(this.CSS.inputShowed), this.nodes.input.value = "", e && this.selection.clearSaved(), this.inputOpened = !1; + } + /** + * Enter pressed on input + * + * @param {KeyboardEvent} event - enter keydown event + */ + enterPressed(e) { + let t = this.nodes.input.value || ""; + if (!t.trim()) { + this.selection.restore(), this.unlink(), e.preventDefault(), this.closeActions(); + return; + } + if (!this.validateURL(t)) { + this.notifier.show({ + message: "Pasted link is not valid.", + style: "error" + }), S("Incorrect Link pasted", "warn", t); + return; + } + t = this.prepareLink(t), this.selection.restore(), this.selection.removeFakeBackground(), this.insertLink(t), e.preventDefault(), e.stopPropagation(), e.stopImmediatePropagation(), this.selection.collapseToEnd(), this.inlineToolbar.close(); + } + /** + * Detects if passed string is URL + * + * @param {string} str - string to validate + * @returns {boolean} + */ + validateURL(e) { + return !/\s/.test(e); + } + /** + * Process link before injection + * - sanitize + * - add protocol for links like 'google.com' + * + * @param {string} link - raw user input + */ + prepareLink(e) { + return e = e.trim(), e = this.addProtocol(e), e; + } + /** + * Add 'http' protocol to the links like 'vc.ru', 'google.com' + * + * @param {string} link - string to process + */ + addProtocol(e) { + if (/^(\w+):(\/\/)?/.test(e)) + return e; + const t = /^\/[^/\s]/.test(e), o = e.substring(0, 1) === "#", i = /^\/\/[^/\s]/.test(e); + return !t && !o && !i && (e = "http://" + e), e; + } + /** + * Inserts tag with "href" + * + * @param {string} link - "href" value + */ + insertLink(e) { + const t = this.selection.findParentTag("A"); + t && this.selection.expandToTag(t), document.execCommand(this.commandLink, !1, e); + } + /** + * Removes tag + */ + unlink() { + document.execCommand(this.commandUnlink); + } +} +bo.isInline = !0; +bo.title = "Link"; +class Fn { + /** + * @param api - Editor.js API + */ + constructor({ api: e }) { + this.i18nAPI = e.i18n, this.blocksAPI = e.blocks, this.selectionAPI = e.selection, this.toolsAPI = e.tools, this.caretAPI = e.caret; + } + /** + * Returns tool's UI config + */ + async render() { + const e = b.get(), t = this.blocksAPI.getBlockByElement(e.anchorNode); + if (t === void 0) + return []; + const o = this.toolsAPI.getBlockTools(), i = await Yo(t, o); + if (i.length === 0) + return []; + const s = i.reduce((c, d) => { + var h; + return (h = d.toolbox) == null || h.forEach((p) => { + c.push({ + icon: p.icon, + title: z.t(K.toolNames, p.title), + name: d.name, + closeOnActivate: !0, + onActivate: async () => { + const g = await this.blocksAPI.convert(t.id, d.name, p.data); + this.caretAPI.setToBlock(g, "end"); + } + }); + }), c; + }, []), r = await t.getActiveToolboxEntry(), a = r !== void 0 ? r.icon : Go, l = !be(); + return { + icon: a, + name: "convert-to", + hint: { + title: this.i18nAPI.t("Convert to") + }, + children: { + searchable: l, + items: s, + onOpen: () => { + l && (this.selectionAPI.setFakeBackground(), this.selectionAPI.save()); + }, + onClose: () => { + l && (this.selectionAPI.restore(), this.selectionAPI.removeFakeBackground()); + } + } + }; + } +} +Fn.isInline = !0; +class jn { + /** + * @param options - constructor options + * @param options.data - stub tool data + * @param options.api - Editor.js API + */ + constructor({ data: e, api: t }) { + this.CSS = { + wrapper: "ce-stub", + info: "ce-stub__info", + title: "ce-stub__title", + subtitle: "ce-stub__subtitle" + }, this.api = t, this.title = e.title || this.api.i18n.t("Error"), this.subtitle = this.api.i18n.t("The block can not be displayed correctly."), this.savedData = e.savedData, this.wrapper = this.make(); + } + /** + * Returns stub holder + * + * @returns {HTMLElement} + */ + render() { + return this.wrapper; + } + /** + * Return original Tool data + * + * @returns {BlockToolData} + */ + save() { + return this.savedData; + } + /** + * Create Tool html markup + * + * @returns {HTMLElement} + */ + make() { + const e = u.make("div", this.CSS.wrapper), t = is, o = u.make("div", this.CSS.info), i = u.make("div", this.CSS.title, { + textContent: this.title + }), s = u.make("div", this.CSS.subtitle, { + textContent: this.subtitle + }); + return e.innerHTML = t, o.appendChild(i), o.appendChild(s), e.appendChild(o), e; + } +} +jn.isReadOnlySupported = !0; +class ka extends Tt { + constructor() { + super(...arguments), this.type = ae.Inline; + } + /** + * Returns title for Inline Tool if specified by user + */ + get title() { + return this.constructable[We.Title]; + } + /** + * Constructs new InlineTool instance from constructable + */ + create() { + return new this.constructable({ + api: this.api, + config: this.settings + }); + } + /** + * Allows inline tool to be available in read-only mode + * Can be used, for example, by comments tool + */ + get isReadOnlySupported() { + return this.constructable[We.IsReadOnlySupported] ?? !1; + } +} +class ya extends Tt { + constructor() { + super(...arguments), this.type = ae.Tune; + } + /** + * Constructs new BlockTune instance from constructable + * + * @param data - Tune data + * @param block - Block API object + */ + create(e, t) { + return new this.constructable({ + api: this.api, + config: this.settings, + block: t, + data: e + }); + } +} +class j extends Map { + /** + * Returns Block Tools collection + */ + get blockTools() { + const e = Array.from(this.entries()).filter(([, t]) => t.isBlock()); + return new j(e); + } + /** + * Returns Inline Tools collection + */ + get inlineTools() { + const e = Array.from(this.entries()).filter(([, t]) => t.isInline()); + return new j(e); + } + /** + * Returns Block Tunes collection + */ + get blockTunes() { + const e = Array.from(this.entries()).filter(([, t]) => t.isTune()); + return new j(e); + } + /** + * Returns internal Tools collection + */ + get internalTools() { + const e = Array.from(this.entries()).filter(([, t]) => t.isInternal); + return new j(e); + } + /** + * Returns Tools collection provided by user + */ + get externalTools() { + const e = Array.from(this.entries()).filter(([, t]) => !t.isInternal); + return new j(e); + } +} +var wa = Object.defineProperty, Ea = Object.getOwnPropertyDescriptor, Hn = (n, e, t, o) => { + for (var i = o > 1 ? void 0 : o ? Ea(e, t) : e, s = n.length - 1, r; s >= 0; s--) + (r = n[s]) && (i = (o ? r(e, t, i) : r(i)) || i); + return o && i && wa(e, t, i), i; +}; +class vo extends Tt { + constructor() { + super(...arguments), this.type = ae.Block, this.inlineTools = new j(), this.tunes = new j(); + } + /** + * Creates new Tool instance + * + * @param data - Tool data + * @param block - BlockAPI for current Block + * @param readOnly - True if Editor is in read-only mode + */ + create(e, t, o) { + return new this.constructable({ + data: e, + block: t, + readOnly: o, + api: this.api, + config: this.settings + }); + } + /** + * Returns true if read-only mode is supported by Tool + */ + get isReadOnlySupported() { + return this.constructable[pe.IsReadOnlySupported] === !0; + } + /** + * Returns true if Tool supports linebreaks + */ + get isLineBreaksEnabled() { + return this.constructable[pe.IsEnabledLineBreaks]; + } + /** + * Returns Tool toolbox configuration (internal or user-specified). + * + * Merges internal and user-defined toolbox configs based on the following rules: + * + * - If both internal and user-defined toolbox configs are arrays their items are merged. + * Length of the second one is kept. + * + * - If both are objects their properties are merged. + * + * - If one is an object and another is an array than internal config is replaced with user-defined + * config. This is made to allow user to override default tool's toolbox representation (single/multiple entries) + */ + get toolbox() { + const e = this.constructable[pe.Toolbox], t = this.config[Pe.Toolbox]; + if (!V(e) && t !== !1) + return t ? Array.isArray(e) ? Array.isArray(t) ? t.map((o, i) => { + const s = e[i]; + return s ? { + ...s, + ...o + } : o; + }) : [t] : Array.isArray(t) ? t : [ + { + ...e, + ...t + } + ] : Array.isArray(e) ? e : [e]; + } + /** + * Returns Tool conversion configuration + */ + get conversionConfig() { + return this.constructable[pe.ConversionConfig]; + } + /** + * Returns enabled inline tools for Tool + */ + get enabledInlineTools() { + return this.config[Pe.EnabledInlineTools] || !1; + } + /** + * Returns enabled tunes for Tool + */ + get enabledBlockTunes() { + return this.config[Pe.EnabledBlockTunes]; + } + /** + * Returns Tool paste configuration + */ + get pasteConfig() { + return this.constructable[pe.PasteConfig] ?? {}; + } + get sanitizeConfig() { + const e = super.sanitizeConfig, t = this.baseSanitizeConfig; + if (V(e)) + return t; + const o = {}; + for (const i in e) + if (Object.prototype.hasOwnProperty.call(e, i)) { + const s = e[i]; + D(s) ? o[i] = Object.assign({}, t, s) : o[i] = s; + } + return o; + } + get baseSanitizeConfig() { + const e = {}; + return Array.from(this.inlineTools.values()).forEach((t) => Object.assign(e, t.sanitizeConfig)), Array.from(this.tunes.values()).forEach((t) => Object.assign(e, t.sanitizeConfig)), e; + } +} +Hn([ + me +], vo.prototype, "sanitizeConfig", 1); +Hn([ + me +], vo.prototype, "baseSanitizeConfig", 1); +class xa { + /** + * @class + * @param config - tools config + * @param editorConfig - EditorJS config + * @param api - EditorJS API module + */ + constructor(e, t, o) { + this.api = o, this.config = e, this.editorConfig = t; + } + /** + * Returns Tool object based on it's type + * + * @param name - tool name + */ + get(e) { + const { class: t, isInternal: o = !1, ...i } = this.config[e], s = this.getConstructor(t), r = t[mt.IsTune]; + return new s({ + name: e, + constructable: t, + config: i, + api: this.api.getMethodsForTool(e, r), + isDefault: e === this.editorConfig.defaultBlock, + defaultPlaceholder: this.editorConfig.placeholder, + isInternal: o + }); + } + /** + * Find appropriate Tool object constructor for Tool constructable + * + * @param constructable - Tools constructable + */ + getConstructor(e) { + switch (!0) { + case e[We.IsInline]: + return ka; + case e[mt.IsTune]: + return ya; + default: + return vo; + } + } +} +class $n { + /** + * MoveDownTune constructor + * + * @param {API} api — Editor's API + */ + constructor({ api: e }) { + this.CSS = { + animation: "wobble" + }, this.api = e; + } + /** + * Tune's appearance in block settings menu + */ + render() { + return { + icon: Xi, + title: this.api.i18n.t("Move down"), + onActivate: () => this.handleClick(), + name: "move-down" + }; + } + /** + * Handle clicks on 'move down' button + */ + handleClick() { + const e = this.api.blocks.getCurrentBlockIndex(), t = this.api.blocks.getBlockByIndex(e + 1); + if (!t) + throw new Error("Unable to move Block down since it is already the last"); + const o = t.holder, i = o.getBoundingClientRect(); + let s = Math.abs(window.innerHeight - o.offsetHeight); + i.top < window.innerHeight && (s = window.scrollY + o.offsetHeight), window.scrollTo(0, s), this.api.blocks.move(e + 1), this.api.toolbar.toggleBlockSettings(!0); + } +} +$n.isTune = !0; +class zn { + /** + * DeleteTune constructor + * + * @param {API} api - Editor's API + */ + constructor({ api: e }) { + this.api = e; + } + /** + * Tune's appearance in block settings menu + */ + render() { + return { + icon: Gi, + title: this.api.i18n.t("Delete"), + name: "delete", + confirmation: { + title: this.api.i18n.t("Click to delete"), + onActivate: () => this.handleClick() + } + }; + } + /** + * Delete block conditions passed + */ + handleClick() { + this.api.blocks.delete(); + } +} +zn.isTune = !0; +class Un { + /** + * MoveUpTune constructor + * + * @param {API} api - Editor's API + */ + constructor({ api: e }) { + this.CSS = { + animation: "wobble" + }, this.api = e; + } + /** + * Tune's appearance in block settings menu + */ + render() { + return { + icon: Zi, + title: this.api.i18n.t("Move up"), + onActivate: () => this.handleClick(), + name: "move-up" + }; + } + /** + * Move current block up + */ + handleClick() { + const e = this.api.blocks.getCurrentBlockIndex(), t = this.api.blocks.getBlockByIndex(e), o = this.api.blocks.getBlockByIndex(e - 1); + if (e === 0 || !t || !o) + throw new Error("Unable to move Block up since it is already the first"); + const i = t.holder, s = o.holder, r = i.getBoundingClientRect(), a = s.getBoundingClientRect(); + let l; + a.top > 0 ? l = Math.abs(r.top) - Math.abs(a.top) : l = Math.abs(r.top) + a.height, window.scrollBy(0, -1 * l), this.api.blocks.move(e - 1), this.api.toolbar.toggleBlockSettings(!0); + } +} +Un.isTune = !0; +var Ba = Object.defineProperty, Ca = Object.getOwnPropertyDescriptor, Ta = (n, e, t, o) => { + for (var i = o > 1 ? void 0 : o ? Ca(e, t) : e, s = n.length - 1, r; s >= 0; s--) + (r = n[s]) && (i = (o ? r(e, t, i) : r(i)) || i); + return o && i && Ba(e, t, i), i; +}; +class Wn extends E { + constructor() { + super(...arguments), this.stubTool = "stub", this.toolsAvailable = new j(), this.toolsUnavailable = new j(); + } + /** + * Returns available Tools + */ + get available() { + return this.toolsAvailable; + } + /** + * Returns unavailable Tools + */ + get unavailable() { + return this.toolsUnavailable; + } + /** + * Return Tools for the Inline Toolbar + */ + get inlineTools() { + return this.available.inlineTools; + } + /** + * Return editor block tools + */ + get blockTools() { + return this.available.blockTools; + } + /** + * Return available Block Tunes + * + * @returns {object} - object of Inline Tool's classes + */ + get blockTunes() { + return this.available.blockTunes; + } + /** + * Returns default Tool object + */ + get defaultTool() { + return this.blockTools.get(this.config.defaultBlock); + } + /** + * Returns internal tools + */ + get internal() { + return this.available.internalTools; + } + /** + * Creates instances via passed or default configuration + * + * @returns {Promise} + */ + async prepare() { + if (this.validateTools(), this.config.tools = ut({}, this.internalTools, this.config.tools), !Object.prototype.hasOwnProperty.call(this.config, "tools") || Object.keys(this.config.tools).length === 0) + throw Error("Can't start without tools"); + const e = this.prepareConfig(); + this.factory = new xa(e, this.config, this.Editor.API); + const t = this.getListOfPrepareFunctions(e); + if (t.length === 0) + return Promise.resolve(); + await Qn(t, (o) => { + this.toolPrepareMethodSuccess(o); + }, (o) => { + this.toolPrepareMethodFallback(o); + }), this.prepareBlockTools(); + } + getAllInlineToolsSanitizeConfig() { + const e = {}; + return Array.from(this.inlineTools.values()).forEach((t) => { + Object.assign(e, t.sanitizeConfig); + }), e; + } + /** + * Calls each Tool reset method to clean up anything set by Tool + */ + destroy() { + Object.values(this.available).forEach(async (e) => { + A(e.reset) && await e.reset(); + }); + } + /** + * Returns internal tools + * Includes Bold, Italic, Link and Paragraph + */ + get internalTools() { + return { + convertTo: { + class: Fn, + isInternal: !0 + }, + link: { + class: bo, + isInternal: !0 + }, + bold: { + class: go, + isInternal: !0 + }, + italic: { + class: mo, + isInternal: !0 + }, + paragraph: { + class: fo, + inlineToolbar: !0, + isInternal: !0 + }, + stub: { + class: jn, + isInternal: !0 + }, + moveUp: { + class: Un, + isInternal: !0 + }, + delete: { + class: zn, + isInternal: !0 + }, + moveDown: { + class: $n, + isInternal: !0 + } + }; + } + /** + * Tool prepare method success callback + * + * @param {object} data - append tool to available list + */ + toolPrepareMethodSuccess(e) { + const t = this.factory.get(e.toolName); + if (t.isInline()) { + const i = ["render"].filter((s) => !t.create()[s]); + if (i.length) { + S( + `Incorrect Inline Tool: ${t.name}. Some of required methods is not implemented %o`, + "warn", + i + ), this.toolsUnavailable.set(t.name, t); + return; + } + } + this.toolsAvailable.set(t.name, t); + } + /** + * Tool prepare method fail callback + * + * @param {object} data - append tool to unavailable list + */ + toolPrepareMethodFallback(e) { + this.toolsUnavailable.set(e.toolName, this.factory.get(e.toolName)); + } + /** + * Binds prepare function of plugins with user or default config + * + * @returns {Array} list of functions that needs to be fired sequentially + * @param config - tools config + */ + getListOfPrepareFunctions(e) { + const t = []; + return Object.entries(e).forEach(([o, i]) => { + t.push({ + // eslint-disable-next-line @typescript-eslint/no-empty-function + function: A(i.class.prepare) ? i.class.prepare : () => { + }, + data: { + toolName: o, + config: i.config + } + }); + }), t; + } + /** + * Assign enabled Inline Tools and Block Tunes for Block Tool + */ + prepareBlockTools() { + Array.from(this.blockTools.values()).forEach((e) => { + this.assignInlineToolsToBlockTool(e), this.assignBlockTunesToBlockTool(e); + }); + } + /** + * Assign enabled Inline Tools for Block Tool + * + * @param tool - Block Tool + */ + assignInlineToolsToBlockTool(e) { + if (this.config.inlineToolbar !== !1) { + if (e.enabledInlineTools === !0) { + e.inlineTools = new j( + Array.isArray(this.config.inlineToolbar) ? this.config.inlineToolbar.map((t) => [t, this.inlineTools.get(t)]) : Array.from(this.inlineTools.entries()) + ); + return; + } + Array.isArray(e.enabledInlineTools) && (e.inlineTools = new j( + /** Prepend ConvertTo Inline Tool */ + ["convertTo", ...e.enabledInlineTools].map((t) => [t, this.inlineTools.get(t)]) + )); + } + } + /** + * Assign enabled Block Tunes for Block Tool + * + * @param tool — Block Tool + */ + assignBlockTunesToBlockTool(e) { + if (e.enabledBlockTunes !== !1) { + if (Array.isArray(e.enabledBlockTunes)) { + const t = new j( + e.enabledBlockTunes.map((o) => [o, this.blockTunes.get(o)]) + ); + e.tunes = new j([...t, ...this.blockTunes.internalTools]); + return; + } + if (Array.isArray(this.config.tunes)) { + const t = new j( + this.config.tunes.map((o) => [o, this.blockTunes.get(o)]) + ); + e.tunes = new j([...t, ...this.blockTunes.internalTools]); + return; + } + e.tunes = this.blockTunes.internalTools; + } + } + /** + * Validate Tools configuration objects and throw Error for user if it is invalid + */ + validateTools() { + for (const e in this.config.tools) + if (Object.prototype.hasOwnProperty.call(this.config.tools, e)) { + if (e in this.internalTools) + return; + const t = this.config.tools[e]; + if (!A(t) && !A(t.class)) + throw Error( + `Tool «${e}» must be a constructor function or an object with function in the «class» property` + ); + } + } + /** + * Unify tools config + */ + prepareConfig() { + const e = {}; + for (const t in this.config.tools) + D(this.config.tools[t]) ? e[t] = this.config.tools[t] : e[t] = { class: this.config.tools[t] }; + return e; + } +} +Ta([ + me +], Wn.prototype, "getAllInlineToolsSanitizeConfig", 1); +const Sa = `:root{--selectionColor: #e1f2ff;--inlineSelectionColor: #d4ecff;--bg-light: #eff2f5;--grayText: #707684;--color-dark: #1D202B;--color-active-icon: #388AE5;--color-gray-border: rgba(201, 201, 204, .48);--content-width: 650px;--narrow-mode-right-padding: 50px;--toolbox-buttons-size: 26px;--toolbox-buttons-size--mobile: 36px;--icon-size: 20px;--icon-size--mobile: 28px;--block-padding-vertical: .4em;--color-line-gray: #EFF0F1 }.codex-editor{position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;z-index:1}.codex-editor .hide{display:none}.codex-editor__redactor [contenteditable]:empty:after{content:"\\feff"}@media (min-width: 651px){.codex-editor--narrow .codex-editor__redactor{margin-right:50px}}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .codex-editor__redactor{margin-left:50px;margin-right:0}}@media (min-width: 651px){.codex-editor--narrow .ce-toolbar__actions{right:-5px}}.codex-editor-copyable{position:absolute;height:1px;width:1px;top:-400%;opacity:.001}.codex-editor-overlay{position:fixed;top:0;left:0;right:0;bottom:0;z-index:999;pointer-events:none;overflow:hidden}.codex-editor-overlay__container{position:relative;pointer-events:auto;z-index:0}.codex-editor-overlay__rectangle{position:absolute;pointer-events:none;background-color:#2eaadc33;border:1px solid transparent}.codex-editor svg{max-height:100%}.codex-editor path{stroke:currentColor}.codex-editor ::-moz-selection{background-color:#d4ecff}.codex-editor ::selection{background-color:#d4ecff}.codex-editor--toolbox-opened [contentEditable=true][data-placeholder]:focus:before{opacity:0!important}.ce-scroll-locked{overflow:hidden}.ce-scroll-locked--hard{overflow:hidden;top:calc(-1 * var(--window-scroll-offset));position:fixed;width:100%}.ce-toolbar{position:absolute;left:0;right:0;top:0;-webkit-transition:opacity .1s ease;transition:opacity .1s ease;will-change:opacity,top;display:none}.ce-toolbar--opened{display:block}.ce-toolbar__content{max-width:650px;margin:0 auto;position:relative}.ce-toolbar__plus{color:#1d202b;cursor:pointer;width:26px;height:26px;border-radius:7px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-ms-flex-negative:0;flex-shrink:0}@media (max-width: 650px){.ce-toolbar__plus{width:36px;height:36px}}@media (hover: hover){.ce-toolbar__plus:hover{background-color:#eff2f5}}.ce-toolbar__plus--active{background-color:#eff2f5;-webkit-animation:bounceIn .75s 1;animation:bounceIn .75s 1;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.ce-toolbar__plus-shortcut{opacity:.6;word-spacing:-2px;margin-top:5px}@media (max-width: 650px){.ce-toolbar__plus{position:absolute;background-color:#fff;border:1px solid #E8E8EB;-webkit-box-shadow:0 3px 15px -3px rgba(13,20,33,.13);box-shadow:0 3px 15px -3px #0d142121;border-radius:6px;z-index:2;position:static}.ce-toolbar__plus--left-oriented:before{left:15px;margin-left:0}.ce-toolbar__plus--right-oriented:before{left:auto;right:15px;margin-left:0}}.ce-toolbar__actions{position:absolute;right:100%;opacity:0;display:-webkit-box;display:-ms-flexbox;display:flex;padding-right:5px}.ce-toolbar__actions--opened{opacity:1}@media (max-width: 650px){.ce-toolbar__actions{right:auto}}.ce-toolbar__settings-btn{color:#1d202b;width:26px;height:26px;border-radius:7px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;margin-left:3px;cursor:pointer;user-select:none}@media (max-width: 650px){.ce-toolbar__settings-btn{width:36px;height:36px}}@media (hover: hover){.ce-toolbar__settings-btn:hover{background-color:#eff2f5}}.ce-toolbar__settings-btn--active{background-color:#eff2f5;-webkit-animation:bounceIn .75s 1;animation:bounceIn .75s 1;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@media (min-width: 651px){.ce-toolbar__settings-btn{width:24px}}.ce-toolbar__settings-btn--hidden{display:none}@media (max-width: 650px){.ce-toolbar__settings-btn{position:absolute;background-color:#fff;border:1px solid #E8E8EB;-webkit-box-shadow:0 3px 15px -3px rgba(13,20,33,.13);box-shadow:0 3px 15px -3px #0d142121;border-radius:6px;z-index:2;position:static}.ce-toolbar__settings-btn--left-oriented:before{left:15px;margin-left:0}.ce-toolbar__settings-btn--right-oriented:before{left:auto;right:15px;margin-left:0}}.ce-toolbar__plus svg,.ce-toolbar__settings-btn svg{width:24px;height:24px}@media (min-width: 651px){.codex-editor--narrow .ce-toolbar__plus{left:5px}}@media (min-width: 651px){.codex-editor--narrow .ce-toolbox .ce-popover{right:0;left:auto;left:initial}}.ce-inline-toolbar{--y-offset: 8px;--color-background-icon-active: rgba(56, 138, 229, .1);--color-text-icon-active: #388AE5;--color-text-primary: black;position:absolute;visibility:hidden;-webkit-transition:opacity .25s ease;transition:opacity .25s ease;will-change:opacity,left,top;top:0;left:0;z-index:3;opacity:1;visibility:visible}.ce-inline-toolbar [hidden]{display:none!important}.ce-inline-toolbar__toggler-and-button-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;padding:0 6px}.ce-inline-toolbar__buttons{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-inline-toolbar__dropdown{display:-webkit-box;display:-ms-flexbox;display:flex;padding:6px;margin:0 6px 0 -6px;-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:pointer;border-right:1px solid rgba(201,201,204,.48);-webkit-box-sizing:border-box;box-sizing:border-box}@media (hover: hover){.ce-inline-toolbar__dropdown:hover{background:#eff2f5}}.ce-inline-toolbar__dropdown--hidden{display:none}.ce-inline-toolbar__dropdown-content,.ce-inline-toolbar__dropdown-arrow{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-inline-toolbar__dropdown-content svg,.ce-inline-toolbar__dropdown-arrow svg{width:20px;height:20px}.ce-inline-toolbar__shortcut{opacity:.6;word-spacing:-3px;margin-top:3px}.ce-inline-tool{color:var(--color-text-primary);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;border-radius:4px;line-height:normal;height:100%;padding:0;width:28px;background-color:transparent;cursor:pointer}@media (max-width: 650px){.ce-inline-tool{width:36px;height:36px}}@media (hover: hover){.ce-inline-tool:hover{background-color:#f8f8f8}}.ce-inline-tool svg{display:block;width:20px;height:20px}@media (max-width: 650px){.ce-inline-tool svg{width:28px;height:28px}}.ce-inline-tool--link .icon--unlink,.ce-inline-tool--unlink .icon--link{display:none}.ce-inline-tool--unlink .icon--unlink{display:inline-block;margin-bottom:-1px}.ce-inline-tool-input{background:#F8F8F8;border:1px solid rgba(226,226,229,.2);border-radius:6px;padding:4px 8px;font-size:14px;line-height:22px;outline:none;margin:0;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box;display:none;font-weight:500;-webkit-appearance:none;font-family:inherit}@media (max-width: 650px){.ce-inline-tool-input{font-size:15px;font-weight:500}}.ce-inline-tool-input::-webkit-input-placeholder{color:#707684}.ce-inline-tool-input::-moz-placeholder{color:#707684}.ce-inline-tool-input:-ms-input-placeholder{color:#707684}.ce-inline-tool-input::-ms-input-placeholder{color:#707684}.ce-inline-tool-input::placeholder{color:#707684}.ce-inline-tool-input--showed{display:block}.ce-inline-tool--active{background:var(--color-background-icon-active);color:var(--color-text-icon-active)}@-webkit-keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.ce-block{-webkit-animation:fade-in .3s ease;animation:fade-in .3s ease;-webkit-animation-fill-mode:none;animation-fill-mode:none;-webkit-animation-fill-mode:initial;animation-fill-mode:initial}.ce-block:first-of-type{margin-top:0}.ce-block--selected .ce-block__content{background:#e1f2ff}.ce-block--selected .ce-block__content [contenteditable]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ce-block--selected .ce-block__content img,.ce-block--selected .ce-block__content .ce-stub{opacity:.55}.ce-block--stretched .ce-block__content{max-width:none}.ce-block__content{position:relative;max-width:650px;margin:0 auto;-webkit-transition:background-color .15s ease;transition:background-color .15s ease}.ce-block--drop-target .ce-block__content:before{content:"";position:absolute;top:100%;left:-20px;margin-top:-1px;height:8px;width:8px;border:solid #388AE5;border-width:1px 1px 0 0;-webkit-transform-origin:right;transform-origin:right;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.ce-block--drop-target .ce-block__content:after{content:"";position:absolute;top:100%;height:1px;width:100%;color:#388ae5;background:repeating-linear-gradient(90deg,#388AE5,#388AE5 1px,#fff 1px,#fff 6px)}.ce-block a{cursor:pointer;-webkit-text-decoration:underline;text-decoration:underline}.ce-block b{font-weight:700}.ce-block i{font-style:italic}@-webkit-keyframes bounceIn{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}20%{-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}60%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes bounceIn{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}20%{-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}60%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@-webkit-keyframes selectionBounce{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}50%{-webkit-transform:scale3d(1.01,1.01,1.01);transform:scale3d(1.01,1.01,1.01)}70%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes selectionBounce{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}50%{-webkit-transform:scale3d(1.01,1.01,1.01);transform:scale3d(1.01,1.01,1.01)}70%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@-webkit-keyframes buttonClicked{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.95,.95,.95);transform:scale3d(.95,.95,.95)}60%{-webkit-transform:scale3d(1.02,1.02,1.02);transform:scale3d(1.02,1.02,1.02)}80%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes buttonClicked{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.95,.95,.95);transform:scale3d(.95,.95,.95)}60%{-webkit-transform:scale3d(1.02,1.02,1.02);transform:scale3d(1.02,1.02,1.02)}80%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}.cdx-block{padding:.4em 0}.cdx-block::-webkit-input-placeholder{line-height:normal!important}.cdx-input{border:1px solid rgba(201,201,204,.48);-webkit-box-shadow:inset 0 1px 2px 0 rgba(35,44,72,.06);box-shadow:inset 0 1px 2px #232c480f;border-radius:3px;padding:10px 12px;outline:none;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.cdx-input[data-placeholder]:before{position:static!important}.cdx-input[data-placeholder]:before{display:inline-block;width:0;white-space:nowrap;pointer-events:none}.cdx-settings-button{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;border-radius:3px;cursor:pointer;border:0;outline:none;background-color:transparent;vertical-align:bottom;color:inherit;margin:0;min-width:26px;min-height:26px}.cdx-settings-button--focused{background:rgba(34,186,255,.08)!important}.cdx-settings-button--focused{-webkit-box-shadow:inset 0 0 0px 1px rgba(7,161,227,.08);box-shadow:inset 0 0 0 1px #07a1e314}.cdx-settings-button--focused-animated{-webkit-animation-name:buttonClicked;animation-name:buttonClicked;-webkit-animation-duration:.25s;animation-duration:.25s}.cdx-settings-button--active{color:#388ae5}.cdx-settings-button svg{width:auto;height:auto}@media (max-width: 650px){.cdx-settings-button svg{width:28px;height:28px}}@media (max-width: 650px){.cdx-settings-button{width:36px;height:36px;border-radius:8px}}@media (hover: hover){.cdx-settings-button:hover{background-color:#eff2f5}}.cdx-loader{position:relative;border:1px solid rgba(201,201,204,.48)}.cdx-loader:before{content:"";position:absolute;left:50%;top:50%;width:18px;height:18px;margin:-11px 0 0 -11px;border:2px solid rgba(201,201,204,.48);border-left-color:#388ae5;border-radius:50%;-webkit-animation:cdxRotation 1.2s infinite linear;animation:cdxRotation 1.2s infinite linear}@-webkit-keyframes cdxRotation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes cdxRotation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.cdx-button{padding:13px;border-radius:3px;border:1px solid rgba(201,201,204,.48);font-size:14.9px;background:#fff;-webkit-box-shadow:0 2px 2px 0 rgba(18,30,57,.04);box-shadow:0 2px 2px #121e390a;color:#707684;text-align:center;cursor:pointer}@media (hover: hover){.cdx-button:hover{background:#FBFCFE;-webkit-box-shadow:0 1px 3px 0 rgba(18,30,57,.08);box-shadow:0 1px 3px #121e3914}}.cdx-button svg{height:20px;margin-right:.2em;margin-top:-2px}.ce-stub{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:12px 18px;margin:10px 0;border-radius:10px;background:#eff2f5;border:1px solid #EFF0F1;color:#707684;font-size:14px}.ce-stub svg{width:20px;height:20px}.ce-stub__info{margin-left:14px}.ce-stub__title{font-weight:500;text-transform:capitalize}.codex-editor.codex-editor--rtl{direction:rtl}.codex-editor.codex-editor--rtl .cdx-list{padding-left:0;padding-right:40px}.codex-editor.codex-editor--rtl .ce-toolbar__plus{right:-26px;left:auto}.codex-editor.codex-editor--rtl .ce-toolbar__actions{right:auto;left:-26px}@media (max-width: 650px){.codex-editor.codex-editor--rtl .ce-toolbar__actions{margin-left:0;margin-right:auto;padding-right:0;padding-left:10px}}.codex-editor.codex-editor--rtl .ce-settings{left:5px;right:auto}.codex-editor.codex-editor--rtl .ce-settings:before{right:auto;left:25px}.codex-editor.codex-editor--rtl .ce-settings__button:not(:nth-child(3n+3)){margin-left:3px;margin-right:0}.codex-editor.codex-editor--rtl .ce-conversion-tool__icon{margin-right:0;margin-left:10px}.codex-editor.codex-editor--rtl .ce-inline-toolbar__dropdown{border-right:0px solid transparent;border-left:1px solid rgba(201,201,204,.48);margin:0 -6px 0 6px}.codex-editor.codex-editor--rtl .ce-inline-toolbar__dropdown .icon--toggler-down{margin-left:0;margin-right:4px}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .ce-toolbar__plus{left:0;right:5px}}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .ce-toolbar__actions{left:-5px}}.cdx-search-field{--icon-margin-right: 10px;background:#F8F8F8;border:1px solid rgba(226,226,229,.2);border-radius:6px;padding:2px;display:grid;grid-template-columns:auto auto 1fr;grid-template-rows:auto}.cdx-search-field__icon{width:26px;height:26px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-right:var(--icon-margin-right)}.cdx-search-field__icon svg{width:20px;height:20px;color:#707684}.cdx-search-field__input{font-size:14px;outline:none;font-weight:500;font-family:inherit;border:0;background:transparent;margin:0;padding:0;line-height:22px;min-width:calc(100% - 26px - var(--icon-margin-right))}.cdx-search-field__input::-webkit-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::-moz-placeholder{color:#707684;font-weight:500}.cdx-search-field__input:-ms-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::-ms-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::placeholder{color:#707684;font-weight:500}.ce-popover{--border-radius: 6px;--width: 200px;--max-height: 270px;--padding: 6px;--offset-from-target: 8px;--color-border: #EFF0F1;--color-shadow: rgba(13, 20, 33, .1);--color-background: white;--color-text-primary: black;--color-text-secondary: #707684;--color-border-icon: rgba(201, 201, 204, .48);--color-border-icon-disabled: #EFF0F1;--color-text-icon-active: #388AE5;--color-background-icon-active: rgba(56, 138, 229, .1);--color-background-item-focus: rgba(34, 186, 255, .08);--color-shadow-item-focus: rgba(7, 161, 227, .08);--color-background-item-hover: #F8F8F8;--color-background-item-confirm: #E24A4A;--color-background-item-confirm-hover: #CE4343;--popover-top: calc(100% + var(--offset-from-target));--popover-left: 0;--nested-popover-overlap: 4px;--icon-size: 20px;--item-padding: 3px;--item-height: calc(var(--icon-size) + 2 * var(--item-padding))}.ce-popover__container{min-width:var(--width);width:var(--width);max-height:var(--max-height);border-radius:var(--border-radius);overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-box-shadow:0px 3px 15px -3px var(--color-shadow);box-shadow:0 3px 15px -3px var(--color-shadow);position:absolute;left:var(--popover-left);top:var(--popover-top);background:var(--color-background);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;z-index:4;opacity:0;max-height:0;pointer-events:none;padding:0;border:none}.ce-popover--opened>.ce-popover__container{opacity:1;padding:var(--padding);max-height:var(--max-height);pointer-events:auto;-webkit-animation:panelShowing .1s ease;animation:panelShowing .1s ease;border:1px solid var(--color-border)}@media (max-width: 650px){.ce-popover--opened>.ce-popover__container{-webkit-animation:panelShowingMobile .25s ease;animation:panelShowingMobile .25s ease}}.ce-popover--open-top .ce-popover__container{--popover-top: calc(-1 * (var(--offset-from-target) + var(--popover-height)))}.ce-popover--open-left .ce-popover__container{--popover-left: calc(-1 * var(--width) + 100%)}.ce-popover__items{overflow-y:auto;-ms-scroll-chaining:none;overscroll-behavior:contain}@media (max-width: 650px){.ce-popover__overlay{position:fixed;top:0;bottom:0;left:0;right:0;background:#1D202B;z-index:3;opacity:.5;-webkit-transition:opacity .12s ease-in;transition:opacity .12s ease-in;will-change:opacity;visibility:visible}}.ce-popover__overlay--hidden{display:none}@media (max-width: 650px){.ce-popover .ce-popover__container{--offset: 5px;position:fixed;max-width:none;min-width:calc(100% - var(--offset) * 2);left:var(--offset);right:var(--offset);bottom:calc(var(--offset) + env(safe-area-inset-bottom));top:auto;border-radius:10px}}.ce-popover__search{margin-bottom:5px}.ce-popover__nothing-found-message{color:#707684;display:none;cursor:default;padding:3px;font-size:14px;line-height:20px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ce-popover__nothing-found-message--displayed{display:block}.ce-popover--nested .ce-popover__container{--popover-left: calc(var(--nesting-level) * (var(--width) - var(--nested-popover-overlap)));top:calc(var(--trigger-item-top) - var(--nested-popover-overlap));position:absolute}.ce-popover--open-top.ce-popover--nested .ce-popover__container{top:calc(var(--trigger-item-top) - var(--popover-height) + var(--item-height) + var(--offset-from-target) + var(--nested-popover-overlap))}.ce-popover--open-left .ce-popover--nested .ce-popover__container{--popover-left: calc(-1 * (var(--nesting-level) + 1) * var(--width) + 100%)}.ce-popover-item-separator{padding:4px 3px}.ce-popover-item-separator--hidden{display:none}.ce-popover-item-separator__line{height:1px;background:var(--color-border);width:100%}.ce-popover-item-html--hidden{display:none}.ce-popover-item{--border-radius: 6px;border-radius:var(--border-radius);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:var(--item-padding);color:var(--color-text-primary);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:none;background:transparent}@media (max-width: 650px){.ce-popover-item{padding:4px}}.ce-popover-item:not(:last-of-type){margin-bottom:1px}.ce-popover-item__icon{width:26px;height:26px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.ce-popover-item__icon svg{width:20px;height:20px}@media (max-width: 650px){.ce-popover-item__icon{width:36px;height:36px;border-radius:8px}.ce-popover-item__icon svg{width:28px;height:28px}}.ce-popover-item__icon--tool{margin-right:4px}.ce-popover-item__title{font-size:14px;line-height:20px;font-weight:500;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-right:auto}@media (max-width: 650px){.ce-popover-item__title{font-size:16px}}.ce-popover-item__secondary-title{color:var(--color-text-secondary);font-size:12px;white-space:nowrap;letter-spacing:-.1em;padding-right:5px;opacity:.6}@media (max-width: 650px){.ce-popover-item__secondary-title{display:none}}.ce-popover-item--active{background:var(--color-background-icon-active);color:var(--color-text-icon-active)}.ce-popover-item--disabled{color:var(--color-text-secondary);cursor:default;pointer-events:none}.ce-popover-item--focused:not(.ce-popover-item--no-focus){background:var(--color-background-item-focus)!important}.ce-popover-item--hidden{display:none}@media (hover: hover){.ce-popover-item:hover{cursor:pointer}.ce-popover-item:hover:not(.ce-popover-item--no-hover){background-color:var(--color-background-item-hover)}}.ce-popover-item--confirmation{background:var(--color-background-item-confirm)}.ce-popover-item--confirmation .ce-popover-item__title,.ce-popover-item--confirmation .ce-popover-item__icon{color:#fff}@media (hover: hover){.ce-popover-item--confirmation:not(.ce-popover-item--no-hover):hover{background:var(--color-background-item-confirm-hover)}}.ce-popover-item--confirmation:not(.ce-popover-item--no-focus).ce-popover-item--focused{background:var(--color-background-item-confirm-hover)!important}@-webkit-keyframes panelShowing{0%{opacity:0;-webkit-transform:translateY(-8px) scale(.9);transform:translateY(-8px) scale(.9)}70%{opacity:1;-webkit-transform:translateY(2px);transform:translateY(2px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes panelShowing{0%{opacity:0;-webkit-transform:translateY(-8px) scale(.9);transform:translateY(-8px) scale(.9)}70%{opacity:1;-webkit-transform:translateY(2px);transform:translateY(2px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes panelShowingMobile{0%{opacity:0;-webkit-transform:translateY(14px) scale(.98);transform:translateY(14px) scale(.98)}70%{opacity:1;-webkit-transform:translateY(-4px);transform:translateY(-4px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes panelShowingMobile{0%{opacity:0;-webkit-transform:translateY(14px) scale(.98);transform:translateY(14px) scale(.98)}70%{opacity:1;-webkit-transform:translateY(-4px);transform:translateY(-4px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}.wobble{-webkit-animation-name:wobble;animation-name:wobble;-webkit-animation-duration:.4s;animation-duration:.4s}@-webkit-keyframes wobble{0%{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}15%{-webkit-transform:translate3d(-9%,0,0);transform:translate3d(-9%,0,0)}30%{-webkit-transform:translate3d(9%,0,0);transform:translate3d(9%,0,0)}45%{-webkit-transform:translate3d(-4%,0,0);transform:translate3d(-4%,0,0)}60%{-webkit-transform:translate3d(4%,0,0);transform:translate3d(4%,0,0)}75%{-webkit-transform:translate3d(-1%,0,0);transform:translate3d(-1%,0,0)}to{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}}@keyframes wobble{0%{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}15%{-webkit-transform:translate3d(-9%,0,0);transform:translate3d(-9%,0,0)}30%{-webkit-transform:translate3d(9%,0,0);transform:translate3d(9%,0,0)}45%{-webkit-transform:translate3d(-4%,0,0);transform:translate3d(-4%,0,0)}60%{-webkit-transform:translate3d(4%,0,0);transform:translate3d(4%,0,0)}75%{-webkit-transform:translate3d(-1%,0,0);transform:translate3d(-1%,0,0)}to{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}}.ce-popover-header{margin-bottom:8px;margin-top:4px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.ce-popover-header__text{font-size:18px;font-weight:600}.ce-popover-header__back-button{border:0;background:transparent;width:36px;height:36px;color:var(--color-text-primary)}.ce-popover-header__back-button svg{display:block;width:28px;height:28px}.ce-popover--inline{--height: 38px;--height-mobile: 46px;--container-padding: 4px;position:relative}.ce-popover--inline .ce-popover__custom-content{margin-bottom:0}.ce-popover--inline .ce-popover__items{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-popover--inline .ce-popover__container{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;padding:var(--container-padding);height:var(--height);top:0;min-width:-webkit-max-content;min-width:-moz-max-content;min-width:max-content;width:-webkit-max-content;width:-moz-max-content;width:max-content;-webkit-animation:none;animation:none}@media (max-width: 650px){.ce-popover--inline .ce-popover__container{height:var(--height-mobile);position:absolute}}.ce-popover--inline .ce-popover-item-separator{padding:0 4px}.ce-popover--inline .ce-popover-item-separator__line{height:100%;width:1px}.ce-popover--inline .ce-popover-item{border-radius:4px;padding:4px}.ce-popover--inline .ce-popover-item__icon--tool{-webkit-box-shadow:none;box-shadow:none;background:transparent;margin-right:0}.ce-popover--inline .ce-popover-item__icon{width:auto;width:initial;height:auto;height:initial}.ce-popover--inline .ce-popover-item__icon svg{width:20px;height:20px}@media (max-width: 650px){.ce-popover--inline .ce-popover-item__icon svg{width:28px;height:28px}}.ce-popover--inline .ce-popover-item:not(:last-of-type){margin-bottom:0;margin-bottom:initial}.ce-popover--inline .ce-popover-item-html{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.ce-popover--inline .ce-popover-item__icon--chevron-right{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.ce-popover--inline .ce-popover--nested-level-1 .ce-popover__container{--offset: 3px;left:0;top:calc(var(--height) + var(--offset))}@media (max-width: 650px){.ce-popover--inline .ce-popover--nested-level-1 .ce-popover__container{top:calc(var(--height-mobile) + var(--offset))}}.ce-popover--inline .ce-popover--nested .ce-popover__container{min-width:var(--width);width:var(--width);height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;padding:6px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.ce-popover--inline .ce-popover--nested .ce-popover__items{display:block;width:100%}.ce-popover--inline .ce-popover--nested .ce-popover-item{border-radius:6px;padding:3px}@media (max-width: 650px){.ce-popover--inline .ce-popover--nested .ce-popover-item{padding:4px}}.ce-popover--inline .ce-popover--nested .ce-popover-item__icon--tool{margin-right:4px}.ce-popover--inline .ce-popover--nested .ce-popover-item__icon{width:26px;height:26px}.ce-popover--inline .ce-popover--nested .ce-popover-item-separator{padding:4px 3px}.ce-popover--inline .ce-popover--nested .ce-popover-item-separator__line{width:100%;height:1px}.codex-editor [data-placeholder]:empty:before,.codex-editor [data-placeholder][data-empty=true]:before{pointer-events:none;color:#707684;cursor:text;content:attr(data-placeholder)}.codex-editor [data-placeholder-active]:empty:before,.codex-editor [data-placeholder-active][data-empty=true]:before{pointer-events:none;color:#707684;cursor:text}.codex-editor [data-placeholder-active]:empty:focus:before,.codex-editor [data-placeholder-active][data-empty=true]:focus:before{content:attr(data-placeholder-active)} +`; +class Ia extends E { + constructor() { + super(...arguments), this.isMobile = !1, this.contentRectCache = null, this.resizeDebouncer = Eo(() => { + this.windowResize(); + }, 200), this.selectionChangeDebounced = Eo(() => { + this.selectionChanged(); + }, da), this.documentTouchedListener = (e) => { + this.documentTouched(e); + }; + } + /** + * Editor.js UI CSS class names + * + * @returns {{editorWrapper: string, editorZone: string}} + */ + get CSS() { + return { + editorWrapper: "codex-editor", + editorWrapperNarrow: "codex-editor--narrow", + editorZone: "codex-editor__redactor", + editorZoneHidden: "codex-editor__redactor--hidden", + editorEmpty: "codex-editor--empty", + editorRtlFix: "codex-editor--rtl" + }; + } + /** + * Return Width of center column of Editor + * + * @returns {DOMRect} + */ + get contentRect() { + if (this.contentRectCache !== null) + return this.contentRectCache; + const e = this.nodes.wrapper.querySelector(`.${R.CSS.content}`); + return e ? (this.contentRectCache = e.getBoundingClientRect(), this.contentRectCache) : { + width: 650, + left: 0, + right: 0 + }; + } + /** + * Making main interface + */ + async prepare() { + this.setIsMobile(), this.make(), this.loadStyles(); + } + /** + * Toggle read-only state + * + * If readOnly is true: + * - removes all listeners from main UI module elements + * + * if readOnly is false: + * - enables all listeners to UI module elements + * + * @param {boolean} readOnlyEnabled - "read only" state + */ + toggleReadOnly(e) { + e ? this.unbindReadOnlySensitiveListeners() : window.requestIdleCallback(() => { + this.bindReadOnlySensitiveListeners(); + }, { + timeout: 2e3 + }); + } + /** + * Check if Editor is empty and set CSS class to wrapper + */ + checkEmptiness() { + const { BlockManager: e } = this.Editor; + this.nodes.wrapper.classList.toggle(this.CSS.editorEmpty, e.isEditorEmpty); + } + /** + * Check if one of Toolbar is opened + * Used to prevent global keydowns (for example, Enter) conflicts with Enter-on-toolbar + * + * @returns {boolean} + */ + get someToolbarOpened() { + const { Toolbar: e, BlockSettings: t, InlineToolbar: o } = this.Editor; + return !!(t.opened || o.opened || e.toolbox.opened); + } + /** + * Check for some Flipper-buttons is under focus + */ + get someFlipperButtonFocused() { + return this.Editor.Toolbar.toolbox.hasFocus() ? !0 : Object.entries(this.Editor).filter(([e, t]) => t.flipper instanceof ce).some(([e, t]) => t.flipper.hasFocus()); + } + /** + * Clean editor`s UI + */ + destroy() { + this.nodes.holder.innerHTML = "", this.unbindReadOnlyInsensitiveListeners(); + } + /** + * Close all Editor's toolbars + */ + closeAllToolbars() { + const { Toolbar: e, BlockSettings: t, InlineToolbar: o } = this.Editor; + t.close(), o.close(), e.toolbox.close(); + } + /** + * Check for mobile mode and save the result + */ + setIsMobile() { + const e = window.innerWidth < Ro; + e !== this.isMobile && this.eventsDispatcher.emit(Te, { + isEnabled: this.isMobile + }), this.isMobile = e; + } + /** + * Makes Editor.js interface + */ + make() { + this.nodes.holder = u.getHolder(this.config.holder), this.nodes.wrapper = u.make("div", [ + this.CSS.editorWrapper, + ...this.isRtl ? [this.CSS.editorRtlFix] : [] + ]), this.nodes.redactor = u.make("div", this.CSS.editorZone), this.nodes.holder.offsetWidth < this.contentRect.width && this.nodes.wrapper.classList.add(this.CSS.editorWrapperNarrow), this.nodes.redactor.style.paddingBottom = this.config.minHeight + "px", this.nodes.wrapper.appendChild(this.nodes.redactor), this.nodes.holder.appendChild(this.nodes.wrapper), this.bindReadOnlyInsensitiveListeners(); + } + /** + * Appends CSS + */ + loadStyles() { + const e = "editor-js-styles"; + if (u.get(e)) + return; + const t = u.make("style", null, { + id: e, + textContent: Sa.toString() + }); + this.config.style && !V(this.config.style) && this.config.style.nonce && t.setAttribute("nonce", this.config.style.nonce), u.prepend(document.head, t); + } + /** + * Adds listeners that should work both in read-only and read-write modes + */ + bindReadOnlyInsensitiveListeners() { + this.listeners.on(document, "selectionchange", this.selectionChangeDebounced), this.listeners.on(window, "resize", this.resizeDebouncer, { + passive: !0 + }), this.listeners.on(this.nodes.redactor, "mousedown", this.documentTouchedListener, { + capture: !0, + passive: !0 + }), this.listeners.on(this.nodes.redactor, "touchstart", this.documentTouchedListener, { + capture: !0, + passive: !0 + }); + } + /** + * Removes listeners that should work both in read-only and read-write modes + */ + unbindReadOnlyInsensitiveListeners() { + this.listeners.off(document, "selectionchange", this.selectionChangeDebounced), this.listeners.off(window, "resize", this.resizeDebouncer), this.listeners.off(this.nodes.redactor, "mousedown", this.documentTouchedListener), this.listeners.off(this.nodes.redactor, "touchstart", this.documentTouchedListener); + } + /** + * Adds listeners that should work only in read-only mode + */ + bindReadOnlySensitiveListeners() { + this.readOnlyMutableListeners.on(this.nodes.redactor, "click", (e) => { + this.redactorClicked(e); + }, !1), this.readOnlyMutableListeners.on(document, "keydown", (e) => { + this.documentKeydown(e); + }, !0), this.readOnlyMutableListeners.on(document, "mousedown", (e) => { + this.documentClicked(e); + }, !0), this.watchBlockHoveredEvents(), this.enableInputsEmptyMark(); + } + /** + * Listen redactor mousemove to emit 'block-hovered' event + */ + watchBlockHoveredEvents() { + let e; + this.readOnlyMutableListeners.on(this.nodes.redactor, "mousemove", dt((t) => { + const o = t.target.closest(".ce-block"); + this.Editor.BlockSelection.anyBlockSelected || o && e !== o && (e = o, this.eventsDispatcher.emit(ln, { + block: this.Editor.BlockManager.getBlockByChildNode(o) + })); + }, 20), { + passive: !0 + }); + } + /** + * Unbind events that should work only in read-only mode + */ + unbindReadOnlySensitiveListeners() { + this.readOnlyMutableListeners.clearAll(); + } + /** + * Resize window handler + */ + windowResize() { + this.contentRectCache = null, this.setIsMobile(); + } + /** + * All keydowns on document + * + * @param {KeyboardEvent} event - keyboard event + */ + documentKeydown(e) { + switch (e.keyCode) { + case y.ENTER: + this.enterPressed(e); + break; + case y.BACKSPACE: + case y.DELETE: + this.backspacePressed(e); + break; + case y.ESC: + this.escapePressed(e); + break; + default: + this.defaultBehaviour(e); + break; + } + } + /** + * Ignore all other document's keydown events + * + * @param {KeyboardEvent} event - keyboard event + */ + defaultBehaviour(e) { + const { currentBlock: t } = this.Editor.BlockManager, o = e.target.closest(`.${this.CSS.editorWrapper}`), i = e.altKey || e.ctrlKey || e.metaKey || e.shiftKey; + if (t !== void 0 && o === null) { + this.Editor.BlockEvents.keydown(e); + return; + } + o || t && i || (this.Editor.BlockManager.unsetCurrentBlock(), this.Editor.Toolbar.close()); + } + /** + * @param {KeyboardEvent} event - keyboard event + */ + backspacePressed(e) { + const { BlockManager: t, BlockSelection: o, Caret: i } = this.Editor; + if (o.anyBlockSelected && !b.isSelectionExists) { + const s = t.removeSelectedBlocks(), r = t.insertDefaultBlockAtIndex(s, !0); + i.setToBlock(r, i.positions.START), o.clearSelection(e), e.preventDefault(), e.stopPropagation(), e.stopImmediatePropagation(); + } + } + /** + * Escape pressed + * If some of Toolbar components are opened, then close it otherwise close Toolbar + * + * @param {Event} event - escape keydown event + */ + escapePressed(e) { + this.Editor.BlockSelection.clearSelection(e), this.Editor.Toolbar.toolbox.opened ? (this.Editor.Toolbar.toolbox.close(), this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock, this.Editor.Caret.positions.END)) : this.Editor.BlockSettings.opened ? this.Editor.BlockSettings.close() : this.Editor.InlineToolbar.opened ? this.Editor.InlineToolbar.close() : this.Editor.Toolbar.close(); + } + /** + * Enter pressed on document + * + * @param {KeyboardEvent} event - keyboard event + */ + enterPressed(e) { + const { BlockManager: t, BlockSelection: o } = this.Editor; + if (this.someToolbarOpened) + return; + const i = t.currentBlockIndex >= 0; + if (o.anyBlockSelected && !b.isSelectionExists) { + o.clearSelection(e), e.preventDefault(), e.stopImmediatePropagation(), e.stopPropagation(); + return; + } + if (!this.someToolbarOpened && i && e.target.tagName === "BODY") { + const s = this.Editor.BlockManager.insert(); + e.preventDefault(), this.Editor.Caret.setToBlock(s), this.Editor.Toolbar.moveAndOpen(s); + } + this.Editor.BlockSelection.clearSelection(e); + } + /** + * All clicks on document + * + * @param {MouseEvent} event - Click event + */ + documentClicked(e) { + var a, l; + if (!e.isTrusted) + return; + const t = e.target; + this.nodes.holder.contains(t) || b.isAtEditor || (this.Editor.BlockManager.unsetCurrentBlock(), this.Editor.Toolbar.close()); + const i = (a = this.Editor.BlockSettings.nodes.wrapper) == null ? void 0 : a.contains(t), s = (l = this.Editor.Toolbar.nodes.settingsToggler) == null ? void 0 : l.contains(t), r = i || s; + if (this.Editor.BlockSettings.opened && !r) { + this.Editor.BlockSettings.close(); + const c = this.Editor.BlockManager.getBlockByChildNode(t); + this.Editor.Toolbar.moveAndOpen(c); + } + this.Editor.BlockSelection.clearSelection(e); + } + /** + * First touch on editor + * Fired before click + * + * Used to change current block — we need to do it before 'selectionChange' event. + * Also: + * - Move and show the Toolbar + * - Set a Caret + * + * @param event - touch or mouse event + */ + documentTouched(e) { + let t = e.target; + if (t === this.nodes.redactor) { + const o = e instanceof MouseEvent ? e.clientX : e.touches[0].clientX, i = e instanceof MouseEvent ? e.clientY : e.touches[0].clientY; + t = document.elementFromPoint(o, i); + } + try { + this.Editor.BlockManager.setCurrentBlockByChildNode(t); + } catch { + this.Editor.RectangleSelection.isRectActivated() || this.Editor.Caret.setToTheLastBlock(); + } + this.Editor.ReadOnly.isEnabled || this.Editor.Toolbar.moveAndOpen(); + } + /** + * All clicks on the redactor zone + * + * @param {MouseEvent} event - click event + * @description + * - By clicks on the Editor's bottom zone: + * - if last Block is empty, set a Caret to this + * - otherwise, add a new empty Block and set a Caret to that + */ + redactorClicked(e) { + if (!b.isCollapsed) + return; + const t = e.target, o = e.metaKey || e.ctrlKey; + if (u.isAnchor(t) && o) { + e.stopImmediatePropagation(), e.stopPropagation(); + const i = t.getAttribute("href"), s = oi(i); + ii(s); + return; + } + this.processBottomZoneClick(e); + } + /** + * Check if user clicks on the Editor's bottom zone: + * - set caret to the last block + * - or add new empty block + * + * @param event - click event + */ + processBottomZoneClick(e) { + const t = this.Editor.BlockManager.getBlockByIndex(-1), o = u.offset(t.holder).bottom, i = e.pageY, { BlockSelection: s } = this.Editor; + if (e.target instanceof Element && e.target.isEqualNode(this.nodes.redactor) && /** + * If there is cross block selection started, target will be equal to redactor so we need additional check + */ + !s.anyBlockSelected && /** + * Prevent caret jumping (to last block) when clicking between blocks + */ + o < i) { + e.stopImmediatePropagation(), e.stopPropagation(); + const { BlockManager: a, Caret: l, Toolbar: c } = this.Editor; + (!a.lastBlock.tool.isDefault || !a.lastBlock.isEmpty) && a.insertAtEnd(), l.setToTheLastBlock(), c.moveAndOpen(a.lastBlock); + } + } + /** + * Handle selection changes on mobile devices + * Uses for showing the Inline Toolbar + */ + selectionChanged() { + const { CrossBlockSelection: e, BlockSelection: t } = this.Editor, o = b.anchorElement; + if (e.isCrossBlockSelectionStarted && t.anyBlockSelected && b.get().removeAllRanges(), !o) { + b.range || this.Editor.InlineToolbar.close(); + return; + } + const i = o.closest(`.${R.CSS.content}`); + (i === null || i.closest(`.${b.CSS.editorWrapper}`) !== this.nodes.wrapper) && (this.Editor.InlineToolbar.containsNode(o) || this.Editor.InlineToolbar.close(), !(o.dataset.inlineToolbar === "true")) || (this.Editor.BlockManager.currentBlock || this.Editor.BlockManager.setCurrentBlockByChildNode(o), this.Editor.InlineToolbar.tryToShow(!0)); + } + /** + * Editor.js provides and ability to show placeholders for empty contenteditable elements + * + * This method watches for input and focus events and toggles 'data-empty' attribute + * to workaroud the case, when inputs contains only
    s and has no visible content + * Then, CSS could rely on this attribute to show placeholders + */ + enableInputsEmptyMark() { + function e(t) { + const o = t.target; + Do(o); + } + this.readOnlyMutableListeners.on(this.nodes.wrapper, "input", e), this.readOnlyMutableListeners.on(this.nodes.wrapper, "focusin", e), this.readOnlyMutableListeners.on(this.nodes.wrapper, "focusout", e); + } +} +const Oa = { + // API Modules + BlocksAPI: gi, + CaretAPI: bi, + EventsAPI: vi, + I18nAPI: kt, + API: ki, + InlineToolbarAPI: yi, + ListenersAPI: wi, + NotifierAPI: Ci, + ReadOnlyAPI: Ti, + SanitizerAPI: Li, + SaverAPI: Pi, + SelectionAPI: Ni, + ToolsAPI: Ri, + StylesAPI: Di, + ToolbarAPI: Fi, + TooltipAPI: Ui, + UiAPI: Wi, + // Toolbar Modules + BlockSettings: ms, + Toolbar: Bs, + InlineToolbar: Cs, + // Modules + BlockEvents: na, + BlockManager: ra, + BlockSelection: aa, + Caret: Ye, + CrossBlockSelection: la, + DragNDrop: ca, + ModificationsObserver: ha, + Paste: pa, + ReadOnly: fa, + RectangleSelection: Be, + Renderer: ga, + Saver: ma, + Tools: Wn, + UI: Ia +}; +class _a { + /** + * @param {EditorConfig} config - user configuration + */ + constructor(e) { + this.moduleInstances = {}, this.eventsDispatcher = new Oe(); + let t, o; + this.isReady = new Promise((i, s) => { + t = i, o = s; + }), Promise.resolve().then(async () => { + this.configuration = e, this.validate(), this.init(), await this.start(), await this.render(); + const { BlockManager: i, Caret: s, UI: r, ModificationsObserver: a } = this.moduleInstances; + r.checkEmptiness(), a.enable(), this.configuration.autofocus === !0 && this.configuration.readOnly !== !0 && s.setToBlock(i.blocks[0], s.positions.START), t(); + }).catch((i) => { + S(`Editor.js is not ready because of ${i}`, "error"), o(i); + }); + } + /** + * Setting for configuration + * + * @param {EditorConfig|string} config - Editor's config to set + */ + set configuration(e) { + var o, i; + D(e) ? this.config = { + ...e + } : this.config = { + holder: e + }, ht(!!this.config.holderId, "config.holderId", "config.holder"), this.config.holderId && !this.config.holder && (this.config.holder = this.config.holderId, this.config.holderId = null), this.config.holder == null && (this.config.holder = "editorjs"), this.config.logLevel || (this.config.logLevel = Lo.VERBOSE), Zn(this.config.logLevel), ht(!!this.config.initialBlock, "config.initialBlock", "config.defaultBlock"), this.config.defaultBlock = this.config.defaultBlock || this.config.initialBlock || "paragraph", this.config.minHeight = this.config.minHeight !== void 0 ? this.config.minHeight : 300; + const t = { + type: this.config.defaultBlock, + data: {} + }; + this.config.placeholder = this.config.placeholder || !1, this.config.sanitizer = this.config.sanitizer || { + p: !0, + b: !0, + a: !0 + }, this.config.hideToolbar = this.config.hideToolbar ? this.config.hideToolbar : !1, this.config.tools = this.config.tools || {}, this.config.i18n = this.config.i18n || {}, this.config.data = this.config.data || { blocks: [] }, this.config.onReady = this.config.onReady || (() => { + }), this.config.onChange = this.config.onChange || (() => { + }), this.config.inlineToolbar = this.config.inlineToolbar !== void 0 ? this.config.inlineToolbar : !0, (V(this.config.data) || !this.config.data.blocks || this.config.data.blocks.length === 0) && (this.config.data = { blocks: [t] }), this.config.readOnly = this.config.readOnly || !1, (o = this.config.i18n) != null && o.messages && z.setDictionary(this.config.i18n.messages), this.config.i18n.direction = ((i = this.config.i18n) == null ? void 0 : i.direction) || "ltr"; + } + /** + * Returns private property + * + * @returns {EditorConfig} + */ + get configuration() { + return this.config; + } + /** + * Checks for required fields in Editor's config + */ + validate() { + const { holderId: e, holder: t } = this.config; + if (e && t) + throw Error("«holderId» and «holder» param can't assign at the same time."); + if (te(t) && !u.get(t)) + throw Error(`element with ID «${t}» is missing. Pass correct holder's ID.`); + if (t && D(t) && !u.isElement(t)) + throw Error("«holder» value must be an Element node"); + } + /** + * Initializes modules: + * - make and save instances + * - configure + */ + init() { + this.constructModules(), this.configureModules(); + } + /** + * Start Editor! + * + * Get list of modules that needs to be prepared and return a sequence (Promise) + * + * @returns {Promise} + */ + async start() { + await [ + "Tools", + "UI", + "BlockManager", + "Paste", + "BlockSelection", + "RectangleSelection", + "CrossBlockSelection", + "ReadOnly" + ].reduce( + (t, o) => t.then(async () => { + try { + await this.moduleInstances[o].prepare(); + } catch (i) { + if (i instanceof Ho) + throw new Error(i.message); + S(`Module ${o} was skipped because of %o`, "warn", i); + } + }), + Promise.resolve() + ); + } + /** + * Render initial data + */ + render() { + return this.moduleInstances.Renderer.render(this.config.data.blocks); + } + /** + * Make modules instances and save it to the @property this.moduleInstances + */ + constructModules() { + Object.entries(Oa).forEach(([e, t]) => { + try { + this.moduleInstances[e] = new t({ + config: this.configuration, + eventsDispatcher: this.eventsDispatcher + }); + } catch (o) { + S("[constructModules]", `Module ${e} skipped because`, "error", o); + } + }); + } + /** + * Modules instances configuration: + * - pass other modules to the 'state' property + * - ... + */ + configureModules() { + for (const e in this.moduleInstances) + Object.prototype.hasOwnProperty.call(this.moduleInstances, e) && (this.moduleInstances[e].state = this.getModulesDiff(e)); + } + /** + * Return modules without passed name + * + * @param {string} name - module for witch modules difference should be calculated + */ + getModulesDiff(e) { + const t = {}; + for (const o in this.moduleInstances) + o !== e && (t[o] = this.moduleInstances[o]); + return t; + } +} +/** + * Editor.js + * + * @license Apache-2.0 + * @see Editor.js + * @author CodeX Team + */ +class Aa { + /** Editor version */ + static get version() { + return "2.31.1"; + } + /** + * @param {EditorConfig|string|undefined} [configuration] - user configuration + */ + constructor(e) { + let t = () => { + }; + D(e) && A(e.onReady) && (t = e.onReady); + const o = new _a(e); + this.isReady = o.isReady.then(() => { + this.exportAPI(o), t(); + }); + } + /** + * Export external API methods + * + * @param {Core} editor — Editor's instance + */ + exportAPI(e) { + const t = ["configuration"], o = () => { + Object.values(e.moduleInstances).forEach((s) => { + A(s.destroy) && s.destroy(), s.listeners.removeAll(); + }), zi(), e = null; + for (const s in this) + Object.prototype.hasOwnProperty.call(this, s) && delete this[s]; + Object.setPrototypeOf(this, null); + }; + t.forEach((s) => { + this[s] = e[s]; + }), this.destroy = o, Object.setPrototypeOf(this, e.moduleInstances.API.methods), delete this.exportAPI, Object.entries({ + blocks: { + clear: "clear", + render: "render" + }, + caret: { + focus: "focus" + }, + events: { + on: "on", + off: "off", + emit: "emit" + }, + saver: { + save: "save" + } + }).forEach(([s, r]) => { + Object.entries(r).forEach(([a, l]) => { + this[l] = e.moduleInstances.API.methods[s][a]; + }); + }); + } +} +export { + Aa as default +}; diff --git a/web/vendor/editorjs/editorjs.umd.js b/web/vendor/editorjs/editorjs.umd.js new file mode 100644 index 0000000..48468c9 --- /dev/null +++ b/web/vendor/editorjs/editorjs.umd.js @@ -0,0 +1,51 @@ +(function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode(".ce-hint--align-start{text-align:left}.ce-hint--align-center{text-align:center}.ce-hint__description{opacity:.6;margin-top:3px}")),document.head.appendChild(e)}}catch(t){console.error("vite-plugin-css-injected-by-js",t)}})(); +(function(J,ne){typeof exports=="object"&&typeof module<"u"?module.exports=ne():typeof define=="function"&&define.amd?define(ne):(J=typeof globalThis<"u"?globalThis:J||self,J.EditorJS=ne())})(this,function(){"use strict";var J=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function ne(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}function Yn(n){if(n.__esModule)return n;var e=n.default;if(typeof e=="function"){var t=function o(){return this instanceof o?Reflect.construct(e,arguments,this.constructor):e.apply(this,arguments)};t.prototype=e.prototype}else t={};return Object.defineProperty(t,"__esModule",{value:!0}),Object.keys(n).forEach(function(o){var i=Object.getOwnPropertyDescriptor(n,o);Object.defineProperty(t,o,i.get?i:{enumerable:!0,get:function(){return n[o]}})}),t}function tt(){}Object.assign(tt,{default:tt,register:tt,revert:function(){},__esModule:!0}),Element.prototype.matches||(Element.prototype.matches=Element.prototype.matchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector||Element.prototype.webkitMatchesSelector||function(n){const e=(this.document||this.ownerDocument).querySelectorAll(n);let t=e.length;for(;--t>=0&&e.item(t)!==this;);return t>-1}),Element.prototype.closest||(Element.prototype.closest=function(n){let e=this;if(!document.documentElement.contains(e))return null;do{if(e.matches(n))return e;e=e.parentElement||e.parentNode}while(e!==null);return null}),Element.prototype.prepend||(Element.prototype.prepend=function(e){const t=document.createDocumentFragment();Array.isArray(e)||(e=[e]),e.forEach(o=>{const i=o instanceof Node;t.appendChild(i?o:document.createTextNode(o))}),this.insertBefore(t,this.firstChild)}),Element.prototype.scrollIntoViewIfNeeded||(Element.prototype.scrollIntoViewIfNeeded=function(n){n=arguments.length===0?!0:!!n;const e=this.parentNode,t=window.getComputedStyle(e,null),o=parseInt(t.getPropertyValue("border-top-width")),i=parseInt(t.getPropertyValue("border-left-width")),s=this.offsetTop-e.offsetTope.scrollTop+e.clientHeight,a=this.offsetLeft-e.offsetLefte.scrollLeft+e.clientWidth,c=s&&!r;(s||r)&&n&&(e.scrollTop=this.offsetTop-e.offsetTop-e.clientHeight/2-o+this.clientHeight/2),(a||l)&&n&&(e.scrollLeft=this.offsetLeft-e.offsetLeft-e.clientWidth/2-i+this.clientWidth/2),(s||r||a||l)&&!n&&this.scrollIntoView(c)}),window.requestIdleCallback=window.requestIdleCallback||function(n){const e=Date.now();return setTimeout(function(){n({didTimeout:!1,timeRemaining:function(){return Math.max(0,50-(Date.now()-e))}})},1)},window.cancelIdleCallback=window.cancelIdleCallback||function(n){clearTimeout(n)};let Kn=(n=21)=>crypto.getRandomValues(new Uint8Array(n)).reduce((e,t)=>(t&=63,t<36?e+=t.toString(36):t<62?e+=(t-26).toString(36).toUpperCase():t>62?e+="-":e+="_",e),"");var ko=(n=>(n.VERBOSE="VERBOSE",n.INFO="INFO",n.WARN="WARN",n.ERROR="ERROR",n))(ko||{});const y={BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,LEFT:37,UP:38,DOWN:40,RIGHT:39,DELETE:46,META:91,SLASH:191},Xn={LEFT:0,WHEEL:1,RIGHT:2,BACKWARD:3,FORWARD:4};function ye(n,e,t="log",o,i="color: inherit"){if(!("console"in window)||!window.console[t])return;const s=["info","log","warn","error"].includes(t),r=[];switch(ye.logLevel){case"ERROR":if(t!=="error")return;break;case"WARN":if(!["error","warn"].includes(t))return;break;case"INFO":if(!s||n)return;break}o&&r.push(o);const a="Editor.js 2.31.1",l=`line-height: 1em; + color: #006FEA; + display: inline-block; + font-size: 11px; + line-height: 1em; + background-color: #fff; + padding: 4px 9px; + border-radius: 30px; + border: 1px solid rgba(56, 138, 229, 0.16); + margin: 4px 5px 4px 0;`;n&&(s?(r.unshift(l,i),e=`%c${a}%c ${e}`):e=`( ${a} )${e}`);try{s?o?console[t](`${e} %o`,...r):console[t](e,...r):console[t](e)}catch{}}ye.logLevel="VERBOSE";function Vn(n){ye.logLevel=n}const T=ye.bind(window,!1),X=ye.bind(window,!0);function re(n){return Object.prototype.toString.call(n).match(/\s([a-zA-Z]+)/)[1].toLowerCase()}function M(n){return re(n)==="function"||re(n)==="asyncfunction"}function N(n){return re(n)==="object"}function Q(n){return re(n)==="string"}function qn(n){return re(n)==="boolean"}function yo(n){return re(n)==="number"}function wo(n){return re(n)==="undefined"}function V(n){return n?Object.keys(n).length===0&&n.constructor===Object:!0}function Eo(n){return n>47&&n<58||n===32||n===13||n===229||n>64&&n<91||n>95&&n<112||n>185&&n<193||n>218&&n<223}async function Zn(n,e=()=>{},t=()=>{}){async function o(i,s,r){try{await i.function(i.data),await s(wo(i.data)?{}:i.data)}catch{r(wo(i.data)?{}:i.data)}}return n.reduce(async(i,s)=>(await i,o(s,e,t)),Promise.resolve())}function xo(n){return Array.prototype.slice.call(n)}function Ae(n,e){return function(){const t=this,o=arguments;window.setTimeout(()=>n.apply(t,o),e)}}function Gn(n){return n.name.split(".").pop()}function Jn(n){return/^[-\w]+\/([-+\w]+|\*)$/.test(n)}function Bo(n,e,t){let o;return(...i)=>{const s=this,r=()=>{o=null,t||n.apply(s,i)},a=t&&!o;window.clearTimeout(o),o=window.setTimeout(r,e),a&&n.apply(s,i)}}function ot(n,e,t=void 0){let o,i,s,r=null,a=0;t||(t={});const l=function(){a=t.leading===!1?0:Date.now(),r=null,s=n.apply(o,i),r||(o=i=null)};return function(){const c=Date.now();!a&&t.leading===!1&&(a=c);const d=e-(c-a);return o=this,i=arguments,d<=0||d>e?(r&&(clearTimeout(r),r=null),a=c,s=n.apply(o,i),r||(o=i=null)):!r&&t.trailing!==!1&&(r=setTimeout(l,d)),s}}function Qn(){const n={win:!1,mac:!1,x11:!1,linux:!1},e=Object.keys(n).find(t=>window.navigator.appVersion.toLowerCase().indexOf(t)!==-1);return e&&(n[e]=!0),n}function Le(n){return n[0].toUpperCase()+n.slice(1)}function nt(n,...e){if(!e.length)return n;const t=e.shift();if(N(n)&&N(t))for(const o in t)N(t[o])?(n[o]||Object.assign(n,{[o]:{}}),nt(n[o],t[o])):Object.assign(n,{[o]:t[o]});return nt(n,...e)}function it(n){const e=Qn();return n=n.replace(/shift/gi,"⇧").replace(/backspace/gi,"⌫").replace(/enter/gi,"⏎").replace(/up/gi,"↑").replace(/left/gi,"→").replace(/down/gi,"↓").replace(/right/gi,"←").replace(/escape/gi,"⎋").replace(/insert/gi,"Ins").replace(/delete/gi,"␡").replace(/\+/gi," + "),e.mac?n=n.replace(/ctrl|cmd/gi,"⌘").replace(/alt/gi,"⌥"):n=n.replace(/cmd/gi,"Ctrl").replace(/windows/gi,"WIN"),n}function ei(n){try{return new URL(n).href}catch{}return n.substring(0,2)==="//"?window.location.protocol+n:window.location.origin+n}function ti(){return Kn(10)}function oi(n){window.open(n,"_blank")}function ni(n=""){return`${n}${Math.floor(Math.random()*1e8).toString(16)}`}function st(n,e,t){const o=`«${e}» is deprecated and will be removed in the next major release. Please use the «${t}» instead.`;n&&X(o,"warn")}function fe(n,e,t){const o=t.value?"value":"get",i=t[o],s=`#${e}Cache`;if(t[o]=function(...r){return this[s]===void 0&&(this[s]=i.apply(this,...r)),this[s]},o==="get"&&t.set){const r=t.set;t.set=function(a){delete n[s],r.apply(this,a)}}return t}const Co=650;function ge(){return window.matchMedia(`(max-width: ${Co}px)`).matches}const rt=typeof window<"u"&&window.navigator&&window.navigator.platform&&(/iP(ad|hone|od)/.test(window.navigator.platform)||window.navigator.platform==="MacIntel"&&window.navigator.maxTouchPoints>1);function ii(n,e){const t=Array.isArray(n)||N(n),o=Array.isArray(e)||N(e);return t||o?JSON.stringify(n)===JSON.stringify(e):n===e}class u{static isSingleTag(e){return e.tagName&&["AREA","BASE","BR","COL","COMMAND","EMBED","HR","IMG","INPUT","KEYGEN","LINK","META","PARAM","SOURCE","TRACK","WBR"].includes(e.tagName)}static isLineBreakTag(e){return e&&e.tagName&&["BR","WBR"].includes(e.tagName)}static make(e,t=null,o={}){const i=document.createElement(e);if(Array.isArray(t)){const s=t.filter(r=>r!==void 0);i.classList.add(...s)}else t&&i.classList.add(t);for(const s in o)Object.prototype.hasOwnProperty.call(o,s)&&(i[s]=o[s]);return i}static text(e){return document.createTextNode(e)}static append(e,t){Array.isArray(t)?t.forEach(o=>e.appendChild(o)):e.appendChild(t)}static prepend(e,t){Array.isArray(t)?(t=t.reverse(),t.forEach(o=>e.prepend(o))):e.prepend(t)}static swap(e,t){const o=document.createElement("div"),i=e.parentNode;i.insertBefore(o,e),i.insertBefore(e,t),i.insertBefore(t,o),i.removeChild(o)}static find(e=document,t){return e.querySelector(t)}static get(e){return document.getElementById(e)}static findAll(e=document,t){return e.querySelectorAll(t)}static get allInputsSelector(){return"[contenteditable=true], textarea, input:not([type]), "+["text","password","email","number","search","tel","url"].map(t=>`input[type="${t}"]`).join(", ")}static findAllInputs(e){return xo(e.querySelectorAll(u.allInputsSelector)).reduce((t,o)=>u.isNativeInput(o)||u.containsOnlyInlineElements(o)?[...t,o]:[...t,...u.getDeepestBlockElements(o)],[])}static getDeepestNode(e,t=!1){const o=t?"lastChild":"firstChild",i=t?"previousSibling":"nextSibling";if(e&&e.nodeType===Node.ELEMENT_NODE&&e[o]){let s=e[o];if(u.isSingleTag(s)&&!u.isNativeInput(s)&&!u.isLineBreakTag(s))if(s[i])s=s[i];else if(s.parentNode[i])s=s.parentNode[i];else return s.parentNode;return this.getDeepestNode(s,t)}return e}static isElement(e){return yo(e)?!1:e&&e.nodeType&&e.nodeType===Node.ELEMENT_NODE}static isFragment(e){return yo(e)?!1:e&&e.nodeType&&e.nodeType===Node.DOCUMENT_FRAGMENT_NODE}static isContentEditable(e){return e.contentEditable==="true"}static isNativeInput(e){const t=["INPUT","TEXTAREA"];return e&&e.tagName?t.includes(e.tagName):!1}static canSetCaret(e){let t=!0;if(u.isNativeInput(e))switch(e.type){case"file":case"checkbox":case"radio":case"hidden":case"submit":case"button":case"image":case"reset":t=!1;break}else t=u.isContentEditable(e);return t}static isNodeEmpty(e,t){let o;return this.isSingleTag(e)&&!this.isLineBreakTag(e)?!1:(this.isElement(e)&&this.isNativeInput(e)?o=e.value:o=e.textContent.replace("​",""),t&&(o=o.replace(new RegExp(t,"g"),"")),o.length===0)}static isLeaf(e){return e?e.childNodes.length===0:!1}static isEmpty(e,t){const o=[e];for(;o.length>0;)if(e=o.shift(),!!e){if(this.isLeaf(e)&&!this.isNodeEmpty(e,t))return!1;e.childNodes&&o.push(...Array.from(e.childNodes))}return!0}static isHTMLString(e){const t=u.make("div");return t.innerHTML=e,t.childElementCount>0}static getContentLength(e){return u.isNativeInput(e)?e.value.length:e.nodeType===Node.TEXT_NODE?e.length:e.textContent.length}static get blockElements(){return["address","article","aside","blockquote","canvas","div","dl","dt","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","li","main","nav","noscript","ol","output","p","pre","ruby","section","table","tbody","thead","tr","tfoot","ul","video"]}static containsOnlyInlineElements(e){let t;Q(e)?(t=document.createElement("div"),t.innerHTML=e):t=e;const o=i=>!u.blockElements.includes(i.tagName.toLowerCase())&&Array.from(i.children).every(o);return Array.from(t.children).every(o)}static getDeepestBlockElements(e){return u.containsOnlyInlineElements(e)?[e]:Array.from(e.children).reduce((t,o)=>[...t,...u.getDeepestBlockElements(o)],[])}static getHolder(e){return Q(e)?document.getElementById(e):e}static isAnchor(e){return e.tagName.toLowerCase()==="a"}static offset(e){const t=e.getBoundingClientRect(),o=window.pageXOffset||document.documentElement.scrollLeft,i=window.pageYOffset||document.documentElement.scrollTop,s=t.top+i,r=t.left+o;return{top:s,left:r,bottom:s+t.height,right:r+t.width}}static getNodeByOffset(e,t){let o=0,i=null;const s=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,null);let r=s.nextNode();for(;r;){const c=r.textContent,d=c===null?0:c.length;if(i=r,o+d>=t)break;o+=d,r=s.nextNode()}if(!i)return{node:null,offset:0};const a=i.textContent;if(a===null||a.length===0)return{node:null,offset:0};const l=Math.min(t-o,a.length);return{node:i,offset:l}}}function si(n){return!/[^\t\n\r ]/.test(n)}function ri(n){const e=window.getComputedStyle(n),t=parseFloat(e.fontSize),o=parseFloat(e.lineHeight)||t*1.2,i=parseFloat(e.paddingTop),s=parseFloat(e.borderTopWidth),r=parseFloat(e.marginTop),a=t*.8,l=(o-t)/2;return r+s+i+l+a}function To(n){n.dataset.empty=u.isEmpty(n)?"true":"false"}const So={ui:{blockTunes:{toggler:{"Click to tune":"","or drag to move":""}},inlineToolbar:{converter:{"Convert to":""}},toolbar:{toolbox:{Add:""}},popover:{Filter:"","Nothing found":"","Convert to":""}},toolNames:{Text:"",Link:"",Bold:"",Italic:""},tools:{link:{"Add a link":""},stub:{"The block can not be displayed correctly.":""}},blockTunes:{delete:{Delete:"","Click to delete":""},moveUp:{"Move up":""},moveDown:{"Move down":""}}},Io=class ke{static ui(e,t){return ke._t(e,t)}static t(e,t){return ke._t(e,t)}static setDictionary(e){ke.currentDictionary=e}static _t(e,t){const o=ke.getNamespace(e);return!o||!o[t]?t:o[t]}static getNamespace(e){return e.split(".").reduce((o,i)=>!o||!Object.keys(o).length?{}:o[i],ke.currentDictionary)}};Io.currentDictionary=So;let H=Io;class Oo extends Error{}class we{constructor(){this.subscribers={}}on(e,t){e in this.subscribers||(this.subscribers[e]=[]),this.subscribers[e].push(t)}once(e,t){e in this.subscribers||(this.subscribers[e]=[]);const o=i=>{const s=t(i),r=this.subscribers[e].indexOf(o);return r!==-1&&this.subscribers[e].splice(r,1),s};this.subscribers[e].push(o)}emit(e,t){V(this.subscribers)||!this.subscribers[e]||this.subscribers[e].reduce((o,i)=>{const s=i(o);return s!==void 0?s:o},t)}off(e,t){if(this.subscribers[e]===void 0){console.warn(`EventDispatcher .off(): there is no subscribers for event "${e.toString()}". Probably, .off() called before .on()`);return}for(let o=0;o{const l=this.allListeners.indexOf(s[a]);l>-1&&(this.allListeners.splice(l,1),r.element.removeEventListener(r.eventType,r.handler,r.options))})}offById(e){const t=this.findById(e);t&&t.element.removeEventListener(t.eventType,t.handler,t.options)}findOne(e,t,o){const i=this.findAll(e,t,o);return i.length>0?i[0]:null}findAll(e,t,o){let i;const s=e?this.findByEventTarget(e):[];return e&&t&&o?i=s.filter(r=>r.eventType===t&&r.handler===o):e&&t?i=s.filter(r=>r.eventType===t):i=s,i}removeAll(){this.allListeners.map(e=>{e.element.removeEventListener(e.eventType,e.handler,e.options)}),this.allListeners=[]}destroy(){this.removeAll()}findByEventTarget(e){return this.allListeners.filter(t=>{if(t.element===e)return t})}findByType(e){return this.allListeners.filter(t=>{if(t.eventType===e)return t})}findByHandler(e){return this.allListeners.filter(t=>{if(t.handler===e)return t})}findById(e){return this.allListeners.find(t=>t.id===e)}}class E{constructor({config:e,eventsDispatcher:t}){if(this.nodes={},this.listeners=new Ee,this.readOnlyMutableListeners={on:(o,i,s,r=!1)=>{this.mutableListenerIds.push(this.listeners.on(o,i,s,r))},clearAll:()=>{for(const o of this.mutableListenerIds)this.listeners.offById(o);this.mutableListenerIds=[]}},this.mutableListenerIds=[],new.target===E)throw new TypeError("Constructors for abstract class Module are not allowed.");this.config=e,this.eventsDispatcher=t}set state(e){this.Editor=e}removeAllNodes(){for(const e in this.nodes){const t=this.nodes[e];t instanceof HTMLElement&&t.remove()}}get isRtl(){return this.config.i18n.direction==="rtl"}}class b{constructor(){this.instance=null,this.selection=null,this.savedSelectionRange=null,this.isFakeBackgroundEnabled=!1,this.commandBackground="backColor",this.commandRemoveFormat="removeFormat"}static get CSS(){return{editorWrapper:"codex-editor",editorZone:"codex-editor__redactor"}}static get anchorNode(){const e=window.getSelection();return e?e.anchorNode:null}static get anchorElement(){const e=window.getSelection();if(!e)return null;const t=e.anchorNode;return t?u.isElement(t)?t:t.parentElement:null}static get anchorOffset(){const e=window.getSelection();return e?e.anchorOffset:null}static get isCollapsed(){const e=window.getSelection();return e?e.isCollapsed:null}static get isAtEditor(){return this.isSelectionAtEditor(b.get())}static isSelectionAtEditor(e){if(!e)return!1;let t=e.anchorNode||e.focusNode;t&&t.nodeType===Node.TEXT_NODE&&(t=t.parentNode);let o=null;return t&&t instanceof Element&&(o=t.closest(`.${b.CSS.editorZone}`)),o?o.nodeType===Node.ELEMENT_NODE:!1}static isRangeAtEditor(e){if(!e)return;let t=e.startContainer;t&&t.nodeType===Node.TEXT_NODE&&(t=t.parentNode);let o=null;return t&&t instanceof Element&&(o=t.closest(`.${b.CSS.editorZone}`)),o?o.nodeType===Node.ELEMENT_NODE:!1}static get isSelectionExists(){return!!b.get().anchorNode}static get range(){return this.getRangeFromSelection(this.get())}static getRangeFromSelection(e){return e&&e.rangeCount?e.getRangeAt(0):null}static get rect(){let e=document.selection,t,o={x:0,y:0,width:0,height:0};if(e&&e.type!=="Control")return e=e,t=e.createRange(),o.x=t.boundingLeft,o.y=t.boundingTop,o.width=t.boundingWidth,o.height=t.boundingHeight,o;if(!window.getSelection)return T("Method window.getSelection is not supported","warn"),o;if(e=window.getSelection(),e.rangeCount===null||isNaN(e.rangeCount))return T("Method SelectionUtils.rangeCount is not supported","warn"),o;if(e.rangeCount===0)return o;if(t=e.getRangeAt(0).cloneRange(),t.getBoundingClientRect&&(o=t.getBoundingClientRect()),o.x===0&&o.y===0){const i=document.createElement("span");if(i.getBoundingClientRect){i.appendChild(document.createTextNode("​")),t.insertNode(i),o=i.getBoundingClientRect();const s=i.parentNode;s.removeChild(i),s.normalize()}}return o}static get text(){return window.getSelection?window.getSelection().toString():""}static get(){return window.getSelection()}static setCursor(e,t=0){const o=document.createRange(),i=window.getSelection();return u.isNativeInput(e)?u.canSetCaret(e)?(e.focus(),e.selectionStart=e.selectionEnd=t,e.getBoundingClientRect()):void 0:(o.setStart(e,t),o.setEnd(e,t),i.removeAllRanges(),i.addRange(o),o.getBoundingClientRect())}static isRangeInsideContainer(e){const t=b.range;return t===null?!1:e.contains(t.startContainer)}static addFakeCursor(){const e=b.range;if(e===null)return;const t=u.make("span","codex-editor__fake-cursor");t.dataset.mutationFree="true",e.collapse(),e.insertNode(t)}static isFakeCursorInsideContainer(e){return u.find(e,".codex-editor__fake-cursor")!==null}static removeFakeCursor(e=document.body){const t=u.find(e,".codex-editor__fake-cursor");t&&t.remove()}removeFakeBackground(){this.isFakeBackgroundEnabled&&(this.isFakeBackgroundEnabled=!1,document.execCommand(this.commandRemoveFormat))}setFakeBackground(){document.execCommand(this.commandBackground,!1,"#a8d6ff"),this.isFakeBackgroundEnabled=!0}save(){this.savedSelectionRange=b.range}restore(){if(!this.savedSelectionRange)return;const e=window.getSelection();e.removeAllRanges(),e.addRange(this.savedSelectionRange)}clearSaved(){this.savedSelectionRange=null}collapseToEnd(){const e=window.getSelection(),t=document.createRange();t.selectNodeContents(e.focusNode),t.collapse(!1),e.removeAllRanges(),e.addRange(t)}findParentTag(e,t,o=10){const i=window.getSelection();let s=null;return!i||!i.anchorNode||!i.focusNode?null:([i.anchorNode,i.focusNode].forEach(a=>{let l=o;for(;l>0&&a.parentNode&&!(a.tagName===e&&(s=a,t&&a.classList&&!a.classList.contains(t)&&(s=null),s));)a=a.parentNode,l--}),s)}expandToTag(e){const t=window.getSelection();t.removeAllRanges();const o=document.createRange();o.selectNodeContents(e),t.addRange(o)}}function ai(n,e){const{type:t,target:o,addedNodes:i,removedNodes:s}=n;return n.type==="attributes"&&n.attributeName==="data-empty"?!1:!!(e.contains(o)||t==="childList"&&(Array.from(i).some(l=>l===e)||Array.from(s).some(l=>l===e)))}const at="redactor dom changed",_o="block changed",Mo="fake cursor is about to be toggled",Ao="fake cursor have been set",xe="editor mobile layout toggled";function lt(n,e){if(!n.conversionConfig)return!1;const t=n.conversionConfig[e];return M(t)||Q(t)}function Pe(n,e){return lt(n.tool,e)}function Lo(n,e){return Object.entries(n).some(([t,o])=>e[t]&&ii(e[t],o))}async function Po(n,e){const o=(await n.save()).data,i=e.find(s=>s.name===n.name);return i!==void 0&&!lt(i,"export")?[]:e.reduce((s,r)=>{if(!lt(r,"import")||r.toolbox===void 0)return s;const a=r.toolbox.filter(l=>{if(V(l)||l.icon===void 0)return!1;if(l.data!==void 0){if(Lo(l.data,o))return!1}else if(r.name===n.name)return!1;return!0});return s.push({...r,toolbox:a}),s},[])}function No(n,e){return n.mergeable?n.name===e.name?!0:Pe(e,"export")&&Pe(n,"import"):!1}function li(n,e){const t=e==null?void 0:e.export;return M(t)?t(n):Q(t)?n[t]:(t!==void 0&&T("Conversion «export» property must be a string or function. String means key of saved data object to export. Function should export processed string to export."),"")}function Ro(n,e,t){const o=e==null?void 0:e.import;return M(o)?o(n,t):Q(o)?{[o]:n}:(o!==void 0&&T("Conversion «import» property must be a string or function. String means key of tool data to import. Function accepts a imported string and return composed tool data."),{})}var _=(n=>(n.Default="default",n.Separator="separator",n.Html="html",n))(_||{}),te=(n=>(n.APPEND_CALLBACK="appendCallback",n.RENDERED="rendered",n.MOVED="moved",n.UPDATED="updated",n.REMOVED="removed",n.ON_PASTE="onPaste",n))(te||{});class R extends we{constructor({id:e=ti(),data:t,tool:o,readOnly:i,tunesData:s},r){super(),this.cachedInputs=[],this.toolRenderedElement=null,this.tunesInstances=new Map,this.defaultTunesInstances=new Map,this.unavailableTunesData={},this.inputIndex=0,this.editorEventBus=null,this.handleFocus=()=>{this.dropInputsCache(),this.updateCurrentInput()},this.didMutated=(a=void 0)=>{const l=a===void 0,c=a instanceof InputEvent;!l&&!c&&this.detectToolRootChange(a);let d;l||c?d=!0:d=!(a.length>0&&a.every(p=>{const{addedNodes:g,removedNodes:f,target:v}=p;return[...Array.from(g),...Array.from(f),v].some(S=>(u.isElement(S)||(S=S.parentElement),S&&S.closest('[data-mutation-free="true"]')!==null))})),d&&(this.dropInputsCache(),this.updateCurrentInput(),this.toggleInputsEmptyMark(),this.call("updated"),this.emit("didMutated",this))},this.name=o.name,this.id=e,this.settings=o.settings,this.config=o.settings.config||{},this.editorEventBus=r||null,this.blockAPI=new ee(this),this.tool=o,this.toolInstance=o.create(t,this.blockAPI,i),this.tunes=o.tunes,this.composeTunes(s),this.holder=this.compose(),window.requestIdleCallback(()=>{this.watchBlockMutations(),this.addInputEvents(),this.toggleInputsEmptyMark()})}static get CSS(){return{wrapper:"ce-block",wrapperStretched:"ce-block--stretched",content:"ce-block__content",selected:"ce-block--selected",dropTarget:"ce-block--drop-target"}}get inputs(){if(this.cachedInputs.length!==0)return this.cachedInputs;const e=u.findAllInputs(this.holder);return this.inputIndex>e.length-1&&(this.inputIndex=e.length-1),this.cachedInputs=e,e}get currentInput(){return this.inputs[this.inputIndex]}set currentInput(e){const t=this.inputs.findIndex(o=>o===e||o.contains(e));t!==-1&&(this.inputIndex=t)}get firstInput(){return this.inputs[0]}get lastInput(){const e=this.inputs;return e[e.length-1]}get nextInput(){return this.inputs[this.inputIndex+1]}get previousInput(){return this.inputs[this.inputIndex-1]}get data(){return this.save().then(e=>e&&!V(e.data)?e.data:{})}get sanitize(){return this.tool.sanitizeConfig}get mergeable(){return M(this.toolInstance.merge)}get focusable(){return this.inputs.length!==0}get isEmpty(){const e=u.isEmpty(this.pluginsContent,"/"),t=!this.hasMedia;return e&&t}get hasMedia(){const e=["img","iframe","video","audio","source","input","textarea","twitterwidget"];return!!this.holder.querySelector(e.join(","))}set selected(e){var i,s;this.holder.classList.toggle(R.CSS.selected,e);const t=e===!0&&b.isRangeInsideContainer(this.holder),o=e===!1&&b.isFakeCursorInsideContainer(this.holder);(t||o)&&((i=this.editorEventBus)==null||i.emit(Mo,{state:e}),t?b.addFakeCursor():b.removeFakeCursor(this.holder),(s=this.editorEventBus)==null||s.emit(Ao,{state:e}))}get selected(){return this.holder.classList.contains(R.CSS.selected)}set stretched(e){this.holder.classList.toggle(R.CSS.wrapperStretched,e)}get stretched(){return this.holder.classList.contains(R.CSS.wrapperStretched)}set dropTarget(e){this.holder.classList.toggle(R.CSS.dropTarget,e)}get pluginsContent(){return this.toolRenderedElement}call(e,t){if(M(this.toolInstance[e])){e==="appendCallback"&&T("`appendCallback` hook is deprecated and will be removed in the next major release. Use `rendered` hook instead","warn");try{this.toolInstance[e].call(this.toolInstance,t)}catch(o){T(`Error during '${e}' call: ${o.message}`,"error")}}}async mergeWith(e){await this.toolInstance.merge(e)}async save(){const e=await this.toolInstance.save(this.pluginsContent),t=this.unavailableTunesData;[...this.tunesInstances.entries(),...this.defaultTunesInstances.entries()].forEach(([s,r])=>{if(M(r.save))try{t[s]=r.save()}catch(a){T(`Tune ${r.constructor.name} save method throws an Error %o`,"warn",a)}});const o=window.performance.now();let i;return Promise.resolve(e).then(s=>(i=window.performance.now(),{id:this.id,tool:this.name,data:s,tunes:t,time:i-o})).catch(s=>{T(`Saving process for ${this.name} tool failed due to the ${s}`,"log","red")})}async validate(e){let t=!0;return this.toolInstance.validate instanceof Function&&(t=await this.toolInstance.validate(e)),t}getTunes(){const e=[],t=[],o=typeof this.toolInstance.renderSettings=="function"?this.toolInstance.renderSettings():[];return u.isElement(o)?e.push({type:_.Html,element:o}):Array.isArray(o)?e.push(...o):e.push(o),[...this.tunesInstances.values(),...this.defaultTunesInstances.values()].map(s=>s.render()).forEach(s=>{u.isElement(s)?t.push({type:_.Html,element:s}):Array.isArray(s)?t.push(...s):t.push(s)}),{toolTunes:e,commonTunes:t}}updateCurrentInput(){this.currentInput=u.isNativeInput(document.activeElement)||!b.anchorNode?document.activeElement:b.anchorNode}dispatchChange(){this.didMutated()}destroy(){this.unwatchBlockMutations(),this.removeInputEvents(),super.destroy(),M(this.toolInstance.destroy)&&this.toolInstance.destroy()}async getActiveToolboxEntry(){const e=this.tool.toolbox;if(e.length===1)return Promise.resolve(this.tool.toolbox[0]);const t=await this.data,o=e;return o==null?void 0:o.find(i=>Lo(i.data,t))}async exportDataAsString(){const e=await this.data;return li(e,this.tool.conversionConfig)}compose(){const e=u.make("div",R.CSS.wrapper),t=u.make("div",R.CSS.content),o=this.toolInstance.render();e.dataset.id=this.id,this.toolRenderedElement=o,t.appendChild(this.toolRenderedElement);let i=t;return[...this.tunesInstances.values(),...this.defaultTunesInstances.values()].forEach(s=>{if(M(s.wrap))try{i=s.wrap(i)}catch(r){T(`Tune ${s.constructor.name} wrap method throws an Error %o`,"warn",r)}}),e.appendChild(i),e}composeTunes(e){Array.from(this.tunes.values()).forEach(t=>{(t.isInternal?this.defaultTunesInstances:this.tunesInstances).set(t.name,t.create(e[t.name],this.blockAPI))}),Object.entries(e).forEach(([t,o])=>{this.tunesInstances.has(t)||(this.unavailableTunesData[t]=o)})}addInputEvents(){this.inputs.forEach(e=>{e.addEventListener("focus",this.handleFocus),u.isNativeInput(e)&&e.addEventListener("input",this.didMutated)})}removeInputEvents(){this.inputs.forEach(e=>{e.removeEventListener("focus",this.handleFocus),u.isNativeInput(e)&&e.removeEventListener("input",this.didMutated)})}watchBlockMutations(){var e;this.redactorDomChangedCallback=t=>{const{mutations:o}=t;o.some(s=>ai(s,this.toolRenderedElement))&&this.didMutated(o)},(e=this.editorEventBus)==null||e.on(at,this.redactorDomChangedCallback)}unwatchBlockMutations(){var e;(e=this.editorEventBus)==null||e.off(at,this.redactorDomChangedCallback)}detectToolRootChange(e){e.forEach(t=>{if(Array.from(t.removedNodes).includes(this.toolRenderedElement)){const i=t.addedNodes[t.addedNodes.length-1];this.toolRenderedElement=i}})}dropInputsCache(){this.cachedInputs=[]}toggleInputsEmptyMark(){this.inputs.forEach(To)}}class ci extends E{constructor(){super(...arguments),this.insert=(e=this.config.defaultBlock,t={},o={},i,s,r,a)=>{const l=this.Editor.BlockManager.insert({id:a,tool:e,data:t,index:i,needToFocus:s,replace:r});return new ee(l)},this.composeBlockData=async e=>{const t=this.Editor.Tools.blockTools.get(e);return new R({tool:t,api:this.Editor.API,readOnly:!0,data:{},tunesData:{}}).data},this.update=async(e,t,o)=>{const{BlockManager:i}=this.Editor,s=i.getBlockById(e);if(s===void 0)throw new Error(`Block with id "${e}" not found`);const r=await i.update(s,t,o);return new ee(r)},this.convert=async(e,t,o)=>{var h,p;const{BlockManager:i,Tools:s}=this.Editor,r=i.getBlockById(e);if(!r)throw new Error(`Block with id "${e}" not found`);const a=s.blockTools.get(r.name),l=s.blockTools.get(t);if(!l)throw new Error(`Block Tool with type "${t}" not found`);const c=((h=a==null?void 0:a.conversionConfig)==null?void 0:h.export)!==void 0,d=((p=l.conversionConfig)==null?void 0:p.import)!==void 0;if(c&&d){const g=await i.convert(r,t,o);return new ee(g)}else{const g=[c?!1:Le(r.name),d?!1:Le(t)].filter(Boolean).join(" and ");throw new Error(`Conversion from "${r.name}" to "${t}" is not possible. ${g} tool(s) should provide a "conversionConfig"`)}},this.insertMany=(e,t=this.Editor.BlockManager.blocks.length-1)=>{this.validateIndex(t);const o=e.map(({id:i,type:s,data:r})=>this.Editor.BlockManager.composeBlock({id:i,tool:s||this.config.defaultBlock,data:r}));return this.Editor.BlockManager.insertMany(o,t),o.map(i=>new ee(i))}}get methods(){return{clear:()=>this.clear(),render:e=>this.render(e),renderFromHTML:e=>this.renderFromHTML(e),delete:e=>this.delete(e),swap:(e,t)=>this.swap(e,t),move:(e,t)=>this.move(e,t),getBlockByIndex:e=>this.getBlockByIndex(e),getById:e=>this.getById(e),getCurrentBlockIndex:()=>this.getCurrentBlockIndex(),getBlockIndex:e=>this.getBlockIndex(e),getBlocksCount:()=>this.getBlocksCount(),getBlockByElement:e=>this.getBlockByElement(e),stretchBlock:(e,t=!0)=>this.stretchBlock(e,t),insertNewBlock:()=>this.insertNewBlock(),insert:this.insert,insertMany:this.insertMany,update:this.update,composeBlockData:this.composeBlockData,convert:this.convert}}getBlocksCount(){return this.Editor.BlockManager.blocks.length}getCurrentBlockIndex(){return this.Editor.BlockManager.currentBlockIndex}getBlockIndex(e){const t=this.Editor.BlockManager.getBlockById(e);if(!t){X("There is no block with id `"+e+"`","warn");return}return this.Editor.BlockManager.getBlockIndex(t)}getBlockByIndex(e){const t=this.Editor.BlockManager.getBlockByIndex(e);if(t===void 0){X("There is no block at index `"+e+"`","warn");return}return new ee(t)}getById(e){const t=this.Editor.BlockManager.getBlockById(e);return t===void 0?(X("There is no block with id `"+e+"`","warn"),null):new ee(t)}getBlockByElement(e){const t=this.Editor.BlockManager.getBlock(e);if(t===void 0){X("There is no block corresponding to element `"+e+"`","warn");return}return new ee(t)}swap(e,t){T("`blocks.swap()` method is deprecated and will be removed in the next major release. Use `block.move()` method instead","info"),this.Editor.BlockManager.swap(e,t)}move(e,t){this.Editor.BlockManager.move(e,t)}delete(e=this.Editor.BlockManager.currentBlockIndex){try{const t=this.Editor.BlockManager.getBlockByIndex(e);this.Editor.BlockManager.removeBlock(t)}catch(t){X(t,"warn");return}this.Editor.BlockManager.blocks.length===0&&this.Editor.BlockManager.insert(),this.Editor.BlockManager.currentBlock&&this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock,this.Editor.Caret.positions.END),this.Editor.Toolbar.close()}async clear(){await this.Editor.BlockManager.clear(!0),this.Editor.InlineToolbar.close()}async render(e){if(e===void 0||e.blocks===void 0)throw new Error("Incorrect data passed to the render() method");this.Editor.ModificationsObserver.disable(),await this.Editor.BlockManager.clear(),await this.Editor.Renderer.render(e.blocks),this.Editor.ModificationsObserver.enable()}async renderFromHTML(e){return await this.Editor.BlockManager.clear(),this.Editor.Paste.processText(e,!0)}stretchBlock(e,t=!0){st(!0,"blocks.stretchBlock()","BlockAPI");const o=this.Editor.BlockManager.getBlockByIndex(e);o&&(o.stretched=t)}insertNewBlock(){T("Method blocks.insertNewBlock() is deprecated and it will be removed in the next major release. Use blocks.insert() instead.","warn"),this.insert()}validateIndex(e){if(typeof e!="number")throw new Error("Index should be a number");if(e<0)throw new Error("Index should be greater than or equal to 0");if(e===null)throw new Error("Index should be greater than or equal to 0")}}function di(n,e){return typeof n=="number"?e.BlockManager.getBlockByIndex(n):typeof n=="string"?e.BlockManager.getBlockById(n):e.BlockManager.getBlockById(n.id)}class ui extends E{constructor(){super(...arguments),this.setToFirstBlock=(e=this.Editor.Caret.positions.DEFAULT,t=0)=>this.Editor.BlockManager.firstBlock?(this.Editor.Caret.setToBlock(this.Editor.BlockManager.firstBlock,e,t),!0):!1,this.setToLastBlock=(e=this.Editor.Caret.positions.DEFAULT,t=0)=>this.Editor.BlockManager.lastBlock?(this.Editor.Caret.setToBlock(this.Editor.BlockManager.lastBlock,e,t),!0):!1,this.setToPreviousBlock=(e=this.Editor.Caret.positions.DEFAULT,t=0)=>this.Editor.BlockManager.previousBlock?(this.Editor.Caret.setToBlock(this.Editor.BlockManager.previousBlock,e,t),!0):!1,this.setToNextBlock=(e=this.Editor.Caret.positions.DEFAULT,t=0)=>this.Editor.BlockManager.nextBlock?(this.Editor.Caret.setToBlock(this.Editor.BlockManager.nextBlock,e,t),!0):!1,this.setToBlock=(e,t=this.Editor.Caret.positions.DEFAULT,o=0)=>{const i=di(e,this.Editor);return i===void 0?!1:(this.Editor.Caret.setToBlock(i,t,o),!0)},this.focus=(e=!1)=>e?this.setToLastBlock(this.Editor.Caret.positions.END):this.setToFirstBlock(this.Editor.Caret.positions.START)}get methods(){return{setToFirstBlock:this.setToFirstBlock,setToLastBlock:this.setToLastBlock,setToPreviousBlock:this.setToPreviousBlock,setToNextBlock:this.setToNextBlock,setToBlock:this.setToBlock,focus:this.focus}}}class hi extends E{get methods(){return{emit:(e,t)=>this.emit(e,t),off:(e,t)=>this.off(e,t),on:(e,t)=>this.on(e,t)}}on(e,t){this.eventsDispatcher.on(e,t)}emit(e,t){this.eventsDispatcher.emit(e,t)}off(e,t){this.eventsDispatcher.off(e,t)}}class ct extends E{static getNamespace(e,t){return t?`blockTunes.${e}`:`tools.${e}`}get methods(){return{t:()=>{X("I18n.t() method can be accessed only from Tools","warn")}}}getMethodsForTool(e,t){return Object.assign(this.methods,{t:o=>H.t(ct.getNamespace(e,t),o)})}}class pi extends E{get methods(){return{blocks:this.Editor.BlocksAPI.methods,caret:this.Editor.CaretAPI.methods,tools:this.Editor.ToolsAPI.methods,events:this.Editor.EventsAPI.methods,listeners:this.Editor.ListenersAPI.methods,notifier:this.Editor.NotifierAPI.methods,sanitizer:this.Editor.SanitizerAPI.methods,saver:this.Editor.SaverAPI.methods,selection:this.Editor.SelectionAPI.methods,styles:this.Editor.StylesAPI.classes,toolbar:this.Editor.ToolbarAPI.methods,inlineToolbar:this.Editor.InlineToolbarAPI.methods,tooltip:this.Editor.TooltipAPI.methods,i18n:this.Editor.I18nAPI.methods,readOnly:this.Editor.ReadOnlyAPI.methods,ui:this.Editor.UiAPI.methods}}getMethodsForTool(e,t){return Object.assign(this.methods,{i18n:this.Editor.I18nAPI.getMethodsForTool(e,t)})}}class fi extends E{get methods(){return{close:()=>this.close(),open:()=>this.open()}}open(){this.Editor.InlineToolbar.tryToShow()}close(){this.Editor.InlineToolbar.close()}}class gi extends E{get methods(){return{on:(e,t,o,i)=>this.on(e,t,o,i),off:(e,t,o,i)=>this.off(e,t,o,i),offById:e=>this.offById(e)}}on(e,t,o,i){return this.listeners.on(e,t,o,i)}off(e,t,o,i){this.listeners.off(e,t,o,i)}offById(e){this.listeners.offById(e)}}var Do={exports:{}};(function(n,e){(function(t,o){n.exports=o()})(window,function(){return function(t){var o={};function i(s){if(o[s])return o[s].exports;var r=o[s]={i:s,l:!1,exports:{}};return t[s].call(r.exports,r,r.exports,i),r.l=!0,r.exports}return i.m=t,i.c=o,i.d=function(s,r,a){i.o(s,r)||Object.defineProperty(s,r,{enumerable:!0,get:a})},i.r=function(s){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(s,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(s,"__esModule",{value:!0})},i.t=function(s,r){if(1&r&&(s=i(s)),8&r||4&r&&typeof s=="object"&&s&&s.__esModule)return s;var a=Object.create(null);if(i.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:s}),2&r&&typeof s!="string")for(var l in s)i.d(a,l,(function(c){return s[c]}).bind(null,l));return a},i.n=function(s){var r=s&&s.__esModule?function(){return s.default}:function(){return s};return i.d(r,"a",r),r},i.o=function(s,r){return Object.prototype.hasOwnProperty.call(s,r)},i.p="/",i(i.s=0)}([function(t,o,i){i(1),t.exports=function(){var s=i(6),r="cdx-notify--bounce-in",a=null;return{show:function(l){if(l.message){(function(){if(a)return!0;a=s.getWrapper(),document.body.appendChild(a)})();var c=null,d=l.time||8e3;switch(l.type){case"confirm":c=s.confirm(l);break;case"prompt":c=s.prompt(l);break;default:c=s.alert(l),window.setTimeout(function(){c.remove()},d)}a.appendChild(c),c.classList.add(r)}}}}()},function(t,o,i){var s=i(2);typeof s=="string"&&(s=[[t.i,s,""]]);var r={hmr:!0,transform:void 0,insertInto:void 0};i(4)(s,r),s.locals&&(t.exports=s.locals)},function(t,o,i){(t.exports=i(3)(!1)).push([t.i,`.cdx-notify--error{background:#fffbfb!important}.cdx-notify--error::before{background:#fb5d5d!important}.cdx-notify__input{max-width:130px;padding:5px 10px;background:#f7f7f7;border:0;border-radius:3px;font-size:13px;color:#656b7c;outline:0}.cdx-notify__input:-ms-input-placeholder{color:#656b7c}.cdx-notify__input::placeholder{color:#656b7c}.cdx-notify__input:focus:-ms-input-placeholder{color:rgba(101,107,124,.3)}.cdx-notify__input:focus::placeholder{color:rgba(101,107,124,.3)}.cdx-notify__button{border:none;border-radius:3px;font-size:13px;padding:5px 10px;cursor:pointer}.cdx-notify__button:last-child{margin-left:10px}.cdx-notify__button--cancel{background:#f2f5f7;box-shadow:0 2px 1px 0 rgba(16,19,29,0);color:#656b7c}.cdx-notify__button--cancel:hover{background:#eee}.cdx-notify__button--confirm{background:#34c992;box-shadow:0 1px 1px 0 rgba(18,49,35,.05);color:#fff}.cdx-notify__button--confirm:hover{background:#33b082}.cdx-notify__btns-wrapper{display:-ms-flexbox;display:flex;-ms-flex-flow:row nowrap;flex-flow:row nowrap;margin-top:5px}.cdx-notify__cross{position:absolute;top:5px;right:5px;width:10px;height:10px;padding:5px;opacity:.54;cursor:pointer}.cdx-notify__cross::after,.cdx-notify__cross::before{content:'';position:absolute;left:9px;top:5px;height:12px;width:2px;background:#575d67}.cdx-notify__cross::before{transform:rotate(-45deg)}.cdx-notify__cross::after{transform:rotate(45deg)}.cdx-notify__cross:hover{opacity:1}.cdx-notifies{position:fixed;z-index:2;bottom:20px;left:20px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",sans-serif}.cdx-notify{position:relative;width:220px;margin-top:15px;padding:13px 16px;background:#fff;box-shadow:0 11px 17px 0 rgba(23,32,61,.13);border-radius:5px;font-size:14px;line-height:1.4em;word-wrap:break-word}.cdx-notify::before{content:'';position:absolute;display:block;top:0;left:0;width:3px;height:calc(100% - 6px);margin:3px;border-radius:5px;background:0 0}@keyframes bounceIn{0%{opacity:0;transform:scale(.3)}50%{opacity:1;transform:scale(1.05)}70%{transform:scale(.9)}100%{transform:scale(1)}}.cdx-notify--bounce-in{animation-name:bounceIn;animation-duration:.6s;animation-iteration-count:1}.cdx-notify--success{background:#fafffe!important}.cdx-notify--success::before{background:#41ffb1!important}`,""])},function(t,o){t.exports=function(i){var s=[];return s.toString=function(){return this.map(function(r){var a=function(l,c){var d=l[1]||"",h=l[3];if(!h)return d;if(c&&typeof btoa=="function"){var p=(f=h,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(f))))+" */"),g=h.sources.map(function(v){return"/*# sourceURL="+h.sourceRoot+v+" */"});return[d].concat(g).concat([p]).join(` +`)}var f;return[d].join(` +`)}(r,i);return r[2]?"@media "+r[2]+"{"+a+"}":a}).join("")},s.i=function(r,a){typeof r=="string"&&(r=[[null,r,""]]);for(var l={},c=0;c=0&&p.splice(m,1)}function A(k){var m=document.createElement("style");return k.attrs.type===void 0&&(k.attrs.type="text/css"),G(m,k.attrs),O(k,m),m}function G(k,m){Object.keys(m).forEach(function(w){k.setAttribute(w,m[w])})}function j(k,m){var w,x,I,C;if(m.transform&&k.css){if(!(C=m.transform(k.css)))return function(){};k.css=C}if(m.singleton){var D=h++;w=d||(d=A(m)),x=he.bind(null,w,D,!1),I=he.bind(null,w,D,!0)}else k.sourceMap&&typeof URL=="function"&&typeof URL.createObjectURL=="function"&&typeof URL.revokeObjectURL=="function"&&typeof Blob=="function"&&typeof btoa=="function"?(w=function(B){var K=document.createElement("link");return B.attrs.type===void 0&&(B.attrs.type="text/css"),B.attrs.rel="stylesheet",G(K,B.attrs),O(B,K),K}(m),x=(function(B,K,Oe){var pe=Oe.css,vo=Oe.sourceMap,Ca=K.convertToAbsoluteUrls===void 0&&vo;(K.convertToAbsoluteUrls||Ca)&&(pe=g(pe)),vo&&(pe+=` +/*# sourceMappingURL=data:application/json;base64,`+btoa(unescape(encodeURIComponent(JSON.stringify(vo))))+" */");var Ta=new Blob([pe],{type:"text/css"}),$n=B.href;B.href=URL.createObjectURL(Ta),$n&&URL.revokeObjectURL($n)}).bind(null,w,m),I=function(){S(w),w.href&&URL.revokeObjectURL(w.href)}):(w=A(m),x=(function(B,K){var Oe=K.css,pe=K.media;if(pe&&B.setAttribute("media",pe),B.styleSheet)B.styleSheet.cssText=Oe;else{for(;B.firstChild;)B.removeChild(B.firstChild);B.appendChild(document.createTextNode(Oe))}}).bind(null,w),I=function(){S(w)});return x(k),function(B){if(B){if(B.css===k.css&&B.media===k.media&&B.sourceMap===k.sourceMap)return;x(k=B)}else I()}}t.exports=function(k,m){if(typeof DEBUG<"u"&&DEBUG&&typeof document!="object")throw new Error("The style-loader cannot be used in a non-browser environment");(m=m||{}).attrs=typeof m.attrs=="object"?m.attrs:{},m.singleton||typeof m.singleton=="boolean"||(m.singleton=l()),m.insertInto||(m.insertInto="head"),m.insertAt||(m.insertAt="bottom");var w=v(k,m);return f(w,m),function(x){for(var I=[],C=0;Cthis.show(e)}}show(e){return this.notifier.show(e)}}class yi extends E{get methods(){const e=()=>this.isEnabled;return{toggle:t=>this.toggle(t),get isEnabled(){return e()}}}toggle(e){return this.Editor.ReadOnly.toggle(e)}get isEnabled(){return this.Editor.ReadOnly.isEnabled}}var Fo={exports:{}};(function(n,e){(function(t,o){n.exports=o()})(J,function(){function t(h){var p=h.tags,g=Object.keys(p),f=g.map(function(v){return typeof p[v]}).every(function(v){return v==="object"||v==="boolean"||v==="function"});if(!f)throw new Error("The configuration was invalid");this.config=h}var o=["P","LI","TD","TH","DIV","H1","H2","H3","H4","H5","H6","PRE"];function i(h){return o.indexOf(h.nodeName)!==-1}var s=["A","B","STRONG","I","EM","SUB","SUP","U","STRIKE"];function r(h){return s.indexOf(h.nodeName)!==-1}t.prototype.clean=function(h){const p=document.implementation.createHTMLDocument(),g=p.createElement("div");return g.innerHTML=h,this._sanitize(p,g),g.innerHTML},t.prototype._sanitize=function(h,p){var g=a(h,p),f=g.firstChild();if(f)do{if(f.nodeType===Node.TEXT_NODE)if(f.data.trim()===""&&(f.previousElementSibling&&i(f.previousElementSibling)||f.nextElementSibling&&i(f.nextElementSibling))){p.removeChild(f),this._sanitize(h,p);break}else continue;if(f.nodeType===Node.COMMENT_NODE){p.removeChild(f),this._sanitize(h,p);break}var v=r(f),O;v&&(O=Array.prototype.some.call(f.childNodes,i));var S=!!p.parentNode,A=i(p)&&i(f)&&S,G=f.nodeName.toLowerCase(),j=l(this.config,G,f),U=v&&O;if(U||c(f,j)||!this.config.keepNestedBlockElements&&A){if(!(f.nodeName==="SCRIPT"||f.nodeName==="STYLE"))for(;f.childNodes.length>0;)p.insertBefore(f.childNodes[0],f);p.removeChild(f),this._sanitize(h,p);break}for(var oe=0;oe"u"?!0:typeof p=="boolean"?!p:!1}function d(h,p,g){var f=h.name.toLowerCase();return p===!0?!1:typeof p[f]=="function"?!p[f](h.value,g):typeof p[f]>"u"||p[f]===!1?!0:typeof p[f]=="string"?p[f]!==h.value:!1}return t})})(Fo);var wi=Fo.exports;const Ei=ne(wi);function dt(n,e){return n.map(t=>{const o=M(e)?e(t.tool):e;return V(o)||(t.data=ut(t.data,o)),t})}function q(n,e={}){const t={tags:e};return new Ei(t).clean(n)}function ut(n,e){return Array.isArray(n)?xi(n,e):N(n)?Bi(n,e):Q(n)?Ci(n,e):n}function xi(n,e){return n.map(t=>ut(t,e))}function Bi(n,e){const t={};for(const o in n){if(!Object.prototype.hasOwnProperty.call(n,o))continue;const i=n[o],s=Ti(e[o])?e[o]:e;t[o]=ut(i,s)}return t}function Ci(n,e){return N(e)?q(n,e):e===!1?q(n,{}):n}function Ti(n){return N(n)||qn(n)||M(n)}class Si extends E{get methods(){return{clean:(e,t)=>this.clean(e,t)}}clean(e,t){return q(e,t)}}class Ii extends E{get methods(){return{save:()=>this.save()}}save(){const e="Editor's content can not be saved in read-only mode";return this.Editor.ReadOnly.isEnabled?(X(e,"warn"),Promise.reject(new Error(e))):this.Editor.Saver.save()}}class Oi extends E{constructor(){super(...arguments),this.selectionUtils=new b}get methods(){return{findParentTag:(e,t)=>this.findParentTag(e,t),expandToTag:e=>this.expandToTag(e),save:()=>this.selectionUtils.save(),restore:()=>this.selectionUtils.restore(),setFakeBackground:()=>this.selectionUtils.setFakeBackground(),removeFakeBackground:()=>this.selectionUtils.removeFakeBackground()}}findParentTag(e,t){return this.selectionUtils.findParentTag(e,t)}expandToTag(e){this.selectionUtils.expandToTag(e)}}class _i extends E{get methods(){return{getBlockTools:()=>Array.from(this.Editor.Tools.blockTools.values())}}}class Mi extends E{get classes(){return{block:"cdx-block",inlineToolButton:"ce-inline-tool",inlineToolButtonActive:"ce-inline-tool--active",input:"cdx-input",loader:"cdx-loader",button:"cdx-button",settingsButton:"cdx-settings-button",settingsButtonActive:"cdx-settings-button--active"}}}class Ai extends E{get methods(){return{close:()=>this.close(),open:()=>this.open(),toggleBlockSettings:e=>this.toggleBlockSettings(e),toggleToolbox:e=>this.toggleToolbox(e)}}open(){this.Editor.Toolbar.moveAndOpen()}close(){this.Editor.Toolbar.close()}toggleBlockSettings(e){if(this.Editor.BlockManager.currentBlockIndex===-1){X("Could't toggle the Toolbar because there is no block selected ","warn");return}e??!this.Editor.BlockSettings.opened?(this.Editor.Toolbar.moveAndOpen(),this.Editor.BlockSettings.open()):this.Editor.BlockSettings.close()}toggleToolbox(e){if(this.Editor.BlockManager.currentBlockIndex===-1){X("Could't toggle the Toolbox because there is no block selected ","warn");return}e??!this.Editor.Toolbar.toolbox.opened?(this.Editor.Toolbar.moveAndOpen(),this.Editor.Toolbar.toolbox.open()):this.Editor.Toolbar.toolbox.close()}}var jo={exports:{}};/*! + * CodeX.Tooltips + * + * @version 1.0.5 + * + * @licence MIT + * @author CodeX + * + * + */(function(n,e){(function(t,o){n.exports=o()})(window,function(){return function(t){var o={};function i(s){if(o[s])return o[s].exports;var r=o[s]={i:s,l:!1,exports:{}};return t[s].call(r.exports,r,r.exports,i),r.l=!0,r.exports}return i.m=t,i.c=o,i.d=function(s,r,a){i.o(s,r)||Object.defineProperty(s,r,{enumerable:!0,get:a})},i.r=function(s){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(s,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(s,"__esModule",{value:!0})},i.t=function(s,r){if(1&r&&(s=i(s)),8&r||4&r&&typeof s=="object"&&s&&s.__esModule)return s;var a=Object.create(null);if(i.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:s}),2&r&&typeof s!="string")for(var l in s)i.d(a,l,(function(c){return s[c]}).bind(null,l));return a},i.n=function(s){var r=s&&s.__esModule?function(){return s.default}:function(){return s};return i.d(r,"a",r),r},i.o=function(s,r){return Object.prototype.hasOwnProperty.call(s,r)},i.p="",i(i.s=0)}([function(t,o,i){t.exports=i(1)},function(t,o,i){i.r(o),i.d(o,"default",function(){return s});class s{constructor(){this.nodes={wrapper:null,content:null},this.showed=!1,this.offsetTop=10,this.offsetLeft=10,this.offsetRight=10,this.hidingDelay=0,this.handleWindowScroll=()=>{this.showed&&this.hide(!0)},this.loadStyles(),this.prepare(),window.addEventListener("scroll",this.handleWindowScroll,{passive:!0})}get CSS(){return{tooltip:"ct",tooltipContent:"ct__content",tooltipShown:"ct--shown",placement:{left:"ct--left",bottom:"ct--bottom",right:"ct--right",top:"ct--top"}}}show(a,l,c){this.nodes.wrapper||this.prepare(),this.hidingTimeout&&clearTimeout(this.hidingTimeout);const d=Object.assign({placement:"bottom",marginTop:0,marginLeft:0,marginRight:0,marginBottom:0,delay:70,hidingDelay:0},c);if(d.hidingDelay&&(this.hidingDelay=d.hidingDelay),this.nodes.content.innerHTML="",typeof l=="string")this.nodes.content.appendChild(document.createTextNode(l));else{if(!(l instanceof Node))throw Error("[CodeX Tooltip] Wrong type of «content» passed. It should be an instance of Node or String. But "+typeof l+" given.");this.nodes.content.appendChild(l)}switch(this.nodes.wrapper.classList.remove(...Object.values(this.CSS.placement)),d.placement){case"top":this.placeTop(a,d);break;case"left":this.placeLeft(a,d);break;case"right":this.placeRight(a,d);break;case"bottom":default:this.placeBottom(a,d)}d&&d.delay?this.showingTimeout=setTimeout(()=>{this.nodes.wrapper.classList.add(this.CSS.tooltipShown),this.showed=!0},d.delay):(this.nodes.wrapper.classList.add(this.CSS.tooltipShown),this.showed=!0)}hide(a=!1){if(this.hidingDelay&&!a)return this.hidingTimeout&&clearTimeout(this.hidingTimeout),void(this.hidingTimeout=setTimeout(()=>{this.hide(!0)},this.hidingDelay));this.nodes.wrapper.classList.remove(this.CSS.tooltipShown),this.showed=!1,this.showingTimeout&&clearTimeout(this.showingTimeout)}onHover(a,l,c){a.addEventListener("mouseenter",()=>{this.show(a,l,c)}),a.addEventListener("mouseleave",()=>{this.hide()})}destroy(){this.nodes.wrapper.remove(),window.removeEventListener("scroll",this.handleWindowScroll)}prepare(){this.nodes.wrapper=this.make("div",this.CSS.tooltip),this.nodes.content=this.make("div",this.CSS.tooltipContent),this.append(this.nodes.wrapper,this.nodes.content),this.append(document.body,this.nodes.wrapper)}loadStyles(){const a="codex-tooltips-style";if(document.getElementById(a))return;const l=i(2),c=this.make("style",null,{textContent:l.toString(),id:a});this.prepend(document.head,c)}placeBottom(a,l){const c=a.getBoundingClientRect(),d=c.left+a.clientWidth/2-this.nodes.wrapper.offsetWidth/2,h=c.bottom+window.pageYOffset+this.offsetTop+l.marginTop;this.applyPlacement("bottom",d,h)}placeTop(a,l){const c=a.getBoundingClientRect(),d=c.left+a.clientWidth/2-this.nodes.wrapper.offsetWidth/2,h=c.top+window.pageYOffset-this.nodes.wrapper.clientHeight-this.offsetTop;this.applyPlacement("top",d,h)}placeLeft(a,l){const c=a.getBoundingClientRect(),d=c.left-this.nodes.wrapper.offsetWidth-this.offsetLeft-l.marginLeft,h=c.top+window.pageYOffset+a.clientHeight/2-this.nodes.wrapper.offsetHeight/2;this.applyPlacement("left",d,h)}placeRight(a,l){const c=a.getBoundingClientRect(),d=c.right+this.offsetRight+l.marginRight,h=c.top+window.pageYOffset+a.clientHeight/2-this.nodes.wrapper.offsetHeight/2;this.applyPlacement("right",d,h)}applyPlacement(a,l,c){this.nodes.wrapper.classList.add(this.CSS.placement[a]),this.nodes.wrapper.style.left=l+"px",this.nodes.wrapper.style.top=c+"px"}make(a,l=null,c={}){const d=document.createElement(a);Array.isArray(l)?d.classList.add(...l):l&&d.classList.add(l);for(const h in c)c.hasOwnProperty(h)&&(d[h]=c[h]);return d}append(a,l){Array.isArray(l)?l.forEach(c=>a.appendChild(c)):a.appendChild(l)}prepend(a,l){Array.isArray(l)?(l=l.reverse()).forEach(c=>a.prepend(c)):a.prepend(l)}}},function(t,o){t.exports=`.ct{z-index:999;opacity:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none;-webkit-transition:opacity 50ms ease-in,-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,transform 70ms cubic-bezier(.215,.61,.355,1),-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);will-change:opacity,top,left;-webkit-box-shadow:0 8px 12px 0 rgba(29,32,43,.17),0 4px 5px -3px rgba(5,6,12,.49);box-shadow:0 8px 12px 0 rgba(29,32,43,.17),0 4px 5px -3px rgba(5,6,12,.49);border-radius:9px}.ct,.ct:before{position:absolute;top:0;left:0}.ct:before{content:"";bottom:0;right:0;background-color:#1d202b;z-index:-1;border-radius:4px}@supports(-webkit-mask-box-image:url("")){.ct:before{border-radius:0;-webkit-mask-box-image:url('data:image/svg+xml;charset=utf-8,') 48% 41% 37.9% 53.3%}}@media (--mobile){.ct{display:none}}.ct__content{padding:6px 10px;color:#cdd1e0;font-size:12px;text-align:center;letter-spacing:.02em;line-height:1em}.ct:after{content:"";width:8px;height:8px;position:absolute;background-color:#1d202b;z-index:-1}.ct--bottom{-webkit-transform:translateY(5px);transform:translateY(5px)}.ct--bottom:after{top:-3px;left:50%;-webkit-transform:translateX(-50%) rotate(-45deg);transform:translateX(-50%) rotate(-45deg)}.ct--top{-webkit-transform:translateY(-5px);transform:translateY(-5px)}.ct--top:after{top:auto;bottom:-3px;left:50%;-webkit-transform:translateX(-50%) rotate(-45deg);transform:translateX(-50%) rotate(-45deg)}.ct--left{-webkit-transform:translateX(-5px);transform:translateX(-5px)}.ct--left:after{top:50%;left:auto;right:0;-webkit-transform:translate(41.6%,-50%) rotate(-45deg);transform:translate(41.6%,-50%) rotate(-45deg)}.ct--right{-webkit-transform:translateX(5px);transform:translateX(5px)}.ct--right:after{top:50%;left:0;-webkit-transform:translate(-41.6%,-50%) rotate(-45deg);transform:translate(-41.6%,-50%) rotate(-45deg)}.ct--shown{opacity:1;-webkit-transform:none;transform:none}`}]).default})})(jo);var Li=jo.exports;const Pi=ne(Li);let $=null;function ht(){$||($=new Pi)}function Ni(n,e,t){ht(),$==null||$.show(n,e,t)}function Ne(n=!1){ht(),$==null||$.hide(n)}function Re(n,e,t){ht(),$==null||$.onHover(n,e,t)}function Ri(){$==null||$.destroy(),$=null}class Di extends E{constructor({config:e,eventsDispatcher:t}){super({config:e,eventsDispatcher:t})}get methods(){return{show:(e,t,o)=>this.show(e,t,o),hide:()=>this.hide(),onHover:(e,t,o)=>this.onHover(e,t,o)}}show(e,t,o){Ni(e,t,o)}hide(){Ne()}onHover(e,t,o){Re(e,t,o)}}class Fi extends E{get methods(){return{nodes:this.editorNodes}}get editorNodes(){return{wrapper:this.Editor.UI.nodes.wrapper,redactor:this.Editor.UI.nodes.redactor}}}function Ho(n,e){const t={};return Object.entries(n).forEach(([o,i])=>{if(N(i)){const s=e?`${e}.${o}`:o;Object.values(i).every(a=>Q(a))?t[o]=s:t[o]=Ho(i,s);return}t[o]=i}),t}const W=Ho(So);function ji(n,e){const t={};return Object.keys(n).forEach(o=>{const i=e[o];i!==void 0?t[i]=n[o]:t[o]=n[o]}),t}const $o=class _e{constructor(e,t){this.cursor=-1,this.items=[],this.items=e||[],this.focusedCssClass=t}get currentItem(){return this.cursor===-1?null:this.items[this.cursor]}setCursor(e){e=-1&&(this.dropCursor(),this.cursor=e,this.items[this.cursor].classList.add(this.focusedCssClass))}setItems(e){this.items=e}next(){this.cursor=this.leafNodesAndReturnIndex(_e.directions.RIGHT)}previous(){this.cursor=this.leafNodesAndReturnIndex(_e.directions.LEFT)}dropCursor(){this.cursor!==-1&&(this.items[this.cursor].classList.remove(this.focusedCssClass),this.cursor=-1)}leafNodesAndReturnIndex(e){if(this.items.length===0)return this.cursor;let t=this.cursor;return t===-1?t=e===_e.directions.RIGHT?-1:0:this.items[t].classList.remove(this.focusedCssClass),e===_e.directions.RIGHT?t=(t+1)%this.items.length:t=(this.items.length+t-1)%this.items.length,u.canSetCaret(this.items[t])&&Ae(()=>b.setCursor(this.items[t]),50)(),this.items[t].classList.add(this.focusedCssClass),t}};$o.directions={RIGHT:"right",LEFT:"left"};let Be=$o;class ae{constructor(e){this.iterator=null,this.activated=!1,this.flipCallbacks=[],this.onKeyDown=t=>{if(!(!this.isEventReadyForHandling(t)||t.shiftKey===!0))switch(ae.usedKeys.includes(t.keyCode)&&t.preventDefault(),t.keyCode){case y.TAB:this.handleTabPress(t);break;case y.LEFT:case y.UP:this.flipLeft();break;case y.RIGHT:case y.DOWN:this.flipRight();break;case y.ENTER:this.handleEnterPress(t);break}},this.iterator=new Be(e.items,e.focusedItemClass),this.activateCallback=e.activateCallback,this.allowedKeys=e.allowedKeys||ae.usedKeys}get isActivated(){return this.activated}static get usedKeys(){return[y.TAB,y.LEFT,y.RIGHT,y.ENTER,y.UP,y.DOWN]}activate(e,t){this.activated=!0,e&&this.iterator.setItems(e),t!==void 0&&this.iterator.setCursor(t),document.addEventListener("keydown",this.onKeyDown,!0)}deactivate(){this.activated=!1,this.dropCursor(),document.removeEventListener("keydown",this.onKeyDown)}focusFirst(){this.dropCursor(),this.flipRight()}flipLeft(){this.iterator.previous(),this.flipCallback()}flipRight(){this.iterator.next(),this.flipCallback()}hasFocus(){return!!this.iterator.currentItem}onFlip(e){this.flipCallbacks.push(e)}removeOnFlip(e){this.flipCallbacks=this.flipCallbacks.filter(t=>t!==e)}dropCursor(){this.iterator.dropCursor()}isEventReadyForHandling(e){return this.activated&&this.allowedKeys.includes(e.keyCode)}handleTabPress(e){switch(e.shiftKey?Be.directions.LEFT:Be.directions.RIGHT){case Be.directions.RIGHT:this.flipRight();break;case Be.directions.LEFT:this.flipLeft();break}}handleEnterPress(e){this.activated&&(this.iterator.currentItem&&(e.stopPropagation(),e.preventDefault(),this.iterator.currentItem.click()),M(this.activateCallback)&&this.activateCallback(this.iterator.currentItem))}flipCallback(){this.iterator.currentItem&&this.iterator.currentItem.scrollIntoViewIfNeeded(),this.flipCallbacks.forEach(e=>e())}}const Hi='',$i='',zi='',Ui='',Wi='',Yi='',Ki='',Xi='',zo='',Vi='',qi='',Uo='',Zi='',Gi='',Ji='',Qi="__",es="--";function ie(n){return(e,t)=>[[n,e].filter(i=>!!i).join(Qi),t].filter(i=>!!i).join(es)}const Ce=ie("ce-hint"),Te={root:Ce(),alignedStart:Ce(null,"align-left"),alignedCenter:Ce(null,"align-center"),title:Ce("title"),description:Ce("description")},Ma="";class ts{constructor(e){this.nodes={root:u.make("div",[Te.root,e.alignment==="center"?Te.alignedCenter:Te.alignedStart]),title:u.make("div",Te.title,{textContent:e.title})},this.nodes.root.appendChild(this.nodes.title),e.description!==void 0&&(this.nodes.description=u.make("div",Te.description,{textContent:e.description}),this.nodes.root.appendChild(this.nodes.description))}getElement(){return this.nodes.root}}class pt{constructor(e){this.params=e}get name(){if(this.params!==void 0&&"name"in this.params)return this.params.name}destroy(){Ne()}onChildrenOpen(){var e;this.params!==void 0&&"children"in this.params&&typeof((e=this.params.children)==null?void 0:e.onOpen)=="function"&&this.params.children.onOpen()}onChildrenClose(){var e;this.params!==void 0&&"children"in this.params&&typeof((e=this.params.children)==null?void 0:e.onClose)=="function"&&this.params.children.onClose()}handleClick(){var e,t;this.params!==void 0&&"onActivate"in this.params&&((t=(e=this.params).onActivate)==null||t.call(e,this.params))}addHint(e,t){const o=new ts(t);Re(e,o.getElement(),{placement:t.position,hidingDelay:100})}get children(){var e;return this.params!==void 0&&"children"in this.params&&((e=this.params.children)==null?void 0:e.items)!==void 0?this.params.children.items:[]}get hasChildren(){return this.children.length>0}get isChildrenOpen(){var e;return this.params!==void 0&&"children"in this.params&&((e=this.params.children)==null?void 0:e.isOpen)===!0}get isChildrenFlippable(){var e;return!(this.params===void 0||!("children"in this.params)||((e=this.params.children)==null?void 0:e.isFlippable)===!1)}get isChildrenSearchable(){var e;return this.params!==void 0&&"children"in this.params&&((e=this.params.children)==null?void 0:e.searchable)===!0}get closeOnActivate(){return this.params!==void 0&&"closeOnActivate"in this.params&&this.params.closeOnActivate}get isActive(){return this.params===void 0||!("isActive"in this.params)?!1:typeof this.params.isActive=="function"?this.params.isActive():this.params.isActive===!0}}const Y=ie("ce-popover-item"),L={container:Y(),active:Y(null,"active"),disabled:Y(null,"disabled"),focused:Y(null,"focused"),hidden:Y(null,"hidden"),confirmationState:Y(null,"confirmation"),noHover:Y(null,"no-hover"),noFocus:Y(null,"no-focus"),title:Y("title"),secondaryTitle:Y("secondary-title"),icon:Y("icon"),iconTool:Y("icon","tool"),iconChevronRight:Y("icon","chevron-right"),wobbleAnimation:ie("wobble")()};class le extends pt{constructor(e,t){super(e),this.params=e,this.nodes={root:null,icon:null},this.confirmationState=null,this.removeSpecialFocusBehavior=()=>{var o;(o=this.nodes.root)==null||o.classList.remove(L.noFocus)},this.removeSpecialHoverBehavior=()=>{var o;(o=this.nodes.root)==null||o.classList.remove(L.noHover)},this.onErrorAnimationEnd=()=>{var o,i;(o=this.nodes.icon)==null||o.classList.remove(L.wobbleAnimation),(i=this.nodes.icon)==null||i.removeEventListener("animationend",this.onErrorAnimationEnd)},this.nodes.root=this.make(e,t)}get isDisabled(){return this.params.isDisabled===!0}get toggle(){return this.params.toggle}get title(){return this.params.title}get isConfirmationStateEnabled(){return this.confirmationState!==null}get isFocused(){return this.nodes.root===null?!1:this.nodes.root.classList.contains(L.focused)}getElement(){return this.nodes.root}handleClick(){if(this.isConfirmationStateEnabled&&this.confirmationState!==null){this.activateOrEnableConfirmationMode(this.confirmationState);return}this.activateOrEnableConfirmationMode(this.params)}toggleActive(e){var t;(t=this.nodes.root)==null||t.classList.toggle(L.active,e)}toggleHidden(e){var t;(t=this.nodes.root)==null||t.classList.toggle(L.hidden,e)}reset(){this.isConfirmationStateEnabled&&this.disableConfirmationMode()}onFocus(){this.disableSpecialHoverAndFocusBehavior()}make(e,t){var s,r;const o=(t==null?void 0:t.wrapperTag)||"div",i=u.make(o,L.container,{type:o==="button"?"button":void 0});return e.name&&(i.dataset.itemName=e.name),this.nodes.icon=u.make("div",[L.icon,L.iconTool],{innerHTML:e.icon||Ki}),i.appendChild(this.nodes.icon),e.title!==void 0&&i.appendChild(u.make("div",L.title,{innerHTML:e.title||""})),e.secondaryLabel&&i.appendChild(u.make("div",L.secondaryTitle,{textContent:e.secondaryLabel})),this.hasChildren&&i.appendChild(u.make("div",[L.icon,L.iconChevronRight],{innerHTML:Ui})),this.isActive&&i.classList.add(L.active),e.isDisabled&&i.classList.add(L.disabled),e.hint!==void 0&&((s=t==null?void 0:t.hint)==null?void 0:s.enabled)!==!1&&this.addHint(i,{...e.hint,position:((r=t==null?void 0:t.hint)==null?void 0:r.position)||"right"}),i}enableConfirmationMode(e){if(this.nodes.root===null)return;const t={...this.params,...e,confirmation:"confirmation"in e?e.confirmation:void 0},o=this.make(t);this.nodes.root.innerHTML=o.innerHTML,this.nodes.root.classList.add(L.confirmationState),this.confirmationState=e,this.enableSpecialHoverAndFocusBehavior()}disableConfirmationMode(){if(this.nodes.root===null)return;const e=this.make(this.params);this.nodes.root.innerHTML=e.innerHTML,this.nodes.root.classList.remove(L.confirmationState),this.confirmationState=null,this.disableSpecialHoverAndFocusBehavior()}enableSpecialHoverAndFocusBehavior(){var e,t,o;(e=this.nodes.root)==null||e.classList.add(L.noHover),(t=this.nodes.root)==null||t.classList.add(L.noFocus),(o=this.nodes.root)==null||o.addEventListener("mouseleave",this.removeSpecialHoverBehavior,{once:!0})}disableSpecialHoverAndFocusBehavior(){var e;this.removeSpecialFocusBehavior(),this.removeSpecialHoverBehavior(),(e=this.nodes.root)==null||e.removeEventListener("mouseleave",this.removeSpecialHoverBehavior)}activateOrEnableConfirmationMode(e){var t;if(!("confirmation"in e)||e.confirmation===void 0)try{(t=e.onActivate)==null||t.call(e,e),this.disableConfirmationMode()}catch{this.animateError()}else this.enableConfirmationMode(e.confirmation)}animateError(){var e,t,o;(e=this.nodes.icon)!=null&&e.classList.contains(L.wobbleAnimation)||((t=this.nodes.icon)==null||t.classList.add(L.wobbleAnimation),(o=this.nodes.icon)==null||o.addEventListener("animationend",this.onErrorAnimationEnd))}}const ft=ie("ce-popover-item-separator"),gt={container:ft(),line:ft("line"),hidden:ft(null,"hidden")};class Wo extends pt{constructor(){super(),this.nodes={root:u.make("div",gt.container),line:u.make("div",gt.line)},this.nodes.root.appendChild(this.nodes.line)}getElement(){return this.nodes.root}toggleHidden(e){var t;(t=this.nodes.root)==null||t.classList.toggle(gt.hidden,e)}}var Z=(n=>(n.Closed="closed",n.ClosedOnActivate="closed-on-activate",n))(Z||{});const z=ie("ce-popover"),P={popover:z(),popoverContainer:z("container"),popoverOpenTop:z(null,"open-top"),popoverOpenLeft:z(null,"open-left"),popoverOpened:z(null,"opened"),search:z("search"),nothingFoundMessage:z("nothing-found-message"),nothingFoundMessageDisplayed:z("nothing-found-message","displayed"),items:z("items"),overlay:z("overlay"),overlayHidden:z("overlay","hidden"),popoverNested:z(null,"nested"),getPopoverNestedClass:n=>z(null,`nested-level-${n.toString()}`),popoverInline:z(null,"inline"),popoverHeader:z("header")};var me=(n=>(n.NestingLevel="--nesting-level",n.PopoverHeight="--popover-height",n.InlinePopoverWidth="--inline-popover-width",n.TriggerItemLeft="--trigger-item-left",n.TriggerItemTop="--trigger-item-top",n))(me||{});const Yo=ie("ce-popover-item-html"),Ko={root:Yo(),hidden:Yo(null,"hidden")};class Se extends pt{constructor(e,t){var o,i;super(e),this.nodes={root:u.make("div",Ko.root)},this.nodes.root.appendChild(e.element),e.name&&(this.nodes.root.dataset.itemName=e.name),e.hint!==void 0&&((o=t==null?void 0:t.hint)==null?void 0:o.enabled)!==!1&&this.addHint(this.nodes.root,{...e.hint,position:((i=t==null?void 0:t.hint)==null?void 0:i.position)||"right"})}getElement(){return this.nodes.root}toggleHidden(e){var t;(t=this.nodes.root)==null||t.classList.toggle(Ko.hidden,e)}getControls(){const e=this.nodes.root.querySelectorAll(`button, ${u.allInputsSelector}`);return Array.from(e)}}class Xo extends we{constructor(e,t={}){super(),this.params=e,this.itemsRenderParams=t,this.listeners=new Ee,this.messages={nothingFound:"Nothing found",search:"Search"},this.items=this.buildItems(e.items),e.messages&&(this.messages={...this.messages,...e.messages}),this.nodes={},this.nodes.popoverContainer=u.make("div",[P.popoverContainer]),this.nodes.nothingFoundMessage=u.make("div",[P.nothingFoundMessage],{textContent:this.messages.nothingFound}),this.nodes.popoverContainer.appendChild(this.nodes.nothingFoundMessage),this.nodes.items=u.make("div",[P.items]),this.items.forEach(o=>{const i=o.getElement();i!==null&&this.nodes.items.appendChild(i)}),this.nodes.popoverContainer.appendChild(this.nodes.items),this.listeners.on(this.nodes.popoverContainer,"click",o=>this.handleClick(o)),this.nodes.popover=u.make("div",[P.popover,this.params.class]),this.nodes.popover.appendChild(this.nodes.popoverContainer)}get itemsDefault(){return this.items.filter(e=>e instanceof le)}getElement(){return this.nodes.popover}show(){this.nodes.popover.classList.add(P.popoverOpened),this.search!==void 0&&this.search.focus()}hide(){this.nodes.popover.classList.remove(P.popoverOpened),this.nodes.popover.classList.remove(P.popoverOpenTop),this.itemsDefault.forEach(e=>e.reset()),this.search!==void 0&&this.search.clear(),this.emit(Z.Closed)}destroy(){var e;this.items.forEach(t=>t.destroy()),this.nodes.popover.remove(),this.listeners.removeAll(),(e=this.search)==null||e.destroy()}activateItemByName(e){const t=this.items.find(o=>o.name===e);this.handleItemClick(t)}buildItems(e){return e.map(t=>{switch(t.type){case _.Separator:return new Wo;case _.Html:return new Se(t,this.itemsRenderParams[_.Html]);default:return new le(t,this.itemsRenderParams[_.Default])}})}getTargetItem(e){return this.items.filter(t=>t instanceof le||t instanceof Se).find(t=>{const o=t.getElement();return o===null?!1:e.composedPath().includes(o)})}handleItemClick(e){if(!("isDisabled"in e&&e.isDisabled)){if(e.hasChildren){this.showNestedItems(e),"handleClick"in e&&typeof e.handleClick=="function"&&e.handleClick();return}this.itemsDefault.filter(t=>t!==e).forEach(t=>t.reset()),"handleClick"in e&&typeof e.handleClick=="function"&&e.handleClick(),this.toggleItemActivenessIfNeeded(e),e.closeOnActivate&&(this.hide(),this.emit(Z.ClosedOnActivate))}}handleClick(e){const t=this.getTargetItem(e);t!==void 0&&this.handleItemClick(t)}toggleItemActivenessIfNeeded(e){if(e instanceof le&&(e.toggle===!0&&e.toggleActive(),typeof e.toggle=="string")){const t=this.itemsDefault.filter(o=>o.toggle===e.toggle);if(t.length===1){e.toggleActive();return}t.forEach(o=>{o.toggleActive(o===e)})}}}var De=(n=>(n.Search="search",n))(De||{});const mt=ie("cdx-search-field"),bt={wrapper:mt(),icon:mt("icon"),input:mt("input")};class os extends we{constructor({items:e,placeholder:t}){super(),this.listeners=new Ee,this.items=e,this.wrapper=u.make("div",bt.wrapper);const o=u.make("div",bt.icon,{innerHTML:Zi});this.input=u.make("input",bt.input,{placeholder:t,tabIndex:-1}),this.wrapper.appendChild(o),this.wrapper.appendChild(this.input),this.listeners.on(this.input,"input",()=>{this.searchQuery=this.input.value,this.emit(De.Search,{query:this.searchQuery,items:this.foundItems})})}getElement(){return this.wrapper}focus(){this.input.focus()}clear(){this.input.value="",this.searchQuery="",this.emit(De.Search,{query:"",items:this.foundItems})}destroy(){this.listeners.removeAll()}get foundItems(){return this.items.filter(e=>this.checkItem(e))}checkItem(e){var i,s;const t=((i=e.title)==null?void 0:i.toLowerCase())||"",o=(s=this.searchQuery)==null?void 0:s.toLowerCase();return o!==void 0?t.includes(o):!1}}var ns=Object.defineProperty,is=Object.getOwnPropertyDescriptor,ss=(n,e,t,o)=>{for(var i=o>1?void 0:o?is(e,t):e,s=n.length-1,r;s>=0;s--)(r=n[s])&&(i=(o?r(e,t,i):r(i))||i);return o&&i&&ns(e,t,i),i};const Vo=class zn extends Xo{constructor(e,t){super(e,t),this.nestingLevel=0,this.nestedPopoverTriggerItem=null,this.previouslyHoveredItem=null,this.scopeElement=document.body,this.hide=()=>{var o;super.hide(),this.destroyNestedPopoverIfExists(),(o=this.flipper)==null||o.deactivate(),this.previouslyHoveredItem=null},this.onFlip=()=>{const o=this.itemsDefault.find(i=>i.isFocused);o==null||o.onFocus()},this.onSearch=o=>{var a;const i=o.query==="",s=o.items.length===0;this.items.forEach(l=>{let c=!1;l instanceof le?c=!o.items.includes(l):(l instanceof Wo||l instanceof Se)&&(c=s||!i),l.toggleHidden(c)}),this.toggleNothingFoundMessage(s);const r=o.query===""?this.flippableElements:o.items.map(l=>l.getElement());(a=this.flipper)!=null&&a.isActivated&&(this.flipper.deactivate(),this.flipper.activate(r))},e.nestingLevel!==void 0&&(this.nestingLevel=e.nestingLevel),this.nestingLevel>0&&this.nodes.popover.classList.add(P.popoverNested),e.scopeElement!==void 0&&(this.scopeElement=e.scopeElement),this.nodes.popoverContainer!==null&&this.listeners.on(this.nodes.popoverContainer,"mouseover",o=>this.handleHover(o)),e.searchable&&this.addSearch(),e.flippable!==!1&&(this.flipper=new ae({items:this.flippableElements,focusedItemClass:L.focused,allowedKeys:[y.TAB,y.UP,y.DOWN,y.ENTER]}),this.flipper.onFlip(this.onFlip))}hasFocus(){return this.flipper===void 0?!1:this.flipper.hasFocus()}get scrollTop(){return this.nodes.items===null?0:this.nodes.items.scrollTop}get offsetTop(){return this.nodes.popoverContainer===null?0:this.nodes.popoverContainer.offsetTop}show(){var e;this.nodes.popover.style.setProperty(me.PopoverHeight,this.size.height+"px"),this.shouldOpenBottom||this.nodes.popover.classList.add(P.popoverOpenTop),this.shouldOpenRight||this.nodes.popover.classList.add(P.popoverOpenLeft),super.show(),(e=this.flipper)==null||e.activate(this.flippableElements)}destroy(){this.hide(),super.destroy()}showNestedItems(e){this.nestedPopover!==null&&this.nestedPopover!==void 0||(this.nestedPopoverTriggerItem=e,this.showNestedPopoverForItem(e))}handleHover(e){const t=this.getTargetItem(e);t!==void 0&&this.previouslyHoveredItem!==t&&(this.destroyNestedPopoverIfExists(),this.previouslyHoveredItem=t,t.hasChildren&&this.showNestedPopoverForItem(t))}setTriggerItemPosition(e,t){const o=t.getElement(),i=(o?o.offsetTop:0)-this.scrollTop,s=this.offsetTop+i;e.style.setProperty(me.TriggerItemTop,s+"px")}destroyNestedPopoverIfExists(){var e,t;this.nestedPopover===void 0||this.nestedPopover===null||(this.nestedPopover.off(Z.ClosedOnActivate,this.hide),this.nestedPopover.hide(),this.nestedPopover.destroy(),this.nestedPopover.getElement().remove(),this.nestedPopover=null,(e=this.flipper)==null||e.activate(this.flippableElements),(t=this.nestedPopoverTriggerItem)==null||t.onChildrenClose())}showNestedPopoverForItem(e){var o;this.nestedPopover=new zn({searchable:e.isChildrenSearchable,items:e.children,nestingLevel:this.nestingLevel+1,flippable:e.isChildrenFlippable,messages:this.messages}),e.onChildrenOpen(),this.nestedPopover.on(Z.ClosedOnActivate,this.hide);const t=this.nestedPopover.getElement();return this.nodes.popover.appendChild(t),this.setTriggerItemPosition(t,e),t.style.setProperty(me.NestingLevel,this.nestedPopover.nestingLevel.toString()),this.nestedPopover.show(),(o=this.flipper)==null||o.deactivate(),this.nestedPopover}get shouldOpenBottom(){if(this.nodes.popover===void 0||this.nodes.popover===null)return!1;const e=this.nodes.popoverContainer.getBoundingClientRect(),t=this.scopeElement.getBoundingClientRect(),o=this.size.height,i=e.top+o,s=e.top-o,r=Math.min(window.innerHeight,t.bottom);return s{if(t instanceof le)return t.getElement();if(t instanceof Se)return t.getControls()}).flat().filter(t=>t!=null)}addSearch(){this.search=new os({items:this.itemsDefault,placeholder:this.messages.search}),this.search.on(De.Search,this.onSearch);const e=this.search.getElement();e.classList.add(P.search),this.nodes.popoverContainer.insertBefore(e,this.nodes.popoverContainer.firstChild)}toggleNothingFoundMessage(e){this.nodes.nothingFoundMessage.classList.toggle(P.nothingFoundMessageDisplayed,e)}};ss([fe],Vo.prototype,"size",1);let vt=Vo;class rs extends vt{constructor(e){const t=!ge();super({...e,class:P.popoverInline},{[_.Default]:{wrapperTag:"button",hint:{position:"top",alignment:"center",enabled:t}},[_.Html]:{hint:{position:"top",alignment:"center",enabled:t}}}),this.items.forEach(o=>{!(o instanceof le)&&!(o instanceof Se)||o.hasChildren&&o.isChildrenOpen&&this.showNestedItems(o)})}get offsetLeft(){return this.nodes.popoverContainer===null?0:this.nodes.popoverContainer.offsetLeft}show(){this.nestingLevel===0&&this.nodes.popover.style.setProperty(me.InlinePopoverWidth,this.size.width+"px"),super.show()}handleHover(){}setTriggerItemPosition(e,t){const o=t.getElement(),i=o?o.offsetLeft:0,s=this.offsetLeft+i;e.style.setProperty(me.TriggerItemLeft,s+"px")}showNestedItems(e){if(this.nestedPopoverTriggerItem===e){this.destroyNestedPopoverIfExists(),this.nestedPopoverTriggerItem=null;return}super.showNestedItems(e)}showNestedPopoverForItem(e){const t=super.showNestedPopoverForItem(e);return t.getElement().classList.add(P.getPopoverNestedClass(t.nestingLevel)),t}handleItemClick(e){var t;e!==this.nestedPopoverTriggerItem&&((t=this.nestedPopoverTriggerItem)==null||t.handleClick(),super.destroyNestedPopoverIfExists()),super.handleItemClick(e)}}const qo=class Me{constructor(){this.scrollPosition=null}lock(){rt?this.lockHard():document.body.classList.add(Me.CSS.scrollLocked)}unlock(){rt?this.unlockHard():document.body.classList.remove(Me.CSS.scrollLocked)}lockHard(){this.scrollPosition=window.pageYOffset,document.documentElement.style.setProperty("--window-scroll-offset",`${this.scrollPosition}px`),document.body.classList.add(Me.CSS.scrollLockedHard)}unlockHard(){document.body.classList.remove(Me.CSS.scrollLockedHard),this.scrollPosition!==null&&window.scrollTo(0,this.scrollPosition),this.scrollPosition=null}};qo.CSS={scrollLocked:"ce-scroll-locked",scrollLockedHard:"ce-scroll-locked--hard"};let as=qo;const kt=ie("ce-popover-header"),yt={root:kt(),text:kt("text"),backButton:kt("back-button")};class ls{constructor({text:e,onBackButtonClick:t}){this.listeners=new Ee,this.text=e,this.onBackButtonClick=t,this.nodes={root:u.make("div",[yt.root]),backButton:u.make("button",[yt.backButton]),text:u.make("div",[yt.text])},this.nodes.backButton.innerHTML=zi,this.nodes.root.appendChild(this.nodes.backButton),this.listeners.on(this.nodes.backButton,"click",this.onBackButtonClick),this.nodes.text.innerText=this.text,this.nodes.root.appendChild(this.nodes.text)}getElement(){return this.nodes.root}destroy(){this.nodes.root.remove(),this.listeners.destroy()}}class cs{constructor(){this.history=[]}push(e){this.history.push(e)}pop(){return this.history.pop()}get currentTitle(){return this.history.length===0?"":this.history[this.history.length-1].title}get currentItems(){return this.history.length===0?[]:this.history[this.history.length-1].items}reset(){for(;this.history.length>1;)this.pop()}}class Zo extends Xo{constructor(e){super(e,{[_.Default]:{hint:{enabled:!1}},[_.Html]:{hint:{enabled:!1}}}),this.scrollLocker=new as,this.history=new cs,this.isHidden=!0,this.nodes.overlay=u.make("div",[P.overlay,P.overlayHidden]),this.nodes.popover.insertBefore(this.nodes.overlay,this.nodes.popover.firstChild),this.listeners.on(this.nodes.overlay,"click",()=>{this.hide()}),this.history.push({items:e.items})}show(){this.nodes.overlay.classList.remove(P.overlayHidden),super.show(),this.scrollLocker.lock(),this.isHidden=!1}hide(){this.isHidden||(super.hide(),this.nodes.overlay.classList.add(P.overlayHidden),this.scrollLocker.unlock(),this.history.reset(),this.isHidden=!0)}destroy(){super.destroy(),this.scrollLocker.unlock()}showNestedItems(e){this.updateItemsAndHeader(e.children,e.title),this.history.push({title:e.title,items:e.children})}updateItemsAndHeader(e,t){if(this.header!==null&&this.header!==void 0&&(this.header.destroy(),this.header=null),t!==void 0){this.header=new ls({text:t,onBackButtonClick:()=>{this.history.pop(),this.updateItemsAndHeader(this.history.currentItems,this.history.currentTitle)}});const o=this.header.getElement();o!==null&&this.nodes.popoverContainer.insertBefore(o,this.nodes.popoverContainer.firstChild)}this.items.forEach(o=>{var i;return(i=o.getElement())==null?void 0:i.remove()}),this.items=this.buildItems(e),this.items.forEach(o=>{var s;const i=o.getElement();i!==null&&((s=this.nodes.items)==null||s.appendChild(i))})}}class ds extends E{constructor(){super(...arguments),this.opened=!1,this.hasMobileLayoutToggleListener=!1,this.selection=new b,this.popover=null,this.close=()=>{this.opened&&(this.opened=!1,b.isAtEditor||this.selection.restore(),this.selection.clearSaved(),!this.Editor.CrossBlockSelection.isCrossBlockSelectionStarted&&this.Editor.BlockManager.currentBlock&&this.Editor.BlockSelection.unselectBlock(this.Editor.BlockManager.currentBlock),this.eventsDispatcher.emit(this.events.closed),this.popover&&(this.popover.off(Z.Closed,this.onPopoverClose),this.popover.destroy(),this.popover.getElement().remove(),this.popover=null))},this.onPopoverClose=()=>{this.close()}}get events(){return{opened:"block-settings-opened",closed:"block-settings-closed"}}get CSS(){return{settings:"ce-settings"}}get flipper(){var e;if(this.popover!==null)return"flipper"in this.popover?(e=this.popover)==null?void 0:e.flipper:void 0}make(){this.nodes.wrapper=u.make("div",[this.CSS.settings]),this.eventsDispatcher.on(xe,this.close),this.hasMobileLayoutToggleListener=!0}destroy(){this.removeAllNodes(),this.listeners.destroy(),this.hasMobileLayoutToggleListener&&(this.eventsDispatcher.off(xe,this.close),this.hasMobileLayoutToggleListener=!1)}async open(e=this.Editor.BlockManager.currentBlock){var s;this.opened=!0,this.selection.save(),this.Editor.BlockSelection.selectBlock(e),this.Editor.BlockSelection.clearCache();const{toolTunes:t,commonTunes:o}=e.getTunes();this.eventsDispatcher.emit(this.events.opened);const i=ge()?Zo:vt;this.popover=new i({searchable:!0,items:await this.getTunesItems(e,o,t),scopeElement:this.Editor.API.methods.ui.nodes.redactor,messages:{nothingFound:H.ui(W.ui.popover,"Nothing found"),search:H.ui(W.ui.popover,"Filter")}}),this.popover.on(Z.Closed,this.onPopoverClose),(s=this.nodes.wrapper)==null||s.append(this.popover.getElement()),this.popover.show()}getElement(){return this.nodes.wrapper}async getTunesItems(e,t,o){const i=[];o!==void 0&&o.length>0&&(i.push(...o),i.push({type:_.Separator}));const s=Array.from(this.Editor.Tools.blockTools.values()),a=(await Po(e,s)).reduce((l,c)=>(c.toolbox.forEach(d=>{l.push({icon:d.icon,title:H.t(W.toolNames,d.title),name:c.name,closeOnActivate:!0,onActivate:async()=>{const{BlockManager:h,Caret:p,Toolbar:g}=this.Editor,f=await h.convert(e,c.name,d.data);g.close(),p.setToBlock(f,p.positions.END)}})}),l),[]);return a.length>0&&(i.push({icon:Uo,name:"convert-to",title:H.ui(W.ui.popover,"Convert to"),children:{searchable:!0,items:a}}),i.push({type:_.Separator})),i.push(...t),i.map(l=>this.resolveTuneAliases(l))}resolveTuneAliases(e){if(e.type===_.Separator||e.type===_.Html)return e;const t=ji(e,{label:"title"});return e.confirmation&&(t.confirmation=this.resolveTuneAliases(e.confirmation)),t}}var Go={exports:{}};/*! + * Library for handling keyboard shortcuts + * @copyright CodeX (https://codex.so) + * @license MIT + * @author CodeX (https://codex.so) + * @version 1.2.0 + */(function(n,e){(function(t,o){n.exports=o()})(window,function(){return function(t){var o={};function i(s){if(o[s])return o[s].exports;var r=o[s]={i:s,l:!1,exports:{}};return t[s].call(r.exports,r,r.exports,i),r.l=!0,r.exports}return i.m=t,i.c=o,i.d=function(s,r,a){i.o(s,r)||Object.defineProperty(s,r,{enumerable:!0,get:a})},i.r=function(s){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(s,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(s,"__esModule",{value:!0})},i.t=function(s,r){if(1&r&&(s=i(s)),8&r||4&r&&typeof s=="object"&&s&&s.__esModule)return s;var a=Object.create(null);if(i.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:s}),2&r&&typeof s!="string")for(var l in s)i.d(a,l,(function(c){return s[c]}).bind(null,l));return a},i.n=function(s){var r=s&&s.__esModule?function(){return s.default}:function(){return s};return i.d(r,"a",r),r},i.o=function(s,r){return Object.prototype.hasOwnProperty.call(s,r)},i.p="",i(i.s=0)}([function(t,o,i){function s(l,c){for(var d=0;dr!==o);if(s.length===0){this.registeredShortcuts.delete(e);return}this.registeredShortcuts.set(e,s)}findShortcut(e,t){return(this.registeredShortcuts.get(e)||[]).find(({name:i})=>i===t)}}const be=new ps;var fs=Object.defineProperty,gs=Object.getOwnPropertyDescriptor,Jo=(n,e,t,o)=>{for(var i=o>1?void 0:o?gs(e,t):e,s=n.length-1,r;s>=0;s--)(r=n[s])&&(i=(o?r(e,t,i):r(i))||i);return o&&i&&fs(e,t,i),i},Fe=(n=>(n.Opened="toolbox-opened",n.Closed="toolbox-closed",n.BlockAdded="toolbox-block-added",n))(Fe||{});const wt=class Un extends we{constructor({api:e,tools:t,i18nLabels:o}){super(),this.opened=!1,this.listeners=new Ee,this.popover=null,this.handleMobileLayoutToggle=()=>{this.destroyPopover(),this.initPopover()},this.onPopoverClose=()=>{this.opened=!1,this.emit("toolbox-closed")},this.api=e,this.tools=t,this.i18nLabels=o,this.enableShortcuts(),this.nodes={toolbox:u.make("div",Un.CSS.toolbox)},this.initPopover(),this.api.events.on(xe,this.handleMobileLayoutToggle)}get isEmpty(){return this.toolsToBeDisplayed.length===0}static get CSS(){return{toolbox:"ce-toolbox"}}getElement(){return this.nodes.toolbox}hasFocus(){if(this.popover!==null)return"hasFocus"in this.popover?this.popover.hasFocus():void 0}destroy(){var e;super.destroy(),this.nodes&&this.nodes.toolbox&&this.nodes.toolbox.remove(),this.removeAllShortcuts(),(e=this.popover)==null||e.off(Z.Closed,this.onPopoverClose),this.listeners.destroy(),this.api.events.off(xe,this.handleMobileLayoutToggle)}toolButtonActivated(e,t){this.insertNewBlock(e,t)}open(){var e;this.isEmpty||((e=this.popover)==null||e.show(),this.opened=!0,this.emit("toolbox-opened"))}close(){var e;(e=this.popover)==null||e.hide(),this.opened=!1,this.emit("toolbox-closed")}toggle(){this.opened?this.close():this.open()}initPopover(){var t;const e=ge()?Zo:vt;this.popover=new e({scopeElement:this.api.ui.nodes.redactor,searchable:!0,messages:{nothingFound:this.i18nLabels.nothingFound,search:this.i18nLabels.filter},items:this.toolboxItemsToBeDisplayed}),this.popover.on(Z.Closed,this.onPopoverClose),(t=this.nodes.toolbox)==null||t.append(this.popover.getElement())}destroyPopover(){this.popover!==null&&(this.popover.hide(),this.popover.off(Z.Closed,this.onPopoverClose),this.popover.destroy(),this.popover=null),this.nodes.toolbox!==null&&(this.nodes.toolbox.innerHTML="")}get toolsToBeDisplayed(){const e=[];return this.tools.forEach(t=>{t.toolbox&&e.push(t)}),e}get toolboxItemsToBeDisplayed(){const e=(t,o,i=!0)=>({icon:t.icon,title:H.t(W.toolNames,t.title||Le(o.name)),name:o.name,onActivate:()=>{this.toolButtonActivated(o.name,t.data)},secondaryLabel:o.shortcut&&i?it(o.shortcut):""});return this.toolsToBeDisplayed.reduce((t,o)=>(Array.isArray(o.toolbox)?o.toolbox.forEach((i,s)=>{t.push(e(i,o,s===0))}):o.toolbox!==void 0&&t.push(e(o.toolbox,o)),t),[])}enableShortcuts(){this.toolsToBeDisplayed.forEach(e=>{const t=e.shortcut;t&&this.enableShortcutForTool(e.name,t)})}enableShortcutForTool(e,t){be.add({name:t,on:this.api.ui.nodes.redactor,handler:async o=>{o.preventDefault();const i=this.api.blocks.getCurrentBlockIndex(),s=this.api.blocks.getBlockByIndex(i);if(s)try{const r=await this.api.blocks.convert(s.id,e);this.api.caret.setToBlock(r,"end");return}catch{}this.insertNewBlock(e)}})}removeAllShortcuts(){this.toolsToBeDisplayed.forEach(e=>{const t=e.shortcut;t&&be.remove(this.api.ui.nodes.redactor,t)})}async insertNewBlock(e,t){const o=this.api.blocks.getCurrentBlockIndex(),i=this.api.blocks.getBlockByIndex(o);if(!i)return;const s=i.isEmpty?o:o+1;let r;if(t){const l=await this.api.blocks.composeBlockData(e);r=Object.assign(l,t)}const a=this.api.blocks.insert(e,r,void 0,s,void 0,i.isEmpty);a.call(te.APPEND_CALLBACK),this.api.caret.setToBlock(s),this.emit("toolbox-block-added",{block:a}),this.api.toolbar.close()}};Jo([fe],wt.prototype,"toolsToBeDisplayed",1),Jo([fe],wt.prototype,"toolboxItemsToBeDisplayed",1);let ms=wt;const Qo="block hovered";async function bs(n,e){const t=navigator.keyboard;if(!t)return e;try{return(await t.getLayoutMap()).get(n)||e}catch(o){return console.error(o),e}}class vs extends E{constructor({config:e,eventsDispatcher:t}){super({config:e,eventsDispatcher:t}),this.toolboxInstance=null}get CSS(){return{toolbar:"ce-toolbar",content:"ce-toolbar__content",actions:"ce-toolbar__actions",actionsOpened:"ce-toolbar__actions--opened",toolbarOpened:"ce-toolbar--opened",openedToolboxHolderModifier:"codex-editor--toolbox-opened",plusButton:"ce-toolbar__plus",plusButtonShortcut:"ce-toolbar__plus-shortcut",settingsToggler:"ce-toolbar__settings-btn",settingsTogglerHidden:"ce-toolbar__settings-btn--hidden"}}get opened(){return this.nodes.wrapper.classList.contains(this.CSS.toolbarOpened)}get toolbox(){var e;return{opened:(e=this.toolboxInstance)==null?void 0:e.opened,close:()=>{var t;(t=this.toolboxInstance)==null||t.close()},open:()=>{if(this.toolboxInstance===null){T("toolbox.open() called before initialization is finished","warn");return}this.Editor.BlockManager.currentBlock=this.hoveredBlock,this.toolboxInstance.open()},toggle:()=>{if(this.toolboxInstance===null){T("toolbox.toggle() called before initialization is finished","warn");return}this.toolboxInstance.toggle()},hasFocus:()=>{var t;return(t=this.toolboxInstance)==null?void 0:t.hasFocus()}}}get blockActions(){return{hide:()=>{this.nodes.actions.classList.remove(this.CSS.actionsOpened)},show:()=>{this.nodes.actions.classList.add(this.CSS.actionsOpened)}}}get blockTunesToggler(){return{hide:()=>this.nodes.settingsToggler.classList.add(this.CSS.settingsTogglerHidden),show:()=>this.nodes.settingsToggler.classList.remove(this.CSS.settingsTogglerHidden)}}toggleReadOnly(e){e?(this.destroy(),this.Editor.BlockSettings.destroy(),this.disableModuleBindings()):window.requestIdleCallback(()=>{this.drawUI(),this.enableModuleBindings()},{timeout:2e3})}moveAndOpen(e=this.Editor.BlockManager.currentBlock){if(this.toolboxInstance===null){T("Can't open Toolbar since Editor initialization is not finished yet","warn");return}if(this.toolboxInstance.opened&&this.toolboxInstance.close(),this.Editor.BlockSettings.opened&&this.Editor.BlockSettings.close(),!e)return;this.hoveredBlock=e;const t=e.holder,{isMobile:o}=this.Editor.UI;let i;const s=20,r=e.firstInput,a=t.getBoundingClientRect(),l=r!==void 0?r.getBoundingClientRect():null,c=l!==null?l.top-a.top:null,d=c!==null?c>s:void 0;if(o)i=t.offsetTop+t.offsetHeight;else if(r===void 0||d){const h=parseInt(window.getComputedStyle(e.pluginsContent).paddingTop);i=t.offsetTop+h}else{const h=ri(r),p=parseInt(window.getComputedStyle(this.nodes.plusButton).height,10),g=8;i=t.offsetTop+h-p+g+c}this.nodes.wrapper.style.top=`${Math.floor(i)}px`,this.Editor.BlockManager.blocks.length===1&&e.isEmpty?this.blockTunesToggler.hide():this.blockTunesToggler.show(),this.open()}close(){var e,t;this.Editor.ReadOnly.isEnabled||((e=this.nodes.wrapper)==null||e.classList.remove(this.CSS.toolbarOpened),this.blockActions.hide(),(t=this.toolboxInstance)==null||t.close(),this.Editor.BlockSettings.close(),this.reset())}reset(){this.nodes.wrapper.style.top="unset"}open(e=!0){this.nodes.wrapper.classList.add(this.CSS.toolbarOpened),e?this.blockActions.show():this.blockActions.hide()}async make(){this.nodes.wrapper=u.make("div",this.CSS.toolbar),["content","actions"].forEach(s=>{this.nodes[s]=u.make("div",this.CSS[s])}),u.append(this.nodes.wrapper,this.nodes.content),u.append(this.nodes.content,this.nodes.actions),this.nodes.plusButton=u.make("div",this.CSS.plusButton,{innerHTML:qi}),u.append(this.nodes.actions,this.nodes.plusButton),this.readOnlyMutableListeners.on(this.nodes.plusButton,"click",()=>{Ne(!0),this.plusButtonClicked()},!1);const e=u.make("div");e.appendChild(document.createTextNode(H.ui(W.ui.toolbar.toolbox,"Add"))),e.appendChild(u.make("div",this.CSS.plusButtonShortcut,{textContent:"/"})),Re(this.nodes.plusButton,e,{hidingDelay:400}),this.nodes.settingsToggler=u.make("span",this.CSS.settingsToggler,{innerHTML:Vi}),u.append(this.nodes.actions,this.nodes.settingsToggler);const t=u.make("div"),o=u.text(H.ui(W.ui.blockTunes.toggler,"Click to tune")),i=await bs("Slash","/");t.appendChild(o),t.appendChild(u.make("div",this.CSS.plusButtonShortcut,{textContent:it(`CMD + ${i}`)})),Re(this.nodes.settingsToggler,t,{hidingDelay:400}),u.append(this.nodes.actions,this.makeToolbox()),u.append(this.nodes.actions,this.Editor.BlockSettings.getElement()),u.append(this.Editor.UI.nodes.wrapper,this.nodes.wrapper)}makeToolbox(){return this.toolboxInstance=new ms({api:this.Editor.API.methods,tools:this.Editor.Tools.blockTools,i18nLabels:{filter:H.ui(W.ui.popover,"Filter"),nothingFound:H.ui(W.ui.popover,"Nothing found")}}),this.toolboxInstance.on(Fe.Opened,()=>{this.Editor.UI.nodes.wrapper.classList.add(this.CSS.openedToolboxHolderModifier)}),this.toolboxInstance.on(Fe.Closed,()=>{this.Editor.UI.nodes.wrapper.classList.remove(this.CSS.openedToolboxHolderModifier)}),this.toolboxInstance.on(Fe.BlockAdded,({block:e})=>{const{BlockManager:t,Caret:o}=this.Editor,i=t.getBlockById(e.id);i.inputs.length===0&&(i===t.lastBlock?(t.insertAtEnd(),o.setToBlock(t.lastBlock)):o.setToBlock(t.nextBlock))}),this.toolboxInstance.getElement()}plusButtonClicked(){var e;this.Editor.BlockManager.currentBlock=this.hoveredBlock,(e=this.toolboxInstance)==null||e.toggle()}enableModuleBindings(){this.readOnlyMutableListeners.on(this.nodes.settingsToggler,"mousedown",e=>{var t;e.stopPropagation(),this.settingsTogglerClicked(),(t=this.toolboxInstance)!=null&&t.opened&&this.toolboxInstance.close(),Ne(!0)},!0),ge()||this.eventsDispatcher.on(Qo,e=>{var t;this.Editor.BlockSettings.opened||(t=this.toolboxInstance)!=null&&t.opened||this.moveAndOpen(e.block)})}disableModuleBindings(){this.readOnlyMutableListeners.clearAll()}settingsTogglerClicked(){this.Editor.BlockManager.currentBlock=this.hoveredBlock,this.Editor.BlockSettings.opened?this.Editor.BlockSettings.close():this.Editor.BlockSettings.open(this.hoveredBlock)}drawUI(){this.Editor.BlockSettings.make(),this.make()}destroy(){this.removeAllNodes(),this.toolboxInstance&&this.toolboxInstance.destroy()}}var ce=(n=>(n[n.Block=0]="Block",n[n.Inline=1]="Inline",n[n.Tune=2]="Tune",n))(ce||{}),je=(n=>(n.Shortcut="shortcut",n.Toolbox="toolbox",n.EnabledInlineTools="inlineToolbar",n.EnabledBlockTunes="tunes",n.Config="config",n))(je||{}),en=(n=>(n.Shortcut="shortcut",n.SanitizeConfig="sanitize",n))(en||{}),ve=(n=>(n.IsEnabledLineBreaks="enableLineBreaks",n.Toolbox="toolbox",n.ConversionConfig="conversionConfig",n.IsReadOnlySupported="isReadOnlySupported",n.PasteConfig="pasteConfig",n))(ve||{}),He=(n=>(n.IsInline="isInline",n.Title="title",n.IsReadOnlySupported="isReadOnlySupported",n))(He||{}),Et=(n=>(n.IsTune="isTune",n))(Et||{});class xt{constructor({name:e,constructable:t,config:o,api:i,isDefault:s,isInternal:r=!1,defaultPlaceholder:a}){this.api=i,this.name=e,this.constructable=t,this.config=o,this.isDefault=s,this.isInternal=r,this.defaultPlaceholder=a}get settings(){const e=this.config.config||{};return this.isDefault&&!("placeholder"in e)&&this.defaultPlaceholder&&(e.placeholder=this.defaultPlaceholder),e}reset(){if(M(this.constructable.reset))return this.constructable.reset()}prepare(){if(M(this.constructable.prepare))return this.constructable.prepare({toolName:this.name,config:this.settings})}get shortcut(){const e=this.constructable.shortcut;return this.config.shortcut||e}get sanitizeConfig(){return this.constructable.sanitize||{}}isInline(){return this.type===ce.Inline}isBlock(){return this.type===ce.Block}isTune(){return this.type===ce.Tune}}class ks extends E{constructor({config:e,eventsDispatcher:t}){super({config:e,eventsDispatcher:t}),this.CSS={inlineToolbar:"ce-inline-toolbar"},this.opened=!1,this.popover=null,this.toolbarVerticalMargin=ge()?20:6,this.tools=new Map,window.requestIdleCallback(()=>{this.make()},{timeout:2e3})}async tryToShow(e=!1){e&&this.close(),this.allowedToShow()&&(await this.open(),this.Editor.Toolbar.close())}close(){var e,t;if(this.opened){for(const[o,i]of this.tools){const s=this.getToolShortcut(o.name);s!==void 0&&be.remove(this.Editor.UI.nodes.redactor,s),M(i.clear)&&i.clear()}this.tools=new Map,this.reset(),this.opened=!1,(e=this.popover)==null||e.hide(),(t=this.popover)==null||t.destroy(),this.popover=null}}containsNode(e){return this.nodes.wrapper===void 0?!1:this.nodes.wrapper.contains(e)}destroy(){var e;this.removeAllNodes(),(e=this.popover)==null||e.destroy(),this.popover=null}make(){this.nodes.wrapper=u.make("div",[this.CSS.inlineToolbar,...this.isRtl?[this.Editor.UI.CSS.editorRtlFix]:[]]),u.append(this.Editor.UI.nodes.wrapper,this.nodes.wrapper)}async open(){var t;if(this.opened)return;this.opened=!0,this.popover!==null&&this.popover.destroy(),this.createToolsInstances();const e=await this.getPopoverItems();this.popover=new rs({items:e,scopeElement:this.Editor.API.methods.ui.nodes.redactor,messages:{nothingFound:H.ui(W.ui.popover,"Nothing found"),search:H.ui(W.ui.popover,"Filter")}}),this.move(this.popover.size.width),(t=this.nodes.wrapper)==null||t.append(this.popover.getElement()),this.popover.show()}move(e){const t=b.rect,o=this.Editor.UI.nodes.wrapper.getBoundingClientRect(),i={x:t.x-o.x,y:t.y+t.height-o.top+this.toolbarVerticalMargin};i.x+e+o.x>this.Editor.UI.contentRect.right&&(i.x=this.Editor.UI.contentRect.right-e-o.x),this.nodes.wrapper.style.left=Math.floor(i.x)+"px",this.nodes.wrapper.style.top=Math.floor(i.y)+"px"}reset(){this.nodes.wrapper.style.left="0",this.nodes.wrapper.style.top="0"}allowedToShow(){const e=["IMG","INPUT"],t=b.get(),o=b.text;if(!t||!t.anchorNode||t.isCollapsed||o.length<1)return!1;const i=u.isElement(t.anchorNode)?t.anchorNode:t.anchorNode.parentElement;if(i===null||t!==null&&e.includes(i.tagName))return!1;const s=this.Editor.BlockManager.getBlock(t.anchorNode);return!s||this.getTools().some(c=>s.tool.inlineTools.has(c.name))===!1?!1:i.closest("[contenteditable]")!==null}getTools(){const e=this.Editor.BlockManager.currentBlock;return e?Array.from(e.tool.inlineTools.values()).filter(o=>!(this.Editor.ReadOnly.isEnabled&&o.isReadOnlySupported!==!0)):[]}createToolsInstances(){this.tools=new Map,this.getTools().forEach(t=>{const o=t.create();this.tools.set(t,o)})}async getPopoverItems(){const e=[];let t=0;for(const[o,i]of this.tools){const s=await i.render(),r=this.getToolShortcut(o.name);if(r!==void 0)try{this.enableShortcuts(o.name,r)}catch{}const a=r!==void 0?it(r):void 0,l=H.t(W.toolNames,o.title||Le(o.name));[s].flat().forEach(c=>{var h,p;const d={name:o.name,onActivate:()=>{this.toolClicked(i)},hint:{title:l,description:a}};if(u.isElement(c)){const g={...d,element:c,type:_.Html};if(M(i.renderActions)){const f=i.renderActions();g.children={isOpen:(h=i.checkState)==null?void 0:h.call(i,b.get()),isFlippable:!1,items:[{type:_.Html,element:f}]}}else(p=i.checkState)==null||p.call(i,b.get());e.push(g)}else if(c.type===_.Html)e.push({...d,...c,type:_.Html});else if(c.type===_.Separator)e.push({type:_.Separator});else{const g={...d,...c,type:_.Default};"children"in g&&t!==0&&e.push({type:_.Separator}),e.push(g),"children"in g&&t{var s;const{currentBlock:i}=this.Editor.BlockManager;i&&i.tool.enabledInlineTools&&(o.preventDefault(),(s=this.popover)==null||s.activateItemByName(e))},on:document})}toolClicked(e){var o;const t=b.range;(o=e.surround)==null||o.call(e,t),this.checkToolsState()}checkToolsState(){var e;(e=this.tools)==null||e.forEach(t=>{var o;(o=t.checkState)==null||o.call(t,b.get())})}get inlineTools(){const e={};return Array.from(this.Editor.Tools.inlineTools.entries()).forEach(([t,o])=>{e[t]=o.create()}),e}}function tn(){const n=window.getSelection();if(n===null)return[null,0];let e=n.focusNode,t=n.focusOffset;return e===null?[null,0]:(e.nodeType!==Node.TEXT_NODE&&e.childNodes.length>0&&(e.childNodes[t]?(e=e.childNodes[t],t=0):(e=e.childNodes[t-1],t=e.textContent.length)),[e,t])}function on(n,e,t,o){const i=document.createRange();o==="left"?(i.setStart(n,0),i.setEnd(e,t)):(i.setStart(e,t),i.setEnd(n,n.childNodes.length));const s=i.cloneContents(),r=document.createElement("div");r.appendChild(s);const a=r.textContent||"";return si(a)}function $e(n){const e=u.getDeepestNode(n);if(e===null||u.isEmpty(n))return!0;if(u.isNativeInput(e))return e.selectionEnd===0;if(u.isEmpty(n))return!0;const[t,o]=tn();return t===null?!1:on(n,t,o,"left")}function ze(n){const e=u.getDeepestNode(n,!0);if(e===null)return!0;if(u.isNativeInput(e))return e.selectionEnd===e.value.length;const[t,o]=tn();return t===null?!1:on(n,t,o,"right")}var nn={},Bt={},Ue={},de={},Ct={},Tt={};Object.defineProperty(Tt,"__esModule",{value:!0}),Tt.allInputsSelector=ys;function ys(){var n=["text","password","email","number","search","tel","url"];return"[contenteditable=true], textarea, input:not([type]), "+n.map(function(e){return'input[type="'.concat(e,'"]')}).join(", ")}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.allInputsSelector=void 0;var e=Tt;Object.defineProperty(n,"allInputsSelector",{enumerable:!0,get:function(){return e.allInputsSelector}})})(Ct);var ue={},St={};Object.defineProperty(St,"__esModule",{value:!0}),St.isNativeInput=ws;function ws(n){var e=["INPUT","TEXTAREA"];return n&&n.tagName?e.includes(n.tagName):!1}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isNativeInput=void 0;var e=St;Object.defineProperty(n,"isNativeInput",{enumerable:!0,get:function(){return e.isNativeInput}})})(ue);var sn={},It={};Object.defineProperty(It,"__esModule",{value:!0}),It.append=Es;function Es(n,e){Array.isArray(e)?e.forEach(function(t){n.appendChild(t)}):n.appendChild(e)}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.append=void 0;var e=It;Object.defineProperty(n,"append",{enumerable:!0,get:function(){return e.append}})})(sn);var Ot={},_t={};Object.defineProperty(_t,"__esModule",{value:!0}),_t.blockElements=xs;function xs(){return["address","article","aside","blockquote","canvas","div","dl","dt","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","li","main","nav","noscript","ol","output","p","pre","ruby","section","table","tbody","thead","tr","tfoot","ul","video"]}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.blockElements=void 0;var e=_t;Object.defineProperty(n,"blockElements",{enumerable:!0,get:function(){return e.blockElements}})})(Ot);var rn={},Mt={};Object.defineProperty(Mt,"__esModule",{value:!0}),Mt.calculateBaseline=Bs;function Bs(n){var e=window.getComputedStyle(n),t=parseFloat(e.fontSize),o=parseFloat(e.lineHeight)||t*1.2,i=parseFloat(e.paddingTop),s=parseFloat(e.borderTopWidth),r=parseFloat(e.marginTop),a=t*.8,l=(o-t)/2,c=r+s+i+l+a;return c}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.calculateBaseline=void 0;var e=Mt;Object.defineProperty(n,"calculateBaseline",{enumerable:!0,get:function(){return e.calculateBaseline}})})(rn);var an={},At={},Lt={},Pt={};Object.defineProperty(Pt,"__esModule",{value:!0}),Pt.isContentEditable=Cs;function Cs(n){return n.contentEditable==="true"}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isContentEditable=void 0;var e=Pt;Object.defineProperty(n,"isContentEditable",{enumerable:!0,get:function(){return e.isContentEditable}})})(Lt),Object.defineProperty(At,"__esModule",{value:!0}),At.canSetCaret=Is;var Ts=ue,Ss=Lt;function Is(n){var e=!0;if((0,Ts.isNativeInput)(n))switch(n.type){case"file":case"checkbox":case"radio":case"hidden":case"submit":case"button":case"image":case"reset":e=!1;break}else e=(0,Ss.isContentEditable)(n);return e}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.canSetCaret=void 0;var e=At;Object.defineProperty(n,"canSetCaret",{enumerable:!0,get:function(){return e.canSetCaret}})})(an);var We={},Nt={};function Os(n,e,t){const o=t.value!==void 0?"value":"get",i=t[o],s=`#${e}Cache`;if(t[o]=function(...r){return this[s]===void 0&&(this[s]=i.apply(this,r)),this[s]},o==="get"&&t.set){const r=t.set;t.set=function(a){delete n[s],r.apply(this,a)}}return t}function ln(){const n={win:!1,mac:!1,x11:!1,linux:!1},e=Object.keys(n).find(t=>window.navigator.appVersion.toLowerCase().indexOf(t)!==-1);return e!==void 0&&(n[e]=!0),n}function Rt(n){return n!=null&&n!==""&&(typeof n!="object"||Object.keys(n).length>0)}function _s(n){return!Rt(n)}const Ms=()=>typeof window<"u"&&window.navigator!==null&&Rt(window.navigator.platform)&&(/iP(ad|hone|od)/.test(window.navigator.platform)||window.navigator.platform==="MacIntel"&&window.navigator.maxTouchPoints>1);function As(n){const e=ln();return n=n.replace(/shift/gi,"⇧").replace(/backspace/gi,"⌫").replace(/enter/gi,"⏎").replace(/up/gi,"↑").replace(/left/gi,"→").replace(/down/gi,"↓").replace(/right/gi,"←").replace(/escape/gi,"⎋").replace(/insert/gi,"Ins").replace(/delete/gi,"␡").replace(/\+/gi,"+"),e.mac?n=n.replace(/ctrl|cmd/gi,"⌘").replace(/alt/gi,"⌥"):n=n.replace(/cmd/gi,"Ctrl").replace(/windows/gi,"WIN"),n}function Ls(n){return n[0].toUpperCase()+n.slice(1)}function Ps(n){const e=document.createElement("div");e.style.position="absolute",e.style.left="-999px",e.style.bottom="-999px",e.innerHTML=n,document.body.appendChild(e);const t=window.getSelection(),o=document.createRange();if(o.selectNode(e),t===null)throw new Error("Cannot copy text to clipboard");t.removeAllRanges(),t.addRange(o),document.execCommand("copy"),document.body.removeChild(e)}function Ns(n,e,t){let o;return(...i)=>{const s=this,r=()=>{o=void 0,t!==!0&&n.apply(s,i)},a=t===!0&&o!==void 0;window.clearTimeout(o),o=window.setTimeout(r,e),a&&n.apply(s,i)}}function se(n){return Object.prototype.toString.call(n).match(/\s([a-zA-Z]+)/)[1].toLowerCase()}function Rs(n){return se(n)==="boolean"}function cn(n){return se(n)==="function"||se(n)==="asyncfunction"}function Ds(n){return cn(n)&&/^\s*class\s+/.test(n.toString())}function Fs(n){return se(n)==="number"}function Ye(n){return se(n)==="object"}function js(n){return Promise.resolve(n)===n}function Hs(n){return se(n)==="string"}function $s(n){return se(n)==="undefined"}function Dt(n,...e){if(!e.length)return n;const t=e.shift();if(Ye(n)&&Ye(t))for(const o in t)Ye(t[o])?(n[o]===void 0&&Object.assign(n,{[o]:{}}),Dt(n[o],t[o])):Object.assign(n,{[o]:t[o]});return Dt(n,...e)}function zs(n,e,t){const o=`«${e}» is deprecated and will be removed in the next major release. Please use the «${t}» instead.`;n&&console.warn(o)}function Us(n){try{return new URL(n).href}catch{}return n.substring(0,2)==="//"?window.location.protocol+n:window.location.origin+n}function Ws(n){return n>47&&n<58||n===32||n===13||n===229||n>64&&n<91||n>95&&n<112||n>185&&n<193||n>218&&n<223}const Ys={BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,LEFT:37,UP:38,DOWN:40,RIGHT:39,DELETE:46,META:91,SLASH:191},Ks={LEFT:0,WHEEL:1,RIGHT:2,BACKWARD:3,FORWARD:4};let Xs=class{constructor(){this.completed=Promise.resolve()}add(e){return new Promise((t,o)=>{this.completed=this.completed.then(e).then(t).catch(o)})}};function Vs(n,e,t=void 0){let o,i,s,r=null,a=0;t||(t={});const l=function(){a=t.leading===!1?0:Date.now(),r=null,s=n.apply(o,i),r===null&&(o=i=null)};return function(){const c=Date.now();!a&&t.leading===!1&&(a=c);const d=e-(c-a);return o=this,i=arguments,d<=0||d>e?(r&&(clearTimeout(r),r=null),a=c,s=n.apply(o,i),r===null&&(o=i=null)):!r&&t.trailing!==!1&&(r=setTimeout(l,d)),s}}const Ft=Yn(Object.freeze(Object.defineProperty({__proto__:null,PromiseQueue:Xs,beautifyShortcut:As,cacheable:Os,capitalize:Ls,copyTextToClipboard:Ps,debounce:Ns,deepMerge:Dt,deprecationAssert:zs,getUserOS:ln,getValidUrl:Us,isBoolean:Rs,isClass:Ds,isEmpty:_s,isFunction:cn,isIosDevice:Ms,isNumber:Fs,isObject:Ye,isPrintableKey:Ws,isPromise:js,isString:Hs,isUndefined:$s,keyCodes:Ys,mouseButtons:Ks,notEmpty:Rt,throttle:Vs,typeOf:se},Symbol.toStringTag,{value:"Module"})));Object.defineProperty(Nt,"__esModule",{value:!0}),Nt.containsOnlyInlineElements=Gs;var qs=Ft,Zs=Ot;function Gs(n){var e;(0,qs.isString)(n)?(e=document.createElement("div"),e.innerHTML=n):e=n;var t=function(o){return!(0,Zs.blockElements)().includes(o.tagName.toLowerCase())&&Array.from(o.children).every(t)};return Array.from(e.children).every(t)}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.containsOnlyInlineElements=void 0;var e=Nt;Object.defineProperty(n,"containsOnlyInlineElements",{enumerable:!0,get:function(){return e.containsOnlyInlineElements}})})(We);var dn={},jt={},Ke={},Ht={};Object.defineProperty(Ht,"__esModule",{value:!0}),Ht.make=Js;function Js(n,e,t){var o;e===void 0&&(e=null),t===void 0&&(t={});var i=document.createElement(n);if(Array.isArray(e)){var s=e.filter(function(a){return a!==void 0});(o=i.classList).add.apply(o,s)}else e!==null&&i.classList.add(e);for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(i[r]=t[r]);return i}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.make=void 0;var e=Ht;Object.defineProperty(n,"make",{enumerable:!0,get:function(){return e.make}})})(Ke),Object.defineProperty(jt,"__esModule",{value:!0}),jt.fragmentToString=er;var Qs=Ke;function er(n){var e=(0,Qs.make)("div");return e.appendChild(n),e.innerHTML}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.fragmentToString=void 0;var e=jt;Object.defineProperty(n,"fragmentToString",{enumerable:!0,get:function(){return e.fragmentToString}})})(dn);var un={},$t={};Object.defineProperty($t,"__esModule",{value:!0}),$t.getContentLength=or;var tr=ue;function or(n){var e,t;return(0,tr.isNativeInput)(n)?n.value.length:n.nodeType===Node.TEXT_NODE?n.length:(t=(e=n.textContent)===null||e===void 0?void 0:e.length)!==null&&t!==void 0?t:0}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.getContentLength=void 0;var e=$t;Object.defineProperty(n,"getContentLength",{enumerable:!0,get:function(){return e.getContentLength}})})(un);var zt={},Ut={},hn=J&&J.__spreadArray||function(n,e,t){if(t||arguments.length===2)for(var o=0,i=e.length,s;o0;){var o=t.shift();if(o){if(n=o,(0,xr.isLeaf)(n)&&!(0,Br.isNodeEmpty)(n,e))return!1;t.push.apply(t,Array.from(n.childNodes))}}return!0}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isEmpty=void 0;var e=Gt;Object.defineProperty(n,"isEmpty",{enumerable:!0,get:function(){return e.isEmpty}})})(vn);var kn={},oo={};Object.defineProperty(oo,"__esModule",{value:!0}),oo.isFragment=Sr;var Tr=Ft;function Sr(n){return(0,Tr.isNumber)(n)?!1:!!n&&!!n.nodeType&&n.nodeType===Node.DOCUMENT_FRAGMENT_NODE}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isFragment=void 0;var e=oo;Object.defineProperty(n,"isFragment",{enumerable:!0,get:function(){return e.isFragment}})})(kn);var yn={},no={};Object.defineProperty(no,"__esModule",{value:!0}),no.isHTMLString=Or;var Ir=Ke;function Or(n){var e=(0,Ir.make)("div");return e.innerHTML=n,e.childElementCount>0}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isHTMLString=void 0;var e=no;Object.defineProperty(n,"isHTMLString",{enumerable:!0,get:function(){return e.isHTMLString}})})(yn);var wn={},io={};Object.defineProperty(io,"__esModule",{value:!0}),io.offset=_r;function _r(n){var e=n.getBoundingClientRect(),t=window.pageXOffset||document.documentElement.scrollLeft,o=window.pageYOffset||document.documentElement.scrollTop,i=e.top+o,s=e.left+t;return{top:i,left:s,bottom:i+e.height,right:s+e.width}}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.offset=void 0;var e=io;Object.defineProperty(n,"offset",{enumerable:!0,get:function(){return e.offset}})})(wn);var En={},so={};Object.defineProperty(so,"__esModule",{value:!0}),so.prepend=Mr;function Mr(n,e){Array.isArray(e)?(e=e.reverse(),e.forEach(function(t){return n.prepend(t)})):n.prepend(e)}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.prepend=void 0;var e=so;Object.defineProperty(n,"prepend",{enumerable:!0,get:function(){return e.prepend}})})(En),function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.prepend=n.offset=n.make=n.isLineBreakTag=n.isSingleTag=n.isNodeEmpty=n.isLeaf=n.isHTMLString=n.isFragment=n.isEmpty=n.isElement=n.isContentEditable=n.isCollapsedWhitespaces=n.findAllInputs=n.isNativeInput=n.allInputsSelector=n.getDeepestNode=n.getDeepestBlockElements=n.getContentLength=n.fragmentToString=n.containsOnlyInlineElements=n.canSetCaret=n.calculateBaseline=n.blockElements=n.append=void 0;var e=Ct;Object.defineProperty(n,"allInputsSelector",{enumerable:!0,get:function(){return e.allInputsSelector}});var t=ue;Object.defineProperty(n,"isNativeInput",{enumerable:!0,get:function(){return t.isNativeInput}});var o=sn;Object.defineProperty(n,"append",{enumerable:!0,get:function(){return o.append}});var i=Ot;Object.defineProperty(n,"blockElements",{enumerable:!0,get:function(){return i.blockElements}});var s=rn;Object.defineProperty(n,"calculateBaseline",{enumerable:!0,get:function(){return s.calculateBaseline}});var r=an;Object.defineProperty(n,"canSetCaret",{enumerable:!0,get:function(){return r.canSetCaret}});var a=We;Object.defineProperty(n,"containsOnlyInlineElements",{enumerable:!0,get:function(){return a.containsOnlyInlineElements}});var l=dn;Object.defineProperty(n,"fragmentToString",{enumerable:!0,get:function(){return l.fragmentToString}});var c=un;Object.defineProperty(n,"getContentLength",{enumerable:!0,get:function(){return c.getContentLength}});var d=zt;Object.defineProperty(n,"getDeepestBlockElements",{enumerable:!0,get:function(){return d.getDeepestBlockElements}});var h=fn;Object.defineProperty(n,"getDeepestNode",{enumerable:!0,get:function(){return h.getDeepestNode}});var p=mn;Object.defineProperty(n,"findAllInputs",{enumerable:!0,get:function(){return p.findAllInputs}});var g=bn;Object.defineProperty(n,"isCollapsedWhitespaces",{enumerable:!0,get:function(){return g.isCollapsedWhitespaces}});var f=Lt;Object.defineProperty(n,"isContentEditable",{enumerable:!0,get:function(){return f.isContentEditable}});var v=qt;Object.defineProperty(n,"isElement",{enumerable:!0,get:function(){return v.isElement}});var O=vn;Object.defineProperty(n,"isEmpty",{enumerable:!0,get:function(){return O.isEmpty}});var S=kn;Object.defineProperty(n,"isFragment",{enumerable:!0,get:function(){return S.isFragment}});var A=yn;Object.defineProperty(n,"isHTMLString",{enumerable:!0,get:function(){return A.isHTMLString}});var G=Jt;Object.defineProperty(n,"isLeaf",{enumerable:!0,get:function(){return G.isLeaf}});var j=eo;Object.defineProperty(n,"isNodeEmpty",{enumerable:!0,get:function(){return j.isNodeEmpty}});var U=Xe;Object.defineProperty(n,"isLineBreakTag",{enumerable:!0,get:function(){return U.isLineBreakTag}});var oe=Ve;Object.defineProperty(n,"isSingleTag",{enumerable:!0,get:function(){return oe.isSingleTag}});var he=Ke;Object.defineProperty(n,"make",{enumerable:!0,get:function(){return he.make}});var k=wn;Object.defineProperty(n,"offset",{enumerable:!0,get:function(){return k.offset}});var m=En;Object.defineProperty(n,"prepend",{enumerable:!0,get:function(){return m.prepend}})}(de);var Ze={};Object.defineProperty(Ze,"__esModule",{value:!0}),Ze.getContenteditableSlice=Lr;var Ar=de;function Lr(n,e,t,o,i){var s;i===void 0&&(i=!1);var r=document.createRange();if(o==="left"?(r.setStart(n,0),r.setEnd(e,t)):(r.setStart(e,t),r.setEnd(n,n.childNodes.length)),i===!0){var a=r.extractContents();return(0,Ar.fragmentToString)(a)}var l=r.cloneContents(),c=document.createElement("div");c.appendChild(l);var d=(s=c.textContent)!==null&&s!==void 0?s:"";return d}Object.defineProperty(Ue,"__esModule",{value:!0}),Ue.checkContenteditableSliceForEmptiness=Rr;var Pr=de,Nr=Ze;function Rr(n,e,t,o){var i=(0,Nr.getContenteditableSlice)(n,e,t,o);return(0,Pr.isCollapsedWhitespaces)(i)}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.checkContenteditableSliceForEmptiness=void 0;var e=Ue;Object.defineProperty(n,"checkContenteditableSliceForEmptiness",{enumerable:!0,get:function(){return e.checkContenteditableSliceForEmptiness}})})(Bt);var xn={};(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.getContenteditableSlice=void 0;var e=Ze;Object.defineProperty(n,"getContenteditableSlice",{enumerable:!0,get:function(){return e.getContenteditableSlice}})})(xn);var Bn={},ro={};Object.defineProperty(ro,"__esModule",{value:!0}),ro.focus=Fr;var Dr=de;function Fr(n,e){var t,o;if(e===void 0&&(e=!0),(0,Dr.isNativeInput)(n)){n.focus();var i=e?0:n.value.length;n.setSelectionRange(i,i)}else{var s=document.createRange(),r=window.getSelection();if(!r)return;var a=function(p){var g=document.createTextNode("");p.appendChild(g),s.setStart(g,0),s.setEnd(g,0)},l=function(p){return p!=null},c=n.childNodes,d=e?c[0]:c[c.length-1];if(l(d)){for(;l(d)&&d.nodeType!==Node.TEXT_NODE;)d=e?d.firstChild:d.lastChild;if(l(d)&&d.nodeType===Node.TEXT_NODE){var h=(o=(t=d.textContent)===null||t===void 0?void 0:t.length)!==null&&o!==void 0?o:0,i=e?0:h;s.setStart(d,i),s.setEnd(d,i)}else a(n)}else a(n);r.removeAllRanges(),r.addRange(s)}}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.focus=void 0;var e=ro;Object.defineProperty(n,"focus",{enumerable:!0,get:function(){return e.focus}})})(Bn);var ao={},Ge={};Object.defineProperty(Ge,"__esModule",{value:!0}),Ge.getCaretNodeAndOffset=jr;function jr(){var n=window.getSelection();if(n===null)return[null,0];var e=n.focusNode,t=n.focusOffset;return e===null?[null,0]:(e.nodeType!==Node.TEXT_NODE&&e.childNodes.length>0&&(e.childNodes[t]!==void 0?(e=e.childNodes[t],t=0):(e=e.childNodes[t-1],e.textContent!==null&&(t=e.textContent.length))),[e,t])}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.getCaretNodeAndOffset=void 0;var e=Ge;Object.defineProperty(n,"getCaretNodeAndOffset",{enumerable:!0,get:function(){return e.getCaretNodeAndOffset}})})(ao);var Cn={},Je={};Object.defineProperty(Je,"__esModule",{value:!0}),Je.getRange=Hr;function Hr(){var n=window.getSelection();return n&&n.rangeCount?n.getRangeAt(0):null}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.getRange=void 0;var e=Je;Object.defineProperty(n,"getRange",{enumerable:!0,get:function(){return e.getRange}})})(Cn);var Tn={},lo={};Object.defineProperty(lo,"__esModule",{value:!0}),lo.isCaretAtEndOfInput=Ur;var Sn=de,$r=ao,zr=Bt;function Ur(n){var e=(0,Sn.getDeepestNode)(n,!0);if(e===null)return!0;if((0,Sn.isNativeInput)(e))return e.selectionEnd===e.value.length;var t=(0,$r.getCaretNodeAndOffset)(),o=t[0],i=t[1];return o===null?!1:(0,zr.checkContenteditableSliceForEmptiness)(n,o,i,"right")}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isCaretAtEndOfInput=void 0;var e=lo;Object.defineProperty(n,"isCaretAtEndOfInput",{enumerable:!0,get:function(){return e.isCaretAtEndOfInput}})})(Tn);var In={},co={};Object.defineProperty(co,"__esModule",{value:!0}),co.isCaretAtStartOfInput=Kr;var Qe=de,Wr=Ge,Yr=Ue;function Kr(n){var e=(0,Qe.getDeepestNode)(n);if(e===null||(0,Qe.isEmpty)(n))return!0;if((0,Qe.isNativeInput)(e))return e.selectionEnd===0;if((0,Qe.isEmpty)(n))return!0;var t=(0,Wr.getCaretNodeAndOffset)(),o=t[0],i=t[1];return o===null?!1:(0,Yr.checkContenteditableSliceForEmptiness)(n,o,i,"left")}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isCaretAtStartOfInput=void 0;var e=co;Object.defineProperty(n,"isCaretAtStartOfInput",{enumerable:!0,get:function(){return e.isCaretAtStartOfInput}})})(In);var On={},uo={};Object.defineProperty(uo,"__esModule",{value:!0}),uo.save=qr;var Xr=de,Vr=Je;function qr(){var n=(0,Vr.getRange)(),e=(0,Xr.make)("span");if(e.id="cursor",e.hidden=!0,!!n)return n.insertNode(e),function(){var o=window.getSelection();o&&(n.setStartAfter(e),n.setEndAfter(e),o.removeAllRanges(),o.addRange(n),setTimeout(function(){e.remove()},150))}}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.save=void 0;var e=uo;Object.defineProperty(n,"save",{enumerable:!0,get:function(){return e.save}})})(On),function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.save=n.isCaretAtStartOfInput=n.isCaretAtEndOfInput=n.getRange=n.getCaretNodeAndOffset=n.focus=n.getContenteditableSlice=n.checkContenteditableSliceForEmptiness=void 0;var e=Bt;Object.defineProperty(n,"checkContenteditableSliceForEmptiness",{enumerable:!0,get:function(){return e.checkContenteditableSliceForEmptiness}});var t=xn;Object.defineProperty(n,"getContenteditableSlice",{enumerable:!0,get:function(){return t.getContenteditableSlice}});var o=Bn;Object.defineProperty(n,"focus",{enumerable:!0,get:function(){return o.focus}});var i=ao;Object.defineProperty(n,"getCaretNodeAndOffset",{enumerable:!0,get:function(){return i.getCaretNodeAndOffset}});var s=Cn;Object.defineProperty(n,"getRange",{enumerable:!0,get:function(){return s.getRange}});var r=Tn;Object.defineProperty(n,"isCaretAtEndOfInput",{enumerable:!0,get:function(){return r.isCaretAtEndOfInput}});var a=In;Object.defineProperty(n,"isCaretAtStartOfInput",{enumerable:!0,get:function(){return a.isCaretAtStartOfInput}});var l=On;Object.defineProperty(n,"save",{enumerable:!0,get:function(){return l.save}})}(nn);class Zr extends E{keydown(e){switch(this.beforeKeydownProcessing(e),e.keyCode){case y.BACKSPACE:this.backspace(e);break;case y.DELETE:this.delete(e);break;case y.ENTER:this.enter(e);break;case y.DOWN:case y.RIGHT:this.arrowRightAndDown(e);break;case y.UP:case y.LEFT:this.arrowLeftAndUp(e);break;case y.TAB:this.tabPressed(e);break}e.key==="/"&&!e.ctrlKey&&!e.metaKey&&this.slashPressed(e),e.code==="Slash"&&(e.ctrlKey||e.metaKey)&&(e.preventDefault(),this.commandSlashPressed())}beforeKeydownProcessing(e){this.needToolbarClosing(e)&&Eo(e.keyCode)&&(this.Editor.Toolbar.close(),e.ctrlKey||e.metaKey||e.altKey||e.shiftKey||this.Editor.BlockSelection.clearSelection(e))}keyup(e){e.shiftKey||this.Editor.UI.checkEmptiness()}dragOver(e){const t=this.Editor.BlockManager.getBlockByChildNode(e.target);t.dropTarget=!0}dragLeave(e){const t=this.Editor.BlockManager.getBlockByChildNode(e.target);t.dropTarget=!1}handleCommandC(e){const{BlockSelection:t}=this.Editor;t.anyBlockSelected&&t.copySelectedBlocks(e)}handleCommandX(e){const{BlockSelection:t,BlockManager:o,Caret:i}=this.Editor;t.anyBlockSelected&&t.copySelectedBlocks(e).then(()=>{const s=o.removeSelectedBlocks(),r=o.insertDefaultBlockAtIndex(s,!0);i.setToBlock(r,i.positions.START),t.clearSelection(e)})}tabPressed(e){const{InlineToolbar:t,Caret:o}=this.Editor;if(t.opened)return;(e.shiftKey?o.navigatePrevious(!0):o.navigateNext(!0))&&e.preventDefault()}commandSlashPressed(){this.Editor.BlockSelection.selectedBlocks.length>1||this.activateBlockSettings()}slashPressed(e){!this.Editor.UI.nodes.wrapper.contains(e.target)||!this.Editor.BlockManager.currentBlock.isEmpty||(e.preventDefault(),this.Editor.Caret.insertContentAtCaretPosition("/"),this.activateToolbox())}enter(e){const{BlockManager:t,UI:o}=this.Editor,i=t.currentBlock;if(i===void 0||i.tool.isLineBreaksEnabled||o.someToolbarOpened&&o.someFlipperButtonFocused||e.shiftKey&&!rt)return;let s=i;i.currentInput!==void 0&&$e(i.currentInput)&&!i.hasMedia?this.Editor.BlockManager.insertDefaultBlockAtIndex(this.Editor.BlockManager.currentBlockIndex):i.currentInput&&ze(i.currentInput)?s=this.Editor.BlockManager.insertDefaultBlockAtIndex(this.Editor.BlockManager.currentBlockIndex+1):s=this.Editor.BlockManager.split(),this.Editor.Caret.setToBlock(s),this.Editor.Toolbar.moveAndOpen(s),e.preventDefault()}backspace(e){const{BlockManager:t,Caret:o}=this.Editor,{currentBlock:i,previousBlock:s}=t;if(i===void 0||!b.isCollapsed||!i.currentInput||!$e(i.currentInput))return;if(e.preventDefault(),this.Editor.Toolbar.close(),!(i.currentInput===i.firstInput)){o.navigatePrevious();return}if(s===null)return;if(s.isEmpty){t.removeBlock(s);return}if(i.isEmpty){t.removeBlock(i);const l=t.currentBlock;o.setToBlock(l,o.positions.END);return}No(s,i)?this.mergeBlocks(s,i):o.setToBlock(s,o.positions.END)}delete(e){const{BlockManager:t,Caret:o}=this.Editor,{currentBlock:i,nextBlock:s}=t;if(!b.isCollapsed||!ze(i.currentInput))return;if(e.preventDefault(),this.Editor.Toolbar.close(),!(i.currentInput===i.lastInput)){o.navigateNext();return}if(s===null)return;if(s.isEmpty){t.removeBlock(s);return}if(i.isEmpty){t.removeBlock(i),o.setToBlock(s,o.positions.START);return}No(i,s)?this.mergeBlocks(i,s):o.setToBlock(s,o.positions.START)}mergeBlocks(e,t){const{BlockManager:o,Toolbar:i}=this.Editor;e.lastInput!==void 0&&(nn.focus(e.lastInput,!1),o.mergeBlocks(e,t).then(()=>{i.close()}))}arrowRightAndDown(e){const t=ae.usedKeys.includes(e.keyCode)&&(!e.shiftKey||e.keyCode===y.TAB);if(this.Editor.UI.someToolbarOpened&&t)return;this.Editor.Toolbar.close();const{currentBlock:o}=this.Editor.BlockManager,s=((o==null?void 0:o.currentInput)!==void 0?ze(o.currentInput):void 0)||this.Editor.BlockSelection.anyBlockSelected;if(e.shiftKey&&e.keyCode===y.DOWN&&s){this.Editor.CrossBlockSelection.toggleBlockSelectedState();return}if(e.keyCode===y.DOWN||e.keyCode===y.RIGHT&&!this.isRtl?this.Editor.Caret.navigateNext():this.Editor.Caret.navigatePrevious()){e.preventDefault();return}Ae(()=>{this.Editor.BlockManager.currentBlock&&this.Editor.BlockManager.currentBlock.updateCurrentInput()},20)(),this.Editor.BlockSelection.clearSelection(e)}arrowLeftAndUp(e){if(this.Editor.UI.someToolbarOpened){if(ae.usedKeys.includes(e.keyCode)&&(!e.shiftKey||e.keyCode===y.TAB))return;this.Editor.UI.closeAllToolbars()}this.Editor.Toolbar.close();const{currentBlock:t}=this.Editor.BlockManager,i=((t==null?void 0:t.currentInput)!==void 0?$e(t.currentInput):void 0)||this.Editor.BlockSelection.anyBlockSelected;if(e.shiftKey&&e.keyCode===y.UP&&i){this.Editor.CrossBlockSelection.toggleBlockSelectedState(!1);return}if(e.keyCode===y.UP||e.keyCode===y.LEFT&&!this.isRtl?this.Editor.Caret.navigatePrevious():this.Editor.Caret.navigateNext()){e.preventDefault();return}Ae(()=>{this.Editor.BlockManager.currentBlock&&this.Editor.BlockManager.currentBlock.updateCurrentInput()},20)(),this.Editor.BlockSelection.clearSelection(e)}needToolbarClosing(e){const t=e.keyCode===y.ENTER&&this.Editor.Toolbar.toolbox.opened,o=e.keyCode===y.ENTER&&this.Editor.BlockSettings.opened,i=e.keyCode===y.ENTER&&this.Editor.InlineToolbar.opened,s=e.keyCode===y.TAB;return!(e.shiftKey||s||t||o||i)}activateToolbox(){this.Editor.Toolbar.opened||this.Editor.Toolbar.moveAndOpen(),this.Editor.Toolbar.toolbox.open()}activateBlockSettings(){this.Editor.Toolbar.opened||this.Editor.Toolbar.moveAndOpen(),this.Editor.BlockSettings.opened||this.Editor.BlockSettings.open()}}class ho{constructor(e){this.blocks=[],this.workingArea=e}get length(){return this.blocks.length}get array(){return this.blocks}get nodes(){return xo(this.workingArea.children)}static set(e,t,o){return isNaN(Number(t))?(Reflect.set(e,t,o),!0):(e.insert(+t,o),!0)}static get(e,t){return isNaN(Number(t))?Reflect.get(e,t):e.get(+t)}push(e){this.blocks.push(e),this.insertToDOM(e)}swap(e,t){const o=this.blocks[t];u.swap(this.blocks[e].holder,o.holder),this.blocks[t]=this.blocks[e],this.blocks[e]=o}move(e,t){const o=this.blocks.splice(t,1)[0],i=e-1,s=Math.max(0,i),r=this.blocks[s];e>0?this.insertToDOM(o,"afterend",r):this.insertToDOM(o,"beforebegin",r),this.blocks.splice(e,0,o);const a=this.composeBlockEvent("move",{fromIndex:t,toIndex:e});o.call(te.MOVED,a)}insert(e,t,o=!1){if(!this.length){this.push(t);return}e>this.length&&(e=this.length),o&&(this.blocks[e].holder.remove(),this.blocks[e].call(te.REMOVED));const i=o?1:0;if(this.blocks.splice(e,i,t),e>0){const s=this.blocks[e-1];this.insertToDOM(t,"afterend",s)}else{const s=this.blocks[e+1];s?this.insertToDOM(t,"beforebegin",s):this.insertToDOM(t)}}replace(e,t){if(this.blocks[e]===void 0)throw Error("Incorrect index");this.blocks[e].holder.replaceWith(t.holder),this.blocks[e]=t}insertMany(e,t){const o=new DocumentFragment;for(const i of e)o.appendChild(i.holder);if(this.length>0){if(t>0){const i=Math.min(t-1,this.length-1);this.blocks[i].holder.after(o)}else t===0&&this.workingArea.prepend(o);this.blocks.splice(t,0,...e)}else this.blocks.push(...e),this.workingArea.appendChild(o);e.forEach(i=>i.call(te.RENDERED))}remove(e){isNaN(e)&&(e=this.length-1),this.blocks[e].holder.remove(),this.blocks[e].call(te.REMOVED),this.blocks.splice(e,1)}removeAll(){this.workingArea.innerHTML="",this.blocks.forEach(e=>e.call(te.REMOVED)),this.blocks.length=0}insertAfter(e,t){const o=this.blocks.indexOf(e);this.insert(o+1,t)}get(e){return this.blocks[e]}indexOf(e){return this.blocks.indexOf(e)}insertToDOM(e,t,o){t?o.holder.insertAdjacentElement(t,e.holder):this.workingArea.appendChild(e.holder),e.call(te.RENDERED)}composeBlockEvent(e,t){return new CustomEvent(e,{detail:t})}}const _n="block-removed",Mn="block-added",Gr="block-moved",An="block-changed";class Jr{constructor(){this.completed=Promise.resolve()}add(e){return new Promise((t,o)=>{this.completed=this.completed.then(e).then(t).catch(o)})}}class Qr extends E{constructor(){super(...arguments),this._currentBlockIndex=-1,this._blocks=null}get currentBlockIndex(){return this._currentBlockIndex}set currentBlockIndex(e){this._currentBlockIndex=e}get firstBlock(){return this._blocks[0]}get lastBlock(){return this._blocks[this._blocks.length-1]}get currentBlock(){return this._blocks[this.currentBlockIndex]}set currentBlock(e){this.currentBlockIndex=this.getBlockIndex(e)}get nextBlock(){return this.currentBlockIndex===this._blocks.length-1?null:this._blocks[this.currentBlockIndex+1]}get nextContentfulBlock(){return this.blocks.slice(this.currentBlockIndex+1).find(t=>!!t.inputs.length)}get previousContentfulBlock(){return this.blocks.slice(0,this.currentBlockIndex).reverse().find(t=>!!t.inputs.length)}get previousBlock(){return this.currentBlockIndex===0?null:this._blocks[this.currentBlockIndex-1]}get blocks(){return this._blocks.array}get isEditorEmpty(){return this.blocks.every(e=>e.isEmpty)}prepare(){const e=new ho(this.Editor.UI.nodes.redactor);this._blocks=new Proxy(e,{set:ho.set,get:ho.get}),this.listeners.on(document,"copy",t=>this.Editor.BlockEvents.handleCommandC(t))}toggleReadOnly(e){e?this.disableModuleBindings():this.enableModuleBindings()}composeBlock({tool:e,data:t={},id:o=void 0,tunes:i={}}){const s=this.Editor.ReadOnly.isEnabled,r=this.Editor.Tools.blockTools.get(e),a=new R({id:o,data:t,tool:r,api:this.Editor.API,readOnly:s,tunesData:i},this.eventsDispatcher);return s||window.requestIdleCallback(()=>{this.bindBlockEvents(a)},{timeout:2e3}),a}insert({id:e=void 0,tool:t=this.config.defaultBlock,data:o={},index:i,needToFocus:s=!0,replace:r=!1,tunes:a={}}={}){let l=i;l===void 0&&(l=this.currentBlockIndex+(r?0:1));const c=this.composeBlock({id:e,tool:t,data:o,tunes:a});return r&&this.blockDidMutated(_n,this.getBlockByIndex(l),{index:l}),this._blocks.insert(l,c,r),this.blockDidMutated(Mn,c,{index:l}),s?this.currentBlockIndex=l:l<=this.currentBlockIndex&&this.currentBlockIndex++,c}insertMany(e,t=0){this._blocks.insertMany(e,t)}async update(e,t,o){if(!t&&!o)return e;const i=await e.data,s=this.composeBlock({id:e.id,tool:e.name,data:Object.assign({},i,t??{}),tunes:o??e.tunes}),r=this.getBlockIndex(e);return this._blocks.replace(r,s),this.blockDidMutated(An,s,{index:r}),s}replace(e,t,o){const i=this.getBlockIndex(e);return this.insert({tool:t,data:o,index:i,replace:!0})}paste(e,t,o=!1){const i=this.insert({tool:e,replace:o});try{window.requestIdleCallback(()=>{i.call(te.ON_PASTE,t)})}catch(s){T(`${e}: onPaste callback call is failed`,"error",s)}return i}insertDefaultBlockAtIndex(e,t=!1){const o=this.composeBlock({tool:this.config.defaultBlock});return this._blocks[e]=o,this.blockDidMutated(Mn,o,{index:e}),t?this.currentBlockIndex=e:e<=this.currentBlockIndex&&this.currentBlockIndex++,o}insertAtEnd(){return this.currentBlockIndex=this.blocks.length-1,this.insert()}async mergeBlocks(e,t){let o;if(e.name===t.name&&e.mergeable){const i=await t.data;if(V(i)){console.error("Could not merge Block. Failed to extract original Block data.");return}const[s]=dt([i],e.tool.sanitizeConfig);o=s}else if(e.mergeable&&Pe(t,"export")&&Pe(e,"import")){const i=await t.exportDataAsString(),s=q(i,e.tool.sanitizeConfig);o=Ro(s,e.tool.conversionConfig)}o!==void 0&&(await e.mergeWith(o),this.removeBlock(t),this.currentBlockIndex=this._blocks.indexOf(e))}removeBlock(e,t=!0){return new Promise(o=>{const i=this._blocks.indexOf(e);if(!this.validateIndex(i))throw new Error("Can't find a Block to remove");this._blocks.remove(i),e.destroy(),this.blockDidMutated(_n,e,{index:i}),this.currentBlockIndex>=i&&this.currentBlockIndex--,this.blocks.length?i===0&&(this.currentBlockIndex=0):(this.unsetCurrentBlock(),t&&this.insert()),o()})}removeSelectedBlocks(){let e;for(let t=this.blocks.length-1;t>=0;t--)this.blocks[t].selected&&(this.removeBlock(this.blocks[t]),e=t);return e}removeAllBlocks(){for(let e=this.blocks.length-1;e>=0;e--)this._blocks.remove(e);this.unsetCurrentBlock(),this.insert(),this.currentBlock.firstInput.focus()}split(){const e=this.Editor.Caret.extractFragmentFromCaretPosition(),t=u.make("div");t.appendChild(e);const o={text:u.isEmpty(t)?"":t.innerHTML};return this.insert({data:o})}getBlockByIndex(e){return e===-1&&(e=this._blocks.length-1),this._blocks[e]}getBlockIndex(e){return this._blocks.indexOf(e)}getBlockById(e){return this._blocks.array.find(t=>t.id===e)}getBlock(e){u.isElement(e)||(e=e.parentNode);const t=this._blocks.nodes,o=e.closest(`.${R.CSS.wrapper}`),i=t.indexOf(o);if(i>=0)return this._blocks[i]}setCurrentBlockByChildNode(e){u.isElement(e)||(e=e.parentNode);const t=e.closest(`.${R.CSS.wrapper}`);if(!t)return;const o=t.closest(`.${this.Editor.UI.CSS.editorWrapper}`);if(o!=null&&o.isEqualNode(this.Editor.UI.nodes.wrapper))return this.currentBlockIndex=this._blocks.nodes.indexOf(t),this.currentBlock.updateCurrentInput(),this.currentBlock}getBlockByChildNode(e){if(!e||!(e instanceof Node))return;u.isElement(e)||(e=e.parentNode);const t=e.closest(`.${R.CSS.wrapper}`);return this.blocks.find(o=>o.holder===t)}swap(e,t){this._blocks.swap(e,t),this.currentBlockIndex=t}move(e,t=this.currentBlockIndex){if(isNaN(e)||isNaN(t)){T("Warning during 'move' call: incorrect indices provided.","warn");return}if(!this.validateIndex(e)||!this.validateIndex(t)){T("Warning during 'move' call: indices cannot be lower than 0 or greater than the amount of blocks.","warn");return}this._blocks.move(e,t),this.currentBlockIndex=e,this.blockDidMutated(Gr,this.currentBlock,{fromIndex:t,toIndex:e})}async convert(e,t,o){if(!await e.save())throw new Error("Could not convert Block. Failed to extract original Block data.");const s=this.Editor.Tools.blockTools.get(t);if(!s)throw new Error(`Could not convert Block. Tool «${t}» not found.`);const r=await e.exportDataAsString(),a=q(r,s.sanitizeConfig);let l=Ro(a,s.conversionConfig,s.settings);return o&&(l=Object.assign(l,o)),this.replace(e,s.name,l)}unsetCurrentBlock(){this.currentBlockIndex=-1}async clear(e=!1){const t=new Jr;[...this.blocks].forEach(i=>{t.add(async()=>{await this.removeBlock(i,!1)})}),await t.completed,this.unsetCurrentBlock(),e&&this.insert(),this.Editor.UI.checkEmptiness()}async destroy(){await Promise.all(this.blocks.map(e=>e.destroy()))}bindBlockEvents(e){const{BlockEvents:t}=this.Editor;this.readOnlyMutableListeners.on(e.holder,"keydown",o=>{t.keydown(o)}),this.readOnlyMutableListeners.on(e.holder,"keyup",o=>{t.keyup(o)}),this.readOnlyMutableListeners.on(e.holder,"dragover",o=>{t.dragOver(o)}),this.readOnlyMutableListeners.on(e.holder,"dragleave",o=>{t.dragLeave(o)}),e.on("didMutated",o=>this.blockDidMutated(An,o,{index:this.getBlockIndex(o)}))}disableModuleBindings(){this.readOnlyMutableListeners.clearAll()}enableModuleBindings(){this.readOnlyMutableListeners.on(document,"cut",e=>this.Editor.BlockEvents.handleCommandX(e)),this.blocks.forEach(e=>{this.bindBlockEvents(e)})}validateIndex(e){return!(e<0||e>=this._blocks.length)}blockDidMutated(e,t,o){const i=new CustomEvent(e,{detail:{target:new ee(t),...o}});return this.eventsDispatcher.emit(_o,{event:i}),t}}class ea extends E{constructor(){super(...arguments),this.anyBlockSelectedCache=null,this.needToSelectAll=!1,this.nativeInputSelected=!1,this.readyToBlockSelection=!1}get sanitizerConfig(){return{p:{},h1:{},h2:{},h3:{},h4:{},h5:{},h6:{},ol:{},ul:{},li:{},br:!0,img:{src:!0,width:!0,height:!0},a:{href:!0},b:{},i:{},u:{}}}get allBlocksSelected(){const{BlockManager:e}=this.Editor;return e.blocks.every(t=>t.selected===!0)}set allBlocksSelected(e){const{BlockManager:t}=this.Editor;t.blocks.forEach(o=>{o.selected=e}),this.clearCache()}get anyBlockSelected(){const{BlockManager:e}=this.Editor;return this.anyBlockSelectedCache===null&&(this.anyBlockSelectedCache=e.blocks.some(t=>t.selected===!0)),this.anyBlockSelectedCache}get selectedBlocks(){return this.Editor.BlockManager.blocks.filter(e=>e.selected)}prepare(){this.selection=new b,be.add({name:"CMD+A",handler:e=>{const{BlockManager:t,ReadOnly:o}=this.Editor;if(o.isEnabled){e.preventDefault(),this.selectAllBlocks();return}t.currentBlock&&this.handleCommandA(e)},on:this.Editor.UI.nodes.redactor})}toggleReadOnly(){b.get().removeAllRanges(),this.allBlocksSelected=!1}unSelectBlockByIndex(e){const{BlockManager:t}=this.Editor;let o;isNaN(e)?o=t.currentBlock:o=t.getBlockByIndex(e),o.selected=!1,this.clearCache()}clearSelection(e,t=!1){const{BlockManager:o,Caret:i,RectangleSelection:s}=this.Editor;this.needToSelectAll=!1,this.nativeInputSelected=!1,this.readyToBlockSelection=!1;const r=e&&e instanceof KeyboardEvent,a=r&&Eo(e.keyCode);if(this.anyBlockSelected&&r&&a&&!b.isSelectionExists){const l=o.removeSelectedBlocks();o.insertDefaultBlockAtIndex(l,!0),i.setToBlock(o.currentBlock),Ae(()=>{const c=e.key;i.insertContentAtCaretPosition(c.length>1?"":c)},20)()}if(this.Editor.CrossBlockSelection.clear(e),!this.anyBlockSelected||s.isRectActivated()){this.Editor.RectangleSelection.clearSelection();return}t&&this.selection.restore(),this.allBlocksSelected=!1}copySelectedBlocks(e){e.preventDefault();const t=u.make("div");this.selectedBlocks.forEach(s=>{const r=q(s.holder.innerHTML,this.sanitizerConfig),a=u.make("p");a.innerHTML=r,t.appendChild(a)});const o=Array.from(t.childNodes).map(s=>s.textContent).join(` + +`),i=t.innerHTML;return e.clipboardData.setData("text/plain",o),e.clipboardData.setData("text/html",i),Promise.all(this.selectedBlocks.map(s=>s.save())).then(s=>{try{e.clipboardData.setData(this.Editor.Paste.MIME_TYPE,JSON.stringify(s))}catch{}})}selectBlockByIndex(e){const{BlockManager:t}=this.Editor,o=t.getBlockByIndex(e);o!==void 0&&this.selectBlock(o)}selectBlock(e){this.selection.save(),b.get().removeAllRanges(),e.selected=!0,this.clearCache(),this.Editor.InlineToolbar.close()}unselectBlock(e){e.selected=!1,this.clearCache()}clearCache(){this.anyBlockSelectedCache=null}destroy(){be.remove(this.Editor.UI.nodes.redactor,"CMD+A")}handleCommandA(e){if(this.Editor.RectangleSelection.clearSelection(),u.isNativeInput(e.target)&&!this.readyToBlockSelection){this.readyToBlockSelection=!0;return}const t=this.Editor.BlockManager.getBlock(e.target),o=t.inputs;if(o.length>1&&!this.readyToBlockSelection){this.readyToBlockSelection=!0;return}if(o.length===1&&!this.needToSelectAll){this.needToSelectAll=!0;return}this.needToSelectAll?(e.preventDefault(),this.selectAllBlocks(),this.needToSelectAll=!1,this.readyToBlockSelection=!1):this.readyToBlockSelection&&(e.preventDefault(),this.selectBlock(t),this.needToSelectAll=!0)}selectAllBlocks(){this.selection.save(),b.get().removeAllRanges(),this.allBlocksSelected=!0,this.Editor.InlineToolbar.close()}}class et extends E{get positions(){return{START:"start",END:"end",DEFAULT:"default"}}static get CSS(){return{shadowCaret:"cdx-shadow-caret"}}setToBlock(e,t=this.positions.DEFAULT,o=0){var c;const{BlockManager:i,BlockSelection:s}=this.Editor;if(s.clearSelection(),!e.focusable){(c=window.getSelection())==null||c.removeAllRanges(),s.selectBlock(e),i.currentBlock=e;return}let r;switch(t){case this.positions.START:r=e.firstInput;break;case this.positions.END:r=e.lastInput;break;default:r=e.currentInput}if(!r)return;let a,l=o;if(t===this.positions.START)a=u.getDeepestNode(r,!1),l=0;else if(t===this.positions.END)a=u.getDeepestNode(r,!0),l=u.getContentLength(a);else{const{node:d,offset:h}=u.getNodeByOffset(r,o);d?(a=d,l=h):(a=u.getDeepestNode(r,!1),l=0)}this.set(a,l),i.setCurrentBlockByChildNode(e.holder),i.currentBlock.currentInput=r}setToInput(e,t=this.positions.DEFAULT,o=0){const{currentBlock:i}=this.Editor.BlockManager,s=u.getDeepestNode(e);switch(t){case this.positions.START:this.set(s,0);break;case this.positions.END:this.set(s,u.getContentLength(s));break;default:o&&this.set(s,o)}i.currentInput=e}set(e,t=0){const{top:i,bottom:s}=b.setCursor(e,t),{innerHeight:r}=window;i<0?window.scrollBy(0,i-30):s>r&&window.scrollBy(0,s-r+30)}setToTheLastBlock(){const e=this.Editor.BlockManager.lastBlock;if(e)if(e.tool.isDefault&&e.isEmpty)this.setToBlock(e);else{const t=this.Editor.BlockManager.insertAtEnd();this.setToBlock(t)}}extractFragmentFromCaretPosition(){const e=b.get();if(e.rangeCount){const t=e.getRangeAt(0),o=this.Editor.BlockManager.currentBlock.currentInput;if(t.deleteContents(),o)if(u.isNativeInput(o)){const i=o,s=document.createDocumentFragment(),r=i.value.substring(0,i.selectionStart),a=i.value.substring(i.selectionStart);return s.textContent=a,i.value=r,s}else{const i=t.cloneRange();return i.selectNodeContents(o),i.setStart(t.endContainer,t.endOffset),i.extractContents()}}}navigateNext(e=!1){const{BlockManager:t}=this.Editor,{currentBlock:o,nextBlock:i}=t;if(o===void 0)return!1;const{nextInput:s,currentInput:r}=o,a=r!==void 0?ze(r):void 0;let l=i;const c=e||a||!o.focusable;if(s&&c)return this.setToInput(s,this.positions.START),!0;if(l===null){if(o.tool.isDefault||!c)return!1;l=t.insertAtEnd()}return c?(this.setToBlock(l,this.positions.START),!0):!1}navigatePrevious(e=!1){const{currentBlock:t,previousBlock:o}=this.Editor.BlockManager;if(!t)return!1;const{previousInput:i,currentInput:s}=t,r=s!==void 0?$e(s):void 0,a=e||r||!t.focusable;return i&&a?(this.setToInput(i,this.positions.END),!0):o!==null&&a?(this.setToBlock(o,this.positions.END),!0):!1}createShadow(e){const t=document.createElement("span");t.classList.add(et.CSS.shadowCaret),e.insertAdjacentElement("beforeend",t)}restoreCaret(e){const t=e.querySelector(`.${et.CSS.shadowCaret}`);if(!t)return;new b().expandToTag(t);const i=document.createRange();i.selectNode(t),i.extractContents()}insertContentAtCaretPosition(e){const t=document.createDocumentFragment(),o=document.createElement("div"),i=b.get(),s=b.range;o.innerHTML=e,Array.from(o.childNodes).forEach(c=>t.appendChild(c)),t.childNodes.length===0&&t.appendChild(new Text);const r=t.lastChild;s.deleteContents(),s.insertNode(t);const a=document.createRange(),l=r.nodeType===Node.TEXT_NODE?r:r.firstChild;l!==null&&l.textContent!==null&&a.setStart(l,l.textContent.length),i.removeAllRanges(),i.addRange(a)}}class ta extends E{constructor(){super(...arguments),this.onMouseUp=()=>{this.listeners.off(document,"mouseover",this.onMouseOver),this.listeners.off(document,"mouseup",this.onMouseUp)},this.onMouseOver=e=>{const{BlockManager:t,BlockSelection:o}=this.Editor;if(e.relatedTarget===null&&e.target===null)return;const i=t.getBlockByChildNode(e.relatedTarget)||this.lastSelectedBlock,s=t.getBlockByChildNode(e.target);if(!(!i||!s)&&s!==i){if(i===this.firstSelectedBlock){b.get().removeAllRanges(),i.selected=!0,s.selected=!0,o.clearCache();return}if(s===this.firstSelectedBlock){i.selected=!1,s.selected=!1,o.clearCache();return}this.Editor.InlineToolbar.close(),this.toggleBlocksSelectedState(i,s),this.lastSelectedBlock=s}}}async prepare(){this.listeners.on(document,"mousedown",e=>{this.enableCrossBlockSelection(e)})}watchSelection(e){if(e.button!==Xn.LEFT)return;const{BlockManager:t}=this.Editor;this.firstSelectedBlock=t.getBlock(e.target),this.lastSelectedBlock=this.firstSelectedBlock,this.listeners.on(document,"mouseover",this.onMouseOver),this.listeners.on(document,"mouseup",this.onMouseUp)}get isCrossBlockSelectionStarted(){return!!this.firstSelectedBlock&&!!this.lastSelectedBlock&&this.firstSelectedBlock!==this.lastSelectedBlock}toggleBlockSelectedState(e=!0){const{BlockManager:t,BlockSelection:o}=this.Editor;this.lastSelectedBlock||(this.lastSelectedBlock=this.firstSelectedBlock=t.currentBlock),this.firstSelectedBlock===this.lastSelectedBlock&&(this.firstSelectedBlock.selected=!0,o.clearCache(),b.get().removeAllRanges());const i=t.blocks.indexOf(this.lastSelectedBlock)+(e?1:-1),s=t.blocks[i];s&&(this.lastSelectedBlock.selected!==s.selected?(s.selected=!0,o.clearCache()):(this.lastSelectedBlock.selected=!1,o.clearCache()),this.lastSelectedBlock=s,this.Editor.InlineToolbar.close(),s.holder.scrollIntoView({block:"nearest"}))}clear(e){const{BlockManager:t,BlockSelection:o,Caret:i}=this.Editor,s=t.blocks.indexOf(this.firstSelectedBlock),r=t.blocks.indexOf(this.lastSelectedBlock);if(o.anyBlockSelected&&s>-1&&r>-1&&e&&e instanceof KeyboardEvent)switch(e.keyCode){case y.DOWN:case y.RIGHT:i.setToBlock(t.blocks[Math.max(s,r)],i.positions.END);break;case y.UP:case y.LEFT:i.setToBlock(t.blocks[Math.min(s,r)],i.positions.START);break;default:i.setToBlock(t.blocks[Math.max(s,r)],i.positions.END)}this.firstSelectedBlock=this.lastSelectedBlock=null}enableCrossBlockSelection(e){const{UI:t}=this.Editor;b.isCollapsed||this.Editor.BlockSelection.clearSelection(e),t.nodes.redactor.contains(e.target)?this.watchSelection(e):this.Editor.BlockSelection.clearSelection(e)}toggleBlocksSelectedState(e,t){const{BlockManager:o,BlockSelection:i}=this.Editor,s=o.blocks.indexOf(e),r=o.blocks.indexOf(t),a=e.selected!==t.selected;for(let l=Math.min(s,r);l<=Math.max(s,r);l++){const c=o.blocks[l];c!==this.firstSelectedBlock&&c!==(a?e:t)&&(o.blocks[l].selected=!o.blocks[l].selected,i.clearCache())}}}class oa extends E{constructor(){super(...arguments),this.isStartedAtEditor=!1}toggleReadOnly(e){e?this.disableModuleBindings():this.enableModuleBindings()}enableModuleBindings(){const{UI:e}=this.Editor;this.readOnlyMutableListeners.on(e.nodes.holder,"drop",async t=>{await this.processDrop(t)},!0),this.readOnlyMutableListeners.on(e.nodes.holder,"dragstart",()=>{this.processDragStart()}),this.readOnlyMutableListeners.on(e.nodes.holder,"dragover",t=>{this.processDragOver(t)},!0)}disableModuleBindings(){this.readOnlyMutableListeners.clearAll()}async processDrop(e){const{BlockManager:t,Paste:o,Caret:i}=this.Editor;e.preventDefault(),t.blocks.forEach(r=>{r.dropTarget=!1}),b.isAtEditor&&!b.isCollapsed&&this.isStartedAtEditor&&document.execCommand("delete"),this.isStartedAtEditor=!1;const s=t.setCurrentBlockByChildNode(e.target);if(s)this.Editor.Caret.setToBlock(s,i.positions.END);else{const r=t.setCurrentBlockByChildNode(t.lastBlock.holder);this.Editor.Caret.setToBlock(r,i.positions.END)}await o.processDataTransfer(e.dataTransfer,!0)}processDragStart(){b.isAtEditor&&!b.isCollapsed&&(this.isStartedAtEditor=!0),this.Editor.InlineToolbar.close()}processDragOver(e){e.preventDefault()}}const na=180,ia=400;class sa extends E{constructor({config:e,eventsDispatcher:t}){super({config:e,eventsDispatcher:t}),this.disabled=!1,this.batchingTimeout=null,this.batchingOnChangeQueue=new Map,this.batchTime=ia,this.mutationObserver=new MutationObserver(o=>{this.redactorChanged(o)}),this.eventsDispatcher.on(_o,o=>{this.particularBlockChanged(o.event)}),this.eventsDispatcher.on(Mo,()=>{this.disable()}),this.eventsDispatcher.on(Ao,()=>{this.enable()})}enable(){this.mutationObserver.observe(this.Editor.UI.nodes.redactor,{childList:!0,subtree:!0,characterData:!0,attributes:!0}),this.disabled=!1}disable(){this.mutationObserver.disconnect(),this.disabled=!0}particularBlockChanged(e){this.disabled||!M(this.config.onChange)||(this.batchingOnChangeQueue.set(`block:${e.detail.target.id}:event:${e.type}`,e),this.batchingTimeout&&clearTimeout(this.batchingTimeout),this.batchingTimeout=setTimeout(()=>{let t;this.batchingOnChangeQueue.size===1?t=this.batchingOnChangeQueue.values().next().value:t=Array.from(this.batchingOnChangeQueue.values()),this.config.onChange&&this.config.onChange(this.Editor.API.methods,t),this.batchingOnChangeQueue.clear()},this.batchTime))}redactorChanged(e){this.eventsDispatcher.emit(at,{mutations:e})}}const Ln=class Wn extends E{constructor(){super(...arguments),this.MIME_TYPE="application/x-editor-js",this.toolsTags={},this.tagsByTool={},this.toolsPatterns=[],this.toolsFiles={},this.exceptionList=[],this.processTool=e=>{try{const t=e.create({},{},!1);if(e.pasteConfig===!1){this.exceptionList.push(e.name);return}if(!M(t.onPaste))return;this.getTagsConfig(e),this.getFilesConfig(e),this.getPatternsConfig(e)}catch(t){T(`Paste handling for «${e.name}» Tool hasn't been set up because of the error`,"warn",t)}},this.handlePasteEvent=async e=>{const{BlockManager:t,Toolbar:o}=this.Editor,i=t.setCurrentBlockByChildNode(e.target);!i||this.isNativeBehaviour(e.target)&&!e.clipboardData.types.includes("Files")||i&&this.exceptionList.includes(i.name)||(e.preventDefault(),this.processDataTransfer(e.clipboardData),o.close())}}async prepare(){this.processTools()}toggleReadOnly(e){e?this.unsetCallback():this.setCallback()}async processDataTransfer(e,t=!1){const{Tools:o}=this.Editor,i=e.types;if((i.includes?i.includes("Files"):i.contains("Files"))&&!V(this.toolsFiles)){await this.processFiles(e.files);return}const r=e.getData(this.MIME_TYPE),a=e.getData("text/plain");let l=e.getData("text/html");if(r)try{this.insertEditorJSData(JSON.parse(r));return}catch{}t&&a.trim()&&l.trim()&&(l="

    "+(l.trim()?l:a)+"

    ");const c=Object.keys(this.toolsTags).reduce((p,g)=>(p[g.toLowerCase()]=this.toolsTags[g].sanitizationConfig??{},p),{}),d=Object.assign({},c,o.getAllInlineToolsSanitizeConfig(),{br:{}}),h=q(l,d);!h.trim()||h.trim()===a||!u.isHTMLString(h)?await this.processText(a):await this.processText(h,!0)}async processText(e,t=!1){const{Caret:o,BlockManager:i}=this.Editor,s=t?this.processHTML(e):this.processPlain(e);if(!s.length)return;if(s.length===1){s[0].isBlock?this.processSingleBlock(s.pop()):this.processInlinePaste(s.pop());return}const a=i.currentBlock&&i.currentBlock.tool.isDefault&&i.currentBlock.isEmpty;s.map(async(l,c)=>this.insertBlock(l,c===0&&a)),i.currentBlock&&o.setToBlock(i.currentBlock,o.positions.END)}setCallback(){this.listeners.on(this.Editor.UI.nodes.holder,"paste",this.handlePasteEvent)}unsetCallback(){this.listeners.off(this.Editor.UI.nodes.holder,"paste",this.handlePasteEvent)}processTools(){const e=this.Editor.Tools.blockTools;Array.from(e.values()).forEach(this.processTool)}collectTagNames(e){return Q(e)?[e]:N(e)?Object.keys(e):[]}getTagsConfig(e){if(e.pasteConfig===!1)return;const t=e.pasteConfig.tags||[],o=[];t.forEach(i=>{const s=this.collectTagNames(i);o.push(...s),s.forEach(r=>{if(Object.prototype.hasOwnProperty.call(this.toolsTags,r)){T(`Paste handler for «${e.name}» Tool on «${r}» tag is skipped because it is already used by «${this.toolsTags[r].tool.name}» Tool.`,"warn");return}const a=N(i)?i[r]:null;this.toolsTags[r.toUpperCase()]={tool:e,sanitizationConfig:a}})}),this.tagsByTool[e.name]=o.map(i=>i.toUpperCase())}getFilesConfig(e){if(e.pasteConfig===!1)return;const{files:t={}}=e.pasteConfig;let{extensions:o,mimeTypes:i}=t;!o&&!i||(o&&!Array.isArray(o)&&(T(`«extensions» property of the onDrop config for «${e.name}» Tool should be an array`),o=[]),i&&!Array.isArray(i)&&(T(`«mimeTypes» property of the onDrop config for «${e.name}» Tool should be an array`),i=[]),i&&(i=i.filter(s=>Jn(s)?!0:(T(`MIME type value «${s}» for the «${e.name}» Tool is not a valid MIME type`,"warn"),!1))),this.toolsFiles[e.name]={extensions:o||[],mimeTypes:i||[]})}getPatternsConfig(e){e.pasteConfig===!1||!e.pasteConfig.patterns||V(e.pasteConfig.patterns)||Object.entries(e.pasteConfig.patterns).forEach(([t,o])=>{o instanceof RegExp||T(`Pattern ${o} for «${e.name}» Tool is skipped because it should be a Regexp instance.`,"warn"),this.toolsPatterns.push({key:t,pattern:o,tool:e})})}isNativeBehaviour(e){return u.isNativeInput(e)}async processFiles(e){const{BlockManager:t}=this.Editor;let o;o=await Promise.all(Array.from(e).map(r=>this.processFile(r))),o=o.filter(r=>!!r);const s=t.currentBlock.tool.isDefault&&t.currentBlock.isEmpty;o.forEach((r,a)=>{t.paste(r.type,r.event,a===0&&s)})}async processFile(e){const t=Gn(e),o=Object.entries(this.toolsFiles).find(([r,{mimeTypes:a,extensions:l}])=>{const[c,d]=e.type.split("/"),h=l.find(g=>g.toLowerCase()===t.toLowerCase()),p=a.find(g=>{const[f,v]=g.split("/");return f===c&&(v===d||v==="*")});return!!h||!!p});if(!o)return;const[i]=o;return{event:this.composePasteEvent("file",{file:e}),type:i}}processHTML(e){const{Tools:t}=this.Editor,o=u.make("DIV");return o.innerHTML=e,this.getNodes(o).map(s=>{let r,a=t.defaultTool,l=!1;switch(s.nodeType){case Node.DOCUMENT_FRAGMENT_NODE:r=u.make("div"),r.appendChild(s);break;case Node.ELEMENT_NODE:r=s,l=!0,this.toolsTags[r.tagName]&&(a=this.toolsTags[r.tagName].tool);break}const{tags:c}=a.pasteConfig||{tags:[]},d=c.reduce((g,f)=>(this.collectTagNames(f).forEach(O=>{const S=N(f)?f[O]:null;g[O.toLowerCase()]=S||{}}),g),{}),h=Object.assign({},d,a.baseSanitizeConfig);if(r.tagName.toLowerCase()==="table"){const g=q(r.outerHTML,h);r=u.make("div",void 0,{innerHTML:g}).firstChild}else r.innerHTML=q(r.innerHTML,h);const p=this.composePasteEvent("tag",{data:r});return{content:r,isBlock:l,tool:a.name,event:p}}).filter(s=>{const r=u.isEmpty(s.content),a=u.isSingleTag(s.content);return!r||a})}processPlain(e){const{defaultBlock:t}=this.config;if(!e)return[];const o=t;return e.split(/\r?\n/).filter(i=>i.trim()).map(i=>{const s=u.make("div");s.textContent=i;const r=this.composePasteEvent("tag",{data:s});return{content:s,tool:o,isBlock:!1,event:r}})}async processSingleBlock(e){const{Caret:t,BlockManager:o}=this.Editor,{currentBlock:i}=o;if(!i||e.tool!==i.name||!u.containsOnlyInlineElements(e.content.innerHTML)){this.insertBlock(e,(i==null?void 0:i.tool.isDefault)&&i.isEmpty);return}t.insertContentAtCaretPosition(e.content.innerHTML)}async processInlinePaste(e){const{BlockManager:t,Caret:o}=this.Editor,{content:i}=e;if(t.currentBlock&&t.currentBlock.tool.isDefault&&i.textContent.length{const s=i.pattern.exec(e);return s?e===s.shift():!1});return t?{event:this.composePasteEvent("pattern",{key:t.key,data:e}),tool:t.tool.name}:void 0}insertBlock(e,t=!1){const{BlockManager:o,Caret:i}=this.Editor,{currentBlock:s}=o;let r;if(t&&s&&s.isEmpty){r=o.paste(e.tool,e.event,!0),i.setToBlock(r,i.positions.END);return}r=o.paste(e.tool,e.event),i.setToBlock(r,i.positions.END)}insertEditorJSData(e){const{BlockManager:t,Caret:o,Tools:i}=this.Editor;dt(e,r=>i.blockTools.get(r).sanitizeConfig).forEach(({tool:r,data:a},l)=>{let c=!1;l===0&&(c=t.currentBlock&&t.currentBlock.tool.isDefault&&t.currentBlock.isEmpty);const d=t.insert({tool:r,data:a,replace:c});o.setToBlock(d,o.positions.END)})}processElementNode(e,t,o){const i=Object.keys(this.toolsTags),s=e,{tool:r}=this.toolsTags[s.tagName]||{},a=this.tagsByTool[r==null?void 0:r.name]||[],l=i.includes(s.tagName),c=u.blockElements.includes(s.tagName.toLowerCase()),d=Array.from(s.children).some(({tagName:p})=>i.includes(p)&&!a.includes(p)),h=Array.from(s.children).some(({tagName:p})=>u.blockElements.includes(p.toLowerCase()));if(!c&&!l&&!d)return o.appendChild(s),[...t,o];if(l&&!d||c&&!h&&!d)return[...t,o,s]}getNodes(e){const t=Array.from(e.childNodes);let o;const i=(s,r)=>{if(u.isEmpty(r)&&!u.isSingleTag(r))return s;const a=s[s.length-1];let l=new DocumentFragment;switch(a&&u.isFragment(a)&&(l=s.pop()),r.nodeType){case Node.ELEMENT_NODE:if(o=this.processElementNode(r,s,l),o)return o;break;case Node.TEXT_NODE:return l.appendChild(r),[...s,l];default:return[...s,l]}return[...s,...Array.from(r.childNodes).reduce(i,[])]};return t.reduce(i,[])}composePasteEvent(e,t){return new CustomEvent(e,{detail:t})}};Ln.PATTERN_PROCESSING_MAX_LENGTH=450;let ra=Ln;class aa extends E{constructor(){super(...arguments),this.toolsDontSupportReadOnly=[],this.readOnlyEnabled=!1}get isEnabled(){return this.readOnlyEnabled}async prepare(){const{Tools:e}=this.Editor,{blockTools:t}=e,o=[];Array.from(t.entries()).forEach(([i,s])=>{s.isReadOnlySupported||o.push(i)}),this.toolsDontSupportReadOnly=o,this.config.readOnly&&o.length>0&&this.throwCriticalError(),this.toggle(this.config.readOnly,!0)}async toggle(e=!this.readOnlyEnabled,t=!1){e&&this.toolsDontSupportReadOnly.length>0&&this.throwCriticalError();const o=this.readOnlyEnabled;this.readOnlyEnabled=e;for(const s in this.Editor)this.Editor[s].toggleReadOnly&&this.Editor[s].toggleReadOnly(e);if(o===e)return this.readOnlyEnabled;if(t)return this.readOnlyEnabled;this.Editor.ModificationsObserver.disable();const i=await this.Editor.Saver.save();return await this.Editor.BlockManager.clear(),await this.Editor.Renderer.render(i.blocks),this.Editor.ModificationsObserver.enable(),this.readOnlyEnabled}throwCriticalError(){throw new Oo(`To enable read-only mode all connected tools should support it. Tools ${this.toolsDontSupportReadOnly.join(", ")} don't support read-only mode.`)}}class Ie extends E{constructor(){super(...arguments),this.isRectSelectionActivated=!1,this.SCROLL_SPEED=3,this.HEIGHT_OF_SCROLL_ZONE=40,this.BOTTOM_SCROLL_ZONE=1,this.TOP_SCROLL_ZONE=2,this.MAIN_MOUSE_BUTTON=0,this.mousedown=!1,this.isScrolling=!1,this.inScrollZone=null,this.startX=0,this.startY=0,this.mouseX=0,this.mouseY=0,this.stackOfSelected=[],this.listenerIds=[]}static get CSS(){return{overlay:"codex-editor-overlay",overlayContainer:"codex-editor-overlay__container",rect:"codex-editor-overlay__rectangle",topScrollZone:"codex-editor-overlay__scroll-zone--top",bottomScrollZone:"codex-editor-overlay__scroll-zone--bottom"}}prepare(){this.enableModuleBindings()}startSelection(e,t){const o=document.elementFromPoint(e-window.pageXOffset,t-window.pageYOffset);o.closest(`.${this.Editor.Toolbar.CSS.toolbar}`)||(this.Editor.BlockSelection.allBlocksSelected=!1,this.clearSelection(),this.stackOfSelected=[]);const s=[`.${R.CSS.content}`,`.${this.Editor.Toolbar.CSS.toolbar}`,`.${this.Editor.InlineToolbar.CSS.inlineToolbar}`],r=o.closest("."+this.Editor.UI.CSS.editorWrapper),a=s.some(l=>!!o.closest(l));!r||a||(this.mousedown=!0,this.startX=e,this.startY=t)}endSelection(){this.mousedown=!1,this.startX=0,this.startY=0,this.overlayRectangle.style.display="none"}isRectActivated(){return this.isRectSelectionActivated}clearSelection(){this.isRectSelectionActivated=!1}enableModuleBindings(){const{container:e}=this.genHTML();this.listeners.on(e,"mousedown",t=>{this.processMouseDown(t)},!1),this.listeners.on(document.body,"mousemove",ot(t=>{this.processMouseMove(t)},10),{passive:!0}),this.listeners.on(document.body,"mouseleave",()=>{this.processMouseLeave()}),this.listeners.on(window,"scroll",ot(t=>{this.processScroll(t)},10),{passive:!0}),this.listeners.on(document.body,"mouseup",()=>{this.processMouseUp()},!1)}processMouseDown(e){if(e.button!==this.MAIN_MOUSE_BUTTON)return;e.target.closest(u.allInputsSelector)!==null||this.startSelection(e.pageX,e.pageY)}processMouseMove(e){this.changingRectangle(e),this.scrollByZones(e.clientY)}processMouseLeave(){this.clearSelection(),this.endSelection()}processScroll(e){this.changingRectangle(e)}processMouseUp(){this.clearSelection(),this.endSelection()}scrollByZones(e){if(this.inScrollZone=null,e<=this.HEIGHT_OF_SCROLL_ZONE&&(this.inScrollZone=this.TOP_SCROLL_ZONE),document.documentElement.clientHeight-e<=this.HEIGHT_OF_SCROLL_ZONE&&(this.inScrollZone=this.BOTTOM_SCROLL_ZONE),!this.inScrollZone){this.isScrolling=!1;return}this.isScrolling||(this.scrollVertical(this.inScrollZone===this.TOP_SCROLL_ZONE?-this.SCROLL_SPEED:this.SCROLL_SPEED),this.isScrolling=!0)}genHTML(){const{UI:e}=this.Editor,t=e.nodes.holder.querySelector("."+e.CSS.editorWrapper),o=u.make("div",Ie.CSS.overlay,{}),i=u.make("div",Ie.CSS.overlayContainer,{}),s=u.make("div",Ie.CSS.rect,{});return i.appendChild(s),o.appendChild(i),t.appendChild(o),this.overlayRectangle=s,{container:t,overlay:o}}scrollVertical(e){if(!(this.inScrollZone&&this.mousedown))return;const t=window.pageYOffset;window.scrollBy(0,e),this.mouseY+=window.pageYOffset-t,setTimeout(()=>{this.scrollVertical(e)},0)}changingRectangle(e){if(!this.mousedown)return;e.pageY!==void 0&&(this.mouseX=e.pageX,this.mouseY=e.pageY);const{rightPos:t,leftPos:o,index:i}=this.genInfoForMouseSelection(),s=this.startX>t&&this.mouseX>t,r=this.startX=this.startY?(this.overlayRectangle.style.top=`${this.startY-window.pageYOffset}px`,this.overlayRectangle.style.bottom=`calc(100% - ${this.mouseY-window.pageYOffset}px`):(this.overlayRectangle.style.bottom=`calc(100% - ${this.startY-window.pageYOffset}px`,this.overlayRectangle.style.top=`${this.mouseY-window.pageYOffset}px`),this.mouseX>=this.startX?(this.overlayRectangle.style.left=`${this.startX-window.pageXOffset}px`,this.overlayRectangle.style.right=`calc(100% - ${this.mouseX-window.pageXOffset}px`):(this.overlayRectangle.style.right=`calc(100% - ${this.startX-window.pageXOffset}px`,this.overlayRectangle.style.left=`${this.mouseX-window.pageXOffset}px`)}genInfoForMouseSelection(){const t=document.body.offsetWidth/2,o=this.mouseY-window.pageYOffset,i=document.elementFromPoint(t,o),s=this.Editor.BlockManager.getBlockByChildNode(i);let r;s!==void 0&&(r=this.Editor.BlockManager.blocks.findIndex(h=>h.holder===s.holder));const a=this.Editor.BlockManager.lastBlock.holder.querySelector("."+R.CSS.content),l=Number.parseInt(window.getComputedStyle(a).width,10)/2,c=t-l,d=t+l;return{index:r,leftPos:c,rightPos:d}}addBlockInSelection(e){this.rectCrossesBlocks&&this.Editor.BlockSelection.selectBlockByIndex(e),this.stackOfSelected.push(e)}trySelectNextBlock(e){const t=this.stackOfSelected[this.stackOfSelected.length-1]===e,o=this.stackOfSelected.length,i=1,s=-1,r=0;if(t)return;const a=this.stackOfSelected[o-1]-this.stackOfSelected[o-2]>0;let l=r;o>1&&(l=a?i:s);const c=e>this.stackOfSelected[o-1]&&l===i,d=ethis.stackOfSelected[o-1]||this.stackOfSelected[o-1]===void 0)){let v=this.stackOfSelected[o-1]+1||e;for(v;v<=e;v++)this.addBlockInSelection(v);return}if(!p&&e=e;v--)this.addBlockInSelection(v);return}if(!p)return;let g=o-1,f;for(e>this.stackOfSelected[o-1]?f=()=>e>this.stackOfSelected[g]:f=()=>e{const{Tools:o,BlockManager:i}=this.Editor;if(e.length===0)i.insert();else{const s=e.map(({type:r,data:a,tunes:l,id:c})=>{o.available.has(r)===!1&&(X(`Tool «${r}» is not found. Check 'tools' property at the Editor.js config.`,"warn"),a=this.composeStubDataForTool(r,a,c),r=o.stubTool);let d;try{d=i.composeBlock({id:c,tool:r,data:a,tunes:l})}catch(h){T(`Block «${r}» skipped because of plugins error`,"error",{data:a,error:h}),a=this.composeStubDataForTool(r,a,c),r=o.stubTool,d=i.composeBlock({id:c,tool:r,data:a,tunes:l})}return d});i.insertMany(s)}window.requestIdleCallback(()=>{t()},{timeout:2e3})})}composeStubDataForTool(e,t,o){const{Tools:i}=this.Editor;let s=e;if(i.unavailable.has(e)){const r=i.unavailable.get(e).toolbox;r!==void 0&&r[0].title!==void 0&&(s=r[0].title)}return{savedData:{id:o,type:e,data:t},title:s}}}class ca extends E{async save(){const{BlockManager:e,Tools:t}=this.Editor,o=e.blocks,i=[];try{o.forEach(a=>{i.push(this.getSavedData(a))});const s=await Promise.all(i),r=await dt(s,a=>t.blockTools.get(a).sanitizeConfig);return this.makeOutput(r)}catch(s){X("Saving failed due to the Error %o","error",s)}}async getSavedData(e){const t=await e.save(),o=t&&await e.validate(t.data);return{...t,isValid:o}}makeOutput(e){const t=[];return e.forEach(({id:o,tool:i,data:s,tunes:r,isValid:a})=>{if(!a){T(`Block «${i}» skipped because saved data is invalid`);return}if(i===this.Editor.Tools.stubTool){t.push(s);return}const l={id:o,type:i,data:s,...!V(r)&&{tunes:r}};t.push(l)}),{time:+new Date,blocks:t,version:"2.31.1"}}}(function(){try{if(typeof document<"u"){var n=document.createElement("style");n.appendChild(document.createTextNode(".ce-paragraph{line-height:1.6em;outline:none}.ce-block:only-of-type .ce-paragraph[data-placeholder-active]:empty:before,.ce-block:only-of-type .ce-paragraph[data-placeholder-active][data-empty=true]:before{content:attr(data-placeholder-active)}.ce-paragraph p:first-of-type{margin-top:0}.ce-paragraph p:last-of-type{margin-bottom:0}")),document.head.appendChild(n)}}catch(e){console.error("vite-plugin-css-injected-by-js",e)}})();const da='';function ua(n){const e=document.createElement("div");e.innerHTML=n.trim();const t=document.createDocumentFragment();return t.append(...Array.from(e.childNodes)),t}/** + * Base Paragraph Block for the Editor.js. + * Represents a regular text block + * + * @author CodeX (team@codex.so) + * @copyright CodeX 2018 + * @license The MIT License (MIT) + */class po{static get DEFAULT_PLACEHOLDER(){return""}constructor({data:e,config:t,api:o,readOnly:i}){this.api=o,this.readOnly=i,this._CSS={block:this.api.styles.block,wrapper:"ce-paragraph"},this.readOnly||(this.onKeyUp=this.onKeyUp.bind(this)),this._placeholder=t.placeholder?t.placeholder:po.DEFAULT_PLACEHOLDER,this._data=e??{},this._element=null,this._preserveBlank=t.preserveBlank??!1}onKeyUp(e){if(e.code!=="Backspace"&&e.code!=="Delete"||!this._element)return;const{textContent:t}=this._element;t===""&&(this._element.innerHTML="")}drawView(){const e=document.createElement("DIV");return e.classList.add(this._CSS.wrapper,this._CSS.block),e.contentEditable="false",e.dataset.placeholderActive=this.api.i18n.t(this._placeholder),this._data.text&&(e.innerHTML=this._data.text),this.readOnly||(e.contentEditable="true",e.addEventListener("keyup",this.onKeyUp)),e}render(){return this._element=this.drawView(),this._element}merge(e){if(!this._element)return;this._data.text+=e.text;const t=ua(e.text);this._element.appendChild(t),this._element.normalize()}validate(e){return!(e.text.trim()===""&&!this._preserveBlank)}save(e){return{text:e.innerHTML}}onPaste(e){const t={text:e.detail.data.innerHTML};this._data=t,window.requestAnimationFrame(()=>{this._element&&(this._element.innerHTML=this._data.text||"")})}static get conversionConfig(){return{export:"text",import:"text"}}static get sanitize(){return{text:{br:!0}}}static get isReadOnlySupported(){return!0}static get pasteConfig(){return{tags:["P"]}}static get toolbox(){return{icon:da,title:"Text"}}}class fo{constructor(){this.commandName="bold"}static get sanitize(){return{b:{}}}render(){return{icon:Hi,name:"bold",onActivate:()=>{document.execCommand(this.commandName)},isActive:()=>document.queryCommandState(this.commandName)}}get shortcut(){return"CMD+B"}}fo.isInline=!0,fo.title="Bold";class go{constructor(){this.commandName="italic",this.CSS={button:"ce-inline-tool",buttonActive:"ce-inline-tool--active",buttonModifier:"ce-inline-tool--italic"},this.nodes={button:null}}static get sanitize(){return{i:{}}}render(){return this.nodes.button=document.createElement("button"),this.nodes.button.type="button",this.nodes.button.classList.add(this.CSS.button,this.CSS.buttonModifier),this.nodes.button.innerHTML=Xi,this.nodes.button}surround(){document.execCommand(this.commandName)}checkState(){const e=document.queryCommandState(this.commandName);return this.nodes.button.classList.toggle(this.CSS.buttonActive,e),e}get shortcut(){return"CMD+I"}}go.isInline=!0,go.title="Italic";class mo{constructor({api:e}){this.commandLink="createLink",this.commandUnlink="unlink",this.ENTER_KEY=13,this.CSS={button:"ce-inline-tool",buttonActive:"ce-inline-tool--active",buttonModifier:"ce-inline-tool--link",buttonUnlink:"ce-inline-tool--unlink",input:"ce-inline-tool-input",inputShowed:"ce-inline-tool-input--showed"},this.nodes={button:null,input:null},this.inputOpened=!1,this.toolbar=e.toolbar,this.inlineToolbar=e.inlineToolbar,this.notifier=e.notifier,this.i18n=e.i18n,this.selection=new b}static get sanitize(){return{a:{href:!0,target:"_blank",rel:"nofollow"}}}render(){return this.nodes.button=document.createElement("button"),this.nodes.button.type="button",this.nodes.button.classList.add(this.CSS.button,this.CSS.buttonModifier),this.nodes.button.innerHTML=zo,this.nodes.button}renderActions(){return this.nodes.input=document.createElement("input"),this.nodes.input.placeholder=this.i18n.t("Add a link"),this.nodes.input.enterKeyHint="done",this.nodes.input.classList.add(this.CSS.input),this.nodes.input.addEventListener("keydown",e=>{e.keyCode===this.ENTER_KEY&&this.enterPressed(e)}),this.nodes.input}surround(e){if(e){this.inputOpened?(this.selection.restore(),this.selection.removeFakeBackground()):(this.selection.setFakeBackground(),this.selection.save());const t=this.selection.findParentTag("A");if(t){this.selection.expandToTag(t),this.unlink(),this.closeActions(),this.checkState(),this.toolbar.close();return}}this.toggleActions()}checkState(){const e=this.selection.findParentTag("A");if(e){this.nodes.button.innerHTML=Gi,this.nodes.button.classList.add(this.CSS.buttonUnlink),this.nodes.button.classList.add(this.CSS.buttonActive),this.openActions();const t=e.getAttribute("href");this.nodes.input.value=t!=="null"?t:"",this.selection.save()}else this.nodes.button.innerHTML=zo,this.nodes.button.classList.remove(this.CSS.buttonUnlink),this.nodes.button.classList.remove(this.CSS.buttonActive);return!!e}clear(){this.closeActions()}get shortcut(){return"CMD+K"}toggleActions(){this.inputOpened?this.closeActions(!1):this.openActions(!0)}openActions(e=!1){this.nodes.input.classList.add(this.CSS.inputShowed),e&&this.nodes.input.focus(),this.inputOpened=!0}closeActions(e=!0){if(this.selection.isFakeBackgroundEnabled){const t=new b;t.save(),this.selection.restore(),this.selection.removeFakeBackground(),t.restore()}this.nodes.input.classList.remove(this.CSS.inputShowed),this.nodes.input.value="",e&&this.selection.clearSaved(),this.inputOpened=!1}enterPressed(e){let t=this.nodes.input.value||"";if(!t.trim()){this.selection.restore(),this.unlink(),e.preventDefault(),this.closeActions();return}if(!this.validateURL(t)){this.notifier.show({message:"Pasted link is not valid.",style:"error"}),T("Incorrect Link pasted","warn",t);return}t=this.prepareLink(t),this.selection.restore(),this.selection.removeFakeBackground(),this.insertLink(t),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.selection.collapseToEnd(),this.inlineToolbar.close()}validateURL(e){return!/\s/.test(e)}prepareLink(e){return e=e.trim(),e=this.addProtocol(e),e}addProtocol(e){if(/^(\w+):(\/\/)?/.test(e))return e;const t=/^\/[^/\s]/.test(e),o=e.substring(0,1)==="#",i=/^\/\/[^/\s]/.test(e);return!t&&!o&&!i&&(e="http://"+e),e}insertLink(e){const t=this.selection.findParentTag("A");t&&this.selection.expandToTag(t),document.execCommand(this.commandLink,!1,e)}unlink(){document.execCommand(this.commandUnlink)}}mo.isInline=!0,mo.title="Link";class Pn{constructor({api:e}){this.i18nAPI=e.i18n,this.blocksAPI=e.blocks,this.selectionAPI=e.selection,this.toolsAPI=e.tools,this.caretAPI=e.caret}async render(){const e=b.get(),t=this.blocksAPI.getBlockByElement(e.anchorNode);if(t===void 0)return[];const o=this.toolsAPI.getBlockTools(),i=await Po(t,o);if(i.length===0)return[];const s=i.reduce((c,d)=>{var h;return(h=d.toolbox)==null||h.forEach(p=>{c.push({icon:p.icon,title:H.t(W.toolNames,p.title),name:d.name,closeOnActivate:!0,onActivate:async()=>{const g=await this.blocksAPI.convert(t.id,d.name,p.data);this.caretAPI.setToBlock(g,"end")}})}),c},[]),r=await t.getActiveToolboxEntry(),a=r!==void 0?r.icon:Uo,l=!ge();return{icon:a,name:"convert-to",hint:{title:this.i18nAPI.t("Convert to")},children:{searchable:l,items:s,onOpen:()=>{l&&(this.selectionAPI.setFakeBackground(),this.selectionAPI.save())},onClose:()=>{l&&(this.selectionAPI.restore(),this.selectionAPI.removeFakeBackground())}}}}}Pn.isInline=!0;class Nn{constructor({data:e,api:t}){this.CSS={wrapper:"ce-stub",info:"ce-stub__info",title:"ce-stub__title",subtitle:"ce-stub__subtitle"},this.api=t,this.title=e.title||this.api.i18n.t("Error"),this.subtitle=this.api.i18n.t("The block can not be displayed correctly."),this.savedData=e.savedData,this.wrapper=this.make()}render(){return this.wrapper}save(){return this.savedData}make(){const e=u.make("div",this.CSS.wrapper),t=Ji,o=u.make("div",this.CSS.info),i=u.make("div",this.CSS.title,{textContent:this.title}),s=u.make("div",this.CSS.subtitle,{textContent:this.subtitle});return e.innerHTML=t,o.appendChild(i),o.appendChild(s),e.appendChild(o),e}}Nn.isReadOnlySupported=!0;class ha extends xt{constructor(){super(...arguments),this.type=ce.Inline}get title(){return this.constructable[He.Title]}create(){return new this.constructable({api:this.api,config:this.settings})}get isReadOnlySupported(){return this.constructable[He.IsReadOnlySupported]??!1}}class pa extends xt{constructor(){super(...arguments),this.type=ce.Tune}create(e,t){return new this.constructable({api:this.api,config:this.settings,block:t,data:e})}}class F extends Map{get blockTools(){const e=Array.from(this.entries()).filter(([,t])=>t.isBlock());return new F(e)}get inlineTools(){const e=Array.from(this.entries()).filter(([,t])=>t.isInline());return new F(e)}get blockTunes(){const e=Array.from(this.entries()).filter(([,t])=>t.isTune());return new F(e)}get internalTools(){const e=Array.from(this.entries()).filter(([,t])=>t.isInternal);return new F(e)}get externalTools(){const e=Array.from(this.entries()).filter(([,t])=>!t.isInternal);return new F(e)}}var fa=Object.defineProperty,ga=Object.getOwnPropertyDescriptor,Rn=(n,e,t,o)=>{for(var i=o>1?void 0:o?ga(e,t):e,s=n.length-1,r;s>=0;s--)(r=n[s])&&(i=(o?r(e,t,i):r(i))||i);return o&&i&&fa(e,t,i),i};class bo extends xt{constructor(){super(...arguments),this.type=ce.Block,this.inlineTools=new F,this.tunes=new F}create(e,t,o){return new this.constructable({data:e,block:t,readOnly:o,api:this.api,config:this.settings})}get isReadOnlySupported(){return this.constructable[ve.IsReadOnlySupported]===!0}get isLineBreaksEnabled(){return this.constructable[ve.IsEnabledLineBreaks]}get toolbox(){const e=this.constructable[ve.Toolbox],t=this.config[je.Toolbox];if(!V(e)&&t!==!1)return t?Array.isArray(e)?Array.isArray(t)?t.map((o,i)=>{const s=e[i];return s?{...s,...o}:o}):[t]:Array.isArray(t)?t:[{...e,...t}]:Array.isArray(e)?e:[e]}get conversionConfig(){return this.constructable[ve.ConversionConfig]}get enabledInlineTools(){return this.config[je.EnabledInlineTools]||!1}get enabledBlockTunes(){return this.config[je.EnabledBlockTunes]}get pasteConfig(){return this.constructable[ve.PasteConfig]??{}}get sanitizeConfig(){const e=super.sanitizeConfig,t=this.baseSanitizeConfig;if(V(e))return t;const o={};for(const i in e)if(Object.prototype.hasOwnProperty.call(e,i)){const s=e[i];N(s)?o[i]=Object.assign({},t,s):o[i]=s}return o}get baseSanitizeConfig(){const e={};return Array.from(this.inlineTools.values()).forEach(t=>Object.assign(e,t.sanitizeConfig)),Array.from(this.tunes.values()).forEach(t=>Object.assign(e,t.sanitizeConfig)),e}}Rn([fe],bo.prototype,"sanitizeConfig",1),Rn([fe],bo.prototype,"baseSanitizeConfig",1);class ma{constructor(e,t,o){this.api=o,this.config=e,this.editorConfig=t}get(e){const{class:t,isInternal:o=!1,...i}=this.config[e],s=this.getConstructor(t),r=t[Et.IsTune];return new s({name:e,constructable:t,config:i,api:this.api.getMethodsForTool(e,r),isDefault:e===this.editorConfig.defaultBlock,defaultPlaceholder:this.editorConfig.placeholder,isInternal:o})}getConstructor(e){switch(!0){case e[He.IsInline]:return ha;case e[Et.IsTune]:return pa;default:return bo}}}class Dn{constructor({api:e}){this.CSS={animation:"wobble"},this.api=e}render(){return{icon:$i,title:this.api.i18n.t("Move down"),onActivate:()=>this.handleClick(),name:"move-down"}}handleClick(){const e=this.api.blocks.getCurrentBlockIndex(),t=this.api.blocks.getBlockByIndex(e+1);if(!t)throw new Error("Unable to move Block down since it is already the last");const o=t.holder,i=o.getBoundingClientRect();let s=Math.abs(window.innerHeight-o.offsetHeight);i.topthis.handleClick()}}}handleClick(){this.api.blocks.delete()}}Fn.isTune=!0;class jn{constructor({api:e}){this.CSS={animation:"wobble"},this.api=e}render(){return{icon:Wi,title:this.api.i18n.t("Move up"),onActivate:()=>this.handleClick(),name:"move-up"}}handleClick(){const e=this.api.blocks.getCurrentBlockIndex(),t=this.api.blocks.getBlockByIndex(e),o=this.api.blocks.getBlockByIndex(e-1);if(e===0||!t||!o)throw new Error("Unable to move Block up since it is already the first");const i=t.holder,s=o.holder,r=i.getBoundingClientRect(),a=s.getBoundingClientRect();let l;a.top>0?l=Math.abs(r.top)-Math.abs(a.top):l=Math.abs(r.top)+a.height,window.scrollBy(0,-1*l),this.api.blocks.move(e-1),this.api.toolbar.toggleBlockSettings(!0)}}jn.isTune=!0;var ba=Object.defineProperty,va=Object.getOwnPropertyDescriptor,ka=(n,e,t,o)=>{for(var i=o>1?void 0:o?va(e,t):e,s=n.length-1,r;s>=0;s--)(r=n[s])&&(i=(o?r(e,t,i):r(i))||i);return o&&i&&ba(e,t,i),i};class Hn extends E{constructor(){super(...arguments),this.stubTool="stub",this.toolsAvailable=new F,this.toolsUnavailable=new F}get available(){return this.toolsAvailable}get unavailable(){return this.toolsUnavailable}get inlineTools(){return this.available.inlineTools}get blockTools(){return this.available.blockTools}get blockTunes(){return this.available.blockTunes}get defaultTool(){return this.blockTools.get(this.config.defaultBlock)}get internal(){return this.available.internalTools}async prepare(){if(this.validateTools(),this.config.tools=nt({},this.internalTools,this.config.tools),!Object.prototype.hasOwnProperty.call(this.config,"tools")||Object.keys(this.config.tools).length===0)throw Error("Can't start without tools");const e=this.prepareConfig();this.factory=new ma(e,this.config,this.Editor.API);const t=this.getListOfPrepareFunctions(e);if(t.length===0)return Promise.resolve();await Zn(t,o=>{this.toolPrepareMethodSuccess(o)},o=>{this.toolPrepareMethodFallback(o)}),this.prepareBlockTools()}getAllInlineToolsSanitizeConfig(){const e={};return Array.from(this.inlineTools.values()).forEach(t=>{Object.assign(e,t.sanitizeConfig)}),e}destroy(){Object.values(this.available).forEach(async e=>{M(e.reset)&&await e.reset()})}get internalTools(){return{convertTo:{class:Pn,isInternal:!0},link:{class:mo,isInternal:!0},bold:{class:fo,isInternal:!0},italic:{class:go,isInternal:!0},paragraph:{class:po,inlineToolbar:!0,isInternal:!0},stub:{class:Nn,isInternal:!0},moveUp:{class:jn,isInternal:!0},delete:{class:Fn,isInternal:!0},moveDown:{class:Dn,isInternal:!0}}}toolPrepareMethodSuccess(e){const t=this.factory.get(e.toolName);if(t.isInline()){const i=["render"].filter(s=>!t.create()[s]);if(i.length){T(`Incorrect Inline Tool: ${t.name}. Some of required methods is not implemented %o`,"warn",i),this.toolsUnavailable.set(t.name,t);return}}this.toolsAvailable.set(t.name,t)}toolPrepareMethodFallback(e){this.toolsUnavailable.set(e.toolName,this.factory.get(e.toolName))}getListOfPrepareFunctions(e){const t=[];return Object.entries(e).forEach(([o,i])=>{t.push({function:M(i.class.prepare)?i.class.prepare:()=>{},data:{toolName:o,config:i.config}})}),t}prepareBlockTools(){Array.from(this.blockTools.values()).forEach(e=>{this.assignInlineToolsToBlockTool(e),this.assignBlockTunesToBlockTool(e)})}assignInlineToolsToBlockTool(e){if(this.config.inlineToolbar!==!1){if(e.enabledInlineTools===!0){e.inlineTools=new F(Array.isArray(this.config.inlineToolbar)?this.config.inlineToolbar.map(t=>[t,this.inlineTools.get(t)]):Array.from(this.inlineTools.entries()));return}Array.isArray(e.enabledInlineTools)&&(e.inlineTools=new F(["convertTo",...e.enabledInlineTools].map(t=>[t,this.inlineTools.get(t)])))}}assignBlockTunesToBlockTool(e){if(e.enabledBlockTunes!==!1){if(Array.isArray(e.enabledBlockTunes)){const t=new F(e.enabledBlockTunes.map(o=>[o,this.blockTunes.get(o)]));e.tunes=new F([...t,...this.blockTunes.internalTools]);return}if(Array.isArray(this.config.tunes)){const t=new F(this.config.tunes.map(o=>[o,this.blockTunes.get(o)]));e.tunes=new F([...t,...this.blockTunes.internalTools]);return}e.tunes=this.blockTunes.internalTools}}validateTools(){for(const e in this.config.tools)if(Object.prototype.hasOwnProperty.call(this.config.tools,e)){if(e in this.internalTools)return;const t=this.config.tools[e];if(!M(t)&&!M(t.class))throw Error(`Tool «${e}» must be a constructor function or an object with function in the «class» property`)}}prepareConfig(){const e={};for(const t in this.config.tools)N(this.config.tools[t])?e[t]=this.config.tools[t]:e[t]={class:this.config.tools[t]};return e}}ka([fe],Hn.prototype,"getAllInlineToolsSanitizeConfig",1);const ya=`:root{--selectionColor: #e1f2ff;--inlineSelectionColor: #d4ecff;--bg-light: #eff2f5;--grayText: #707684;--color-dark: #1D202B;--color-active-icon: #388AE5;--color-gray-border: rgba(201, 201, 204, .48);--content-width: 650px;--narrow-mode-right-padding: 50px;--toolbox-buttons-size: 26px;--toolbox-buttons-size--mobile: 36px;--icon-size: 20px;--icon-size--mobile: 28px;--block-padding-vertical: .4em;--color-line-gray: #EFF0F1 }.codex-editor{position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;z-index:1}.codex-editor .hide{display:none}.codex-editor__redactor [contenteditable]:empty:after{content:"\\feff"}@media (min-width: 651px){.codex-editor--narrow .codex-editor__redactor{margin-right:50px}}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .codex-editor__redactor{margin-left:50px;margin-right:0}}@media (min-width: 651px){.codex-editor--narrow .ce-toolbar__actions{right:-5px}}.codex-editor-copyable{position:absolute;height:1px;width:1px;top:-400%;opacity:.001}.codex-editor-overlay{position:fixed;top:0;left:0;right:0;bottom:0;z-index:999;pointer-events:none;overflow:hidden}.codex-editor-overlay__container{position:relative;pointer-events:auto;z-index:0}.codex-editor-overlay__rectangle{position:absolute;pointer-events:none;background-color:#2eaadc33;border:1px solid transparent}.codex-editor svg{max-height:100%}.codex-editor path{stroke:currentColor}.codex-editor ::-moz-selection{background-color:#d4ecff}.codex-editor ::selection{background-color:#d4ecff}.codex-editor--toolbox-opened [contentEditable=true][data-placeholder]:focus:before{opacity:0!important}.ce-scroll-locked{overflow:hidden}.ce-scroll-locked--hard{overflow:hidden;top:calc(-1 * var(--window-scroll-offset));position:fixed;width:100%}.ce-toolbar{position:absolute;left:0;right:0;top:0;-webkit-transition:opacity .1s ease;transition:opacity .1s ease;will-change:opacity,top;display:none}.ce-toolbar--opened{display:block}.ce-toolbar__content{max-width:650px;margin:0 auto;position:relative}.ce-toolbar__plus{color:#1d202b;cursor:pointer;width:26px;height:26px;border-radius:7px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-ms-flex-negative:0;flex-shrink:0}@media (max-width: 650px){.ce-toolbar__plus{width:36px;height:36px}}@media (hover: hover){.ce-toolbar__plus:hover{background-color:#eff2f5}}.ce-toolbar__plus--active{background-color:#eff2f5;-webkit-animation:bounceIn .75s 1;animation:bounceIn .75s 1;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.ce-toolbar__plus-shortcut{opacity:.6;word-spacing:-2px;margin-top:5px}@media (max-width: 650px){.ce-toolbar__plus{position:absolute;background-color:#fff;border:1px solid #E8E8EB;-webkit-box-shadow:0 3px 15px -3px rgba(13,20,33,.13);box-shadow:0 3px 15px -3px #0d142121;border-radius:6px;z-index:2;position:static}.ce-toolbar__plus--left-oriented:before{left:15px;margin-left:0}.ce-toolbar__plus--right-oriented:before{left:auto;right:15px;margin-left:0}}.ce-toolbar__actions{position:absolute;right:100%;opacity:0;display:-webkit-box;display:-ms-flexbox;display:flex;padding-right:5px}.ce-toolbar__actions--opened{opacity:1}@media (max-width: 650px){.ce-toolbar__actions{right:auto}}.ce-toolbar__settings-btn{color:#1d202b;width:26px;height:26px;border-radius:7px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;margin-left:3px;cursor:pointer;user-select:none}@media (max-width: 650px){.ce-toolbar__settings-btn{width:36px;height:36px}}@media (hover: hover){.ce-toolbar__settings-btn:hover{background-color:#eff2f5}}.ce-toolbar__settings-btn--active{background-color:#eff2f5;-webkit-animation:bounceIn .75s 1;animation:bounceIn .75s 1;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@media (min-width: 651px){.ce-toolbar__settings-btn{width:24px}}.ce-toolbar__settings-btn--hidden{display:none}@media (max-width: 650px){.ce-toolbar__settings-btn{position:absolute;background-color:#fff;border:1px solid #E8E8EB;-webkit-box-shadow:0 3px 15px -3px rgba(13,20,33,.13);box-shadow:0 3px 15px -3px #0d142121;border-radius:6px;z-index:2;position:static}.ce-toolbar__settings-btn--left-oriented:before{left:15px;margin-left:0}.ce-toolbar__settings-btn--right-oriented:before{left:auto;right:15px;margin-left:0}}.ce-toolbar__plus svg,.ce-toolbar__settings-btn svg{width:24px;height:24px}@media (min-width: 651px){.codex-editor--narrow .ce-toolbar__plus{left:5px}}@media (min-width: 651px){.codex-editor--narrow .ce-toolbox .ce-popover{right:0;left:auto;left:initial}}.ce-inline-toolbar{--y-offset: 8px;--color-background-icon-active: rgba(56, 138, 229, .1);--color-text-icon-active: #388AE5;--color-text-primary: black;position:absolute;visibility:hidden;-webkit-transition:opacity .25s ease;transition:opacity .25s ease;will-change:opacity,left,top;top:0;left:0;z-index:3;opacity:1;visibility:visible}.ce-inline-toolbar [hidden]{display:none!important}.ce-inline-toolbar__toggler-and-button-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;padding:0 6px}.ce-inline-toolbar__buttons{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-inline-toolbar__dropdown{display:-webkit-box;display:-ms-flexbox;display:flex;padding:6px;margin:0 6px 0 -6px;-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:pointer;border-right:1px solid rgba(201,201,204,.48);-webkit-box-sizing:border-box;box-sizing:border-box}@media (hover: hover){.ce-inline-toolbar__dropdown:hover{background:#eff2f5}}.ce-inline-toolbar__dropdown--hidden{display:none}.ce-inline-toolbar__dropdown-content,.ce-inline-toolbar__dropdown-arrow{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-inline-toolbar__dropdown-content svg,.ce-inline-toolbar__dropdown-arrow svg{width:20px;height:20px}.ce-inline-toolbar__shortcut{opacity:.6;word-spacing:-3px;margin-top:3px}.ce-inline-tool{color:var(--color-text-primary);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;border-radius:4px;line-height:normal;height:100%;padding:0;width:28px;background-color:transparent;cursor:pointer}@media (max-width: 650px){.ce-inline-tool{width:36px;height:36px}}@media (hover: hover){.ce-inline-tool:hover{background-color:#f8f8f8}}.ce-inline-tool svg{display:block;width:20px;height:20px}@media (max-width: 650px){.ce-inline-tool svg{width:28px;height:28px}}.ce-inline-tool--link .icon--unlink,.ce-inline-tool--unlink .icon--link{display:none}.ce-inline-tool--unlink .icon--unlink{display:inline-block;margin-bottom:-1px}.ce-inline-tool-input{background:#F8F8F8;border:1px solid rgba(226,226,229,.2);border-radius:6px;padding:4px 8px;font-size:14px;line-height:22px;outline:none;margin:0;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box;display:none;font-weight:500;-webkit-appearance:none;font-family:inherit}@media (max-width: 650px){.ce-inline-tool-input{font-size:15px;font-weight:500}}.ce-inline-tool-input::-webkit-input-placeholder{color:#707684}.ce-inline-tool-input::-moz-placeholder{color:#707684}.ce-inline-tool-input:-ms-input-placeholder{color:#707684}.ce-inline-tool-input::-ms-input-placeholder{color:#707684}.ce-inline-tool-input::placeholder{color:#707684}.ce-inline-tool-input--showed{display:block}.ce-inline-tool--active{background:var(--color-background-icon-active);color:var(--color-text-icon-active)}@-webkit-keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.ce-block{-webkit-animation:fade-in .3s ease;animation:fade-in .3s ease;-webkit-animation-fill-mode:none;animation-fill-mode:none;-webkit-animation-fill-mode:initial;animation-fill-mode:initial}.ce-block:first-of-type{margin-top:0}.ce-block--selected .ce-block__content{background:#e1f2ff}.ce-block--selected .ce-block__content [contenteditable]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ce-block--selected .ce-block__content img,.ce-block--selected .ce-block__content .ce-stub{opacity:.55}.ce-block--stretched .ce-block__content{max-width:none}.ce-block__content{position:relative;max-width:650px;margin:0 auto;-webkit-transition:background-color .15s ease;transition:background-color .15s ease}.ce-block--drop-target .ce-block__content:before{content:"";position:absolute;top:100%;left:-20px;margin-top:-1px;height:8px;width:8px;border:solid #388AE5;border-width:1px 1px 0 0;-webkit-transform-origin:right;transform-origin:right;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.ce-block--drop-target .ce-block__content:after{content:"";position:absolute;top:100%;height:1px;width:100%;color:#388ae5;background:repeating-linear-gradient(90deg,#388AE5,#388AE5 1px,#fff 1px,#fff 6px)}.ce-block a{cursor:pointer;-webkit-text-decoration:underline;text-decoration:underline}.ce-block b{font-weight:700}.ce-block i{font-style:italic}@-webkit-keyframes bounceIn{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}20%{-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}60%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes bounceIn{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}20%{-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}60%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@-webkit-keyframes selectionBounce{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}50%{-webkit-transform:scale3d(1.01,1.01,1.01);transform:scale3d(1.01,1.01,1.01)}70%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes selectionBounce{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}50%{-webkit-transform:scale3d(1.01,1.01,1.01);transform:scale3d(1.01,1.01,1.01)}70%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@-webkit-keyframes buttonClicked{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.95,.95,.95);transform:scale3d(.95,.95,.95)}60%{-webkit-transform:scale3d(1.02,1.02,1.02);transform:scale3d(1.02,1.02,1.02)}80%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes buttonClicked{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.95,.95,.95);transform:scale3d(.95,.95,.95)}60%{-webkit-transform:scale3d(1.02,1.02,1.02);transform:scale3d(1.02,1.02,1.02)}80%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}.cdx-block{padding:.4em 0}.cdx-block::-webkit-input-placeholder{line-height:normal!important}.cdx-input{border:1px solid rgba(201,201,204,.48);-webkit-box-shadow:inset 0 1px 2px 0 rgba(35,44,72,.06);box-shadow:inset 0 1px 2px #232c480f;border-radius:3px;padding:10px 12px;outline:none;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.cdx-input[data-placeholder]:before{position:static!important}.cdx-input[data-placeholder]:before{display:inline-block;width:0;white-space:nowrap;pointer-events:none}.cdx-settings-button{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;border-radius:3px;cursor:pointer;border:0;outline:none;background-color:transparent;vertical-align:bottom;color:inherit;margin:0;min-width:26px;min-height:26px}.cdx-settings-button--focused{background:rgba(34,186,255,.08)!important}.cdx-settings-button--focused{-webkit-box-shadow:inset 0 0 0px 1px rgba(7,161,227,.08);box-shadow:inset 0 0 0 1px #07a1e314}.cdx-settings-button--focused-animated{-webkit-animation-name:buttonClicked;animation-name:buttonClicked;-webkit-animation-duration:.25s;animation-duration:.25s}.cdx-settings-button--active{color:#388ae5}.cdx-settings-button svg{width:auto;height:auto}@media (max-width: 650px){.cdx-settings-button svg{width:28px;height:28px}}@media (max-width: 650px){.cdx-settings-button{width:36px;height:36px;border-radius:8px}}@media (hover: hover){.cdx-settings-button:hover{background-color:#eff2f5}}.cdx-loader{position:relative;border:1px solid rgba(201,201,204,.48)}.cdx-loader:before{content:"";position:absolute;left:50%;top:50%;width:18px;height:18px;margin:-11px 0 0 -11px;border:2px solid rgba(201,201,204,.48);border-left-color:#388ae5;border-radius:50%;-webkit-animation:cdxRotation 1.2s infinite linear;animation:cdxRotation 1.2s infinite linear}@-webkit-keyframes cdxRotation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes cdxRotation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.cdx-button{padding:13px;border-radius:3px;border:1px solid rgba(201,201,204,.48);font-size:14.9px;background:#fff;-webkit-box-shadow:0 2px 2px 0 rgba(18,30,57,.04);box-shadow:0 2px 2px #121e390a;color:#707684;text-align:center;cursor:pointer}@media (hover: hover){.cdx-button:hover{background:#FBFCFE;-webkit-box-shadow:0 1px 3px 0 rgba(18,30,57,.08);box-shadow:0 1px 3px #121e3914}}.cdx-button svg{height:20px;margin-right:.2em;margin-top:-2px}.ce-stub{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:12px 18px;margin:10px 0;border-radius:10px;background:#eff2f5;border:1px solid #EFF0F1;color:#707684;font-size:14px}.ce-stub svg{width:20px;height:20px}.ce-stub__info{margin-left:14px}.ce-stub__title{font-weight:500;text-transform:capitalize}.codex-editor.codex-editor--rtl{direction:rtl}.codex-editor.codex-editor--rtl .cdx-list{padding-left:0;padding-right:40px}.codex-editor.codex-editor--rtl .ce-toolbar__plus{right:-26px;left:auto}.codex-editor.codex-editor--rtl .ce-toolbar__actions{right:auto;left:-26px}@media (max-width: 650px){.codex-editor.codex-editor--rtl .ce-toolbar__actions{margin-left:0;margin-right:auto;padding-right:0;padding-left:10px}}.codex-editor.codex-editor--rtl .ce-settings{left:5px;right:auto}.codex-editor.codex-editor--rtl .ce-settings:before{right:auto;left:25px}.codex-editor.codex-editor--rtl .ce-settings__button:not(:nth-child(3n+3)){margin-left:3px;margin-right:0}.codex-editor.codex-editor--rtl .ce-conversion-tool__icon{margin-right:0;margin-left:10px}.codex-editor.codex-editor--rtl .ce-inline-toolbar__dropdown{border-right:0px solid transparent;border-left:1px solid rgba(201,201,204,.48);margin:0 -6px 0 6px}.codex-editor.codex-editor--rtl .ce-inline-toolbar__dropdown .icon--toggler-down{margin-left:0;margin-right:4px}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .ce-toolbar__plus{left:0;right:5px}}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .ce-toolbar__actions{left:-5px}}.cdx-search-field{--icon-margin-right: 10px;background:#F8F8F8;border:1px solid rgba(226,226,229,.2);border-radius:6px;padding:2px;display:grid;grid-template-columns:auto auto 1fr;grid-template-rows:auto}.cdx-search-field__icon{width:26px;height:26px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-right:var(--icon-margin-right)}.cdx-search-field__icon svg{width:20px;height:20px;color:#707684}.cdx-search-field__input{font-size:14px;outline:none;font-weight:500;font-family:inherit;border:0;background:transparent;margin:0;padding:0;line-height:22px;min-width:calc(100% - 26px - var(--icon-margin-right))}.cdx-search-field__input::-webkit-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::-moz-placeholder{color:#707684;font-weight:500}.cdx-search-field__input:-ms-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::-ms-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::placeholder{color:#707684;font-weight:500}.ce-popover{--border-radius: 6px;--width: 200px;--max-height: 270px;--padding: 6px;--offset-from-target: 8px;--color-border: #EFF0F1;--color-shadow: rgba(13, 20, 33, .1);--color-background: white;--color-text-primary: black;--color-text-secondary: #707684;--color-border-icon: rgba(201, 201, 204, .48);--color-border-icon-disabled: #EFF0F1;--color-text-icon-active: #388AE5;--color-background-icon-active: rgba(56, 138, 229, .1);--color-background-item-focus: rgba(34, 186, 255, .08);--color-shadow-item-focus: rgba(7, 161, 227, .08);--color-background-item-hover: #F8F8F8;--color-background-item-confirm: #E24A4A;--color-background-item-confirm-hover: #CE4343;--popover-top: calc(100% + var(--offset-from-target));--popover-left: 0;--nested-popover-overlap: 4px;--icon-size: 20px;--item-padding: 3px;--item-height: calc(var(--icon-size) + 2 * var(--item-padding))}.ce-popover__container{min-width:var(--width);width:var(--width);max-height:var(--max-height);border-radius:var(--border-radius);overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-box-shadow:0px 3px 15px -3px var(--color-shadow);box-shadow:0 3px 15px -3px var(--color-shadow);position:absolute;left:var(--popover-left);top:var(--popover-top);background:var(--color-background);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;z-index:4;opacity:0;max-height:0;pointer-events:none;padding:0;border:none}.ce-popover--opened>.ce-popover__container{opacity:1;padding:var(--padding);max-height:var(--max-height);pointer-events:auto;-webkit-animation:panelShowing .1s ease;animation:panelShowing .1s ease;border:1px solid var(--color-border)}@media (max-width: 650px){.ce-popover--opened>.ce-popover__container{-webkit-animation:panelShowingMobile .25s ease;animation:panelShowingMobile .25s ease}}.ce-popover--open-top .ce-popover__container{--popover-top: calc(-1 * (var(--offset-from-target) + var(--popover-height)))}.ce-popover--open-left .ce-popover__container{--popover-left: calc(-1 * var(--width) + 100%)}.ce-popover__items{overflow-y:auto;-ms-scroll-chaining:none;overscroll-behavior:contain}@media (max-width: 650px){.ce-popover__overlay{position:fixed;top:0;bottom:0;left:0;right:0;background:#1D202B;z-index:3;opacity:.5;-webkit-transition:opacity .12s ease-in;transition:opacity .12s ease-in;will-change:opacity;visibility:visible}}.ce-popover__overlay--hidden{display:none}@media (max-width: 650px){.ce-popover .ce-popover__container{--offset: 5px;position:fixed;max-width:none;min-width:calc(100% - var(--offset) * 2);left:var(--offset);right:var(--offset);bottom:calc(var(--offset) + env(safe-area-inset-bottom));top:auto;border-radius:10px}}.ce-popover__search{margin-bottom:5px}.ce-popover__nothing-found-message{color:#707684;display:none;cursor:default;padding:3px;font-size:14px;line-height:20px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ce-popover__nothing-found-message--displayed{display:block}.ce-popover--nested .ce-popover__container{--popover-left: calc(var(--nesting-level) * (var(--width) - var(--nested-popover-overlap)));top:calc(var(--trigger-item-top) - var(--nested-popover-overlap));position:absolute}.ce-popover--open-top.ce-popover--nested .ce-popover__container{top:calc(var(--trigger-item-top) - var(--popover-height) + var(--item-height) + var(--offset-from-target) + var(--nested-popover-overlap))}.ce-popover--open-left .ce-popover--nested .ce-popover__container{--popover-left: calc(-1 * (var(--nesting-level) + 1) * var(--width) + 100%)}.ce-popover-item-separator{padding:4px 3px}.ce-popover-item-separator--hidden{display:none}.ce-popover-item-separator__line{height:1px;background:var(--color-border);width:100%}.ce-popover-item-html--hidden{display:none}.ce-popover-item{--border-radius: 6px;border-radius:var(--border-radius);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:var(--item-padding);color:var(--color-text-primary);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:none;background:transparent}@media (max-width: 650px){.ce-popover-item{padding:4px}}.ce-popover-item:not(:last-of-type){margin-bottom:1px}.ce-popover-item__icon{width:26px;height:26px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.ce-popover-item__icon svg{width:20px;height:20px}@media (max-width: 650px){.ce-popover-item__icon{width:36px;height:36px;border-radius:8px}.ce-popover-item__icon svg{width:28px;height:28px}}.ce-popover-item__icon--tool{margin-right:4px}.ce-popover-item__title{font-size:14px;line-height:20px;font-weight:500;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-right:auto}@media (max-width: 650px){.ce-popover-item__title{font-size:16px}}.ce-popover-item__secondary-title{color:var(--color-text-secondary);font-size:12px;white-space:nowrap;letter-spacing:-.1em;padding-right:5px;opacity:.6}@media (max-width: 650px){.ce-popover-item__secondary-title{display:none}}.ce-popover-item--active{background:var(--color-background-icon-active);color:var(--color-text-icon-active)}.ce-popover-item--disabled{color:var(--color-text-secondary);cursor:default;pointer-events:none}.ce-popover-item--focused:not(.ce-popover-item--no-focus){background:var(--color-background-item-focus)!important}.ce-popover-item--hidden{display:none}@media (hover: hover){.ce-popover-item:hover{cursor:pointer}.ce-popover-item:hover:not(.ce-popover-item--no-hover){background-color:var(--color-background-item-hover)}}.ce-popover-item--confirmation{background:var(--color-background-item-confirm)}.ce-popover-item--confirmation .ce-popover-item__title,.ce-popover-item--confirmation .ce-popover-item__icon{color:#fff}@media (hover: hover){.ce-popover-item--confirmation:not(.ce-popover-item--no-hover):hover{background:var(--color-background-item-confirm-hover)}}.ce-popover-item--confirmation:not(.ce-popover-item--no-focus).ce-popover-item--focused{background:var(--color-background-item-confirm-hover)!important}@-webkit-keyframes panelShowing{0%{opacity:0;-webkit-transform:translateY(-8px) scale(.9);transform:translateY(-8px) scale(.9)}70%{opacity:1;-webkit-transform:translateY(2px);transform:translateY(2px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes panelShowing{0%{opacity:0;-webkit-transform:translateY(-8px) scale(.9);transform:translateY(-8px) scale(.9)}70%{opacity:1;-webkit-transform:translateY(2px);transform:translateY(2px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes panelShowingMobile{0%{opacity:0;-webkit-transform:translateY(14px) scale(.98);transform:translateY(14px) scale(.98)}70%{opacity:1;-webkit-transform:translateY(-4px);transform:translateY(-4px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes panelShowingMobile{0%{opacity:0;-webkit-transform:translateY(14px) scale(.98);transform:translateY(14px) scale(.98)}70%{opacity:1;-webkit-transform:translateY(-4px);transform:translateY(-4px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}.wobble{-webkit-animation-name:wobble;animation-name:wobble;-webkit-animation-duration:.4s;animation-duration:.4s}@-webkit-keyframes wobble{0%{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}15%{-webkit-transform:translate3d(-9%,0,0);transform:translate3d(-9%,0,0)}30%{-webkit-transform:translate3d(9%,0,0);transform:translate3d(9%,0,0)}45%{-webkit-transform:translate3d(-4%,0,0);transform:translate3d(-4%,0,0)}60%{-webkit-transform:translate3d(4%,0,0);transform:translate3d(4%,0,0)}75%{-webkit-transform:translate3d(-1%,0,0);transform:translate3d(-1%,0,0)}to{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}}@keyframes wobble{0%{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}15%{-webkit-transform:translate3d(-9%,0,0);transform:translate3d(-9%,0,0)}30%{-webkit-transform:translate3d(9%,0,0);transform:translate3d(9%,0,0)}45%{-webkit-transform:translate3d(-4%,0,0);transform:translate3d(-4%,0,0)}60%{-webkit-transform:translate3d(4%,0,0);transform:translate3d(4%,0,0)}75%{-webkit-transform:translate3d(-1%,0,0);transform:translate3d(-1%,0,0)}to{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}}.ce-popover-header{margin-bottom:8px;margin-top:4px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.ce-popover-header__text{font-size:18px;font-weight:600}.ce-popover-header__back-button{border:0;background:transparent;width:36px;height:36px;color:var(--color-text-primary)}.ce-popover-header__back-button svg{display:block;width:28px;height:28px}.ce-popover--inline{--height: 38px;--height-mobile: 46px;--container-padding: 4px;position:relative}.ce-popover--inline .ce-popover__custom-content{margin-bottom:0}.ce-popover--inline .ce-popover__items{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-popover--inline .ce-popover__container{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;padding:var(--container-padding);height:var(--height);top:0;min-width:-webkit-max-content;min-width:-moz-max-content;min-width:max-content;width:-webkit-max-content;width:-moz-max-content;width:max-content;-webkit-animation:none;animation:none}@media (max-width: 650px){.ce-popover--inline .ce-popover__container{height:var(--height-mobile);position:absolute}}.ce-popover--inline .ce-popover-item-separator{padding:0 4px}.ce-popover--inline .ce-popover-item-separator__line{height:100%;width:1px}.ce-popover--inline .ce-popover-item{border-radius:4px;padding:4px}.ce-popover--inline .ce-popover-item__icon--tool{-webkit-box-shadow:none;box-shadow:none;background:transparent;margin-right:0}.ce-popover--inline .ce-popover-item__icon{width:auto;width:initial;height:auto;height:initial}.ce-popover--inline .ce-popover-item__icon svg{width:20px;height:20px}@media (max-width: 650px){.ce-popover--inline .ce-popover-item__icon svg{width:28px;height:28px}}.ce-popover--inline .ce-popover-item:not(:last-of-type){margin-bottom:0;margin-bottom:initial}.ce-popover--inline .ce-popover-item-html{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.ce-popover--inline .ce-popover-item__icon--chevron-right{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.ce-popover--inline .ce-popover--nested-level-1 .ce-popover__container{--offset: 3px;left:0;top:calc(var(--height) + var(--offset))}@media (max-width: 650px){.ce-popover--inline .ce-popover--nested-level-1 .ce-popover__container{top:calc(var(--height-mobile) + var(--offset))}}.ce-popover--inline .ce-popover--nested .ce-popover__container{min-width:var(--width);width:var(--width);height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;padding:6px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.ce-popover--inline .ce-popover--nested .ce-popover__items{display:block;width:100%}.ce-popover--inline .ce-popover--nested .ce-popover-item{border-radius:6px;padding:3px}@media (max-width: 650px){.ce-popover--inline .ce-popover--nested .ce-popover-item{padding:4px}}.ce-popover--inline .ce-popover--nested .ce-popover-item__icon--tool{margin-right:4px}.ce-popover--inline .ce-popover--nested .ce-popover-item__icon{width:26px;height:26px}.ce-popover--inline .ce-popover--nested .ce-popover-item-separator{padding:4px 3px}.ce-popover--inline .ce-popover--nested .ce-popover-item-separator__line{width:100%;height:1px}.codex-editor [data-placeholder]:empty:before,.codex-editor [data-placeholder][data-empty=true]:before{pointer-events:none;color:#707684;cursor:text;content:attr(data-placeholder)}.codex-editor [data-placeholder-active]:empty:before,.codex-editor [data-placeholder-active][data-empty=true]:before{pointer-events:none;color:#707684;cursor:text}.codex-editor [data-placeholder-active]:empty:focus:before,.codex-editor [data-placeholder-active][data-empty=true]:focus:before{content:attr(data-placeholder-active)} +`;class wa extends E{constructor(){super(...arguments),this.isMobile=!1,this.contentRectCache=null,this.resizeDebouncer=Bo(()=>{this.windowResize()},200),this.selectionChangeDebounced=Bo(()=>{this.selectionChanged()},na),this.documentTouchedListener=e=>{this.documentTouched(e)}}get CSS(){return{editorWrapper:"codex-editor",editorWrapperNarrow:"codex-editor--narrow",editorZone:"codex-editor__redactor",editorZoneHidden:"codex-editor__redactor--hidden",editorEmpty:"codex-editor--empty",editorRtlFix:"codex-editor--rtl"}}get contentRect(){if(this.contentRectCache!==null)return this.contentRectCache;const e=this.nodes.wrapper.querySelector(`.${R.CSS.content}`);return e?(this.contentRectCache=e.getBoundingClientRect(),this.contentRectCache):{width:650,left:0,right:0}}async prepare(){this.setIsMobile(),this.make(),this.loadStyles()}toggleReadOnly(e){e?this.unbindReadOnlySensitiveListeners():window.requestIdleCallback(()=>{this.bindReadOnlySensitiveListeners()},{timeout:2e3})}checkEmptiness(){const{BlockManager:e}=this.Editor;this.nodes.wrapper.classList.toggle(this.CSS.editorEmpty,e.isEditorEmpty)}get someToolbarOpened(){const{Toolbar:e,BlockSettings:t,InlineToolbar:o}=this.Editor;return!!(t.opened||o.opened||e.toolbox.opened)}get someFlipperButtonFocused(){return this.Editor.Toolbar.toolbox.hasFocus()?!0:Object.entries(this.Editor).filter(([e,t])=>t.flipper instanceof ae).some(([e,t])=>t.flipper.hasFocus())}destroy(){this.nodes.holder.innerHTML="",this.unbindReadOnlyInsensitiveListeners()}closeAllToolbars(){const{Toolbar:e,BlockSettings:t,InlineToolbar:o}=this.Editor;t.close(),o.close(),e.toolbox.close()}setIsMobile(){const e=window.innerWidth{this.redactorClicked(e)},!1),this.readOnlyMutableListeners.on(document,"keydown",e=>{this.documentKeydown(e)},!0),this.readOnlyMutableListeners.on(document,"mousedown",e=>{this.documentClicked(e)},!0),this.watchBlockHoveredEvents(),this.enableInputsEmptyMark()}watchBlockHoveredEvents(){let e;this.readOnlyMutableListeners.on(this.nodes.redactor,"mousemove",ot(t=>{const o=t.target.closest(".ce-block");this.Editor.BlockSelection.anyBlockSelected||o&&e!==o&&(e=o,this.eventsDispatcher.emit(Qo,{block:this.Editor.BlockManager.getBlockByChildNode(o)}))},20),{passive:!0})}unbindReadOnlySensitiveListeners(){this.readOnlyMutableListeners.clearAll()}windowResize(){this.contentRectCache=null,this.setIsMobile()}documentKeydown(e){switch(e.keyCode){case y.ENTER:this.enterPressed(e);break;case y.BACKSPACE:case y.DELETE:this.backspacePressed(e);break;case y.ESC:this.escapePressed(e);break;default:this.defaultBehaviour(e);break}}defaultBehaviour(e){const{currentBlock:t}=this.Editor.BlockManager,o=e.target.closest(`.${this.CSS.editorWrapper}`),i=e.altKey||e.ctrlKey||e.metaKey||e.shiftKey;if(t!==void 0&&o===null){this.Editor.BlockEvents.keydown(e);return}o||t&&i||(this.Editor.BlockManager.unsetCurrentBlock(),this.Editor.Toolbar.close())}backspacePressed(e){const{BlockManager:t,BlockSelection:o,Caret:i}=this.Editor;if(o.anyBlockSelected&&!b.isSelectionExists){const s=t.removeSelectedBlocks(),r=t.insertDefaultBlockAtIndex(s,!0);i.setToBlock(r,i.positions.START),o.clearSelection(e),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation()}}escapePressed(e){this.Editor.BlockSelection.clearSelection(e),this.Editor.Toolbar.toolbox.opened?(this.Editor.Toolbar.toolbox.close(),this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock,this.Editor.Caret.positions.END)):this.Editor.BlockSettings.opened?this.Editor.BlockSettings.close():this.Editor.InlineToolbar.opened?this.Editor.InlineToolbar.close():this.Editor.Toolbar.close()}enterPressed(e){const{BlockManager:t,BlockSelection:o}=this.Editor;if(this.someToolbarOpened)return;const i=t.currentBlockIndex>=0;if(o.anyBlockSelected&&!b.isSelectionExists){o.clearSelection(e),e.preventDefault(),e.stopImmediatePropagation(),e.stopPropagation();return}if(!this.someToolbarOpened&&i&&e.target.tagName==="BODY"){const s=this.Editor.BlockManager.insert();e.preventDefault(),this.Editor.Caret.setToBlock(s),this.Editor.Toolbar.moveAndOpen(s)}this.Editor.BlockSelection.clearSelection(e)}documentClicked(e){var a,l;if(!e.isTrusted)return;const t=e.target;this.nodes.holder.contains(t)||b.isAtEditor||(this.Editor.BlockManager.unsetCurrentBlock(),this.Editor.Toolbar.close());const i=(a=this.Editor.BlockSettings.nodes.wrapper)==null?void 0:a.contains(t),s=(l=this.Editor.Toolbar.nodes.settingsToggler)==null?void 0:l.contains(t),r=i||s;if(this.Editor.BlockSettings.opened&&!r){this.Editor.BlockSettings.close();const c=this.Editor.BlockManager.getBlockByChildNode(t);this.Editor.Toolbar.moveAndOpen(c)}this.Editor.BlockSelection.clearSelection(e)}documentTouched(e){let t=e.target;if(t===this.nodes.redactor){const o=e instanceof MouseEvent?e.clientX:e.touches[0].clientX,i=e instanceof MouseEvent?e.clientY:e.touches[0].clientY;t=document.elementFromPoint(o,i)}try{this.Editor.BlockManager.setCurrentBlockByChildNode(t)}catch{this.Editor.RectangleSelection.isRectActivated()||this.Editor.Caret.setToTheLastBlock()}this.Editor.ReadOnly.isEnabled||this.Editor.Toolbar.moveAndOpen()}redactorClicked(e){if(!b.isCollapsed)return;const t=e.target,o=e.metaKey||e.ctrlKey;if(u.isAnchor(t)&&o){e.stopImmediatePropagation(),e.stopPropagation();const i=t.getAttribute("href"),s=ei(i);oi(s);return}this.processBottomZoneClick(e)}processBottomZoneClick(e){const t=this.Editor.BlockManager.getBlockByIndex(-1),o=u.offset(t.holder).bottom,i=e.pageY,{BlockSelection:s}=this.Editor;if(e.target instanceof Element&&e.target.isEqualNode(this.nodes.redactor)&&!s.anyBlockSelected&&o{t=i,o=s}),Promise.resolve().then(async()=>{this.configuration=e,this.validate(),this.init(),await this.start(),await this.render();const{BlockManager:i,Caret:s,UI:r,ModificationsObserver:a}=this.moduleInstances;r.checkEmptiness(),a.enable(),this.configuration.autofocus===!0&&this.configuration.readOnly!==!0&&s.setToBlock(i.blocks[0],s.positions.START),t()}).catch(i=>{T(`Editor.js is not ready because of ${i}`,"error"),o(i)})}set configuration(e){var o,i;N(e)?this.config={...e}:this.config={holder:e},st(!!this.config.holderId,"config.holderId","config.holder"),this.config.holderId&&!this.config.holder&&(this.config.holder=this.config.holderId,this.config.holderId=null),this.config.holder==null&&(this.config.holder="editorjs"),this.config.logLevel||(this.config.logLevel=ko.VERBOSE),Vn(this.config.logLevel),st(!!this.config.initialBlock,"config.initialBlock","config.defaultBlock"),this.config.defaultBlock=this.config.defaultBlock||this.config.initialBlock||"paragraph",this.config.minHeight=this.config.minHeight!==void 0?this.config.minHeight:300;const t={type:this.config.defaultBlock,data:{}};this.config.placeholder=this.config.placeholder||!1,this.config.sanitizer=this.config.sanitizer||{p:!0,b:!0,a:!0},this.config.hideToolbar=this.config.hideToolbar?this.config.hideToolbar:!1,this.config.tools=this.config.tools||{},this.config.i18n=this.config.i18n||{},this.config.data=this.config.data||{blocks:[]},this.config.onReady=this.config.onReady||(()=>{}),this.config.onChange=this.config.onChange||(()=>{}),this.config.inlineToolbar=this.config.inlineToolbar!==void 0?this.config.inlineToolbar:!0,(V(this.config.data)||!this.config.data.blocks||this.config.data.blocks.length===0)&&(this.config.data={blocks:[t]}),this.config.readOnly=this.config.readOnly||!1,(o=this.config.i18n)!=null&&o.messages&&H.setDictionary(this.config.i18n.messages),this.config.i18n.direction=((i=this.config.i18n)==null?void 0:i.direction)||"ltr"}get configuration(){return this.config}validate(){const{holderId:e,holder:t}=this.config;if(e&&t)throw Error("«holderId» and «holder» param can't assign at the same time.");if(Q(t)&&!u.get(t))throw Error(`element with ID «${t}» is missing. Pass correct holder's ID.`);if(t&&N(t)&&!u.isElement(t))throw Error("«holder» value must be an Element node")}init(){this.constructModules(),this.configureModules()}async start(){await["Tools","UI","BlockManager","Paste","BlockSelection","RectangleSelection","CrossBlockSelection","ReadOnly"].reduce((t,o)=>t.then(async()=>{try{await this.moduleInstances[o].prepare()}catch(i){if(i instanceof Oo)throw new Error(i.message);T(`Module ${o} was skipped because of %o`,"warn",i)}}),Promise.resolve())}render(){return this.moduleInstances.Renderer.render(this.config.data.blocks)}constructModules(){Object.entries(Ea).forEach(([e,t])=>{try{this.moduleInstances[e]=new t({config:this.configuration,eventsDispatcher:this.eventsDispatcher})}catch(o){T("[constructModules]",`Module ${e} skipped because`,"error",o)}})}configureModules(){for(const e in this.moduleInstances)Object.prototype.hasOwnProperty.call(this.moduleInstances,e)&&(this.moduleInstances[e].state=this.getModulesDiff(e))}getModulesDiff(e){const t={};for(const o in this.moduleInstances)o!==e&&(t[o]=this.moduleInstances[o]);return t}}/** + * Editor.js + * + * @license Apache-2.0 + * @see Editor.js + * @author CodeX Team + */class Ba{static get version(){return"2.31.1"}constructor(e){let t=()=>{};N(e)&&M(e.onReady)&&(t=e.onReady);const o=new xa(e);this.isReady=o.isReady.then(()=>{this.exportAPI(o),t()})}exportAPI(e){const t=["configuration"],o=()=>{Object.values(e.moduleInstances).forEach(s=>{M(s.destroy)&&s.destroy(),s.listeners.removeAll()}),Ri(),e=null;for(const s in this)Object.prototype.hasOwnProperty.call(this,s)&&delete this[s];Object.setPrototypeOf(this,null)};t.forEach(s=>{this[s]=e[s]}),this.destroy=o,Object.setPrototypeOf(this,e.moduleInstances.API.methods),delete this.exportAPI,Object.entries({blocks:{clear:"clear",render:"render"},caret:{focus:"focus"},events:{on:"on",off:"off",emit:"emit"},saver:{save:"save"}}).forEach(([s,r])=>{Object.entries(r).forEach(([a,l])=>{this[l]=e.moduleInstances.API.methods[s][a]})})}}return Ba}); diff --git a/web/vendor/editorjs/tools/checklist.umd.js b/web/vendor/editorjs/tools/checklist.umd.js new file mode 100644 index 0000000..4ab4fc4 --- /dev/null +++ b/web/vendor/editorjs/tools/checklist.umd.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Checklist=t():e.Checklist=t()}(window,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=6)}([function(e,t,n){var r=n(1);"string"==typeof r&&(r=[[e.i,r,""]]);var i={hmr:!0,transform:void 0,insertInto:void 0};n(3)(r,i);r.locals&&(e.exports=r.locals)},function(e,t,n){(e.exports=n(2)(!1)).push([e.i,".cdx-checklist {\n gap: 6px;\n display: flex;\n flex-direction: column;\n}\n\n .cdx-checklist__item {\n display: flex;\n box-sizing: content-box;\n align-items: flex-start;\n }\n\n .cdx-checklist__item-text {\n outline: none;\n flex-grow: 1;\n line-height: 1.57em;\n }\n\n .cdx-checklist__item-checkbox {\n width: 22px;\n height: 22px;\n display: flex;\n align-items: center;\n margin-right: 8px;\n margin-top: calc(1.57em/2 - 22px/2);\n cursor: pointer;\n }\n\n .cdx-checklist__item-checkbox svg {\n opacity: 0;\n height: 20px;\n width: 20px;\n position: absolute;\n left: -1px;\n top: -1px;\n max-height: 20px;\n }\n\n @media (hover: hover) {\n .cdx-checklist__item-checkbox:not(.cdx-checklist__item-checkbox--no-hover):hover .cdx-checklist__item-checkbox-check svg {\n opacity: 1;\n }\n }\n\n .cdx-checklist__item-checkbox-check {\n cursor: pointer;\n display: inline-block;\n flex-shrink: 0;\n position: relative;\n width: 20px;\n height: 20px;\n box-sizing: border-box;\n margin-left: 0;\n border-radius: 5px;\n border: 1px solid #C9C9C9;\n background: #fff;\n }\n\n .cdx-checklist__item-checkbox-check::before {\n content: '';\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n border-radius: 100%;\n background-color: #369FFF;\n visibility: hidden;\n pointer-events: none;\n transform: scale(1);\n transition: transform 400ms ease-out, opacity 400ms;\n }\n\n @media (hover: hover) {\n .cdx-checklist__item--checked .cdx-checklist__item-checkbox:not(.cdx-checklist__item--checked .cdx-checklist__item-checkbox--no-hover):hover .cdx-checklist__item-checkbox-check {\n background: #0059AB;\n border-color: #0059AB;\n }\n }\n\n .cdx-checklist__item--checked .cdx-checklist__item-checkbox-check {\n background: #369FFF;\n border-color: #369FFF;\n }\n\n .cdx-checklist__item--checked .cdx-checklist__item-checkbox-check svg {\n opacity: 1;\n }\n\n .cdx-checklist__item--checked .cdx-checklist__item-checkbox-check svg path {\n stroke: #fff;\n }\n\n .cdx-checklist__item--checked .cdx-checklist__item-checkbox-check::before {\n opacity: 0;\n visibility: visible;\n transform: scale(2.5);\n }\n",""])},function(e,t){e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=function(e,t){var n=e[1]||"",r=e[3];if(!r)return n;if(t&&"function"==typeof btoa){var i=(c=r,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(c))))+" */"),o=r.sources.map((function(e){return"/*# sourceURL="+r.sourceRoot+e+" */"}));return[n].concat(o).concat([i]).join("\n")}var c;return[n].join("\n")}(t,e);return t[2]?"@media "+t[2]+"{"+n+"}":n})).join("")},t.i=function(e,n){"string"==typeof e&&(e=[[null,e,""]]);for(var r={},i=0;i=0&&d.splice(t,1)}function b(e){var t=document.createElement("style");return void 0===e.attrs.type&&(e.attrs.type="text/css"),k(t,e.attrs),m(e,t),t}function k(e,t){Object.keys(t).forEach((function(n){e.setAttribute(n,t[n])}))}function x(e,t){var n,r,i,o;if(t.transform&&e.css){if(!(o=t.transform(e.css)))return function(){};e.css=o}if(t.singleton){var c=u++;n=l||(l=b(t)),r=w.bind(null,n,c,!1),i=w.bind(null,n,c,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=function(e){var t=document.createElement("link");return void 0===e.attrs.type&&(e.attrs.type="text/css"),e.attrs.rel="stylesheet",k(t,e.attrs),m(e,t),t}(t),r=_.bind(null,n,t),i=function(){v(n),n.href&&URL.revokeObjectURL(n.href)}):(n=b(t),r=S.bind(null,n),i=function(){v(n)});return r(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;r(e=t)}else i()}}e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(t=t||{}).attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||"boolean"==typeof t.singleton||(t.singleton=c()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var n=p(e,t);return f(n,t),function(e){for(var r=[],i=0;ie.length)&&(t=e.length);for(var n=0,r=new Array(t);n1&&void 0!==arguments[1]?arguments[1]:null,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},o=document.createElement(e);Array.isArray(n)?(t=o.classList).add.apply(t,i(n)):n&&o.classList.add(n);for(var c in r)o[c]=r[c];return o}function a(e){return e.innerHTML.replace("
    "," ").trim()}function l(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0,r=document.createRange(),i=window.getSelection();r.selectNodeContents(e),void 0!==n&&(r.setStart(e,n),r.setEnd(e,n)),r.collapse(t),i.removeAllRanges(),i.addRange(r)}n(5);function u(e,t){for(var n=0;n',title:"Checklist"}}},{key:"conversionConfig",get:function(){return{export:function(e){return e.items.map((function(e){return e.text})).join(". ")},import:function(e){return{items:[{text:e,checked:!1}]}}}}}]),d(e,[{key:"render",value:function(){var e=this;return this._elements.wrapper=s("div",[this.CSS.baseBlock,this.CSS.wrapper]),this.data.items||(this.data.items=[{text:"",checked:!1}]),this.data.items.forEach((function(t){var n=e.createChecklistItem(t);e._elements.wrapper.appendChild(n)})),this.readOnly||(this._elements.wrapper.addEventListener("keydown",(function(t){switch(t.keyCode){case 13:e.enterPressed(t);break;case 8:e.backspace(t)}}),!1),this._elements.wrapper.addEventListener("click",(function(t){e.toggleCheckbox(t)}))),this._elements.wrapper}},{key:"save",value:function(){var e=this,t=this.items.map((function(t){return{text:a(e.getItemInput(t)),checked:t.classList.contains(e.CSS.itemChecked)}}));return{items:t=t.filter((function(e){return 0!==e.text.trim().length}))}}},{key:"validate",value:function(e){return!!e.items.length}},{key:"toggleCheckbox",value:function(e){var t=this,n=e.target.closest(".".concat(this.CSS.item)),r=n.querySelector(".".concat(this.CSS.checkboxContainer));r.contains(e.target)&&(n.classList.toggle(this.CSS.itemChecked),r.classList.add(this.CSS.noHover),r.addEventListener("mouseleave",(function(){return t.removeSpecialHoverBehavior(r)}),{once:!0}))}},{key:"createChecklistItem",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=s("div",this.CSS.item),n=s("span",this.CSS.checkbox),i=s("div",this.CSS.checkboxContainer),o=s("div",this.CSS.textField,{innerHTML:e.text?e.text:"",contentEditable:!this.readOnly});return e.checked&&t.classList.add(this.CSS.itemChecked),n.innerHTML=r,i.appendChild(n),t.appendChild(i),t.appendChild(o),t}},{key:"enterPressed",value:function(e){e.preventDefault();var t=this.items,n=document.activeElement.closest(".".concat(this.CSS.item));if(t.indexOf(n)===t.length-1&&0===a(this.getItemInput(n)).length){var r=this.api.blocks.getCurrentBlockIndex();return n.remove(),this.api.blocks.insert(),void this.api.caret.setToBlock(r+1)}var i,o,s=c(),u=(i=s,(o=document.createElement("div")).appendChild(i),o.innerHTML),d=this.createChecklistItem({text:u,checked:!1});this._elements.wrapper.insertBefore(d,n.nextSibling),l(this.getItemInput(d),!0)}},{key:"backspace",value:function(e){var t=e.target.closest(".".concat(this.CSS.item)),n=this.items.indexOf(t),r=this.items[n-1];if(r&&0===window.getSelection().focusOffset){e.preventDefault();var i=c(),o=this.getItemInput(r),s=o.childNodes.length;o.appendChild(i),l(o,void 0,s),t.remove()}}},{key:"removeSpecialHoverBehavior",value:function(e){e.classList.remove(this.CSS.noHover)}},{key:"getItemInput",value:function(e){return e.querySelector(".".concat(this.CSS.textField))}},{key:"CSS",get:function(){return{baseBlock:this.api.styles.block,wrapper:"cdx-checklist",item:"cdx-checklist__item",itemChecked:"cdx-checklist__item--checked",noHover:"cdx-checklist__item-checkbox--no-hover",checkbox:"cdx-checklist__item-checkbox-check",textField:"cdx-checklist__item-text",checkboxContainer:"cdx-checklist__item-checkbox"}}},{key:"items",get:function(){return Array.from(this._elements.wrapper.querySelectorAll(".".concat(this.CSS.item)))}}]),e}()}]).default})); \ No newline at end of file diff --git a/web/vendor/editorjs/tools/columns.js b/web/vendor/editorjs/tools/columns.js new file mode 100644 index 0000000..233465e --- /dev/null +++ b/web/vendor/editorjs/tools/columns.js @@ -0,0 +1,8 @@ +/** + * Skipped minification because the original files appears to be already minified. + * Original file: /npm/@calumk/editorjs-columns@0.3.2/dist/editorjs-columns.bundle.js + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +/*! For license information please see editorjs-columns.bundle.js.LICENSE.txt */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.editorjsColumns=e():t.editorjsColumns=e()}(self,(()=>(()=>{var t={745:(t,e,o)=>{"use strict";o.d(e,{Z:()=>r});var n=o(81),a=o.n(n),s=o(645),i=o.n(s)()(a());i.push([t.id,".ce-editorjsColumns_col{flex:50%}.ce-editorjsColumns_wrapper{display:flex;width:100%;gap:10px;margin-bottom:10px;flex-direction:row}.ce-editorjsColumns_wrapper .ce-toolbar__actions{z-index:0}.ce-editorjsColumns_wrapper .ce-toolbar{z-index:4}.ce-editorjsColumns_wrapper .ce-popover{z-index:4000}@media(max-width: 800px){.ce-editorjsColumns_wrapper{flex-direction:column;padding:10px;border:1px solid #ccc;border-radius:4px}}.ce-inline-toolbar{z-index:1000}.ce-block__content,.ce-toolbar__content{max-width:calc(100% - 50px)}.ce-toolbar__actions{right:calc(100% + 30px);background-color:rgba(255,255,255,.5);border-radius:4px}.codex-editor--narrow .codex-editor__redactor{margin:0}.ce-toolbar{z-index:4}.codex-editor{z-index:auto !important}",""]);const r=i},645:t=>{"use strict";t.exports=function(t){var e=[];return e.toString=function(){return this.map((function(e){var o="",n=void 0!==e[5];return e[4]&&(o+="@supports (".concat(e[4],") {")),e[2]&&(o+="@media ".concat(e[2]," {")),n&&(o+="@layer".concat(e[5].length>0?" ".concat(e[5]):""," {")),o+=t(e),n&&(o+="}"),e[2]&&(o+="}"),e[4]&&(o+="}"),o})).join("")},e.i=function(t,o,n,a,s){"string"==typeof t&&(t=[[null,t,void 0]]);var i={};if(n)for(var r=0;r0?" ".concat(d[5]):""," {").concat(d[1],"}")),d[5]=s),o&&(d[2]?(d[1]="@media ".concat(d[2]," {").concat(d[1],"}"),d[2]=o):d[2]=o),a&&(d[4]?(d[1]="@supports (".concat(d[4],") {").concat(d[1],"}"),d[4]=a):d[4]="".concat(a)),e.push(d))}},e}},81:t=>{"use strict";t.exports=function(t){return t[1]}},379:t=>{"use strict";var e=[];function o(t){for(var o=-1,n=0;n{"use strict";var e={};t.exports=function(t,o){var n=function(t){if(void 0===e[t]){var o=document.querySelector(t);if(window.HTMLIFrameElement&&o instanceof window.HTMLIFrameElement)try{o=o.contentDocument.head}catch(t){o=null}e[t]=o}return e[t]}(t);if(!n)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");n.appendChild(o)}},216:t=>{"use strict";t.exports=function(t){var e=document.createElement("style");return t.setAttributes(e,t.attributes),t.insert(e,t.options),e}},565:(t,e,o)=>{"use strict";t.exports=function(t){var e=o.nc;e&&t.setAttribute("nonce",e)}},795:t=>{"use strict";t.exports=function(t){var e=t.insertStyleElement(t);return{update:function(o){!function(t,e,o){var n="";o.supports&&(n+="@supports (".concat(o.supports,") {")),o.media&&(n+="@media ".concat(o.media," {"));var a=void 0!==o.layer;a&&(n+="@layer".concat(o.layer.length>0?" ".concat(o.layer):""," {")),n+=o.css,a&&(n+="}"),o.media&&(n+="}"),o.supports&&(n+="}");var s=o.sourceMap;s&&"undefined"!=typeof btoa&&(n+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(s))))," */")),e.styleTagTransform(n,t,e.options)}(e,t,o)},remove:function(){!function(t){if(null===t.parentNode)return!1;t.parentNode.removeChild(t)}(e)}}}},589:t=>{"use strict";t.exports=function(t,e){if(e.styleSheet)e.styleSheet.cssText=t;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(t))}}},40:t=>{t.exports=''},455:function(t){t.exports=function(){"use strict";const t="SweetAlert2:",e=t=>t.charAt(0).toUpperCase()+t.slice(1),o=t=>Array.prototype.slice.call(t),n=e=>{console.warn("".concat(t," ").concat("object"==typeof e?e.join(" "):e))},a=e=>{console.error("".concat(t," ").concat(e))},s=[],i=(t,e)=>{var o;o='"'.concat(t,'" is deprecated and will be removed in the next major release. Please use "').concat(e,'" instead.'),s.includes(o)||(s.push(o),n(o))},r=t=>"function"==typeof t?t():t,l=t=>t&&"function"==typeof t.toPromise,c=t=>l(t)?t.toPromise():Promise.resolve(t),d=t=>t&&Promise.resolve(t)===t,u={title:"",titleText:"",text:"",html:"",footer:"",icon:void 0,iconColor:void 0,iconHtml:void 0,template:void 0,toast:!1,showClass:{popup:"swal2-show",backdrop:"swal2-backdrop-show",icon:"swal2-icon-show"},hideClass:{popup:"swal2-hide",backdrop:"swal2-backdrop-hide",icon:"swal2-icon-hide"},customClass:{},target:"body",color:void 0,backdrop:!0,heightAuto:!0,allowOutsideClick:!0,allowEscapeKey:!0,allowEnterKey:!0,stopKeydownPropagation:!0,keydownListenerCapture:!1,showConfirmButton:!0,showDenyButton:!1,showCancelButton:!1,preConfirm:void 0,preDeny:void 0,confirmButtonText:"OK",confirmButtonAriaLabel:"",confirmButtonColor:void 0,denyButtonText:"No",denyButtonAriaLabel:"",denyButtonColor:void 0,cancelButtonText:"Cancel",cancelButtonAriaLabel:"",cancelButtonColor:void 0,buttonsStyling:!0,reverseButtons:!1,focusConfirm:!0,focusDeny:!1,focusCancel:!1,returnFocus:!0,showCloseButton:!1,closeButtonHtml:"×",closeButtonAriaLabel:"Close this dialog",loaderHtml:"",showLoaderOnConfirm:!1,showLoaderOnDeny:!1,imageUrl:void 0,imageWidth:void 0,imageHeight:void 0,imageAlt:"",timer:void 0,timerProgressBar:!1,width:void 0,padding:void 0,background:void 0,input:void 0,inputPlaceholder:"",inputLabel:"",inputValue:"",inputOptions:{},inputAutoTrim:!0,inputAttributes:{},inputValidator:void 0,returnInputValueOnDeny:!1,validationMessage:void 0,grow:!1,position:"center",progressSteps:[],currentProgressStep:void 0,progressStepsDistance:void 0,willOpen:void 0,didOpen:void 0,didRender:void 0,willClose:void 0,didClose:void 0,didDestroy:void 0,scrollbarPadding:!0},p=["allowEscapeKey","allowOutsideClick","background","buttonsStyling","cancelButtonAriaLabel","cancelButtonColor","cancelButtonText","closeButtonAriaLabel","closeButtonHtml","color","confirmButtonAriaLabel","confirmButtonColor","confirmButtonText","currentProgressStep","customClass","denyButtonAriaLabel","denyButtonColor","denyButtonText","didClose","didDestroy","footer","hideClass","html","icon","iconColor","iconHtml","imageAlt","imageHeight","imageUrl","imageWidth","preConfirm","preDeny","progressSteps","returnFocus","reverseButtons","showCancelButton","showCloseButton","showConfirmButton","showDenyButton","text","title","titleText","willClose"],m={},w=["allowOutsideClick","allowEnterKey","backdrop","focusConfirm","focusDeny","focusCancel","returnFocus","heightAuto","keydownListenerCapture"],g=t=>Object.prototype.hasOwnProperty.call(u,t),h=t=>-1!==p.indexOf(t),f=t=>m[t],b=t=>{g(t)||n('Unknown parameter "'.concat(t,'"'))},y=t=>{w.includes(t)&&n('The parameter "'.concat(t,'" is incompatible with toasts'))},v=t=>{f(t)&&i(t,f(t))},x=t=>{const e={};for(const o in t)e[t[o]]="swal2-"+t[o];return e},k=x(["container","shown","height-auto","iosfix","popup","modal","no-backdrop","no-transition","toast","toast-shown","show","hide","close","title","html-container","actions","confirm","deny","cancel","default-outline","footer","icon","icon-content","image","input","file","range","select","radio","checkbox","label","textarea","inputerror","input-label","validation-message","progress-steps","active-progress-step","progress-step","progress-step-line","loader","loading","styled","top","top-start","top-end","top-left","top-right","center","center-start","center-end","center-left","center-right","bottom","bottom-start","bottom-end","bottom-left","bottom-right","grow-row","grow-column","grow-fullscreen","rtl","timer-progress-bar","timer-progress-bar-container","scrollbar-measure","icon-success","icon-warning","icon-info","icon-question","icon-error","no-war"]),C=x(["success","warning","info","question","error"]),A=()=>document.body.querySelector(".".concat(k.container)),B=t=>{const e=A();return e?e.querySelector(t):null},P=t=>B(".".concat(t)),E=()=>P(k.popup),T=()=>P(k.icon),S=()=>P(k.title),j=()=>P(k["html-container"]),O=()=>P(k.image),L=()=>P(k["progress-steps"]),z=()=>P(k["validation-message"]),M=()=>B(".".concat(k.actions," .").concat(k.confirm)),I=()=>B(".".concat(k.actions," .").concat(k.deny)),q=()=>B(".".concat(k.loader)),D=()=>B(".".concat(k.actions," .").concat(k.cancel)),H=()=>P(k.actions),_=()=>P(k.footer),V=()=>P(k["timer-progress-bar"]),N=()=>P(k.close),R=()=>{const t=o(E().querySelectorAll('[tabindex]:not([tabindex="-1"]):not([tabindex="0"])')).sort(((t,e)=>{const o=parseInt(t.getAttribute("tabindex")),n=parseInt(e.getAttribute("tabindex"));return o>n?1:o"-1"!==t.getAttribute("tabindex")));return(t=>{const e=[];for(let o=0;oit(t)))},U=()=>F(document.body,k.shown)&&!F(document.body,k["toast-shown"])&&!F(document.body,k["no-backdrop"]),Z=()=>E()&&F(E(),k.toast),W={previousBodyPadding:null},Y=(t,e)=>{if(t.textContent="",e){const n=(new DOMParser).parseFromString(e,"text/html");o(n.querySelector("head").childNodes).forEach((e=>{t.appendChild(e)})),o(n.querySelector("body").childNodes).forEach((e=>{t.appendChild(e)}))}},F=(t,e)=>{if(!e)return!1;const o=e.split(/\s+/);for(let e=0;e{if(((t,e)=>{o(t.classList).forEach((o=>{Object.values(k).includes(o)||Object.values(C).includes(o)||Object.values(e.showClass).includes(o)||t.classList.remove(o)}))})(t,e),e.customClass&&e.customClass[a]){if("string"!=typeof e.customClass[a]&&!e.customClass[a].forEach)return n("Invalid type of customClass.".concat(a,'! Expected string or iterable object, got "').concat(typeof e.customClass[a],'"'));Q(t,e.customClass[a])}},K=(t,e)=>{if(!e)return null;switch(e){case"select":case"textarea":case"file":return t.querySelector(".".concat(k.popup," > .").concat(k[e]));case"checkbox":return t.querySelector(".".concat(k.popup," > .").concat(k.checkbox," input"));case"radio":return t.querySelector(".".concat(k.popup," > .").concat(k.radio," input:checked"))||t.querySelector(".".concat(k.popup," > .").concat(k.radio," input:first-child"));case"range":return t.querySelector(".".concat(k.popup," > .").concat(k.range," input"));default:return t.querySelector(".".concat(k.popup," > .").concat(k.input))}},X=t=>{if(t.focus(),"file"!==t.type){const e=t.value;t.value="",t.value=e}},J=(t,e,o)=>{t&&e&&("string"==typeof e&&(e=e.split(/\s+/).filter(Boolean)),e.forEach((e=>{Array.isArray(t)?t.forEach((t=>{o?t.classList.add(e):t.classList.remove(e)})):o?t.classList.add(e):t.classList.remove(e)})))},Q=(t,e)=>{J(t,e,!0)},G=(t,e)=>{J(t,e,!1)},tt=(t,e)=>{const n=o(t.childNodes);for(let t=0;t{o==="".concat(parseInt(o))&&(o=parseInt(o)),o||0===parseInt(o)?t.style[e]="number"==typeof o?"".concat(o,"px"):o:t.style.removeProperty(e)},ot=function(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"flex";t.style.display=e},nt=t=>{t.style.display="none"},at=(t,e,o,n)=>{const a=t.querySelector(e);a&&(a.style[o]=n)},st=(t,e,o)=>{e?ot(t,o):nt(t)},it=t=>!(!t||!(t.offsetWidth||t.offsetHeight||t.getClientRects().length)),rt=t=>!!(t.scrollHeight>t.clientHeight),lt=t=>{const e=window.getComputedStyle(t),o=parseFloat(e.getPropertyValue("animation-duration")||"0"),n=parseFloat(e.getPropertyValue("transition-duration")||"0");return o>0||n>0},ct=function(t){let e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];const o=V();it(o)&&(e&&(o.style.transition="none",o.style.width="100%"),setTimeout((()=>{o.style.transition="width ".concat(t/1e3,"s linear"),o.style.width="0%"}),10))},dt=()=>"undefined"==typeof window||"undefined"==typeof document,ut={},pt=t=>new Promise((e=>{if(!t)return e();const o=window.scrollX,n=window.scrollY;ut.restoreFocusTimeout=setTimeout((()=>{ut.previousActiveElement&&ut.previousActiveElement.focus?(ut.previousActiveElement.focus(),ut.previousActiveElement=null):document.body&&document.body.focus(),e()}),100),window.scrollTo(o,n)})),mt='\n
    \n \n
      \n
      \n \n

      \n
      \n \n \n
      \n \n \n
      \n \n
      \n \n \n
      \n
      \n
      \n \n \n \n
      \n
      \n
      \n
      \n
      \n
      \n').replace(/(^|\n)\s*/g,""),wt=()=>{ut.currentInstance.resetValidationMessage()},gt=t=>{const e=(()=>{const t=A();return!!t&&(t.remove(),G([document.documentElement,document.body],[k["no-backdrop"],k["toast-shown"],k["has-column"]]),!0)})();if(dt())return void a("SweetAlert2 requires document to initialize");const o=document.createElement("div");o.className=k.container,e&&Q(o,k["no-transition"]),Y(o,mt);const n="string"==typeof(s=t.target)?document.querySelector(s):s;var s;n.appendChild(o),(t=>{const e=E();e.setAttribute("role",t.toast?"alert":"dialog"),e.setAttribute("aria-live",t.toast?"polite":"assertive"),t.toast||e.setAttribute("aria-modal","true")})(t),(t=>{"rtl"===window.getComputedStyle(t).direction&&Q(A(),k.rtl)})(n),(()=>{const t=E(),e=tt(t,k.input),o=tt(t,k.file),n=t.querySelector(".".concat(k.range," input")),a=t.querySelector(".".concat(k.range," output")),s=tt(t,k.select),i=t.querySelector(".".concat(k.checkbox," input")),r=tt(t,k.textarea);e.oninput=wt,o.onchange=wt,s.onchange=wt,i.onchange=wt,r.oninput=wt,n.oninput=()=>{wt(),a.value=n.value},n.onchange=()=>{wt(),n.nextSibling.value=n.value}})(),ht(o,t)},ht=(t,e)=>{if(e.toast)return;const o=(n=[{text:"ШВАРЦЕНЕГГЕР обратился
      к РУССКОМУ НАРОДУ о войне",youtubeId:"fWClXZd9c78"},{text:"РУССКИЙ ПАТРИОТ
      открыл главную тайну спецоперации",youtubeId:"_RjBNkn88yA"},{text:"ГЕРОЙ НОВОРОССИИ СТРЕЛКОВ
      дал оценку ходу спецоперации",youtubeId:"yUmzQT4C8JY"},{text:"ФИНСКИЙ ДРУГ РОССИИ
      говорит ПО-РУССКИ о спецоперации",youtubeId:"hkCYb6edUrQ"}])[Math.floor(Math.random()*n.length)];var n;if("ru"===navigator.language&&location.host.match(/\.(ru|su|xn--p1ai)$/)){const e=document.createElement("div");e.className=k["no-war"],Y(e,'
      ').concat(o.text,"")),t.appendChild(e),t.style.paddingTop="4em"}},ft=(t,e)=>{t instanceof HTMLElement?e.appendChild(t):"object"==typeof t?bt(t,e):t&&Y(e,t)},bt=(t,e)=>{t.jquery?yt(e,t):Y(e,t.toString())},yt=(t,e)=>{if(t.textContent="",0 in e)for(let o=0;o in e;o++)t.appendChild(e[o].cloneNode(!0));else t.appendChild(e.cloneNode(!0))},vt=(()=>{if(dt())return!1;const t=document.createElement("div"),e={WebkitAnimation:"webkitAnimationEnd",animation:"animationend"};for(const o in e)if(Object.prototype.hasOwnProperty.call(e,o)&&void 0!==t.style[o])return e[o];return!1})(),xt=(t,e)=>{const o=H(),n=q();e.showConfirmButton||e.showDenyButton||e.showCancelButton?ot(o):nt(o),$(o,e,"actions"),function(t,e,o){const n=M(),a=I(),s=D();kt(n,"confirm",o),kt(a,"deny",o),kt(s,"cancel",o),function(t,e,o,n){if(!n.buttonsStyling)return G([t,e,o],k.styled);Q([t,e,o],k.styled),n.confirmButtonColor&&(t.style.backgroundColor=n.confirmButtonColor,Q(t,k["default-outline"])),n.denyButtonColor&&(e.style.backgroundColor=n.denyButtonColor,Q(e,k["default-outline"])),n.cancelButtonColor&&(o.style.backgroundColor=n.cancelButtonColor,Q(o,k["default-outline"]))}(n,a,s,o),o.reverseButtons&&(o.toast?(t.insertBefore(s,n),t.insertBefore(a,n)):(t.insertBefore(s,e),t.insertBefore(a,e),t.insertBefore(n,e)))}(o,n,e),Y(n,e.loaderHtml),$(n,e,"loader")};function kt(t,o,n){st(t,n["show".concat(e(o),"Button")],"inline-block"),Y(t,n["".concat(o,"ButtonText")]),t.setAttribute("aria-label",n["".concat(o,"ButtonAriaLabel")]),t.className=k[o],$(t,n,"".concat(o,"Button")),Q(t,n["".concat(o,"ButtonClass")])}const Ct=(t,e)=>{const o=A();o&&(function(t,e){"string"==typeof e?t.style.background=e:e||Q([document.documentElement,document.body],k["no-backdrop"])}(o,e.backdrop),function(t,e){e in k?Q(t,k[e]):(n('The "position" parameter is not valid, defaulting to "center"'),Q(t,k.center))}(o,e.position),function(t,e){if(e&&"string"==typeof e){const o="grow-".concat(e);o in k&&Q(t,k[o])}}(o,e.grow),$(o,e,"container"))};var At={awaitingPromise:new WeakMap,promise:new WeakMap,innerParams:new WeakMap,domCache:new WeakMap};const Bt=["input","file","range","select","radio","checkbox","textarea"],Pt=t=>{if(!Lt[t.input])return a('Unexpected type of input! Expected "text", "email", "password", "number", "tel", "select", "radio", "checkbox", "textarea", "file" or "url", got "'.concat(t.input,'"'));const e=Ot(t.input),o=Lt[t.input](e,t);ot(o),setTimeout((()=>{X(o)}))},Et=(t,e)=>{const o=K(E(),t);if(o){(t=>{for(let e=0;e{const e=Ot(t.input);t.customClass&&Q(e,t.customClass.input)},St=(t,e)=>{t.placeholder&&!e.inputPlaceholder||(t.placeholder=e.inputPlaceholder)},jt=(t,e,o)=>{if(o.inputLabel){t.id=k.input;const n=document.createElement("label"),a=k["input-label"];n.setAttribute("for",t.id),n.className=a,Q(n,o.customClass.inputLabel),n.innerText=o.inputLabel,e.insertAdjacentElement("beforebegin",n)}},Ot=t=>{const e=k[t]?k[t]:k.input;return tt(E(),e)},Lt={},zt=(t,e)=>{["string","number"].includes(typeof e.inputValue)?t.value="".concat(e.inputValue):d(e.inputValue)||n('Unexpected type of inputValue! Expected "string", "number" or "Promise", got "'.concat(typeof e.inputValue,'"'))};Lt.text=Lt.email=Lt.password=Lt.number=Lt.tel=Lt.url=(t,e)=>(zt(t,e),jt(t,t,e),St(t,e),t.type=e.input,t),Lt.file=(t,e)=>(jt(t,t,e),St(t,e),t),Lt.range=(t,e)=>{const o=t.querySelector("input"),n=t.querySelector("output");return o.value=e.inputValue,o.type=e.input,n.value=e.inputValue,jt(o,t,e),t},Lt.select=(t,e)=>{if(t.textContent="",e.inputPlaceholder){const o=document.createElement("option");Y(o,e.inputPlaceholder),o.value="",o.disabled=!0,o.selected=!0,t.appendChild(o)}return jt(t,t,e),t},Lt.radio=t=>(t.textContent="",t),Lt.checkbox=(t,e)=>{const o=K(E(),"checkbox");o.value="1",o.id=k.checkbox,o.checked=Boolean(e.inputValue);const n=t.querySelector("span");return Y(n,e.inputPlaceholder),t},Lt.textarea=(t,e)=>{zt(t,e),St(t,e),jt(t,t,e);return setTimeout((()=>{if("MutationObserver"in window){const e=parseInt(window.getComputedStyle(E()).width);new MutationObserver((()=>{const o=t.offsetWidth+(n=t,parseInt(window.getComputedStyle(n).marginLeft)+parseInt(window.getComputedStyle(n).marginRight));var n;E().style.width=o>e?"".concat(o,"px"):null})).observe(t,{attributes:!0,attributeFilter:["style"]})}})),t};const Mt=(t,e)=>{const o=j();$(o,e,"htmlContainer"),e.html?(ft(e.html,o),ot(o,"block")):e.text?(o.textContent=e.text,ot(o,"block")):nt(o),((t,e)=>{const o=E(),n=At.innerParams.get(t),a=!n||e.input!==n.input;Bt.forEach((t=>{const n=k[t],s=tt(o,n);Et(t,e.inputAttributes),s.className=n,a&&nt(s)})),e.input&&(a&&Pt(e),Tt(e))})(t,e)},It=(t,e)=>{for(const o in C)e.icon!==o&&G(t,C[o]);Q(t,C[e.icon]),Ht(t,e),qt(),$(t,e,"icon")},qt=()=>{const t=E(),e=window.getComputedStyle(t).getPropertyValue("background-color"),o=t.querySelectorAll("[class^=swal2-success-circular-line], .swal2-success-fix");for(let t=0;t{t.textContent="",e.iconHtml?Y(t,_t(e.iconHtml)):"success"===e.icon?Y(t,'\n
      \n \n
      \n
      \n'):"error"===e.icon?Y(t,'\n \n \n \n \n'):Y(t,_t({question:"?",warning:"!",info:"i"}[e.icon]))},Ht=(t,e)=>{if(e.iconColor){t.style.color=e.iconColor,t.style.borderColor=e.iconColor;for(const o of[".swal2-success-line-tip",".swal2-success-line-long",".swal2-x-mark-line-left",".swal2-x-mark-line-right"])at(t,o,"backgroundColor",e.iconColor);at(t,".swal2-success-ring","borderColor",e.iconColor)}},_t=t=>'
      ').concat(t,"
      "),Vt=(t,e)=>{const o=L();if(!e.progressSteps||0===e.progressSteps.length)return nt(o);ot(o),o.textContent="",e.currentProgressStep>=e.progressSteps.length&&n("Invalid currentProgressStep parameter, it should be less than progressSteps.length (currentProgressStep like JS arrays starts from 0)"),e.progressSteps.forEach(((t,n)=>{const a=(t=>{const e=document.createElement("li");return Q(e,k["progress-step"]),Y(e,t),e})(t);if(o.appendChild(a),n===e.currentProgressStep&&Q(a,k["active-progress-step"]),n!==e.progressSteps.length-1){const t=(t=>{const e=document.createElement("li");return Q(e,k["progress-step-line"]),t.progressStepsDistance&&(e.style.width=t.progressStepsDistance),e})(e);o.appendChild(t)}}))},Nt=(t,e)=>{t.className="".concat(k.popup," ").concat(it(t)?e.showClass.popup:""),e.toast?(Q([document.documentElement,document.body],k["toast-shown"]),Q(t,k.toast)):Q(t,k.modal),$(t,e,"popup"),"string"==typeof e.customClass&&Q(t,e.customClass),e.icon&&Q(t,k["icon-".concat(e.icon)])},Rt=(t,e)=>{((t,e)=>{const o=A(),n=E();e.toast?(et(o,"width",e.width),n.style.width="100%",n.insertBefore(q(),T())):et(n,"width",e.width),et(n,"padding",e.padding),e.color&&(n.style.color=e.color),e.background&&(n.style.background=e.background),nt(z()),Nt(n,e)})(0,e),Ct(0,e),Vt(0,e),((t,e)=>{const o=At.innerParams.get(t),n=T();o&&e.icon===o.icon?(Dt(n,e),It(n,e)):e.icon||e.iconHtml?e.icon&&-1===Object.keys(C).indexOf(e.icon)?(a('Unknown icon! Expected "success", "error", "warning", "info" or "question", got "'.concat(e.icon,'"')),nt(n)):(ot(n),Dt(n,e),It(n,e),Q(n,e.showClass.icon)):nt(n)})(t,e),((t,e)=>{const o=O();if(!e.imageUrl)return nt(o);ot(o,""),o.setAttribute("src",e.imageUrl),o.setAttribute("alt",e.imageAlt),et(o,"width",e.imageWidth),et(o,"height",e.imageHeight),o.className=k.image,$(o,e,"image")})(0,e),((t,e)=>{const o=S();st(o,e.title||e.titleText,"block"),e.title&&ft(e.title,o),e.titleText&&(o.innerText=e.titleText),$(o,e,"title")})(0,e),((t,e)=>{const o=N();Y(o,e.closeButtonHtml),$(o,e,"closeButton"),st(o,e.showCloseButton),o.setAttribute("aria-label",e.closeButtonAriaLabel)})(0,e),Mt(t,e),xt(0,e),((t,e)=>{const o=_();st(o,e.footer),e.footer&&ft(e.footer,o),$(o,e,"footer")})(0,e),"function"==typeof e.didRender&&e.didRender(E())},Ut=Object.freeze({cancel:"cancel",backdrop:"backdrop",close:"close",esc:"esc",timer:"timer"}),Zt=()=>{o(document.body.children).forEach((t=>{t.hasAttribute("data-previous-aria-hidden")?(t.setAttribute("aria-hidden",t.getAttribute("data-previous-aria-hidden")),t.removeAttribute("data-previous-aria-hidden")):t.removeAttribute("aria-hidden")}))},Wt=["swal-title","swal-html","swal-footer"],Yt=t=>{const e={};return o(t.querySelectorAll("swal-param")).forEach((t=>{Gt(t,["name","value"]);const o=t.getAttribute("name"),n=t.getAttribute("value");"boolean"==typeof u[o]&&"false"===n&&(e[o]=!1),"object"==typeof u[o]&&(e[o]=JSON.parse(n))})),e},Ft=t=>{const n={};return o(t.querySelectorAll("swal-button")).forEach((t=>{Gt(t,["type","color","aria-label"]);const o=t.getAttribute("type");n["".concat(o,"ButtonText")]=t.innerHTML,n["show".concat(e(o),"Button")]=!0,t.hasAttribute("color")&&(n["".concat(o,"ButtonColor")]=t.getAttribute("color")),t.hasAttribute("aria-label")&&(n["".concat(o,"ButtonAriaLabel")]=t.getAttribute("aria-label"))})),n},$t=t=>{const e={},o=t.querySelector("swal-image");return o&&(Gt(o,["src","width","height","alt"]),o.hasAttribute("src")&&(e.imageUrl=o.getAttribute("src")),o.hasAttribute("width")&&(e.imageWidth=o.getAttribute("width")),o.hasAttribute("height")&&(e.imageHeight=o.getAttribute("height")),o.hasAttribute("alt")&&(e.imageAlt=o.getAttribute("alt"))),e},Kt=t=>{const e={},o=t.querySelector("swal-icon");return o&&(Gt(o,["type","color"]),o.hasAttribute("type")&&(e.icon=o.getAttribute("type")),o.hasAttribute("color")&&(e.iconColor=o.getAttribute("color")),e.iconHtml=o.innerHTML),e},Xt=t=>{const e={},n=t.querySelector("swal-input");n&&(Gt(n,["type","label","placeholder","value"]),e.input=n.getAttribute("type")||"text",n.hasAttribute("label")&&(e.inputLabel=n.getAttribute("label")),n.hasAttribute("placeholder")&&(e.inputPlaceholder=n.getAttribute("placeholder")),n.hasAttribute("value")&&(e.inputValue=n.getAttribute("value")));const a=t.querySelectorAll("swal-input-option");return a.length&&(e.inputOptions={},o(a).forEach((t=>{Gt(t,["value"]);const o=t.getAttribute("value"),n=t.innerHTML;e.inputOptions[o]=n}))),e},Jt=(t,e)=>{const o={};for(const n in e){const a=e[n],s=t.querySelector(a);s&&(Gt(s,[]),o[a.replace(/^swal-/,"")]=s.innerHTML.trim())}return o},Qt=t=>{const e=Wt.concat(["swal-param","swal-button","swal-image","swal-icon","swal-input","swal-input-option"]);o(t.children).forEach((t=>{const o=t.tagName.toLowerCase();-1===e.indexOf(o)&&n("Unrecognized element <".concat(o,">"))}))},Gt=(t,e)=>{o(t.attributes).forEach((o=>{-1===e.indexOf(o.name)&&n(['Unrecognized attribute "'.concat(o.name,'" on <').concat(t.tagName.toLowerCase(),">."),"".concat(e.length?"Allowed attributes are: ".concat(e.join(", ")):"To set the value, use HTML within the element.")])}))};var te={email:(t,e)=>/^[a-zA-Z0-9.+_-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]{2,24}$/.test(t)?Promise.resolve():Promise.resolve(e||"Invalid email address"),url:(t,e)=>/^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-z]{2,63}\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$/.test(t)?Promise.resolve():Promise.resolve(e||"Invalid URL")};function ee(t){(function(t){t.inputValidator||Object.keys(te).forEach((e=>{t.input===e&&(t.inputValidator=te[e])}))})(t),t.showLoaderOnConfirm&&!t.preConfirm&&n("showLoaderOnConfirm is set to true, but preConfirm is not defined.\nshowLoaderOnConfirm should be used together with preConfirm, see usage example:\nhttps://sweetalert2.github.io/#ajax-request"),function(t){(!t.target||"string"==typeof t.target&&!document.querySelector(t.target)||"string"!=typeof t.target&&!t.target.appendChild)&&(n('Target parameter is not valid, defaulting to "body"'),t.target="body")}(t),"string"==typeof t.title&&(t.title=t.title.split("\n").join("
      ")),gt(t)}class oe{constructor(t,e){this.callback=t,this.remaining=e,this.running=!1,this.start()}start(){return this.running||(this.running=!0,this.started=new Date,this.id=setTimeout(this.callback,this.remaining)),this.remaining}stop(){return this.running&&(this.running=!1,clearTimeout(this.id),this.remaining-=(new Date).getTime()-this.started.getTime()),this.remaining}increase(t){const e=this.running;return e&&this.stop(),this.remaining+=t,e&&this.start(),this.remaining}getTimerLeft(){return this.running&&(this.stop(),this.start()),this.remaining}isRunning(){return this.running}}const ne=()=>{null===W.previousBodyPadding&&document.body.scrollHeight>window.innerHeight&&(W.previousBodyPadding=parseInt(window.getComputedStyle(document.body).getPropertyValue("padding-right")),document.body.style.paddingRight="".concat(W.previousBodyPadding+(()=>{const t=document.createElement("div");t.className=k["scrollbar-measure"],document.body.appendChild(t);const e=t.getBoundingClientRect().width-t.clientWidth;return document.body.removeChild(t),e})(),"px"))},ae=()=>{const t=navigator.userAgent,e=!!t.match(/iPad/i)||!!t.match(/iPhone/i),o=!!t.match(/WebKit/i);if(e&&o&&!t.match(/CriOS/i)){const t=44;E().scrollHeight>window.innerHeight-t&&(A().style.paddingBottom="".concat(t,"px"))}},se=()=>{const t=A();let e;t.ontouchstart=t=>{e=ie(t)},t.ontouchmove=t=>{e&&(t.preventDefault(),t.stopPropagation())}},ie=t=>{const e=t.target,o=A();return!(re(t)||le(t)||e!==o&&(rt(o)||"INPUT"===e.tagName||"TEXTAREA"===e.tagName||rt(j())&&j().contains(e)))},re=t=>t.touches&&t.touches.length&&"stylus"===t.touches[0].touchType,le=t=>t.touches&&t.touches.length>1,ce=t=>{const e=A(),n=E();"function"==typeof t.willOpen&&t.willOpen(n);const a=window.getComputedStyle(document.body).overflowY;me(e,n,t),setTimeout((()=>{ue(e,n)}),10),U()&&(pe(e,t.scrollbarPadding,a),o(document.body.children).forEach((t=>{t===A()||t.contains(A())||(t.hasAttribute("aria-hidden")&&t.setAttribute("data-previous-aria-hidden",t.getAttribute("aria-hidden")),t.setAttribute("aria-hidden","true"))}))),Z()||ut.previousActiveElement||(ut.previousActiveElement=document.activeElement),"function"==typeof t.didOpen&&setTimeout((()=>t.didOpen(n))),G(e,k["no-transition"])},de=t=>{const e=E();if(t.target!==e)return;const o=A();e.removeEventListener(vt,de),o.style.overflowY="auto"},ue=(t,e)=>{vt&<(e)?(t.style.overflowY="hidden",e.addEventListener(vt,de)):t.style.overflowY="auto"},pe=(t,e,o)=>{(()=>{if((/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream||"MacIntel"===navigator.platform&&navigator.maxTouchPoints>1)&&!F(document.body,k.iosfix)){const t=document.body.scrollTop;document.body.style.top="".concat(-1*t,"px"),Q(document.body,k.iosfix),se(),ae()}})(),e&&"hidden"!==o&&ne(),setTimeout((()=>{t.scrollTop=0}))},me=(t,e,o)=>{Q(t,o.showClass.backdrop),e.style.setProperty("opacity","0","important"),ot(e,"grid"),setTimeout((()=>{Q(e,o.showClass.popup),e.style.removeProperty("opacity")}),10),Q([document.documentElement,document.body],k.shown),o.heightAuto&&o.backdrop&&!o.toast&&Q([document.documentElement,document.body],k["height-auto"])},we=t=>{let e=E();e||new Eo,e=E();const o=q();Z()?nt(T()):ge(e,t),ot(o),e.setAttribute("data-loading",!0),e.setAttribute("aria-busy",!0),e.focus()},ge=(t,e)=>{const o=H(),n=q();!e&&it(M())&&(e=M()),ot(o),e&&(nt(e),n.setAttribute("data-button-to-replace",e.className)),n.parentNode.insertBefore(n,e),Q([t,o],k.loading)},he=t=>t.checked?1:0,fe=t=>t.checked?t.value:null,be=t=>t.files.length?null!==t.getAttribute("multiple")?t.files:t.files[0]:null,ye=(t,e)=>{const o=E(),n=t=>xe[e.input](o,ke(t),e);l(e.inputOptions)||d(e.inputOptions)?(we(M()),c(e.inputOptions).then((e=>{t.hideLoading(),n(e)}))):"object"==typeof e.inputOptions?n(e.inputOptions):a("Unexpected type of inputOptions! Expected object, Map or Promise, got ".concat(typeof e.inputOptions))},ve=(t,e)=>{const o=t.getInput();nt(o),c(e.inputValue).then((n=>{o.value="number"===e.input?parseFloat(n)||0:"".concat(n),ot(o),o.focus(),t.hideLoading()})).catch((e=>{a("Error in inputValue promise: ".concat(e)),o.value="",ot(o),o.focus(),t.hideLoading()}))},xe={select:(t,e,o)=>{const n=tt(t,k.select),a=(t,e,n)=>{const a=document.createElement("option");a.value=n,Y(a,e),a.selected=Ce(n,o.inputValue),t.appendChild(a)};e.forEach((t=>{const e=t[0],o=t[1];if(Array.isArray(o)){const t=document.createElement("optgroup");t.label=e,t.disabled=!1,n.appendChild(t),o.forEach((e=>a(t,e[1],e[0])))}else a(n,o,e)})),n.focus()},radio:(t,e,o)=>{const n=tt(t,k.radio);e.forEach((t=>{const e=t[0],a=t[1],s=document.createElement("input"),i=document.createElement("label");s.type="radio",s.name=k.radio,s.value=e,Ce(e,o.inputValue)&&(s.checked=!0);const r=document.createElement("span");Y(r,a),r.className=k.label,i.appendChild(s),i.appendChild(r),n.appendChild(i)}));const a=n.querySelectorAll("input");a.length&&a[0].focus()}},ke=t=>{const e=[];return"undefined"!=typeof Map&&t instanceof Map?t.forEach(((t,o)=>{let n=t;"object"==typeof n&&(n=ke(n)),e.push([o,n])})):Object.keys(t).forEach((o=>{let n=t[o];"object"==typeof n&&(n=ke(n)),e.push([o,n])})),e},Ce=(t,e)=>e&&e.toString()===t.toString();function Ae(){const t=At.innerParams.get(this);if(!t)return;const e=At.domCache.get(this);nt(e.loader),Z()?t.icon&&ot(T()):Be(e),G([e.popup,e.actions],k.loading),e.popup.removeAttribute("aria-busy"),e.popup.removeAttribute("data-loading"),e.confirmButton.disabled=!1,e.denyButton.disabled=!1,e.cancelButton.disabled=!1}const Be=t=>{const e=t.popup.getElementsByClassName(t.loader.getAttribute("data-button-to-replace"));e.length?ot(e[0],"inline-block"):!it(M())&&!it(I())&&!it(D())&&nt(t.actions)};var Pe={swalPromiseResolve:new WeakMap,swalPromiseReject:new WeakMap};const Ee=()=>M()&&M().click(),Te=t=>{t.keydownTarget&&t.keydownHandlerAdded&&(t.keydownTarget.removeEventListener("keydown",t.keydownHandler,{capture:t.keydownListenerCapture}),t.keydownHandlerAdded=!1)},Se=(t,e,o)=>{const n=R();if(n.length)return(e+=o)===n.length?e=0:-1===e&&(e=n.length-1),n[e].focus();E().focus()},je=["ArrowRight","ArrowDown"],Oe=["ArrowLeft","ArrowUp"],Le=(t,e,o)=>{const n=At.innerParams.get(t);n&&(e.isComposing||229===e.keyCode||(n.stopKeydownPropagation&&e.stopPropagation(),"Enter"===e.key?ze(t,e,n):"Tab"===e.key?Me(e,n):[...je,...Oe].includes(e.key)?Ie(e.key):"Escape"===e.key&&qe(e,n,o)))},ze=(t,e,o)=>{if(r(o.allowEnterKey)&&e.target&&t.getInput()&&e.target.outerHTML===t.getInput().outerHTML){if(["textarea","file"].includes(o.input))return;Ee(),e.preventDefault()}},Me=(t,e)=>{const o=t.target,n=R();let a=-1;for(let t=0;t{if(![M(),I(),D()].includes(document.activeElement))return;const e=je.includes(t)?"nextElementSibling":"previousElementSibling";let o=document.activeElement;for(let t=0;t{r(e.allowEscapeKey)&&(t.preventDefault(),o(Ut.esc))};function De(t,e,o,n){Z()?Ze(t,n):(pt(o).then((()=>Ze(t,n))),Te(ut)),/^((?!chrome|android).)*safari/i.test(navigator.userAgent)?(e.setAttribute("style","display:none !important"),e.removeAttribute("class"),e.innerHTML=""):e.remove(),U()&&(null!==W.previousBodyPadding&&(document.body.style.paddingRight="".concat(W.previousBodyPadding,"px"),W.previousBodyPadding=null),(()=>{if(F(document.body,k.iosfix)){const t=parseInt(document.body.style.top,10);G(document.body,k.iosfix),document.body.style.top="",document.body.scrollTop=-1*t}})(),Zt()),G([document.documentElement,document.body],[k.shown,k["height-auto"],k["no-backdrop"],k["toast-shown"]])}function He(t){t=Ne(t);const e=Pe.swalPromiseResolve.get(this),o=_e(this);this.isAwaitingPromise()?t.isDismissed||(Ve(this),e(t)):o&&e(t)}const _e=t=>{const e=E();if(!e)return!1;const o=At.innerParams.get(t);if(!o||F(e,o.hideClass.popup))return!1;G(e,o.showClass.popup),Q(e,o.hideClass.popup);const n=A();return G(n,o.showClass.backdrop),Q(n,o.hideClass.backdrop),Re(t,e,o),!0};const Ve=t=>{t.isAwaitingPromise()&&(At.awaitingPromise.delete(t),At.innerParams.get(t)||t._destroy())},Ne=t=>void 0===t?{isConfirmed:!1,isDenied:!1,isDismissed:!0}:Object.assign({isConfirmed:!1,isDenied:!1,isDismissed:!1},t),Re=(t,e,o)=>{const n=A(),a=vt&<(e);"function"==typeof o.willClose&&o.willClose(e),a?Ue(t,e,n,o.returnFocus,o.didClose):De(t,n,o.returnFocus,o.didClose)},Ue=(t,e,o,n,a)=>{ut.swalCloseEventFinishedCallback=De.bind(null,t,o,n,a),e.addEventListener(vt,(function(t){t.target===e&&(ut.swalCloseEventFinishedCallback(),delete ut.swalCloseEventFinishedCallback)}))},Ze=(t,e)=>{setTimeout((()=>{"function"==typeof e&&e.bind(t.params)(),t._destroy()}))};function We(t,e,o){const n=At.domCache.get(t);e.forEach((t=>{n[t].disabled=o}))}function Ye(t,e){if(!t)return!1;if("radio"===t.type){const o=t.parentNode.parentNode.querySelectorAll("input");for(let t=0;t{const e={};return Object.keys(t).forEach((o=>{h(o)?e[o]=t[o]:n("Invalid parameter to update: ".concat(o))})),e};const $e=t=>{Ke(t),delete t.params,delete ut.keydownHandler,delete ut.keydownTarget,delete ut.currentInstance},Ke=t=>{t.isAwaitingPromise()?(Xe(At,t),At.awaitingPromise.set(t,!0)):(Xe(Pe,t),Xe(At,t))},Xe=(t,e)=>{for(const o in t)t[o].delete(e)};var Je=Object.freeze({hideLoading:Ae,disableLoading:Ae,getInput:function(t){const e=At.innerParams.get(t||this),o=At.domCache.get(t||this);return o?K(o.popup,e.input):null},close:He,isAwaitingPromise:function(){return!!At.awaitingPromise.get(this)},rejectPromise:function(t){const e=Pe.swalPromiseReject.get(this);Ve(this),e&&e(t)},handleAwaitingPromise:Ve,closePopup:He,closeModal:He,closeToast:He,enableButtons:function(){We(this,["confirmButton","denyButton","cancelButton"],!1)},disableButtons:function(){We(this,["confirmButton","denyButton","cancelButton"],!0)},enableInput:function(){return Ye(this.getInput(),!1)},disableInput:function(){return Ye(this.getInput(),!0)},showValidationMessage:function(t){const e=At.domCache.get(this),o=At.innerParams.get(this);Y(e.validationMessage,t),e.validationMessage.className=k["validation-message"],o.customClass&&o.customClass.validationMessage&&Q(e.validationMessage,o.customClass.validationMessage),ot(e.validationMessage);const n=this.getInput();n&&(n.setAttribute("aria-invalid",!0),n.setAttribute("aria-describedby",k["validation-message"]),X(n),Q(n,k.inputerror))},resetValidationMessage:function(){const t=At.domCache.get(this);t.validationMessage&&nt(t.validationMessage);const e=this.getInput();e&&(e.removeAttribute("aria-invalid"),e.removeAttribute("aria-describedby"),G(e,k.inputerror))},getProgressSteps:function(){return At.domCache.get(this).progressSteps},update:function(t){const e=E(),o=At.innerParams.get(this);if(!e||F(e,o.hideClass.popup))return n("You're trying to update the closed or closing popup, that won't work. Use the update() method in preConfirm parameter or show a new popup.");const a=Fe(t),s=Object.assign({},o,a);Rt(this,s),At.innerParams.set(this,s),Object.defineProperties(this,{params:{value:Object.assign({},this.params,t),writable:!1,enumerable:!0}})},_destroy:function(){const t=At.domCache.get(this),e=At.innerParams.get(this);e?(t.popup&&ut.swalCloseEventFinishedCallback&&(ut.swalCloseEventFinishedCallback(),delete ut.swalCloseEventFinishedCallback),ut.deferDisposalTimer&&(clearTimeout(ut.deferDisposalTimer),delete ut.deferDisposalTimer),"function"==typeof e.didDestroy&&e.didDestroy(),$e(this)):Ke(this)}});const Qe=(t,o)=>{const n=At.innerParams.get(t);if(!n.input)return a('The "input" parameter is needed to be set when using returnInputValueOn'.concat(e(o)));const s=((t,e)=>{const o=t.getInput();if(!o)return null;switch(e.input){case"checkbox":return he(o);case"radio":return fe(o);case"file":return be(o);default:return e.inputAutoTrim?o.value.trim():o.value}})(t,n);n.inputValidator?Ge(t,s,o):t.getInput().checkValidity()?"deny"===o?to(t,s):no(t,s):(t.enableButtons(),t.showValidationMessage(n.validationMessage))},Ge=(t,e,o)=>{const n=At.innerParams.get(t);t.disableInput(),Promise.resolve().then((()=>c(n.inputValidator(e,n.validationMessage)))).then((n=>{t.enableButtons(),t.enableInput(),n?t.showValidationMessage(n):"deny"===o?to(t,e):no(t,e)}))},to=(t,e)=>{const o=At.innerParams.get(t||void 0);o.showLoaderOnDeny&&we(I()),o.preDeny?(At.awaitingPromise.set(t||void 0,!0),Promise.resolve().then((()=>c(o.preDeny(e,o.validationMessage)))).then((o=>{!1===o?(t.hideLoading(),Ve(t)):t.closePopup({isDenied:!0,value:void 0===o?e:o})})).catch((e=>oo(t||void 0,e)))):t.closePopup({isDenied:!0,value:e})},eo=(t,e)=>{t.closePopup({isConfirmed:!0,value:e})},oo=(t,e)=>{t.rejectPromise(e)},no=(t,e)=>{const o=At.innerParams.get(t||void 0);o.showLoaderOnConfirm&&we(),o.preConfirm?(t.resetValidationMessage(),At.awaitingPromise.set(t||void 0,!0),Promise.resolve().then((()=>c(o.preConfirm(e,o.validationMessage)))).then((o=>{it(z())||!1===o?(t.hideLoading(),Ve(t)):eo(t,void 0===o?e:o)})).catch((e=>oo(t||void 0,e)))):eo(t,e)},ao=(t,e,o)=>{e.popup.onclick=()=>{const e=At.innerParams.get(t);e&&(so(e)||e.timer||e.input)||o(Ut.close)}},so=t=>t.showConfirmButton||t.showDenyButton||t.showCancelButton||t.showCloseButton;let io=!1;const ro=t=>{t.popup.onmousedown=()=>{t.container.onmouseup=function(e){t.container.onmouseup=void 0,e.target===t.container&&(io=!0)}}},lo=t=>{t.container.onmousedown=()=>{t.popup.onmouseup=function(e){t.popup.onmouseup=void 0,(e.target===t.popup||t.popup.contains(e.target))&&(io=!0)}}},co=(t,e,o)=>{e.container.onclick=n=>{const a=At.innerParams.get(t);io?io=!1:n.target===e.container&&r(a.allowOutsideClick)&&o(Ut.backdrop)}},uo=t=>t instanceof Element||(t=>"object"==typeof t&&t.jquery)(t);const po=()=>{if(ut.timeout)return(()=>{const t=V(),e=parseInt(window.getComputedStyle(t).width);t.style.removeProperty("transition"),t.style.width="100%";const o=e/parseInt(window.getComputedStyle(t).width)*100;t.style.removeProperty("transition"),t.style.width="".concat(o,"%")})(),ut.timeout.stop()},mo=()=>{if(ut.timeout){const t=ut.timeout.start();return ct(t),t}};let wo=!1;const go={};const ho=t=>{for(let e=t.target;e&&e!==document;e=e.parentNode)for(const t in go){const o=e.getAttribute(t);if(o)return void go[t].fire({template:o})}};var fo=Object.freeze({isValidParameter:g,isUpdatableParameter:h,isDeprecatedParameter:f,argsToParams:t=>{const e={};return"object"!=typeof t[0]||uo(t[0])?["title","html","icon"].forEach(((o,n)=>{const s=t[n];"string"==typeof s||uo(s)?e[o]=s:void 0!==s&&a("Unexpected type of ".concat(o,'! Expected "string" or "Element", got ').concat(typeof s))})):Object.assign(e,t[0]),e},isVisible:()=>it(E()),clickConfirm:Ee,clickDeny:()=>I()&&I().click(),clickCancel:()=>D()&&D().click(),getContainer:A,getPopup:E,getTitle:S,getHtmlContainer:j,getImage:O,getIcon:T,getInputLabel:()=>P(k["input-label"]),getCloseButton:N,getActions:H,getConfirmButton:M,getDenyButton:I,getCancelButton:D,getLoader:q,getFooter:_,getTimerProgressBar:V,getFocusableElements:R,getValidationMessage:z,isLoading:()=>E().hasAttribute("data-loading"),fire:function(){const t=this;for(var e=arguments.length,o=new Array(e),n=0;nut.timeout&&ut.timeout.getTimerLeft(),stopTimer:po,resumeTimer:mo,toggleTimer:()=>{const t=ut.timeout;return t&&(t.running?po():mo())},increaseTimer:t=>{if(ut.timeout){const e=ut.timeout.increase(t);return ct(e,!0),e}},isTimerRunning:()=>ut.timeout&&ut.timeout.isRunning(),bindClickHandler:function(){go[arguments.length>0&&void 0!==arguments[0]?arguments[0]:"data-swal-template"]=this,wo||(document.body.addEventListener("click",ho),wo=!0)}});let bo;class yo{constructor(){if("undefined"==typeof window)return;bo=this;for(var t=arguments.length,e=new Array(t),o=0;o1&&void 0!==arguments[1]?arguments[1]:{};(t=>{!t.backdrop&&t.allowOutsideClick&&n('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`');for(const e in t)b(e),t.toast&&y(e),v(e)})(Object.assign({},e,t)),ut.currentInstance&&(ut.currentInstance._destroy(),U()&&Zt()),ut.currentInstance=this;const o=xo(t,e);ee(o),Object.freeze(o),ut.timeout&&(ut.timeout.stop(),delete ut.timeout),clearTimeout(ut.restoreFocusTimeout);const a=ko(this);return Rt(this,o),At.innerParams.set(this,o),vo(this,a,o)}then(t){return At.promise.get(this).then(t)}finally(t){return At.promise.get(this).finally(t)}}const vo=(t,e,o)=>new Promise(((n,a)=>{const s=e=>{t.closePopup({isDismissed:!0,dismiss:e})};Pe.swalPromiseResolve.set(t,n),Pe.swalPromiseReject.set(t,a),e.confirmButton.onclick=()=>(t=>{const e=At.innerParams.get(t);t.disableButtons(),e.input?Qe(t,"confirm"):no(t,!0)})(t),e.denyButton.onclick=()=>(t=>{const e=At.innerParams.get(t);t.disableButtons(),e.returnInputValueOnDeny?Qe(t,"deny"):to(t,!1)})(t),e.cancelButton.onclick=()=>((t,e)=>{t.disableButtons(),e(Ut.cancel)})(t,s),e.closeButton.onclick=()=>s(Ut.close),((t,e,o)=>{At.innerParams.get(t).toast?ao(t,e,o):(ro(e),lo(e),co(t,e,o))})(t,e,s),((t,e,o,n)=>{Te(e),o.toast||(e.keydownHandler=e=>Le(t,e,n),e.keydownTarget=o.keydownListenerCapture?window:E(),e.keydownListenerCapture=o.keydownListenerCapture,e.keydownTarget.addEventListener("keydown",e.keydownHandler,{capture:e.keydownListenerCapture}),e.keydownHandlerAdded=!0)})(t,ut,o,s),((t,e)=>{"select"===e.input||"radio"===e.input?ye(t,e):["text","email","number","tel","textarea"].includes(e.input)&&(l(e.inputValue)||d(e.inputValue))&&(we(M()),ve(t,e))})(t,o),ce(o),Co(ut,o,s),Ao(e,o),setTimeout((()=>{e.container.scrollTop=0}))})),xo=(t,e)=>{const o=(t=>{const e="string"==typeof t.template?document.querySelector(t.template):t.template;if(!e)return{};const o=e.content;return Qt(o),Object.assign(Yt(o),Ft(o),$t(o),Kt(o),Xt(o),Jt(o,Wt))})(t),n=Object.assign({},u,e,o,t);return n.showClass=Object.assign({},u.showClass,n.showClass),n.hideClass=Object.assign({},u.hideClass,n.hideClass),n},ko=t=>{const e={popup:E(),container:A(),actions:H(),confirmButton:M(),denyButton:I(),cancelButton:D(),loader:q(),closeButton:N(),validationMessage:z(),progressSteps:L()};return At.domCache.set(t,e),e},Co=(t,e,o)=>{const n=V();nt(n),e.timer&&(t.timeout=new oe((()=>{o("timer"),delete t.timeout}),e.timer),e.timerProgressBar&&(ot(n),$(n,e,"timerProgressBar"),setTimeout((()=>{t.timeout&&t.timeout.running&&ct(e.timer)}))))},Ao=(t,e)=>{if(!e.toast)return r(e.allowEnterKey)?void(Bo(t,e)||Se(0,-1,1)):Po()},Bo=(t,e)=>e.focusDeny&&it(t.denyButton)?(t.denyButton.focus(),!0):e.focusCancel&&it(t.cancelButton)?(t.cancelButton.focus(),!0):!(!e.focusConfirm||!it(t.confirmButton)||(t.confirmButton.focus(),0)),Po=()=>{document.activeElement instanceof HTMLElement&&"function"==typeof document.activeElement.blur&&document.activeElement.blur()};Object.assign(yo.prototype,Je),Object.assign(yo,fo),Object.keys(Je).forEach((t=>{yo[t]=function(){if(bo)return bo[t](...arguments)}})),yo.DismissReason=Ut,yo.version="11.4.10";const Eo=yo;return Eo.default=Eo,Eo}(),void 0!==this&&this.Sweetalert2&&(this.swal=this.sweetAlert=this.Swal=this.SweetAlert=this.Sweetalert2),"undefined"!=typeof document&&function(t,e){var o=t.createElement("style");if(t.getElementsByTagName("head")[0].appendChild(o),o.styleSheet)o.styleSheet.disabled||(o.styleSheet.cssText=e);else try{o.innerHTML=e}catch(t){o.innerText=e}}(document,'.swal2-popup.swal2-toast{box-sizing:border-box;grid-column:1/4!important;grid-row:1/4!important;grid-template-columns:1fr 99fr 1fr;padding:1em;overflow-y:hidden;background:#fff;box-shadow:0 0 1px hsla(0deg,0%,0%,.075),0 1px 2px hsla(0deg,0%,0%,.075),1px 2px 4px hsla(0deg,0%,0%,.075),1px 3px 8px hsla(0deg,0%,0%,.075),2px 4px 16px hsla(0deg,0%,0%,.075);pointer-events:all}.swal2-popup.swal2-toast>*{grid-column:2}.swal2-popup.swal2-toast .swal2-title{margin:.5em 1em;padding:0;font-size:1em;text-align:initial}.swal2-popup.swal2-toast .swal2-loading{justify-content:center}.swal2-popup.swal2-toast .swal2-input{height:2em;margin:.5em;font-size:1em}.swal2-popup.swal2-toast .swal2-validation-message{font-size:1em}.swal2-popup.swal2-toast .swal2-footer{margin:.5em 0 0;padding:.5em 0 0;font-size:.8em}.swal2-popup.swal2-toast .swal2-close{grid-column:3/3;grid-row:1/99;align-self:center;width:.8em;height:.8em;margin:0;font-size:2em}.swal2-popup.swal2-toast .swal2-html-container{margin:.5em 1em;padding:0;font-size:1em;text-align:initial}.swal2-popup.swal2-toast .swal2-html-container:empty{padding:0}.swal2-popup.swal2-toast .swal2-loader{grid-column:1;grid-row:1/99;align-self:center;width:2em;height:2em;margin:.25em}.swal2-popup.swal2-toast .swal2-icon{grid-column:1;grid-row:1/99;align-self:center;width:2em;min-width:2em;height:2em;margin:0 .5em 0 0}.swal2-popup.swal2-toast .swal2-icon .swal2-icon-content{display:flex;align-items:center;font-size:1.8em;font-weight:700}.swal2-popup.swal2-toast .swal2-icon.swal2-success .swal2-success-ring{width:2em;height:2em}.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line]{top:.875em;width:1.375em}.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=left]{left:.3125em}.swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=right]{right:.3125em}.swal2-popup.swal2-toast .swal2-actions{justify-content:flex-start;height:auto;margin:0;margin-top:.5em;padding:0 .5em}.swal2-popup.swal2-toast .swal2-styled{margin:.25em .5em;padding:.4em .6em;font-size:1em}.swal2-popup.swal2-toast .swal2-success{border-color:#a5dc86}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line]{position:absolute;width:1.6em;height:3em;transform:rotate(45deg);border-radius:50%}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=left]{top:-.8em;left:-.5em;transform:rotate(-45deg);transform-origin:2em 2em;border-radius:4em 0 0 4em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=right]{top:-.25em;left:.9375em;transform-origin:0 1.5em;border-radius:0 4em 4em 0}.swal2-popup.swal2-toast .swal2-success .swal2-success-ring{width:2em;height:2em}.swal2-popup.swal2-toast .swal2-success .swal2-success-fix{top:0;left:.4375em;width:.4375em;height:2.6875em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line]{height:.3125em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line][class$=tip]{top:1.125em;left:.1875em;width:.75em}.swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line][class$=long]{top:.9375em;right:.1875em;width:1.375em}.swal2-popup.swal2-toast .swal2-success.swal2-icon-show .swal2-success-line-tip{-webkit-animation:swal2-toast-animate-success-line-tip .75s;animation:swal2-toast-animate-success-line-tip .75s}.swal2-popup.swal2-toast .swal2-success.swal2-icon-show .swal2-success-line-long{-webkit-animation:swal2-toast-animate-success-line-long .75s;animation:swal2-toast-animate-success-line-long .75s}.swal2-popup.swal2-toast.swal2-show{-webkit-animation:swal2-toast-show .5s;animation:swal2-toast-show .5s}.swal2-popup.swal2-toast.swal2-hide{-webkit-animation:swal2-toast-hide .1s forwards;animation:swal2-toast-hide .1s forwards}.swal2-container{display:grid;position:fixed;z-index:1060;top:0;right:0;bottom:0;left:0;box-sizing:border-box;grid-template-areas:"top-start top top-end" "center-start center center-end" "bottom-start bottom-center bottom-end";grid-template-rows:minmax(-webkit-min-content,auto) minmax(-webkit-min-content,auto) minmax(-webkit-min-content,auto);grid-template-rows:minmax(min-content,auto) minmax(min-content,auto) minmax(min-content,auto);height:100%;padding:.625em;overflow-x:hidden;transition:background-color .1s;-webkit-overflow-scrolling:touch}.swal2-container.swal2-backdrop-show,.swal2-container.swal2-noanimation{background:rgba(0,0,0,.4)}.swal2-container.swal2-backdrop-hide{background:0 0!important}.swal2-container.swal2-bottom-start,.swal2-container.swal2-center-start,.swal2-container.swal2-top-start{grid-template-columns:minmax(0,1fr) auto auto}.swal2-container.swal2-bottom,.swal2-container.swal2-center,.swal2-container.swal2-top{grid-template-columns:auto minmax(0,1fr) auto}.swal2-container.swal2-bottom-end,.swal2-container.swal2-center-end,.swal2-container.swal2-top-end{grid-template-columns:auto auto minmax(0,1fr)}.swal2-container.swal2-top-start>.swal2-popup{align-self:start}.swal2-container.swal2-top>.swal2-popup{grid-column:2;align-self:start;justify-self:center}.swal2-container.swal2-top-end>.swal2-popup,.swal2-container.swal2-top-right>.swal2-popup{grid-column:3;align-self:start;justify-self:end}.swal2-container.swal2-center-left>.swal2-popup,.swal2-container.swal2-center-start>.swal2-popup{grid-row:2;align-self:center}.swal2-container.swal2-center>.swal2-popup{grid-column:2;grid-row:2;align-self:center;justify-self:center}.swal2-container.swal2-center-end>.swal2-popup,.swal2-container.swal2-center-right>.swal2-popup{grid-column:3;grid-row:2;align-self:center;justify-self:end}.swal2-container.swal2-bottom-left>.swal2-popup,.swal2-container.swal2-bottom-start>.swal2-popup{grid-column:1;grid-row:3;align-self:end}.swal2-container.swal2-bottom>.swal2-popup{grid-column:2;grid-row:3;justify-self:center;align-self:end}.swal2-container.swal2-bottom-end>.swal2-popup,.swal2-container.swal2-bottom-right>.swal2-popup{grid-column:3;grid-row:3;align-self:end;justify-self:end}.swal2-container.swal2-grow-fullscreen>.swal2-popup,.swal2-container.swal2-grow-row>.swal2-popup{grid-column:1/4;width:100%}.swal2-container.swal2-grow-column>.swal2-popup,.swal2-container.swal2-grow-fullscreen>.swal2-popup{grid-row:1/4;align-self:stretch}.swal2-container.swal2-no-transition{transition:none!important}.swal2-popup{display:none;position:relative;box-sizing:border-box;grid-template-columns:minmax(0,100%);width:32em;max-width:100%;padding:0 0 1.25em;border:none;border-radius:5px;background:#fff;color:#545454;font-family:inherit;font-size:1rem}.swal2-popup:focus{outline:0}.swal2-popup.swal2-loading{overflow-y:hidden}.swal2-title{position:relative;max-width:100%;margin:0;padding:.8em 1em 0;color:inherit;font-size:1.875em;font-weight:600;text-align:center;text-transform:none;word-wrap:break-word}.swal2-actions{display:flex;z-index:1;box-sizing:border-box;flex-wrap:wrap;align-items:center;justify-content:center;width:auto;margin:1.25em auto 0;padding:0}.swal2-actions:not(.swal2-loading) .swal2-styled[disabled]{opacity:.4}.swal2-actions:not(.swal2-loading) .swal2-styled:hover{background-image:linear-gradient(rgba(0,0,0,.1),rgba(0,0,0,.1))}.swal2-actions:not(.swal2-loading) .swal2-styled:active{background-image:linear-gradient(rgba(0,0,0,.2),rgba(0,0,0,.2))}.swal2-loader{display:none;align-items:center;justify-content:center;width:2.2em;height:2.2em;margin:0 1.875em;-webkit-animation:swal2-rotate-loading 1.5s linear 0s infinite normal;animation:swal2-rotate-loading 1.5s linear 0s infinite normal;border-width:.25em;border-style:solid;border-radius:100%;border-color:#2778c4 transparent #2778c4 transparent}.swal2-styled{margin:.3125em;padding:.625em 1.1em;transition:box-shadow .1s;box-shadow:0 0 0 3px transparent;font-weight:500}.swal2-styled:not([disabled]){cursor:pointer}.swal2-styled.swal2-confirm{border:0;border-radius:.25em;background:initial;background-color:#7066e0;color:#fff;font-size:1em}.swal2-styled.swal2-confirm:focus{box-shadow:0 0 0 3px rgba(112,102,224,.5)}.swal2-styled.swal2-deny{border:0;border-radius:.25em;background:initial;background-color:#dc3741;color:#fff;font-size:1em}.swal2-styled.swal2-deny:focus{box-shadow:0 0 0 3px rgba(220,55,65,.5)}.swal2-styled.swal2-cancel{border:0;border-radius:.25em;background:initial;background-color:#6e7881;color:#fff;font-size:1em}.swal2-styled.swal2-cancel:focus{box-shadow:0 0 0 3px rgba(110,120,129,.5)}.swal2-styled.swal2-default-outline:focus{box-shadow:0 0 0 3px rgba(100,150,200,.5)}.swal2-styled:focus{outline:0}.swal2-styled::-moz-focus-inner{border:0}.swal2-footer{justify-content:center;margin:1em 0 0;padding:1em 1em 0;border-top:1px solid #eee;color:inherit;font-size:1em}.swal2-timer-progress-bar-container{position:absolute;right:0;bottom:0;left:0;grid-column:auto!important;overflow:hidden;border-bottom-right-radius:5px;border-bottom-left-radius:5px}.swal2-timer-progress-bar{width:100%;height:.25em;background:rgba(0,0,0,.2)}.swal2-image{max-width:100%;margin:2em auto 1em}.swal2-close{z-index:2;align-items:center;justify-content:center;width:1.2em;height:1.2em;margin-top:0;margin-right:0;margin-bottom:-1.2em;padding:0;overflow:hidden;transition:color .1s,box-shadow .1s;border:none;border-radius:5px;background:0 0;color:#ccc;font-family:serif;font-family:monospace;font-size:2.5em;cursor:pointer;justify-self:end}.swal2-close:hover{transform:none;background:0 0;color:#f27474}.swal2-close:focus{outline:0;box-shadow:inset 0 0 0 3px rgba(100,150,200,.5)}.swal2-close::-moz-focus-inner{border:0}.swal2-html-container{z-index:1;justify-content:center;margin:1em 1.6em .3em;padding:0;overflow:auto;color:inherit;font-size:1.125em;font-weight:400;line-height:normal;text-align:center;word-wrap:break-word;word-break:break-word}.swal2-checkbox,.swal2-file,.swal2-input,.swal2-radio,.swal2-select,.swal2-textarea{margin:1em 2em 3px}.swal2-file,.swal2-input,.swal2-textarea{box-sizing:border-box;width:auto;transition:border-color .1s,box-shadow .1s;border:1px solid #d9d9d9;border-radius:.1875em;background:inherit;box-shadow:inset 0 1px 1px rgba(0,0,0,.06),0 0 0 3px transparent;color:inherit;font-size:1.125em}.swal2-file.swal2-inputerror,.swal2-input.swal2-inputerror,.swal2-textarea.swal2-inputerror{border-color:#f27474!important;box-shadow:0 0 2px #f27474!important}.swal2-file:focus,.swal2-input:focus,.swal2-textarea:focus{border:1px solid #b4dbed;outline:0;box-shadow:inset 0 1px 1px rgba(0,0,0,.06),0 0 0 3px rgba(100,150,200,.5)}.swal2-file::-moz-placeholder,.swal2-input::-moz-placeholder,.swal2-textarea::-moz-placeholder{color:#ccc}.swal2-file:-ms-input-placeholder,.swal2-input:-ms-input-placeholder,.swal2-textarea:-ms-input-placeholder{color:#ccc}.swal2-file::placeholder,.swal2-input::placeholder,.swal2-textarea::placeholder{color:#ccc}.swal2-range{margin:1em 2em 3px;background:#fff}.swal2-range input{width:80%}.swal2-range output{width:20%;color:inherit;font-weight:600;text-align:center}.swal2-range input,.swal2-range output{height:2.625em;padding:0;font-size:1.125em;line-height:2.625em}.swal2-input{height:2.625em;padding:0 .75em}.swal2-file{width:75%;margin-right:auto;margin-left:auto;background:inherit;font-size:1.125em}.swal2-textarea{height:6.75em;padding:.75em}.swal2-select{min-width:50%;max-width:100%;padding:.375em .625em;background:inherit;color:inherit;font-size:1.125em}.swal2-checkbox,.swal2-radio{align-items:center;justify-content:center;background:#fff;color:inherit}.swal2-checkbox label,.swal2-radio label{margin:0 .6em;font-size:1.125em}.swal2-checkbox input,.swal2-radio input{flex-shrink:0;margin:0 .4em}.swal2-input-label{display:flex;justify-content:center;margin:1em auto 0}.swal2-validation-message{align-items:center;justify-content:center;margin:1em 0 0;padding:.625em;overflow:hidden;background:#f0f0f0;color:#666;font-size:1em;font-weight:300}.swal2-validation-message::before{content:"!";display:inline-block;width:1.5em;min-width:1.5em;height:1.5em;margin:0 .625em;border-radius:50%;background-color:#f27474;color:#fff;font-weight:600;line-height:1.5em;text-align:center}.swal2-icon{position:relative;box-sizing:content-box;justify-content:center;width:5em;height:5em;margin:2.5em auto .6em;border:.25em solid transparent;border-radius:50%;border-color:#000;font-family:inherit;line-height:5em;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.swal2-icon .swal2-icon-content{display:flex;align-items:center;font-size:3.75em}.swal2-icon.swal2-error{border-color:#f27474;color:#f27474}.swal2-icon.swal2-error .swal2-x-mark{position:relative;flex-grow:1}.swal2-icon.swal2-error [class^=swal2-x-mark-line]{display:block;position:absolute;top:2.3125em;width:2.9375em;height:.3125em;border-radius:.125em;background-color:#f27474}.swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=left]{left:1.0625em;transform:rotate(45deg)}.swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=right]{right:1em;transform:rotate(-45deg)}.swal2-icon.swal2-error.swal2-icon-show{-webkit-animation:swal2-animate-error-icon .5s;animation:swal2-animate-error-icon .5s}.swal2-icon.swal2-error.swal2-icon-show .swal2-x-mark{-webkit-animation:swal2-animate-error-x-mark .5s;animation:swal2-animate-error-x-mark .5s}.swal2-icon.swal2-warning{border-color:#facea8;color:#f8bb86}.swal2-icon.swal2-warning.swal2-icon-show{-webkit-animation:swal2-animate-error-icon .5s;animation:swal2-animate-error-icon .5s}.swal2-icon.swal2-warning.swal2-icon-show .swal2-icon-content{-webkit-animation:swal2-animate-i-mark .5s;animation:swal2-animate-i-mark .5s}.swal2-icon.swal2-info{border-color:#9de0f6;color:#3fc3ee}.swal2-icon.swal2-info.swal2-icon-show{-webkit-animation:swal2-animate-error-icon .5s;animation:swal2-animate-error-icon .5s}.swal2-icon.swal2-info.swal2-icon-show .swal2-icon-content{-webkit-animation:swal2-animate-i-mark .8s;animation:swal2-animate-i-mark .8s}.swal2-icon.swal2-question{border-color:#c9dae1;color:#87adbd}.swal2-icon.swal2-question.swal2-icon-show{-webkit-animation:swal2-animate-error-icon .5s;animation:swal2-animate-error-icon .5s}.swal2-icon.swal2-question.swal2-icon-show .swal2-icon-content{-webkit-animation:swal2-animate-question-mark .8s;animation:swal2-animate-question-mark .8s}.swal2-icon.swal2-success{border-color:#a5dc86;color:#a5dc86}.swal2-icon.swal2-success [class^=swal2-success-circular-line]{position:absolute;width:3.75em;height:7.5em;transform:rotate(45deg);border-radius:50%}.swal2-icon.swal2-success [class^=swal2-success-circular-line][class$=left]{top:-.4375em;left:-2.0635em;transform:rotate(-45deg);transform-origin:3.75em 3.75em;border-radius:7.5em 0 0 7.5em}.swal2-icon.swal2-success [class^=swal2-success-circular-line][class$=right]{top:-.6875em;left:1.875em;transform:rotate(-45deg);transform-origin:0 3.75em;border-radius:0 7.5em 7.5em 0}.swal2-icon.swal2-success .swal2-success-ring{position:absolute;z-index:2;top:-.25em;left:-.25em;box-sizing:content-box;width:100%;height:100%;border:.25em solid rgba(165,220,134,.3);border-radius:50%}.swal2-icon.swal2-success .swal2-success-fix{position:absolute;z-index:1;top:.5em;left:1.625em;width:.4375em;height:5.625em;transform:rotate(-45deg)}.swal2-icon.swal2-success [class^=swal2-success-line]{display:block;position:absolute;z-index:2;height:.3125em;border-radius:.125em;background-color:#a5dc86}.swal2-icon.swal2-success [class^=swal2-success-line][class$=tip]{top:2.875em;left:.8125em;width:1.5625em;transform:rotate(45deg)}.swal2-icon.swal2-success [class^=swal2-success-line][class$=long]{top:2.375em;right:.5em;width:2.9375em;transform:rotate(-45deg)}.swal2-icon.swal2-success.swal2-icon-show .swal2-success-line-tip{-webkit-animation:swal2-animate-success-line-tip .75s;animation:swal2-animate-success-line-tip .75s}.swal2-icon.swal2-success.swal2-icon-show .swal2-success-line-long{-webkit-animation:swal2-animate-success-line-long .75s;animation:swal2-animate-success-line-long .75s}.swal2-icon.swal2-success.swal2-icon-show .swal2-success-circular-line-right{-webkit-animation:swal2-rotate-success-circular-line 4.25s ease-in;animation:swal2-rotate-success-circular-line 4.25s ease-in}.swal2-progress-steps{flex-wrap:wrap;align-items:center;max-width:100%;margin:1.25em auto;padding:0;background:inherit;font-weight:600}.swal2-progress-steps li{display:inline-block;position:relative}.swal2-progress-steps .swal2-progress-step{z-index:20;flex-shrink:0;width:2em;height:2em;border-radius:2em;background:#2778c4;color:#fff;line-height:2em;text-align:center}.swal2-progress-steps .swal2-progress-step.swal2-active-progress-step{background:#2778c4}.swal2-progress-steps .swal2-progress-step.swal2-active-progress-step~.swal2-progress-step{background:#add8e6;color:#fff}.swal2-progress-steps .swal2-progress-step.swal2-active-progress-step~.swal2-progress-step-line{background:#add8e6}.swal2-progress-steps .swal2-progress-step-line{z-index:10;flex-shrink:0;width:2.5em;height:.4em;margin:0 -1px;background:#2778c4}[class^=swal2]{-webkit-tap-highlight-color:transparent}.swal2-show{-webkit-animation:swal2-show .3s;animation:swal2-show .3s}.swal2-hide{-webkit-animation:swal2-hide .15s forwards;animation:swal2-hide .15s forwards}.swal2-noanimation{transition:none}.swal2-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}.swal2-rtl .swal2-close{margin-right:initial;margin-left:0}.swal2-rtl .swal2-timer-progress-bar{right:0;left:auto}.swal2-no-war{display:flex;position:fixed;z-index:1061;top:0;left:0;align-items:center;justify-content:center;width:100%;height:3.375em;background:#20232a;color:#fff;text-align:center}.swal2-no-war a{color:#61dafb;text-decoration:none}.swal2-no-war a:hover{text-decoration:underline}@-webkit-keyframes swal2-toast-show{0%{transform:translateY(-.625em) rotateZ(2deg)}33%{transform:translateY(0) rotateZ(-2deg)}66%{transform:translateY(.3125em) rotateZ(2deg)}100%{transform:translateY(0) rotateZ(0)}}@keyframes swal2-toast-show{0%{transform:translateY(-.625em) rotateZ(2deg)}33%{transform:translateY(0) rotateZ(-2deg)}66%{transform:translateY(.3125em) rotateZ(2deg)}100%{transform:translateY(0) rotateZ(0)}}@-webkit-keyframes swal2-toast-hide{100%{transform:rotateZ(1deg);opacity:0}}@keyframes swal2-toast-hide{100%{transform:rotateZ(1deg);opacity:0}}@-webkit-keyframes swal2-toast-animate-success-line-tip{0%{top:.5625em;left:.0625em;width:0}54%{top:.125em;left:.125em;width:0}70%{top:.625em;left:-.25em;width:1.625em}84%{top:1.0625em;left:.75em;width:.5em}100%{top:1.125em;left:.1875em;width:.75em}}@keyframes swal2-toast-animate-success-line-tip{0%{top:.5625em;left:.0625em;width:0}54%{top:.125em;left:.125em;width:0}70%{top:.625em;left:-.25em;width:1.625em}84%{top:1.0625em;left:.75em;width:.5em}100%{top:1.125em;left:.1875em;width:.75em}}@-webkit-keyframes swal2-toast-animate-success-line-long{0%{top:1.625em;right:1.375em;width:0}65%{top:1.25em;right:.9375em;width:0}84%{top:.9375em;right:0;width:1.125em}100%{top:.9375em;right:.1875em;width:1.375em}}@keyframes swal2-toast-animate-success-line-long{0%{top:1.625em;right:1.375em;width:0}65%{top:1.25em;right:.9375em;width:0}84%{top:.9375em;right:0;width:1.125em}100%{top:.9375em;right:.1875em;width:1.375em}}@-webkit-keyframes swal2-show{0%{transform:scale(.7)}45%{transform:scale(1.05)}80%{transform:scale(.95)}100%{transform:scale(1)}}@keyframes swal2-show{0%{transform:scale(.7)}45%{transform:scale(1.05)}80%{transform:scale(.95)}100%{transform:scale(1)}}@-webkit-keyframes swal2-hide{0%{transform:scale(1);opacity:1}100%{transform:scale(.5);opacity:0}}@keyframes swal2-hide{0%{transform:scale(1);opacity:1}100%{transform:scale(.5);opacity:0}}@-webkit-keyframes swal2-animate-success-line-tip{0%{top:1.1875em;left:.0625em;width:0}54%{top:1.0625em;left:.125em;width:0}70%{top:2.1875em;left:-.375em;width:3.125em}84%{top:3em;left:1.3125em;width:1.0625em}100%{top:2.8125em;left:.8125em;width:1.5625em}}@keyframes swal2-animate-success-line-tip{0%{top:1.1875em;left:.0625em;width:0}54%{top:1.0625em;left:.125em;width:0}70%{top:2.1875em;left:-.375em;width:3.125em}84%{top:3em;left:1.3125em;width:1.0625em}100%{top:2.8125em;left:.8125em;width:1.5625em}}@-webkit-keyframes swal2-animate-success-line-long{0%{top:3.375em;right:2.875em;width:0}65%{top:3.375em;right:2.875em;width:0}84%{top:2.1875em;right:0;width:3.4375em}100%{top:2.375em;right:.5em;width:2.9375em}}@keyframes swal2-animate-success-line-long{0%{top:3.375em;right:2.875em;width:0}65%{top:3.375em;right:2.875em;width:0}84%{top:2.1875em;right:0;width:3.4375em}100%{top:2.375em;right:.5em;width:2.9375em}}@-webkit-keyframes swal2-rotate-success-circular-line{0%{transform:rotate(-45deg)}5%{transform:rotate(-45deg)}12%{transform:rotate(-405deg)}100%{transform:rotate(-405deg)}}@keyframes swal2-rotate-success-circular-line{0%{transform:rotate(-45deg)}5%{transform:rotate(-45deg)}12%{transform:rotate(-405deg)}100%{transform:rotate(-405deg)}}@-webkit-keyframes swal2-animate-error-x-mark{0%{margin-top:1.625em;transform:scale(.4);opacity:0}50%{margin-top:1.625em;transform:scale(.4);opacity:0}80%{margin-top:-.375em;transform:scale(1.15)}100%{margin-top:0;transform:scale(1);opacity:1}}@keyframes swal2-animate-error-x-mark{0%{margin-top:1.625em;transform:scale(.4);opacity:0}50%{margin-top:1.625em;transform:scale(.4);opacity:0}80%{margin-top:-.375em;transform:scale(1.15)}100%{margin-top:0;transform:scale(1);opacity:1}}@-webkit-keyframes swal2-animate-error-icon{0%{transform:rotateX(100deg);opacity:0}100%{transform:rotateX(0);opacity:1}}@keyframes swal2-animate-error-icon{0%{transform:rotateX(100deg);opacity:0}100%{transform:rotateX(0);opacity:1}}@-webkit-keyframes swal2-rotate-loading{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@keyframes swal2-rotate-loading{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@-webkit-keyframes swal2-animate-question-mark{0%{transform:rotateY(-360deg)}100%{transform:rotateY(0)}}@keyframes swal2-animate-question-mark{0%{transform:rotateY(-360deg)}100%{transform:rotateY(0)}}@-webkit-keyframes swal2-animate-i-mark{0%{transform:rotateZ(45deg);opacity:0}25%{transform:rotateZ(-25deg);opacity:.4}50%{transform:rotateZ(15deg);opacity:.8}75%{transform:rotateZ(-5deg);opacity:1}100%{transform:rotateX(0);opacity:1}}@keyframes swal2-animate-i-mark{0%{transform:rotateZ(45deg);opacity:0}25%{transform:rotateZ(-25deg);opacity:.4}50%{transform:rotateZ(15deg);opacity:.8}75%{transform:rotateZ(-5deg);opacity:1}100%{transform:rotateX(0);opacity:1}}body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown){overflow:hidden}body.swal2-height-auto{height:auto!important}body.swal2-no-backdrop .swal2-container{background-color:transparent!important;pointer-events:none}body.swal2-no-backdrop .swal2-container .swal2-popup{pointer-events:all}body.swal2-no-backdrop .swal2-container .swal2-modal{box-shadow:0 0 10px rgba(0,0,0,.4)}@media print{body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown){overflow-y:scroll!important}body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown)>[aria-hidden=true]{display:none}body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown) .swal2-container{position:static!important}}body.swal2-toast-shown .swal2-container{box-sizing:border-box;width:360px;max-width:100%;background-color:transparent;pointer-events:none}body.swal2-toast-shown .swal2-container.swal2-top{top:0;right:auto;bottom:auto;left:50%;transform:translateX(-50%)}body.swal2-toast-shown .swal2-container.swal2-top-end,body.swal2-toast-shown .swal2-container.swal2-top-right{top:0;right:0;bottom:auto;left:auto}body.swal2-toast-shown .swal2-container.swal2-top-left,body.swal2-toast-shown .swal2-container.swal2-top-start{top:0;right:auto;bottom:auto;left:0}body.swal2-toast-shown .swal2-container.swal2-center-left,body.swal2-toast-shown .swal2-container.swal2-center-start{top:50%;right:auto;bottom:auto;left:0;transform:translateY(-50%)}body.swal2-toast-shown .swal2-container.swal2-center{top:50%;right:auto;bottom:auto;left:50%;transform:translate(-50%,-50%)}body.swal2-toast-shown .swal2-container.swal2-center-end,body.swal2-toast-shown .swal2-container.swal2-center-right{top:50%;right:0;bottom:auto;left:auto;transform:translateY(-50%)}body.swal2-toast-shown .swal2-container.swal2-bottom-left,body.swal2-toast-shown .swal2-container.swal2-bottom-start{top:auto;right:auto;bottom:0;left:0}body.swal2-toast-shown .swal2-container.swal2-bottom{top:auto;right:auto;bottom:0;left:50%;transform:translateX(-50%)}body.swal2-toast-shown .swal2-container.swal2-bottom-end,body.swal2-toast-shown .swal2-container.swal2-bottom-right{top:auto;right:0;bottom:0;left:auto}')}},e={};function o(n){var a=e[n];if(void 0!==a)return a.exports;var s=e[n]={id:n,exports:{}};return t[n].call(s.exports,s,s.exports,o),s.exports}o.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return o.d(e,{a:e}),e},o.d=(t,e)=>{for(var n in e)o.o(e,n)&&!o.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},o.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),o.nc=void 0;var n={};return(()=>{"use strict";var t;o.d(n,{default:()=>T});var e=new Uint8Array(16);function a(){if(!t&&!(t="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto)))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return t(e)}const s=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i,i=function(t){return"string"==typeof t&&s.test(t)};for(var r=[],l=0;l<256;++l)r.push((l+256).toString(16).substr(1));const c=function(t,e,o){var n=(t=t||{}).random||(t.rng||a)();if(n[6]=15&n[6]|64,n[8]=63&n[8]|128,e){o=o||0;for(var s=0;s<16;++s)e[o+s]=n[s];return e}return function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,o=(r[t[e+0]]+r[t[e+1]]+r[t[e+2]]+r[t[e+3]]+"-"+r[t[e+4]]+r[t[e+5]]+"-"+r[t[e+6]]+r[t[e+7]]+"-"+r[t[e+8]]+r[t[e+9]]+"-"+r[t[e+10]]+r[t[e+11]]+r[t[e+12]]+r[t[e+13]]+r[t[e+14]]+r[t[e+15]]).toLowerCase();if(!i(o))throw TypeError("Stringified UUID is invalid");return o}(n)};var d=o(455),u=o.n(d),p=o(40),m=o.n(p),w=o(379),g=o.n(w),h=o(795),f=o.n(h),b=o(569),y=o.n(b),v=o(565),x=o.n(v),k=o(216),C=o.n(k),A=o(589),B=o.n(A),P=o(745),E={};E.styleTagTransform=B(),E.setAttributes=x(),E.insert=y().bind(null,"head"),E.domAPI=f(),E.insertStyleElement=C(),g()(P.Z,E),P.Z&&P.Z.locals&&P.Z.locals;class T{static get enableLineBreaks(){return!0}constructor({data:t,config:e,api:o,readOnly:n}){this.api=o,this.readOnly=n,this.config=e||{},this._CSS={block:this.api.styles.block,wrapper:"ce-EditorJsColumns"},this.readOnly||(this.onKeyUp=this.onKeyUp.bind(this)),this._data={},this.editors={},this.colWrapper=void 0,this.editors.cols=[],this.data=t,Array.isArray(this.data.cols)?this.editors.numberOfColumns=this.data.cols.length:(this.data.cols=[],this.editors.numberOfColumns=2)}static get isReadOnlySupported(){return!0}onKeyUp(t){"Backspace"===t.code||t.code}get CSS(){return{settingsButton:this.api.styles.settingsButton,settingsButtonActive:this.api.styles.settingsButtonActive}}renderSettings(){return[{icon:"2",label:"2 Columns",onActivate:()=>{this._updateCols(2)}},{icon:"3",label:"3 Columns",onActivate:()=>{this._updateCols(3)}},{icon:"R",label:"Roll Colls",onActivate:()=>{this._rollCols()}}]}_rollCols(){this.data.cols.unshift(this.data.cols.pop()),this.editors.cols.unshift(this.editors.cols.pop()),this._rerender()}async _updateCols(t){2==t&&3==this.editors.numberOfColumns&&(await u().fire({title:"Are you sure?",text:"This will delete Column 3!",icon:"warning",showCancelButton:!0,confirmButtonColor:"#3085d6",cancelButtonColor:"#d33",confirmButtonText:"Yes, delete it!"})).isConfirmed&&(this.editors.numberOfColumns=2,this.data.cols.pop(),this.editors.cols.pop(),this._rerender()),3==t&&(this.editors.numberOfColumns=3,this._rerender())}async _rerender(){await this.save();for(let t=0;t{t.stopPropagation()}),!0),this.colWrapper.addEventListener("keydown",(t=>{"Enter"===t.key&&(t.preventDefault(),t.stopImmediatePropagation(),t.stopPropagation()),"Tab"===t.key&&(t.preventDefault(),t.stopImmediatePropagation(),t.stopPropagation())}));for(let t=0;t=0&&f.splice(t,1)}function b(e){var t=document.createElement("style");return void 0===e.attrs.type&&(e.attrs.type="text/css"),m(t,e.attrs),v(e,t),t}function m(e,t){Object.keys(t).forEach((function(n){e.setAttribute(n,t[n])}))}function y(e,t){var n,r,o,i;if(t.transform&&e.css){if(!(i=t.transform(e.css)))return function(){};e.css=i}if(t.singleton){var a=c++;n=u||(u=b(t)),r=L.bind(null,n,a,!1),o=L.bind(null,n,a,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=function(e){var t=document.createElement("link");return void 0===e.attrs.type&&(e.attrs.type="text/css"),e.attrs.rel="stylesheet",m(t,e.attrs),v(e,t),t}(t),r=x.bind(null,n,t),o=function(){g(n),n.href&&URL.revokeObjectURL(n.href)}):(n=b(t),r=M.bind(null,n),o=function(){g(n)});return r(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;r(e=t)}else o()}}e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(t=t||{}).attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||"boolean"==typeof t.singleton||(t.singleton=a()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var n=h(e,t);return p(n,t),function(e){for(var r=[],o=0;o',title:"Heading"}}}],(n=[{key:"normalizeData",value:function(e){var t={};return"object"!==r(e)&&(e={}),t.text=e.text||"",t.level=parseInt(e.level)||this.defaultLevel.number,t}},{key:"render",value:function(){return this._element}},{key:"renderSettings",value:function(){var e=this;return this.levels.map((function(t){return{icon:t.svg,label:e.api.i18n.t("Heading ".concat(t.number)),onActivate:function(){return e.setLevel(t.number)},closeOnActivate:!0,isActive:e.currentLevel.number===t.number}}))}},{key:"setLevel",value:function(e){this.data={level:e,text:this.data.text}}},{key:"merge",value:function(e){var t={text:this.data.text+e.text,level:this.data.level};this.data=t}},{key:"validate",value:function(e){return""!==e.text.trim()}},{key:"save",value:function(e){return{text:e.innerHTML,level:this.currentLevel.number}}},{key:"getTag",value:function(){var e=document.createElement(this.currentLevel.tag);return e.innerHTML=this._data.text||"",e.classList.add(this._CSS.wrapper),e.contentEditable=this.readOnly?"false":"true",e.dataset.placeholder=this.api.i18n.t(this._settings.placeholder||""),e}},{key:"onPaste",value:function(e){var t=e.detail.data,n=this.defaultLevel.number;switch(t.tagName){case"H1":n=1;break;case"H2":n=2;break;case"H3":n=3;break;case"H4":n=4;break;case"H5":n=5;break;case"H6":n=6}this._settings.levels&&(n=this._settings.levels.reduce((function(e,t){return Math.abs(t-n)'},{number:2,tag:"H2",svg:''},{number:3,tag:"H3",svg:''},{number:4,tag:"H4",svg:''},{number:5,tag:"H5",svg:''},{number:6,tag:"H6",svg:''}];return this._settings.levels?t.filter((function(t){return e._settings.levels.includes(t.number)})):t}}])&&o(t.prototype,n),i&&o(t,i),e}()}]).default})); \ No newline at end of file diff --git a/web/vendor/editorjs/tools/list.umd.js b/web/vendor/editorjs/tools/list.umd.js new file mode 100644 index 0000000..c8257ec --- /dev/null +++ b/web/vendor/editorjs/tools/list.umd.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.List=t():e.List=t()}(window,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=4)}([function(e,t,n){var r=n(1),i=n(2);"string"==typeof(i=i.__esModule?i.default:i)&&(i=[[e.i,i,""]]);var o={insert:"head",singleton:!1};r(i,o);e.exports=i.locals||{}},function(e,t,n){"use strict";var r,i=function(){return void 0===r&&(r=Boolean(window&&document&&document.all&&!window.atob)),r},o=function(){var e={};return function(t){if(void 0===e[t]){var n=document.querySelector(t);if(window.HTMLIFrameElement&&n instanceof window.HTMLIFrameElement)try{n=n.contentDocument.head}catch(e){n=null}e[t]=n}return e[t]}}(),a=[];function s(e){for(var t=-1,n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n',default:"ordered"===i.defaultStyle||!0}],this._data={style:this.settings.find((function(e){return!0===e.default})).name,items:[]},this.data=n}return u(e,null,[{key:"isReadOnlySupported",get:function(){return!0}},{key:"enableLineBreaks",get:function(){return!0}},{key:"toolbox",get:function(){return{icon:r,title:"List"}}}]),u(e,[{key:"render",value:function(){var e=this;return this._elements.wrapper=this.makeMainTag(this._data.style),this._data.items.length?this._data.items.forEach((function(t){e._elements.wrapper.appendChild(e._make("li",e.CSS.item,{innerHTML:t}))})):this._elements.wrapper.appendChild(this._make("li",this.CSS.item)),this.readOnly||this._elements.wrapper.addEventListener("keydown",(function(t){switch(t.keyCode){case 13:e.getOutofList(t);break;case 8:e.backspace(t)}}),!1),this._elements.wrapper}},{key:"save",value:function(){return this.data}},{key:"renderSettings",value:function(){var e=this;return this.settings.map((function(t){return s(s({},t),{},{isActive:e._data.style===t.name,closeOnActivate:!0,onActivate:function(){return e.toggleTune(t.name)}})}))}},{key:"onPaste",value:function(e){var t=e.detail.data;this.data=this.pasteHandler(t)}},{key:"makeMainTag",value:function(e){var t="ordered"===e?this.CSS.wrapperOrdered:this.CSS.wrapperUnordered,n="ordered"===e?"ol":"ul";return this._make(n,[this.CSS.baseBlock,this.CSS.wrapper,t],{contentEditable:!this.readOnly})}},{key:"toggleTune",value:function(e){for(var t=this.makeMainTag(e);this._elements.wrapper.hasChildNodes();)t.appendChild(this._elements.wrapper.firstChild);this._elements.wrapper.replaceWith(t),this._elements.wrapper=t,this._data.style=e}},{key:"_make",value:function(e){var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},o=document.createElement(e);Array.isArray(n)?(t=o.classList).add.apply(t,i(n)):n&&o.classList.add(n);for(var a in r)o[a]=r[a];return o}},{key:"getOutofList",value:function(e){var t=this._elements.wrapper.querySelectorAll("."+this.CSS.item);if(!(t.length<2)){var n=t[t.length-1],r=this.currentItem;r!==n||n.textContent.trim().length||(r.parentElement.removeChild(r),this.api.blocks.insert(),this.api.caret.setToBlock(this.api.blocks.getCurrentBlockIndex()),e.preventDefault(),e.stopPropagation())}}},{key:"backspace",value:function(e){var t=this._elements.wrapper.querySelectorAll("."+this.CSS.item),n=t[0];n&&t.length<2&&!n.innerHTML.replace("
      "," ").trim()&&e.preventDefault()}},{key:"selectItem",value:function(e){e.preventDefault();var t=window.getSelection(),n=t.anchorNode.parentNode.closest("."+this.CSS.item),r=new Range;r.selectNodeContents(n),t.removeAllRanges(),t.addRange(r)}},{key:"pasteHandler",value:function(e){var t,n=e.tagName;switch(n){case"OL":t="ordered";break;case"UL":case"LI":t="unordered"}var r={style:t,items:[]};if("LI"===n)r.items=[e.innerHTML];else{var i=Array.from(e.querySelectorAll("LI"));r.items=i.map((function(e){return e.innerHTML})).filter((function(e){return!!e.trim()}))}return r}},{key:"CSS",get:function(){return{baseBlock:this.api.styles.block,wrapper:"cdx-list",wrapperOrdered:"cdx-list--ordered",wrapperUnordered:"cdx-list--unordered",item:"cdx-list__item"}}},{key:"data",set:function(e){e||(e={}),this._data.style=e.style||this.settings.find((function(e){return!0===e.default})).name,this._data.items=e.items||[];var t=this._elements.wrapper;t&&t.parentNode.replaceChild(this.render(),t)},get:function(){this._data.items=[];for(var e=this._elements.wrapper.querySelectorAll(".".concat(this.CSS.item)),t=0;t"," ").trim()&&this._data.items.push(e[t].innerHTML)}return this._data}},{key:"currentItem",get:function(){var e=window.getSelection().anchorNode;return e.nodeType!==Node.ELEMENT_NODE&&(e=e.parentNode),e.closest(".".concat(this.CSS.item))}}],[{key:"conversionConfig",get:function(){return{export:function(e){return e.items.join(". ")},import:function(e){return{items:[e],style:"unordered"}}}}},{key:"sanitize",get:function(){return{style:{},items:{br:!0}}}},{key:"pasteConfig",get:function(){return{tags:["OL","UL","LI"]}}}]),e}()}]).default})); \ No newline at end of file diff --git a/web/vendor/editorjs/tools/marker.umd.js b/web/vendor/editorjs/tools/marker.umd.js new file mode 100644 index 0000000..759bde8 --- /dev/null +++ b/web/vendor/editorjs/tools/marker.umd.js @@ -0,0 +1 @@ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Marker=e():t.Marker=e()}(window,function(){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)n.d(r,o,function(e){return t[e]}.bind(null,o));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="/",n(n.s=5)}([function(t,e,n){var r=n(1);"string"==typeof r&&(r=[[t.i,r,""]]);var o={hmr:!0,transform:void 0,insertInto:void 0};n(3)(r,o);r.locals&&(t.exports=r.locals)},function(t,e,n){(t.exports=n(2)(!1)).push([t.i,".cdx-marker {\n background: rgba(245,235,111,0.29);\n padding: 3px 0;\n}",""])},function(t,e){t.exports=function(t){var e=[];return e.toString=function(){return this.map(function(e){var n=function(t,e){var n=t[1]||"",r=t[3];if(!r)return n;if(e&&"function"==typeof btoa){var o=(a=r,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(a))))+" */"),i=r.sources.map(function(t){return"/*# sourceURL="+r.sourceRoot+t+" */"});return[n].concat(i).concat([o]).join("\n")}var a;return[n].join("\n")}(e,t);return e[2]?"@media "+e[2]+"{"+n+"}":n}).join("")},e.i=function(t,n){"string"==typeof t&&(t=[[null,t,""]]);for(var r={},o=0;o=0&&f.splice(e,1)}function b(t){var e=document.createElement("style");return void 0===t.attrs.type&&(t.attrs.type="text/css"),y(e,t.attrs),h(t,e),e}function y(t,e){Object.keys(e).forEach(function(n){t.setAttribute(n,e[n])})}function g(t,e){var n,r,o,i;if(e.transform&&t.css){if(!(i=e.transform(t.css)))return function(){};t.css=i}if(e.singleton){var a=c++;n=u||(u=b(e)),r=x.bind(null,n,a,!1),o=x.bind(null,n,a,!0)}else t.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=function(t){var e=document.createElement("link");return void 0===t.attrs.type&&(t.attrs.type="text/css"),t.attrs.rel="stylesheet",y(e,t.attrs),h(t,e),e}(e),r=function(t,e,n){var r=n.css,o=n.sourceMap,i=void 0===e.convertToAbsoluteUrls&&o;(e.convertToAbsoluteUrls||i)&&(r=l(r));o&&(r+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(o))))+" */");var a=new Blob([r],{type:"text/css"}),s=t.href;t.href=URL.createObjectURL(a),s&&URL.revokeObjectURL(s)}.bind(null,n,e),o=function(){v(n),n.href&&URL.revokeObjectURL(n.href)}):(n=b(e),r=function(t,e){var n=e.css,r=e.media;r&&t.setAttribute("media",r);if(t.styleSheet)t.styleSheet.cssText=n;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(n))}}.bind(null,n),o=function(){v(n)});return r(t),function(e){if(e){if(e.css===t.css&&e.media===t.media&&e.sourceMap===t.sourceMap)return;r(t=e)}else o()}}t.exports=function(t,e){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(e=e||{}).attrs="object"==typeof e.attrs?e.attrs:{},e.singleton||"boolean"==typeof e.singleton||(e.singleton=a()),e.insertInto||(e.insertInto="head"),e.insertAt||(e.insertAt="bottom");var n=d(t,e);return p(n,e),function(t){for(var r=[],o=0;o'}}],[{key:"isInline",get:function(){return!0}},{key:"sanitize",get:function(){return{mark:{class:t.CSS}}}}]),t}()}]).default}); \ No newline at end of file diff --git a/web/vendor/editorjs/tools/table.umd.js b/web/vendor/editorjs/tools/table.umd.js new file mode 100644 index 0000000..2a2ebe6 --- /dev/null +++ b/web/vendor/editorjs/tools/table.umd.js @@ -0,0 +1,8 @@ +/** + * Skipped minification because the original files appears to be already minified. + * Original file: /npm/@editorjs/table@2.4.5/dist/table.umd.js + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +(function(){var r;"use strict";try{if(typeof document<"u"){var o=document.createElement("style");o.nonce=(r=document.head.querySelector("meta[property=csp-nonce]"))==null?void 0:r.content,o.appendChild(document.createTextNode('.tc-wrap{--color-background:#f9f9fb;--color-text-secondary:#7b7e89;--color-border:#e8e8eb;--cell-size:34px;--toolbox-icon-size:18px;--toolbox-padding:6px;--toolbox-aiming-field-size:calc(var(--toolbox-icon-size) + var(--toolbox-padding)*2);border-left:0;position:relative;height:100%;width:100%;margin-top:var(--toolbox-icon-size);box-sizing:border-box;display:grid;grid-template-columns:calc(100% - var(--cell-size)) var(--cell-size);z-index:0}.tc-wrap--readonly{grid-template-columns:100% var(--cell-size)}.tc-wrap svg{vertical-align:top}@media print{.tc-wrap{border-left-color:var(--color-border);border-left-style:solid;border-left-width:1px;grid-template-columns:100% var(--cell-size)}}@media print{.tc-wrap .tc-row:after{display:none}}.tc-table{position:relative;width:100%;height:100%;display:grid;font-size:14px;border-top:1px solid var(--color-border);line-height:1.4}.tc-table:after{width:calc(var(--cell-size));height:100%;left:calc(var(--cell-size)*-1);top:0}.tc-table:after,.tc-table:before{position:absolute;content:""}.tc-table:before{width:100%;height:var(--toolbox-aiming-field-size);top:calc(var(--toolbox-aiming-field-size)*-1);left:0}.tc-table--heading .tc-row:first-child{font-weight:600;border-bottom:2px solid var(--color-border);position:sticky;top:0;z-index:2;background:var(--color-background)}.tc-table--heading .tc-row:first-child [contenteditable]:empty:before{content:attr(heading);color:var(--color-text-secondary)}.tc-table--heading .tc-row:first-child:after{bottom:-2px;border-bottom:2px solid var(--color-border)}.tc-add-column,.tc-add-row{display:flex;color:var(--color-text-secondary)}@media print{.tc-add{display:none}}.tc-add-column{display:grid;border-top:1px solid var(--color-border);grid-template-columns:var(--cell-size);grid-auto-rows:var(--cell-size);place-items:center}.tc-add-column svg{padding:5px;position:sticky;top:0;background-color:var(--color-background)}.tc-add-column--disabled{visibility:hidden}@media print{.tc-add-column{display:none}}.tc-add-row{height:var(--cell-size);align-items:center;padding-left:4px;position:relative}.tc-add-row--disabled{display:none}.tc-add-row:before{content:"";position:absolute;right:calc(var(--cell-size)*-1);width:var(--cell-size);height:100%}@media print{.tc-add-row{display:none}}.tc-add-column,.tc-add-row{transition:0s;cursor:pointer;will-change:background-color}.tc-add-column:hover,.tc-add-row:hover{transition:background-color .1s ease;background-color:var(--color-background)}.tc-add-row{margin-top:1px}.tc-add-row:hover:before{transition:.1s;background-color:var(--color-background)}.tc-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(10px,1fr));position:relative;border-bottom:1px solid var(--color-border)}.tc-row:after{content:"";pointer-events:none;position:absolute;width:var(--cell-size);height:100%;bottom:-1px;right:calc(var(--cell-size)*-1);border-bottom:1px solid var(--color-border)}.tc-row--selected{background:var(--color-background)}.tc-row--selected:after{background:var(--color-background)}.tc-cell{border-right:1px solid var(--color-border);padding:6px 12px;overflow:hidden;outline:none;line-break:normal}.tc-cell--selected{background:var(--color-background)}.tc-wrap--readonly .tc-row:after{display:none}.tc-toolbox{--toolbox-padding:6px;--popover-margin:30px;--toggler-click-zone-size:30px;--toggler-dots-color:#7b7e89;--toggler-dots-color-hovered:#1d202b;position:absolute;cursor:pointer;z-index:1;opacity:0;transition:opacity .1s;will-change:left,opacity}.tc-toolbox--column{top:calc(var(--toggler-click-zone-size)*-1);transform:translate(calc(var(--toggler-click-zone-size)*-1/2));will-change:left,opacity}.tc-toolbox--row{left:calc(var(--popover-margin)*-1);transform:translateY(calc(var(--toggler-click-zone-size)*-1/2));margin-top:-1px;will-change:top,opacity}.tc-toolbox--showed{opacity:1}.tc-toolbox .tc-popover{position:absolute;top:0;left:var(--popover-margin)}.tc-toolbox__toggler{display:flex;align-items:center;justify-content:center;width:var(--toggler-click-zone-size);height:var(--toggler-click-zone-size);color:var(--toggler-dots-color);opacity:0;transition:opacity .15s ease;will-change:opacity}.tc-toolbox__toggler:hover{color:var(--toggler-dots-color-hovered)}.tc-toolbox__toggler svg{fill:currentColor}.tc-wrap:hover .tc-toolbox__toggler{opacity:1}.tc-settings .cdx-settings-button{width:50%;margin:0}.tc-popover{--color-border:#eaeaea;--color-background:#fff;--color-background-hover:rgba(232,232,235,.49);--color-background-confirm:#e24a4a;--color-background-confirm-hover:#d54040;--color-text-confirm:#fff;background:var(--color-background);border:1px solid var(--color-border);box-shadow:0 3px 15px -3px #0d142121;border-radius:6px;padding:6px;display:none;will-change:opacity,transform}.tc-popover--opened{display:block;animation:menuShowing .1s cubic-bezier(.215,.61,.355,1) forwards}.tc-popover__item{display:flex;align-items:center;padding:2px 14px 2px 2px;border-radius:5px;cursor:pointer;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;user-select:none}.tc-popover__item:hover{background:var(--color-background-hover)}.tc-popover__item:not(:last-of-type){margin-bottom:2px}.tc-popover__item-icon{display:inline-flex;width:26px;height:26px;align-items:center;justify-content:center;background:var(--color-background);border-radius:5px;border:1px solid var(--color-border);margin-right:8px}.tc-popover__item-label{line-height:22px;font-size:14px;font-weight:500}.tc-popover__item--confirm{background:var(--color-background-confirm);color:var(--color-text-confirm)}.tc-popover__item--confirm:hover{background-color:var(--color-background-confirm-hover)}.tc-popover__item--confirm .tc-popover__item-icon{background:var(--color-background-confirm);border-color:#0000001a}.tc-popover__item--confirm .tc-popover__item-icon svg{transition:transform .2s ease-in;transform:rotate(90deg) scale(1.2)}.tc-popover__item--hidden{display:none}@keyframes menuShowing{0%{opacity:0;transform:translateY(-8px) scale(.9)}70%{opacity:1;transform:translateY(2px)}to{transform:translateY(0)}}')),document.head.appendChild(o)}}catch(e){console.error("vite-plugin-css-injected-by-js",e)}})(); +(function(d,p){typeof exports=="object"&&typeof module<"u"?module.exports=p():typeof define=="function"&&define.amd?define(p):(d=typeof globalThis<"u"?globalThis:d||self,d.Table=p())})(this,function(){"use strict";function d(a,t,e={}){const o=document.createElement(a);Array.isArray(t)?o.classList.add(...t):t&&o.classList.add(t);for(const i in e)Object.prototype.hasOwnProperty.call(e,i)&&(o[i]=e[i]);return o}function p(a){const t=a.getBoundingClientRect();return{y1:Math.floor(t.top+window.pageYOffset),x1:Math.floor(t.left+window.pageXOffset),x2:Math.floor(t.right+window.pageXOffset),y2:Math.floor(t.bottom+window.pageYOffset)}}function g(a,t){const e=p(a),o=p(t);return{fromTopBorder:o.y1-e.y1,fromLeftBorder:o.x1-e.x1,fromRightBorder:e.x2-o.x2,fromBottomBorder:e.y2-o.y2}}function k(a,t){const e=a.getBoundingClientRect(),{width:o,height:i,x:n,y:r}=e,{clientX:h,clientY:l}=t;return{width:o,height:i,x:h-n,y:l-r}}function m(a,t){return t.parentNode.insertBefore(a,t)}function C(a,t=!0){const e=document.createRange(),o=window.getSelection();e.selectNodeContents(a),e.collapse(t),o.removeAllRanges(),o.addRange(e)}class c{constructor({items:t}){this.items=t,this.wrapper=void 0,this.itemEls=[]}static get CSS(){return{popover:"tc-popover",popoverOpened:"tc-popover--opened",item:"tc-popover__item",itemHidden:"tc-popover__item--hidden",itemConfirmState:"tc-popover__item--confirm",itemIcon:"tc-popover__item-icon",itemLabel:"tc-popover__item-label"}}render(){return this.wrapper=d("div",c.CSS.popover),this.items.forEach((t,e)=>{const o=d("div",c.CSS.item),i=d("div",c.CSS.itemIcon,{innerHTML:t.icon}),n=d("div",c.CSS.itemLabel,{textContent:t.label});o.dataset.index=e,o.appendChild(i),o.appendChild(n),this.wrapper.appendChild(o),this.itemEls.push(o)}),this.wrapper.addEventListener("click",t=>{this.popoverClicked(t)}),this.wrapper}popoverClicked(t){const e=t.target.closest(`.${c.CSS.item}`);if(!e)return;const o=e.dataset.index,i=this.items[o];if(i.confirmationRequired&&!this.hasConfirmationState(e)){this.setConfirmationState(e);return}i.onClick()}setConfirmationState(t){t.classList.add(c.CSS.itemConfirmState)}clearConfirmationState(t){t.classList.remove(c.CSS.itemConfirmState)}hasConfirmationState(t){return t.classList.contains(c.CSS.itemConfirmState)}get opened(){return this.wrapper.classList.contains(c.CSS.popoverOpened)}open(){this.items.forEach((t,e)=>{typeof t.hideIf=="function"&&this.itemEls[e].classList.toggle(c.CSS.itemHidden,t.hideIf())}),this.wrapper.classList.add(c.CSS.popoverOpened)}close(){this.wrapper.classList.remove(c.CSS.popoverOpened),this.itemEls.forEach(t=>{this.clearConfirmationState(t)})}}const R='',b='',x='',S='',y='',L='',M='',v='',O='',T='',H='',A='';class w{constructor({api:t,items:e,onOpen:o,onClose:i,cssModifier:n=""}){this.api=t,this.items=e,this.onOpen=o,this.onClose=i,this.cssModifier=n,this.popover=null,this.wrapper=this.createToolbox()}static get CSS(){return{toolbox:"tc-toolbox",toolboxShowed:"tc-toolbox--showed",toggler:"tc-toolbox__toggler"}}get element(){return this.wrapper}createToolbox(){const t=d("div",[w.CSS.toolbox,this.cssModifier?`${w.CSS.toolbox}--${this.cssModifier}`:""]);t.dataset.mutationFree="true";const e=this.createPopover(),o=this.createToggler();return t.appendChild(o),t.appendChild(e),t}createToggler(){const t=d("div",w.CSS.toggler,{innerHTML:M});return t.addEventListener("click",()=>{this.togglerClicked()}),t}createPopover(){return this.popover=new c({items:this.items}),this.popover.render()}togglerClicked(){this.popover.opened?(this.popover.close(),this.onClose()):(this.popover.open(),this.onOpen())}show(t){const e=t();Object.entries(e).forEach(([o,i])=>{this.wrapper.style[o]=i}),this.wrapper.classList.add(w.CSS.toolboxShowed)}hide(){this.popover.close(),this.wrapper.classList.remove(w.CSS.toolboxShowed)}}function B(a,t){let e=0;return function(...o){const i=new Date().getTime();if(!(i-e{const r=n.target.closest(`.${s.table}`)!==null,h=n.target.closest(`.${s.wrapper}`)===null;(r||h)&&this.hideToolboxes();const u=n.target.closest(`.${s.addRow}`),f=n.target.closest(`.${s.addColumn}`);u&&u.parentNode===this.wrapper?(this.addRow(void 0,!0),this.hideToolboxes()):f&&f.parentNode===this.wrapper&&(this.addColumn(void 0,!0),this.hideToolboxes())},this.readOnly||this.bindEvents()}getWrapper(){return this.wrapper}bindEvents(){document.addEventListener("click",this.documentClicked),this.table.addEventListener("mousemove",B(150,t=>this.onMouseMoveInTable(t)),{passive:!0}),this.table.onkeypress=t=>this.onKeyPressListener(t),this.table.addEventListener("keydown",t=>this.onKeyDownListener(t)),this.table.addEventListener("focusin",t=>this.focusInTableListener(t))}createColumnToolbox(){return new w({api:this.api,cssModifier:"column",items:[{label:this.api.i18n.t("Add column to left"),icon:S,hideIf:()=>this.numberOfColumns===this.config.maxcols,onClick:()=>{this.addColumn(this.selectedColumn,!0),this.hideToolboxes()}},{label:this.api.i18n.t("Add column to right"),icon:y,hideIf:()=>this.numberOfColumns===this.config.maxcols,onClick:()=>{this.addColumn(this.selectedColumn+1,!0),this.hideToolboxes()}},{label:this.api.i18n.t("Delete column"),icon:b,hideIf:()=>this.numberOfColumns===1,confirmationRequired:!0,onClick:()=>{this.deleteColumn(this.selectedColumn),this.hideToolboxes()}}],onOpen:()=>{this.selectColumn(this.hoveredColumn),this.hideRowToolbox()},onClose:()=>{this.unselectColumn()}})}createRowToolbox(){return new w({api:this.api,cssModifier:"row",items:[{label:this.api.i18n.t("Add row above"),icon:L,hideIf:()=>this.numberOfRows===this.config.maxrows,onClick:()=>{this.addRow(this.selectedRow,!0),this.hideToolboxes()}},{label:this.api.i18n.t("Add row below"),icon:x,hideIf:()=>this.numberOfRows===this.config.maxrows,onClick:()=>{this.addRow(this.selectedRow+1,!0),this.hideToolboxes()}},{label:this.api.i18n.t("Delete row"),icon:b,hideIf:()=>this.numberOfRows===1,confirmationRequired:!0,onClick:()=>{this.deleteRow(this.selectedRow),this.hideToolboxes()}}],onOpen:()=>{this.selectRow(this.hoveredRow),this.hideColumnToolbox()},onClose:()=>{this.unselectRow()}})}moveCursorToNextRow(){this.focusedCell.row!==this.numberOfRows?(this.focusedCell.row+=1,this.focusCell(this.focusedCell)):(this.addRow(),this.focusedCell.row+=1,this.focusCell(this.focusedCell),this.updateToolboxesPosition(0,0))}getCell(t,e){return this.table.querySelectorAll(`.${s.row}:nth-child(${t}) .${s.cell}`)[e-1]}getRow(t){return this.table.querySelector(`.${s.row}:nth-child(${t})`)}getRowByCell(t){return t.parentElement}getRowFirstCell(t){return t.querySelector(`.${s.cell}:first-child`)}setCellContent(t,e,o){const i=this.getCell(t,e);i.innerHTML=o}addColumn(t=-1,e=!1){var n;let o=this.numberOfColumns;if(this.config&&this.config.maxcols&&this.numberOfColumns>=this.config.maxcols)return;for(let r=1;r<=this.numberOfRows;r++){let h;const l=this.createCell();if(t>0&&t<=o?(h=this.getCell(r,t),m(l,h)):h=this.getRow(r).appendChild(l),r===1){const u=this.getCell(r,t>0?t:o+1);u&&e&&C(u)}}const i=this.wrapper.querySelector(`.${s.addColumn}`);(n=this.config)!=null&&n.maxcols&&this.numberOfColumns>this.config.maxcols-1&&i&&i.classList.add(s.addColumnDisabled),this.addHeadingAttrToFirstRow()}addRow(t=-1,e=!1){let o,i=d("div",s.row);this.tunes.withHeadings&&this.removeHeadingAttrFromFirstRow();let n=this.numberOfColumns;if(this.config&&this.config.maxrows&&this.numberOfRows>=this.config.maxrows&&h)return;if(t>0&&t<=this.numberOfRows){let l=this.getRow(t);o=m(i,l)}else o=this.table.appendChild(i);this.fillRow(o,n),this.tunes.withHeadings&&this.addHeadingAttrToFirstRow();const r=this.getRowFirstCell(o);r&&e&&C(r);const h=this.wrapper.querySelector(`.${s.addRow}`);return this.config&&this.config.maxrows&&this.numberOfRows>=this.config.maxrows&&h&&h.classList.add(s.addRowDisabled),o}deleteColumn(t){for(let o=1;o<=this.numberOfRows;o++){const i=this.getCell(o,t);if(!i)return;i.remove()}const e=this.wrapper.querySelector(`.${s.addColumn}`);e&&e.classList.remove(s.addColumnDisabled)}deleteRow(t){this.getRow(t).remove();const e=this.wrapper.querySelector(`.${s.addRow}`);e&&e.classList.remove(s.addRowDisabled),this.addHeadingAttrToFirstRow()}createTableWrapper(){if(this.wrapper=d("div",s.wrapper),this.table=d("div",s.table),this.readOnly&&this.wrapper.classList.add(s.wrapperReadOnly),this.wrapper.appendChild(this.toolboxRow.element),this.wrapper.appendChild(this.toolboxColumn.element),this.wrapper.appendChild(this.table),!this.readOnly){const t=d("div",s.addColumn,{innerHTML:v}),e=d("div",s.addRow,{innerHTML:v});this.wrapper.appendChild(t),this.wrapper.appendChild(e)}}computeInitialSize(){const t=this.data&&this.data.content,e=Array.isArray(t),o=e?t.length:!1,i=e?t.length:void 0,n=o?t[0].length:void 0,r=Number.parseInt(this.config&&this.config.rows),h=Number.parseInt(this.config&&this.config.cols),l=!isNaN(r)&&r>0?r:void 0,u=!isNaN(h)&&h>0?h:void 0;return{rows:i||l||2,cols:n||u||2}}resize(){const{rows:t,cols:e}=this.computeInitialSize();for(let o=0;o0&&e<=this.numberOfColumns&&this.toolboxColumn.show(()=>({left:`calc((100% - var(--cell-size)) / (${this.numberOfColumns} * 2) * (1 + (${e} - 1) * 2))`})),this.isRowMenuShowing||t>0&&t<=this.numberOfRows&&this.toolboxRow.show(()=>{const o=this.getRow(t),{fromTopBorder:i}=g(this.table,o),{height:n}=o.getBoundingClientRect();return{top:`${Math.ceil(i+n/2)}px`}})}setHeadingsSetting(t){this.tunes.withHeadings=t,t?(this.table.classList.add(s.withHeadings),this.addHeadingAttrToFirstRow()):(this.table.classList.remove(s.withHeadings),this.removeHeadingAttrFromFirstRow())}addHeadingAttrToFirstRow(){for(let t=1;t<=this.numberOfColumns;t++){let e=this.getCell(1,t);e&&e.setAttribute("heading",this.api.i18n.t("Heading"))}}removeHeadingAttrFromFirstRow(){for(let t=1;t<=this.numberOfColumns;t++){let e=this.getCell(1,t);e&&e.removeAttribute("heading")}}selectRow(t){const e=this.getRow(t);e&&(this.selectedRow=t,e.classList.add(s.rowSelected))}unselectRow(){if(this.selectedRow<=0)return;const t=this.table.querySelector(`.${s.rowSelected}`);t&&t.classList.remove(s.rowSelected),this.selectedRow=0}selectColumn(t){for(let e=1;e<=this.numberOfRows;e++){const o=this.getCell(e,t);o&&o.classList.add(s.cellSelected)}this.selectedColumn=t}unselectColumn(){if(this.selectedColumn<=0)return;let t=this.table.querySelectorAll(`.${s.cellSelected}`);Array.from(t).forEach(e=>{e.classList.remove(s.cellSelected)}),this.selectedColumn=0}getHoveredCell(t){let e=this.hoveredRow,o=this.hoveredColumn;const{width:i,height:n,x:r,y:h}=k(this.table,t);return r>=0&&(o=this.binSearch(this.numberOfColumns,l=>this.getCell(1,l),({fromLeftBorder:l})=>rr>i-l)),h>=0&&(e=this.binSearch(this.numberOfRows,l=>this.getCell(l,1),({fromTopBorder:l})=>hh>n-l)),{row:e||this.hoveredRow,column:o||this.hoveredColumn}}binSearch(t,e,o,i){let n=0,r=t+1,h=0,l;for(;n!r.textContent.trim())||t.push(i.map(r=>r.innerHTML))}return t}destroy(){document.removeEventListener("click",this.documentClicked)}}class ${static get isReadOnlySupported(){return!0}static get enableLineBreaks(){return!0}constructor({data:t,config:e,api:o,readOnly:i,block:n}){this.api=o,this.readOnly=i,this.config=e,this.data={withHeadings:this.getConfig("withHeadings",!1,t),stretched:this.getConfig("stretched",!1,t),content:t&&t.content?t.content:[]},this.table=null,this.block=n}static get toolbox(){return{icon:A,title:"Table"}}render(){return this.table=new E(this.readOnly,this.api,this.data,this.config),this.container=d("div",this.api.styles.block),this.container.appendChild(this.table.getWrapper()),this.table.setHeadingsSetting(this.data.withHeadings),this.container}renderSettings(){return[{label:this.api.i18n.t("With headings"),icon:T,isActive:this.data.withHeadings,closeOnActivate:!0,toggle:!0,onActivate:()=>{this.data.withHeadings=!0,this.table.setHeadingsSetting(this.data.withHeadings)}},{label:this.api.i18n.t("Without headings"),icon:H,isActive:!this.data.withHeadings,closeOnActivate:!0,toggle:!0,onActivate:()=>{this.data.withHeadings=!1,this.table.setHeadingsSetting(this.data.withHeadings)}},{label:this.data.stretched?this.api.i18n.t("Collapse"):this.api.i18n.t("Stretch"),icon:this.data.stretched?R:O,closeOnActivate:!0,toggle:!0,onActivate:()=>{this.data.stretched=!this.data.stretched,this.block.stretched=this.data.stretched}}]}save(){const t=this.table.getData();return{withHeadings:this.data.withHeadings,stretched:this.data.stretched,content:t}}destroy(){this.table.destroy()}getConfig(t,e=void 0,o=void 0){const i=this.data||o;return i?i[t]?i[t]:e:this.config&&this.config[t]?this.config[t]:e}static get pasteConfig(){return{tags:["TABLE","TR","TH","TD"]}}onPaste(t){const e=t.detail.data,o=e.querySelector(":scope > thead, tr:first-of-type th"),n=Array.from(e.querySelectorAll("tr")).map(r=>Array.from(r.querySelectorAll("th, td")).map(l=>l.innerHTML));this.data={withHeadings:o!==null,content:n},this.table.wrapper&&this.table.wrapper.replaceWith(this.render())}}const I="";return $}); diff --git a/web/vendor/fslightbox/README.md b/web/vendor/fslightbox/README.md new file mode 100644 index 0000000..b06db4d --- /dev/null +++ b/web/vendor/fslightbox/README.md @@ -0,0 +1,55 @@ +# Vanilla JavaScript Fullscreen Lightbox Pro + +## Description +A vanilla JavaScript plug-in without production dependencies for displaying images, videos, or, through custom sources, anything you want in a clean overlying box. +The project's website: https://fslightbox.com. + +## Basic usage +```html + + Open the first slide (an image) + + + Open the second slide (a YouTube video) + + + Open the third slide (an HTML video) + + + Open the fourth slide (a Vimeo video—a custom source) + + + + +``` + +## Documentation +Available at: https://fslightbox.com/javascript/documentation. + +## Browser Compatibility + +| Browser | Works? | +| --- | --- | +| Chrome | Yes | +| Firefox | Yes | +| Opera | Yes | +| Safari | Yes | +| Edge | Yes | +| IE 11 | Yes | diff --git a/web/vendor/fslightbox/fslightbox.js b/web/vendor/fslightbox/fslightbox.js new file mode 100644 index 0000000..a06a899 --- /dev/null +++ b/web/vendor/fslightbox/fslightbox.js @@ -0,0 +1 @@ +!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n=e();for(var o in n)("object"==typeof exports?exports:t)[o]=n[o]}}(self,(()=>(()=>{"use strict";var t={};(t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})})(t);var e,n="fslightbox-",i="".concat(n,"styles"),s="".concat(n,"full-dimension"),r="".concat(n,"flex-centered"),a="".concat(n,"open"),c="".concat(n,"absoluted"),u="".concat(n,"opacity-1"),l="".concat(n,"slide-btn"),d="".concat(l,"-container"),h="".concat(n,"fade-in"),f="".concat(n,"fade-out"),p=h+"-strong",m=f+"-strong",b=("".concat(n,"caption"),"".concat(n,"thumb")),g=b+"s",v="".concat(g,"-loader"),x="".concat(g,"-cursorer"),w="".concat(g,"-inner"),y=b+"-wrapper",C=b+"-invalid";function L(t){return L="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},L(t)}function T(t){var e=t.c,n=t.componentsServices,o=t.core.thumbsRenderDispatcher,i=t.data,s=t.ea,r=t.la,a=(t.stageIndexes,t.ui),c=t.z;function u(){for(var t=0;tt&&c>t?i(t-a):a>t?i(innerWidth-e.thumbsInnerWidth-9):c>t&&i(0)},this.runToThinThumbsActions=function(){S(n.thumbsContainer,r),i(0)};var i=function(t){e.thumbsTransform=t,n.thumbsInner.style.transform="translateX(".concat(t,"px)")}}function I(t){var e=this,n=t.core,o=n.eventsDispatcher,i=n.globalEventsController,s=n.scrollbarRecompensor,r=t.data,c=t.elements,u=t.fs,l=t.p,d=t.props,h=t.qs,f=t.ss,p=t.t,b=t.thumbsSwipingProps,g=t.z;this.isLightboxFadingOut=!1,this.runActions=function(){e.isLightboxFadingOut=!0,c.container.classList.add(m),i.removeListeners(),f.r(),d.exitFullscreenOnClose&&r.ifs&&u.x(),g.r(),p((function(){e.isLightboxFadingOut=!1;for(var n=0;n0?c(s.previous,"ne"):void 0!==s.next&&o.swipedX<0&&c(s.next,"p")},this.zs=function(t){o.swipedX=(t.screenX-o.downScreenX)/a,o.swipedY=(t.screenY-o.downScreenY)/a,i[s.current].v(o.ux+o.swipedX,o.uy+o.swipedY).z()}}function B(t,e){var n=t.c,o=t.dss,i=t.p,s=t.r,r=t.zv,a=s(k);if(i.isPinching)return a.a(e),void a.p();2!==i.pc&&(1===r?1===n||o?i.swipedX=1:(a.a(e),a.s()):(a.a(e),a.zs(e)))}function W(t){var e=t.core,n=e.clickZoomer,o=e.slideIndexChanger,i=t.p,s=t.smw,r=t.stageIndexes,a=t.sws,c=t.zv;function u(t){var e=s[r.current];e.a(),e[t]()}function l(t,e){void 0!==t&&(s[t].s(),s[t][e]())}this.p=function(){var t=r.previous;if(void 0===t)u("z");else{u("p");var e=r.next;o.changeTo(t);var n=r.previous;a.d(n),a.b(e),u("z"),l(n,"ne")}},this.n=function(){var t=r.next;if(void 0===t)u("z");else{u("ne");var e=r.previous;o.changeTo(t);var n=r.next;a.d(n),a.b(e),u("z"),l(n,"p")}},this.s=function(){var t=s[r.current];i.ux=t.gx(),i.uy=t.gy()},this.d=function(){c<=1?n.zoomIn():n.zoomOut()}}function M(t,e){t.contains(e)&&t.removeChild(e)}function H(t){t.componentsServices;var e=t.core,n=e.lightboxCloser,o=e.pointeringBucket,i=t.dss,s=t.elements,r=t.p,a=t.props.disableBackgroundClose,c=t.r,u=t.swc,l=(t.ui,t.zv),d=c(W);this.a=function(){M(s.container,t.h),r.isPinching=!1,r.pinchedHypot=0,o.runSwipingTopActionsForPropsAndEvent(r),u.classList.remove("fslightboxswcp")},this.s=function(){1===l?i||(r.swipedX>0?d.p():d.n()):d.s()},this.n=function(t){"VIDEO"!==t.target.tagName&&(r.sd?d.d():a||n.close())}}function D(t,e){var n=t.p;n.p[e.pointerId]={screenX:e.screenX,screenY:e.screenY};var o=Object.keys(n.p).length;return n.pc=o,o<=2}function O(t){var e=t.core.pointeringBucket,n=t.data,o=t.elements,i=t.thumbsSwipingProps;this.runActions=function(t){e.runSwipingMoveActionsForPropsAndEvent(i,t),o.thumbsInner.style.transform="translateX(".concat(n.thumbsTransform+i.swipedX,"px)"),o.thumbsContainer.contains(o.thumbsCursorer)||o.thumbsContainer.appendChild(o.thumbsCursorer)}}function P(t){var e=t.data,n=t.resolve,o=t.thumbsSwipingProps,i=n(O),s=window.innerWidth;this.listener=function(t){e.thumbsInnerWidth>s&&o.i&&i.runActions(t)}}function R(t){var e=t.data,n=t.core,o=n.slideIndexChanger,i=n.thumbsTransformTransitioner,s=n.pointeringBucket,r=t.elements,a=t.thumbsSwipingProps,c=r.thumbsWrappers;this.runNoSwipeActionsForEvent=function(t){M(r.thumbsContainer,r.thumbsCursorer),a.i=!1;for(var e=0;e0)return u(0);e.thumbsTransform0)return;n.b()}var i=.1*o,s=o;e.deltaY<0?s+=i:(s-=i)<1&&(s=1),n.z(s),1===s&&n.e()}(t,e))}}function Y(t,e){var n=t.core,i=n.clickZoomer,s=n.lightboxCloser,r=n.slideChangeFacade,a=n.thumbsToggler,c=t.fs,u=(t.middleware,t.props),l=t.ss;if(t.ui.qps(),"Space"!==e.code)switch(e.key){case"Escape":s.close();break;case"ArrowLeft":r.changeToPrevious();break;case"ArrowRight":r.changeToNext();break;case"t":u.disableThumbs||a.toggleThumbs();break;case"+":o.p.i||i.zoomIn();break;case"-":o.p.i||i.zoomOut();break;case"F11":e.preventDefault(),c.t()}else l.t()}function j(t,e,o,i,s){var r=document.createElementNS("http://www.w3.org/2000/svg","svg");r.setAttributeNS(null,"width",e),r.setAttributeNS(null,"height",e),r.setAttributeNS(null,"viewBox",i);var a=document.createElementNS("http://www.w3.org/2000/svg","path");return a.setAttributeNS(null,"class","".concat(n,"svg-path")),a.setAttributeNS(null,"d",s),r.appendChild(a),t.appendChild(r),r}function V(t,e){var o=document.createElement("div");return o.className="".concat(n,"toolbar-button ").concat(r),o.title=e,t.appendChild(o),o}function U(t,e,n){var o=V(t,e.title);o.onclick=n,j(o,e.width,e.height,e.viewBox,e.d)}function Z(t){var e=t.props.sources,o=t.elements,i=document.createElement("div");o.nav=i,i.className="".concat(n,"nav"),o.container.appendChild(i),function(t,e){var o=t.core,i=o.clickZoomer,s=i.zoomIn,r=i.zoomOut,a=o.lightboxCloser.close,c=o.thumbsToggler,u=t.props,l=u.customToolbarButtons,d=u.disableThumbs,h=u.toolbarButtons,f=document.createElement("div");f.className="".concat(n,"toolbar"),e.appendChild(f);for(var p=function(e){U(f,l[e],(function(){return l[e].onClick(t)}))},m=0;m1&&function(t,e){var o=t.componentsServices,i=t.props.sources,s=document.createElement("div");s.className="".concat(n,"slide-number-container");var a=document.createElement("div");a.className=r;var c=document.createElement("span");o.setSlideNumber=function(t){return c.innerHTML=t};var u=document.createElement("span");u.className="".concat(n,"slash");var l=document.createElement("div");l.innerHTML=i.length,s.appendChild(a),a.appendChild(c),a.appendChild(u),a.appendChild(l),e.appendChild(s),setTimeout((function(){a.offsetWidth>55&&(s.style.justifyContent="flex-start")}))}(t,i)}function _(t,e){var n=t.c,o=t.core.pointeringBucket,i=t.elements.sources,s=t.p,r=t.smw,a=t.stageIndexes,c=t.swc,u=t.z,l=t.zv;if("touch"!==e.pointerType&&"IMG"===e.target.tagName&&e.preventDefault(),o.runSwipingDownActionsForPropsAndEvent(s,e),s.downScreenY=e.screenY,2===s.pc)s.isPinching=!0,s.pinchedHypot=N(s),c.classList.add("fslightboxswcp"),1===l&&u.b();else for(var d=0;d0&&void 0!==arguments[0]?arguments[0]:t.mh,i=t.mw;return(a=i/r)e?e:o)*r,a]},this.d=function(){return c}}function ct(t,e){var n=this,o=t.elements.sources,i=t.isl,s=t.la,r=t.props.initialAnimation,a=t.resolve,c=t.saw,l=t.sew,d=t.sz;function h(t,n){d[e]=a(at,[e,t,n]),d[e].s()}this.a=function(t,a){i[e]=!0,o[e].classList.add(u),c[e].classList.add(r),c[e].removeChild(c[e].firstChild),requestAnimationFrame((function(){requestAnimationFrame((function(){l[e].classList.add("fslightboxtt")}))})),h(t,a),s.s(e),s.t(e),n.a=h}}function ut(t,e){var n,o=this,i=t.elements.sources,s=t.props,r=(0,t.resolve)(ct,[e]);this.handleImageLoad=function(t){var e=t.target,n=e.naturalWidth,o=e.naturalHeight;r.a(n,o)},this.handleVideoLoad=function(t){var e=t.target,o=e.videoWidth,i=e.videoHeight;n=!0,r.a(o,i)},this.handleNotMetaDatedVideoLoad=function(){n||o.handleYoutubeLoad()},this.handleYoutubeLoad=function(){var t=1920,e=1080;s.maxYoutubeDimensions&&(t=s.maxYoutubeDimensions.width,e=s.maxYoutubeDimensions.height),r.a(t,e)},this.handleCustomLoad=function(){var t=i[e];t.offsetWidth&&t.offsetHeight?r.a(t.offsetWidth,t.offsetHeight):setTimeout(o.handleCustomLoad)}}function lt(t,e){var n=t.elements.sources,o=t.props.customAttributes,i=n[e];for(var s in o[e]){var r=o[e][s];"class"!==s?i.setAttribute(s,r):i.classList.add("a")}}function dt(t,e){var n=t.collections.sourceLoadHandlers,o=t.elements.sources,i=t.props.sources,s=t.saw,r=document.createElement("img");o[e]=r,r.className="fslightboxs",r.src=i[e],r.onload=n[e].handleImageLoad,lt(t,e),s[e].appendChild(r)}function ht(t,e){var n=t.collections.sourceLoadHandlers,o=t.elements.sources,i=t.props.sources,s=t.saw,r=document.createElement("video"),a=document.createElement("source");o[e]=r,r.className="fslightboxs",r.src=i[e],r.onloadedmetadata=function(t){n[e].handleVideoLoad(t)},r.controls=!0,lt(t,e),r.appendChild(a),setTimeout(n[e].handleNotMetaDatedVideoLoad,3e3),s[e].appendChild(r)}function ft(t,e){var n=t.collections.sourceLoadHandlers,o=t.elements,i=o.sources,s=o.saw,r=t.props.sources,a=(s=t.saw,document.createElement("iframe")),c=r[e],u=c.split("?")[1];i[e]=a,a.className="fslightboxs fslightboxyt",a.src="https://www.youtube.com/embed/".concat(c.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/)[2],"?").concat(u||""),a.allowFullscreen=!0,lt(t,e),s[e].appendChild(a),n[e].handleYoutubeLoad()}function pt(t,e){var n=t.collections.sourceLoadHandlers,o=t.elements.sources,i=t.props.sources,s=t.saw,r=i[e];o[e]=r,r.classList.add("fslightboxs"),lt(t,e),s[e].appendChild(r),n[e].handleCustomLoad()}function mt(t,e){t.data.isSourceLoaded;var n,o,i=t.elements.sources,s=t.props,a=s.initialAnimation;return s.sources,n=t.saw,o=document.createElement("div"),n=n[e],o.className="fslightboxin ".concat(r),o.innerHTML="Invalid source",n.removeChild(n.firstChild),i[e]=o,n.classList.add(a),void n.appendChild(o)}function bt(t,e,n){var o=t.props.thumbsIcons;if(o[n]){e.appendChild(o[n].cloneNode(!0));var i=document.createElement("div");i.className="fslightboxtd",e.appendChild(i)}}function gt(t,e,n){var o=t.elements,i=o.thumbsWrappers,s=o.thumbsInner;i[e]=document.createElement("div"),i[e].className=y,bt(t,i[e],e),function(t,e,n,o){var i=t.core.thumbLoadHandler.handleLoad,s=t.elements.thumbs,r=t.stageIndexes.current;s[n]=document.createElement("img"),s[n].src=o;var a=b;r===n&&(a+=" fslightboxta"),s[n].className=a,s[n].onload=i,e.appendChild(s[n])}(t,i[e],e,n),s.appendChild(i[e])}function vt(t){var e=t.core.thumbsRenderDispatcher,n=t.data,o=t.props,i=o.showThumbsOnMount,s=o.sources,a=o.thumbs;this.buildThumbForTypeAndIndex=function(o,c){var u;u=a[c]?function(){return gt(t,c,a[c])}:o===nt?function(){return gt(t,c,s[c])}:function(){return function(t,e){var n=t.elements,o=n.thumbsWrappers,i=n.thumbsInner;o[e]=document.createElement("div"),o[e].className="".concat(C," ").concat(y),bt(t,o[e],e),function(t,e,n){var o=t.core.thumbLoadHandler.handleLoad,i=t.elements.thumbs,s=t.stageIndexes.current;i[n]=document.createElement("div");var a="".concat(b," ").concat(r);s===n&&(a+=" fslightboxta"),i[n].className=a,j(i[n],"22px",0,"0 0 30 30","M15,3C8.373,3,3,8.373,3,15c0,6.627,5.373,12,12,12s12-5.373,12-12C27,8.373,21.627,3,15,3z M16.212,8l-0.2,9h-2.024l-0.2-9 H16.212z M15.003,22.189c-0.828,0-1.323-0.441-1.323-1.182c0-0.755,0.494-1.196,1.323-1.196c0.822,0,1.316,0.441,1.316,1.196 C16.319,21.748,15.825,22.189,15.003,22.189z"),e.appendChild(i[n]),setTimeout(o)}(t,o[e],e),i.appendChild(o[e])}(t,c)},e.addFunctionToToBeRenderedAtIndex(u,c),(i||n.isThumbing)&&e.renderThumbsIfNotYetAndAllTypesDetected()}}function xt(t){var e,n=t.collections,o=n.sourceLoadHandlers,i=n.sourcesRenderFunctions,s=t.core.sourceDisplayFacade,r=t.props.disableThumbs,a=t.resolve;r||(e=a(vt)),this.runActionsForSourceTypeAndIndex=function(n,c){var u;switch(n!==rt&&(o[c]=a(ut,[c])),n){case nt:u=dt;break;case ot:u=ht;break;case it:u=ft;break;case st:u=pt;break;default:u=mt}i[c]=function(){return u(t,c)},s.displaySourcesWhichShouldBeDisplayed(),r||e.buildThumbForTypeAndIndex(n,c)}}function wt(t,e,n){var o=t.props,i=o.types,s=o.type,r=o.sources;this.getTypeSetByClientForIndex=function(t){var e;return i&&i[t]?e=i[t]:s&&(e=s),e},this.retrieveTypeWithXhrForIndex=function(t){!function(t,e){var n=document.createElement("a");n.href=t;var o=n.hostname;if("www.youtube.com"===o||"youtu.be"===o)return e(it);var i=new XMLHttpRequest;i.onreadystatechange=function(){if(4!==i.readyState){if(2===i.readyState){var t,n=i.getResponseHeader("content-type");switch(n.slice(0,n.indexOf("/"))){case"image":t=nt;break;case"video":t=ot;break;default:t=rt}i.onreadystatechange=null,i.abort(),e(t)}}else e(rt)},i.open("GET",t),i.send()}(r[t],(function(o){e.handleReceivedSourceTypeForUrl(o,r[t]),n.runActionsForSourceTypeAndIndex(o,t)}))}}function yt(t){var e=t.props.sources,n=t.st,o=t.stageIndexes,i=e.length-1;n.getPreviousSlideIndex=function(){return 0===o.current?i:o.current-1},n.getNextSlideIndex=function(){return o.current===i?0:o.current+1},n.u=0===i?function(){}:1===i?function(){0===o.current?(o.next=1,delete o.previous):(o.previous=0,delete o.next)}:function(){o.previous=n.getPreviousSlideIndex(),o.next=n.getNextSlideIndex()},n.i=i<=2?function(){return!0}:function(t){var e=o.current;if(0===e&&t===i||e===i&&0===t)return!0;var n=e-t;return-1===n||0===n||1===n}}function Ct(t){var e=t.componentsServices,o=t.core,i=o.eventsDispatcher,r=(o.lightboxOpener,o.globalEventsController),l=o.scrollbarRecompensor,d=o.sourceDisplayFacade,h=t.data,m=t.ea,b=t.elements,y=t.la,C=t.smw,L=t.st,N=t.stageIndexes,k=t.sws,B=t.ui,W=!1;function M(){var e,o=t.props,r=o.disableThumbs,a=o.showThumbsOnMount,l=o.sources;W=!0,function(t){var e=t.props;t.dss=e.disableSlideSwiping,t.dt=e.disableThumbs,t.c=e.sources.length,t.tc=e.showThumbsWithCaptions}(t),h.scrollbarWidth=function(){var t=document.createElement("div"),e=t.style,n=document.createElement("div");e.visibility="hidden",e.width="100px",e.msOverflowStyle="scrollbar",e.overflow="scroll",n.style.width="100%",document.body.appendChild(t);var o=t.offsetWidth;t.appendChild(n);var i=n.offsetWidth;return document.body.removeChild(t),o-i}(),h.unloadedThumbsCount=l.length,r||(h.isThumbing=a,function(t){var e=t.core,n=t.data,o=t.elements,i=t.props;n.isThumbing=i.showThumbsOnMount,n.thumbsInnerWidth=null,n.thumbsTransform=0,n.thumbedSourceEnhancementWrapperScale=null,n.thumbedSourceEnhancementWrapperTranslateY=null,n.unloadedThumbsCount=i.sources.length,t.thumbsSwipingProps={i:!1,downScreenX:null,swipedX:null},e.thumbLoadHandler={},e.thumbsRenderDispatcher={},e.thumbsSwipingDown={},e.thumbsToggler={},e.thumbsTransformer={},e.thumbsTransformTransitioner={},o.thumbsContainer=null,o.thumbs=[],o.thumbsWrappers=[],o.thumbsComponents=[],o.thumbsInner=null,function(t){var e=t.core.thumbLoadHandler,n=t.componentsServices,o=t.data,i=t.elements.thumbsWrappers,s=t.la;e.handleLoad=function(){if(o.unloadedThumbsCount--,0===o.unloadedThumbsCount){for(var t=0;tinnerWidth?s.runActions():s.runToThinThumbsActions()},n.transformToCurrentWithTransition=function(){i.thumbsInnerWidth>innerWidth&&o.callActionWithTransition(s.runActions)}}(t),function(t){var e=t.core.thumbsTransformTransitioner,n=t.elements,o=(0,t.q)((function(){n.thumbsInner.classList.remove("fslightboxtt")}),300);e.callActionWithTransition=function(t){n.thumbsInner.classList.add("fslightboxtt"),t(),o()}}(t)}(t)),function(t){!function(t){var e=t.core,n=e.classFacade,o=e.st,i=t.elements;n.removeFromEachElementClassIfContains=function(t,e){for(var n=0;nwindow.innerHeight&&(document.body.style.marginRight=e.scrollbarWidth+"px")};n.removeRecompense=function(){document.body.style.removeProperty("margin-right")}}(t),function(t){var e=t.c,n=t.core.thumbsTransformer,o=t.data,i=t.dt,s=t.elements,r=t.f,a=t.isl,c=t.la,u=t.props.sourceMargin,l=t.sew,d=t.smw,h=t.sz,f=t.stageIndexes,p=t.tc,m=s.captions,b=s.thumbs,g=1-2*u,v=1-u,x=[],w=[],y=[],C=[],L=[],T=0;function z(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;l[arguments.length>2?arguments[2]:void 0].style.transform="translateY(".concat(t,"px) scale(").concat(e,")")}c.r=function(){innerWidth>992?t.mw=g*innerWidth:t.mw=innerWidth,t.mh=g*innerHeight,0===o.unloadedThumbsCount&&c.rt(),void 0!==f.previous&&d[f.previous].ne(),void 0!==f.next&&d[f.next].p(),r((function(t){var e=h[t],n=m[t];e&&e.s(),n&&(x[t]=n.offsetHeight),i||(T=s.thumbsContainer.offsetHeight),c.s(t),d[t].d(),c.t(t)}))},c.s=function(t){var e=h[t];if(e){var n=e.d(),o=n[0]+n[1];if(x[t]){var s=e.g(innerHeight*v-x[t]);w[t]=(s[0]+s[1])/o,L[t]=-(x[t]-innerHeight/2+s[1]/2),L[t]>0&&(L[t]=0)}if(!i){if(p&&x[t]){var r=T+x[t];a=e.g((innerHeight-r)*(1-1.4*u)+34),y[t]=(a[0]+a[1])/o,C[t]=-(r-34-innerHeight/2+a[1]/2)}else{var a=e.g(innerHeight*v-T);y[t]=(a[0]+a[1])/o,C[t]=-(T-innerHeight/2+a[1]/2)}C[t]>0&&(C[t]=0)}}},c.t=function(e){a[e]&&(1!==t.zv?z(0,1,e):o.isThumbing?z(C[e],y[e],e):z(L[e],w[e],e))},c.ut=function(){r((function(t){a[t]&&z(L[t],w[t],t)}))},c.rt=function(){o.thumbsInnerWidth=0;for(var t=0;t1?(n.changeToPrevious=function(){o.jumpTo(s.getPreviousSlideIndex())},n.changeToNext=function(){o.jumpTo(s.getNextSlideIndex())}):(n.changeToPrevious=function(){},n.changeToNext=function(){})}(t),function(t){var e=t.componentsServices,n=t.core,o=n.eventsDispatcher,i=n.slideIndexChanger,s=n.sourceDisplayFacade,r=n.thumbsTransformer,a=t.ea,c=t.isl,u=t.props.disableThumbs,l=t.resolve,d=t.smw,h=t.st,f=t.stageIndexes,p=t.sws,m=t.z;i.changeTo=function(t){var n=f.current;m.r(),a.c(n,t),f.current=t,h.u(),e.setSlideNumber(t+1),u||(a.t(n,t),r.transformToCurrentWithTransition()),s.displaySourcesWhichShouldBeDisplayed(),o.dispatch("onSlideChange")},i.jumpTo=function(t){var e=f.current;if(e!==t){var n=l(E,[{previous:f.previous,current:e,next:f.next},c[e],c[t]]);i.changeTo(t);for(var o=0;o1&&(Q(e=t,"previous"),Q(e,"next")),r||function(t){var e=t.componentsServices,n=t.elements,o=t.data;n.thumbsContainer=document.createElement("div");var i,r,a=g;function u(){r=!0,(i=J(n.thumbsContainer)).classList.add(v)}o.isThumbing?u():a+=" fslightboxx",e.appendThumbsLoaderIfNotYet=function(){r||u()},e.hideThumbsLoader=function(){n.thumbsContainer.removeChild(i)},n.thumbsContainer.className=a,n.container.appendChild(n.thumbsContainer),function(t){var e=t.elements;e.thumbsCursorer=document.createElement("div"),e.thumbsCursorer.className="".concat(x," ").concat(s," ").concat(c)}(t),function(t){var e=t.core.thumbsSwipingDown.listener,n=t.elements;n.thumbsInner=document.createElement("div"),n.thumbsInner.className=w,n.thumbsInner.addEventListener("pointerdown",e),n.thumbsContainer.appendChild(n.thumbsInner)}(t)}(t),function(t){for(var e=t.props.sources,n=t.resolve,o=n(et),i=n(xt),s=n(wt,[o,i]),r=0;r0&&void 0!==arguments[0]?arguments[0]:0,o=N.previous,s=N.current,c=N.next;N.current=n,W||yt(t),L.u(),W?(k.c(),k.a(),k.b(o),k.b(s),k.b(c),m.c(s,N.current),m.t(s,N.current),i.dispatch("onShow")):M(),d.displaySourcesWhichShouldBeDisplayed(),e.setSlideNumber(n+1),document.body.appendChild(b.container),document.documentElement.classList.add(a),l.addRecompense(),r.addListeners(),y.r(),C[N.current].n(),B.q(),i.dispatch("onOpen")}}function Lt(t,e,n){return Lt=Tt()?Reflect.construct.bind():function(t,e,n){var o=[null];o.push.apply(o,e);var i=new(Function.bind.apply(t,o));return n&&zt(i,n.prototype),i},Lt.apply(null,arguments)}function Tt(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(t){return!1}}function zt(t,e){return zt=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t},zt(t,e)}function St(t){return function(t){if(Array.isArray(t))return At(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return At(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?At(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function At(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=new Array(e);n1&&void 0!==arguments[1]?arguments[1]:[];return n.unshift(t),Lt(e,St(n))},this.r=this.resolve,this.collections={sourceLoadHandlers:[],sourcesRenderFunctions:[]},this.sz=[],this.core={classFacade:{},clickZoomer:{},eventsDispatcher:{},globalEventsController:{},lightboxCloser:{},lightboxUpdater:{},pointeringBucket:{},scrollbarRecompensor:{},slideChangeFacade:{},slideIndexChanger:{},sourceDisplayFacade:{},swipingActioner:{}},this.ea={},this.fs={},this.la={},this.ss={},this.st={},this.sws={},this.ui={},this.z={},this.t=function(e,n){var o=t.ts.push(setTimeout((function(){delete t.ts[o-1],e()}),n))},this.q=function(e,n){var o=t.qs.push(0)-1;return function(){t.qs[o]++,t.t((function(){t.qs[o]--,t.qs[o]||e()}),n)}},Ct(this),this.close=function(){return t.core.lightboxCloser.close()}},window.fsLightboxInstances={},It(),window.refreshFsLightbox=function(){for(var t in fsLightboxInstances){var e=fsLightboxInstances[t].props;fsLightboxInstances[t]=new FsLightbox,fsLightboxInstances[t].props=e,fsLightboxInstances[t].props.sources=[],fsLightboxInstances[t].elements.a=[]}It()},t})())); \ No newline at end of file diff --git a/web/vendor/fslightbox/package.json b/web/vendor/fslightbox/package.json new file mode 100644 index 0000000..d605ec7 --- /dev/null +++ b/web/vendor/fslightbox/package.json @@ -0,0 +1,22 @@ +{ + "name": "fslightbox", + "version": "3.6.2", + "description": "A vanilla JavaScript plug-in without production dependencies for dispalying images, videos, or, through custom sources, anything you want in a clean overlying box.", + "author": "Piotr Zdziarski", + "homepage": "https://fslightbox.com", + "main": "fslightbox.js", + "scripts": { + "w": "webpack-dev-server --host 0.0.0.0", + "p": "webpack --config ./webpack.prod.config.js" + }, + "devDependencies": { + "@babel/core": "^7.4.4", + "@babel/preset-env": "^7.4.4", + "@babel/register": "^7.4.4", + "babel-loader": "^8.0.5", + "html-webpack-plugin": "^5.0.0", + "webpack": "^5.0.0", + "webpack-cli": "^4.0.0", + "webpack-dev-server": "^4.0.0" + } +} \ No newline at end of file diff --git a/web/vendor/gridjs/gridjs.umd.js b/web/vendor/gridjs/gridjs.umd.js new file mode 100644 index 0000000..31761d7 --- /dev/null +++ b/web/vendor/gridjs/gridjs.umd.js @@ -0,0 +1,2 @@ +!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t||self).gridjs={})}(this,function(t){function n(t,n){for(var e=0;et.length)&&(n=t.length);for(var e=0,r=new Array(n);e=t.length?{done:!0}:{done:!1,value:t[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var l;!function(t){t[t.Init=0]="Init",t[t.Loading=1]="Loading",t[t.Loaded=2]="Loaded",t[t.Rendered=3]="Rendered",t[t.Error=4]="Error"}(l||(l={}));var c,f,p,d,h,_,m,v={},g=[],y=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function b(t,n){for(var e in n)t[e]=n[e];return t}function w(t){var n=t.parentNode;n&&n.removeChild(t)}function x(t,n,e){var r,o,i,u={};for(i in n)"key"==i?r=n[i]:"ref"==i?o=n[i]:u[i]=n[i];if(arguments.length>2&&(u.children=arguments.length>3?c.call(arguments,2):e),"function"==typeof t&&null!=t.defaultProps)for(i in t.defaultProps)void 0===u[i]&&(u[i]=t.defaultProps[i]);return k(t,u,r,o,null)}function k(t,n,e,r,o){var i={type:t,props:n,key:e,ref:r,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==o?++p:o};return null==o&&null!=f.vnode&&f.vnode(i),i}function P(t){return t.children}function S(t,n){this.props=t,this.context=n}function N(t,n){if(null==n)return t.__?N(t.__,t.__.__k.indexOf(t)+1):null;for(var e;n0?k(d.type,d.props,d.key,d.ref?d.ref:null,d.__v):d)){if(d.__=e,d.__b=e.__b+1,null===(p=y[c])||p&&d.key==p.key&&d.type===p.type)y[c]=void 0;else for(f=0;f0&&(this.callbacks[e].forEach(function(t){return t.apply(void 0,[].slice.call(n,1))}),!0)},t}();function Y(t,n){if(typeof t!=typeof n)return!1;if(null===t&&null===n)return!0;if("object"!=typeof t)return t===n;if(Array.isArray(t)&&Array.isArray(n)){if(t.length!==n.length)return!1;for(var e=0;e=e.__.length&&e.__.push({__V:ft}),e.__[t]}function gt(t){return lt=1,function(t,n,e){var r=vt(ot++,2);if(r.t=t,!r.__c&&(r.__=[Et(void 0,n),function(t){var n=r.__N?r.__N[0]:r.__[0],e=r.t(n,t);n!==e&&(r.__N=[e,r.__[1]],r.__c.setState({}))}],r.__c=it,!it.u)){it.u=!0;var o=it.shouldComponentUpdate;it.shouldComponentUpdate=function(t,n,e){if(!r.__c.__H)return!0;var i=r.__c.__H.__.filter(function(t){return t.__c});if(i.every(function(t){return!t.__N}))return!o||o.call(this,t,n,e);var u=!1;return i.forEach(function(t){if(t.__N){var n=t.__[0];t.__=t.__N,t.__N=void 0,n!==t.__[0]&&(u=!0)}}),!(!u&&r.__c.props===t)&&(!o||o.call(this,t,n,e))}}return r.__N||r.__}(Et,t)}function yt(t,n){var e=vt(ot++,3);!f.__s&&Ct(e.__H,n)&&(e.__=t,e.i=n,it.__H.__h.push(e))}function bt(t){return lt=5,wt(function(){return{current:t}},[])}function wt(t,n){var e=vt(ot++,7);return Ct(e.__H,n)?(e.__V=t(),e.i=n,e.__h=t,e.__V):e.__}function xt(){for(var t;t=ct.shift();)if(t.__P&&t.__H)try{t.__H.__h.forEach(St),t.__H.__h.forEach(Nt),t.__H.__h=[]}catch(n){t.__H.__h=[],f.__e(n,t.__v)}}f.__b=function(t){it=null,pt&&pt(t)},f.__r=function(t){dt&&dt(t),ot=0;var n=(it=t.__c).__H;n&&(ut===it?(n.__h=[],it.__h=[],n.__.forEach(function(t){t.__N&&(t.__=t.__N),t.__V=ft,t.__N=t.i=void 0})):(n.__h.forEach(St),n.__h.forEach(Nt),n.__h=[])),ut=it},f.diffed=function(t){ht&&ht(t);var n=t.__c;n&&n.__H&&(n.__H.__h.length&&(1!==ct.push(n)&&st===f.requestAnimationFrame||((st=f.requestAnimationFrame)||Pt)(xt)),n.__H.__.forEach(function(t){t.i&&(t.__H=t.i),t.__V!==ft&&(t.__=t.__V),t.i=void 0,t.__V=ft})),ut=it=null},f.__c=function(t,n){n.some(function(t){try{t.__h.forEach(St),t.__h=t.__h.filter(function(t){return!t.__||Nt(t)})}catch(e){n.some(function(t){t.__h&&(t.__h=[])}),n=[],f.__e(e,t.__v)}}),_t&&_t(t,n)},f.unmount=function(t){mt&&mt(t);var n,e=t.__c;e&&e.__H&&(e.__H.__.forEach(function(t){try{St(t)}catch(t){n=t}}),e.__H=void 0,n&&f.__e(n,e.__v))};var kt="function"==typeof requestAnimationFrame;function Pt(t){var n,e=function(){clearTimeout(r),kt&&cancelAnimationFrame(n),setTimeout(t)},r=setTimeout(e,100);kt&&(n=requestAnimationFrame(e))}function St(t){var n=it,e=t.__c;"function"==typeof e&&(t.__c=void 0,e()),it=n}function Nt(t){var n=it;t.__c=t.__(),it=n}function Ct(t,n){return!t||t.length!==n.length||n.some(function(n,e){return n!==t[e]})}function Et(t,n){return"function"==typeof n?n(t):n}function It(){return function(t){var n=it.context[t.__c],e=vt(ot++,9);return e.c=t,n?(null==e.__&&(e.__=!0,n.sub(it)),n.props.value):t.__}(fn)}var Tt={search:{placeholder:"Type a keyword..."},sort:{sortAsc:"Sort column ascending",sortDesc:"Sort column descending"},pagination:{previous:"Previous",next:"Next",navigate:function(t,n){return"Page "+t+" of "+n},page:function(t){return"Page "+t},showing:"Showing",of:"of",to:"to",results:"results"},loading:"Loading...",noRecordsFound:"No matching records found",error:"An error happened while fetching the data"},Lt=/*#__PURE__*/function(){function t(t){this._language=void 0,this._defaultLanguage=void 0,this._language=t,this._defaultLanguage=Tt}var n=t.prototype;return n.getString=function(t,n){if(!n||!t)return null;var e=t.split("."),r=e[0];if(n[r]){var o=n[r];return"string"==typeof o?function(){return o}:"function"==typeof o?o:this.getString(e.slice(1).join("."),o)}return null},n.translate=function(t){var n,e=this.getString(t,this._language);return(n=e||this.getString(t,this._defaultLanguage))?n.apply(void 0,[].slice.call(arguments,1)):t},t}();function At(){var t=It();return function(n){var e;return(e=t.translator).translate.apply(e,[n].concat([].slice.call(arguments,1)))}}var Ot=function(t){return function(n){return r({},n,{search:{keyword:t}})}};function jt(){return It().store}function Ht(t){var n=jt(),e=gt(t(n.getState())),r=e[0],o=e[1];return yt(function(){return n.subscribe(function(){var e=t(n.getState());r!==e&&o(e)})},[]),r}function Dt(){var t,n=gt(void 0),e=n[0],r=n[1],o=It(),i=o.search,u=At(),s=jt().dispatch,a=Ht(function(t){return t.search});yt(function(){e&&e.setProps({keyword:null==a?void 0:a.keyword})},[a,e]),yt(function(){r(i.server?new at({keyword:i.keyword,url:i.server.url,body:i.server.body}):new nt({keyword:i.keyword,columns:o.header&&o.header.columns,ignoreHiddenColumns:i.ignoreHiddenColumns||void 0===i.ignoreHiddenColumns,selector:i.selector})),i.keyword&&s(Ot(i.keyword))},[i]),yt(function(){if(e)return o.pipeline.register(e),function(){return o.pipeline.unregister(e)}},[o,e]);var l,c,f,p=function(t,n){return lt=8,wt(function(){return t},n)}((l=function(t){t.target instanceof HTMLInputElement&&s(Ot(t.target.value))},c=e instanceof at?i.debounceTimeout||250:0,function(){var t=arguments;return new Promise(function(n){f&&clearTimeout(f),f=setTimeout(function(){return n(l.apply(void 0,[].slice.call(t)))},c)})}),[i,e]);return x("div",{className:et(rt("search",null==(t=o.className)?void 0:t.search))},x("input",{type:"search",placeholder:u("search.placeholder"),"aria-label":u("search.placeholder"),onInput:p,className:rt(et("input"),et("search","input")),defaultValue:(null==a?void 0:a.keyword)||""}))}var Mt=/*#__PURE__*/function(t){function n(){return t.apply(this,arguments)||this}o(n,t);var r=n.prototype;return r.validateProps=function(){if(isNaN(Number(this.props.limit))||isNaN(Number(this.props.page)))throw Error("Invalid parameters passed")},r._process=function(t){var n=this.props.page;return new J(t.rows.slice(n*this.props.limit,(n+1)*this.props.limit))},e(n,[{key:"type",get:function(){return K.Limit}}]),n}(tt),Rt=/*#__PURE__*/function(t){function n(){return t.apply(this,arguments)||this}return o(n,t),n.prototype._process=function(t){var n={};return this.props.url&&(n.url=this.props.url(t.url,this.props.page,this.props.limit)),this.props.body&&(n.body=this.props.body(t.body,this.props.page,this.props.limit)),r({},t,n)},e(n,[{key:"type",get:function(){return K.ServerLimit}}]),n}(tt);function Ft(){var t=It(),n=t.pagination,e=n.server,r=n.summary,o=void 0===r||r,i=n.nextButton,u=void 0===i||i,s=n.prevButton,a=void 0===s||s,l=n.buttonsCount,c=void 0===l?3:l,f=n.limit,p=void 0===f?10:f,d=n.page,h=void 0===d?0:d,_=n.resetPageOnUpdate,m=void 0===_||_,v=bt(null),g=gt(h),y=g[0],b=g[1],w=gt(0),k=w[0],S=w[1],N=At();yt(function(){return e?(v.current=new Rt({limit:p,page:y,url:e.url,body:e.body}),t.pipeline.register(v.current)):(v.current=new Mt({limit:p,page:y}),t.pipeline.register(v.current)),v.current instanceof Rt?t.pipeline.on("afterProcess",function(t){return S(t.length)}):v.current instanceof Mt&&v.current.on("beforeProcess",function(t){return S(t.length)}),t.pipeline.on("updated",C),t.pipeline.on("error",function(){S(0),b(0)}),function(){t.pipeline.unregister(v.current),t.pipeline.off("updated",C)}},[]);var C=function(t){m&&t!==v.current&&(b(0),0!==v.current.props.page&&v.current.setProps({page:0}))},E=function(){return Math.ceil(k/p)},I=function(t){if(t>=E()||t<0||t===y)return null;b(t),v.current.setProps({page:t})};return x("div",{className:rt(et("pagination"),t.className.pagination)},x(P,null,o&&k>0&&x("div",{role:"status","aria-live":"polite",className:rt(et("summary"),t.className.paginationSummary),title:N("pagination.navigate",y+1,E())},N("pagination.showing")," ",x("b",null,N(""+(y*p+1)))," ",N("pagination.to")," ",x("b",null,N(""+Math.min((y+1)*p,k)))," ",N("pagination.of")," ",x("b",null,N(""+k))," ",N("pagination.results"))),x("div",{className:et("pages")},a&&x("button",{tabIndex:0,role:"button",disabled:0===y,onClick:function(){return I(y-1)},title:N("pagination.previous"),"aria-label":N("pagination.previous"),className:rt(t.className.paginationButton,t.className.paginationButtonPrev)},N("pagination.previous")),function(){if(c<=0)return null;var n=Math.min(E(),c),e=Math.min(y,Math.floor(n/2));return y+Math.floor(n/2)>=E()&&(e=n-(E()-y)),x(P,null,E()>n&&y-e>0&&x(P,null,x("button",{tabIndex:0,role:"button",onClick:function(){return I(0)},title:N("pagination.firstPage"),"aria-label":N("pagination.firstPage"),className:t.className.paginationButton},N("1")),x("button",{tabIndex:-1,className:rt(et("spread"),t.className.paginationButton)},"...")),Array.from(Array(n).keys()).map(function(t){return y+(t-e)}).map(function(n){return x("button",{tabIndex:0,role:"button",onClick:function(){return I(n)},className:rt(y===n?rt(et("currentPage"),t.className.paginationButtonCurrent):null,t.className.paginationButton),title:N("pagination.page",n+1),"aria-label":N("pagination.page",n+1)},N(""+(n+1)))}),E()>n&&E()>y+e+1&&x(P,null,x("button",{tabIndex:-1,className:rt(et("spread"),t.className.paginationButton)},"..."),x("button",{tabIndex:0,role:"button",onClick:function(){return I(E()-1)},title:N("pagination.page",E()),"aria-label":N("pagination.page",E()),className:t.className.paginationButton},N(""+E()))))}(),u&&x("button",{tabIndex:0,role:"button",disabled:E()===y+1||0===E(),onClick:function(){return I(y+1)},title:N("pagination.next"),"aria-label":N("pagination.next"),className:rt(t.className.paginationButton,t.className.paginationButtonNext)},N("pagination.next"))))}function Ut(t,n){return"string"==typeof t?t.indexOf("%")>-1?n/100*parseInt(t,10):parseInt(t,10):t}function Wt(t){return t?Math.floor(t)+"px":""}function Bt(t){var n=t.tableRef.cloneNode(!0);return n.style.position="absolute",n.style.width="100%",n.style.zIndex="-2147483640",n.style.visibility="hidden",x("div",{ref:function(t){t&&t.appendChild(n)}})}function qt(t){if(!t)return"";var n=t.split(" ");return 1===n.length&&/([a-z][A-Z])+/g.test(t)?t:n.map(function(t,n){return 0==n?t.toLowerCase():t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()}).join("")}var zt,Vt=new(/*#__PURE__*/function(){function t(){}var n=t.prototype;return n.format=function(t,n){return"[Grid.js] ["+n.toUpperCase()+"]: "+t},n.error=function(t,n){void 0===n&&(n=!1);var e=this.format(t,"error");if(n)throw Error(e);console.error(e)},n.warn=function(t){console.warn(this.format(t,"warn"))},n.info=function(t){console.info(this.format(t,"info"))},t}());t.PluginPosition=void 0,(zt=t.PluginPosition||(t.PluginPosition={}))[zt.Header=0]="Header",zt[zt.Footer=1]="Footer",zt[zt.Cell=2]="Cell";var $t=/*#__PURE__*/function(){function t(){this.plugins=void 0,this.plugins=[]}var n=t.prototype;return n.get=function(t){return this.plugins.find(function(n){return n.id===t})},n.add=function(t){return t.id?this.get(t.id)?(Vt.error("Duplicate plugin ID: "+t.id),this):(this.plugins.push(t),this):(Vt.error("Plugin ID cannot be empty"),this)},n.remove=function(t){var n=this.get(t);return n&&this.plugins.splice(this.plugins.indexOf(n),1),this},n.list=function(t){var n;return n=null!=t||null!=t?this.plugins.filter(function(n){return n.position===t}):this.plugins,n.sort(function(t,n){return t.order&&n.order?t.order-n.order:1})},t}();function Gt(t){var n=this,e=It();if(t.pluginId){var o=e.plugin.get(t.pluginId);return o?x(P,{},x(o.component,r({plugin:o},t.props))):null}return void 0!==t.position?x(P,{},e.plugin.list(t.position).map(function(t){return x(t.component,r({plugin:t},n.props.props))})):null}var Kt=/*#__PURE__*/function(n){function i(){var t;return(t=n.call(this)||this)._columns=void 0,t._columns=[],t}o(i,n);var u=i.prototype;return u.adjustWidth=function(t,n,e){var o=t.container,u=t.autoWidth;if(!o)return this;var s=o.clientWidth,l={};n.current&&u&&(q(x(Bt,{tableRef:n.current}),e.current),l=function(t){var n=t.querySelector("table");if(!n)return{};var e=n.className,o=n.style.cssText;n.className=e+" "+et("shadowTable"),n.style.tableLayout="auto",n.style.width="auto",n.style.padding="0",n.style.margin="0",n.style.border="none",n.style.outline="none";var i=Array.from(n.parentNode.querySelectorAll("thead th")).reduce(function(t,n){var e;return n.style.width=n.clientWidth+"px",r(((e={})[n.getAttribute("data-column-id")]={minWidth:n.clientWidth},e),t)},{});return n.className=e,n.style.cssText=o,n.style.tableLayout="auto",Array.from(n.parentNode.querySelectorAll("thead th")).reduce(function(t,n){return t[n.getAttribute("data-column-id")].width=n.clientWidth,t},i)}(e.current));for(var c,f=a(i.tabularFormat(this.columns).reduce(function(t,n){return t.concat(n)},[]));!(c=f()).done;){var p=c.value;p.columns&&p.columns.length>0||(!p.width&&u?p.id in l&&(p.width=Wt(l[p.id].width),p.minWidth=Wt(l[p.id].minWidth)):p.width=Wt(Ut(p.width,s)))}return n.current&&u&&q(null,e.current),this},u.setSort=function(t,n){for(var e,o=a(n||this.columns||[]);!(e=o()).done;){var i=e.value;i.columns&&i.columns.length>0?i.sort=void 0:void 0===i.sort&&t?i.sort={}:i.sort?"object"==typeof i.sort&&(i.sort=r({},i.sort)):i.sort=void 0,i.columns&&this.setSort(t,i.columns)}},u.setResizable=function(t,n){for(var e,r=a(n||this.columns||[]);!(e=r()).done;){var o=e.value;void 0===o.resizable&&(o.resizable=t),o.columns&&this.setResizable(t,o.columns)}},u.setID=function(t){for(var n,e=a(t||this.columns||[]);!(n=e()).done;){var r=n.value;r.id||"string"!=typeof r.name||(r.id=qt(r.name)),r.id||Vt.error('Could not find a valid ID for one of the columns. Make sure a valid "id" is set for all columns.'),r.columns&&this.setID(r.columns)}},u.populatePlugins=function(n,e){for(var o,i=a(e);!(o=i()).done;){var u=o.value;void 0!==u.plugin&&n.add(r({id:u.id},u.plugin,{position:t.PluginPosition.Cell}))}},i.fromColumns=function(t){for(var n,e=new i,r=a(t);!(n=r()).done;){var o=n.value;if("string"==typeof o||d(o))e.columns.push({name:o});else if("object"==typeof o){var u=o;u.columns&&(u.columns=i.fromColumns(u.columns).columns),"object"==typeof u.plugin&&void 0===u.data&&(u.data=null),e.columns.push(o)}}return e},i.createFromConfig=function(t){var n=new i;return t.from?n.columns=i.fromHTMLTable(t.from).columns:t.columns?n.columns=i.fromColumns(t.columns).columns:!t.data||"object"!=typeof t.data[0]||t.data[0]instanceof Array||(n.columns=Object.keys(t.data[0]).map(function(t){return{name:t}})),n.columns.length?(n.setID(),n.setSort(t.sort),n.setResizable(t.resizable),n.populatePlugins(t.plugin,n.columns),n):null},i.fromHTMLTable=function(t){for(var n,e=new i,r=a(t.querySelector("thead").querySelectorAll("th"));!(n=r()).done;){var o=n.value;e.columns.push({name:o.innerHTML,width:o.width})}return e},i.tabularFormat=function(t){var n=[],e=t||[],r=[];if(e&&e.length){n.push(e);for(var o,i=a(e);!(o=i()).done;){var u=o.value;u.columns&&u.columns.length&&(r=r.concat(u.columns))}r.length&&(n=n.concat(this.tabularFormat(r)))}return n},i.leafColumns=function(t){var n=[],e=t||[];if(e&&e.length)for(var r,o=a(e);!(r=o()).done;){var i=r.value;i.columns&&0!==i.columns.length||n.push(i),i.columns&&(n=n.concat(this.leafColumns(i.columns)))}return n},i.maximumDepth=function(t){return this.tabularFormat([t]).length-1},e(i,[{key:"columns",get:function(){return this._columns},set:function(t){this._columns=t}},{key:"visibleColumns",get:function(){return this._columns.filter(function(t){return!t.hidden})}}]),i}(V),Xt=function(){},Zt=/*#__PURE__*/function(t){function n(n){var e;return(e=t.call(this)||this).data=void 0,e.set(n),e}o(n,t);var e=n.prototype;return e.get=function(){try{return Promise.resolve(this.data()).then(function(t){return{data:t,total:t.length}})}catch(t){return Promise.reject(t)}},e.set=function(t){return t instanceof Array?this.data=function(){return t}:t instanceof Function&&(this.data=t),this},n}(Xt),Jt=/*#__PURE__*/function(t){function n(n){var e;return(e=t.call(this)||this).options=void 0,e.options=n,e}o(n,t);var e=n.prototype;return e.handler=function(t){return"function"==typeof this.options.handle?this.options.handle(t):t.ok?t.json():(Vt.error("Could not fetch data: "+t.status+" - "+t.statusText,!0),null)},e.get=function(t){var n=r({},this.options,t);return"function"==typeof n.data?n.data(n):fetch(n.url,n).then(this.handler.bind(this)).then(function(t){return{data:n.then(t),total:"function"==typeof n.total?n.total(t):void 0}})},n}(Xt),Qt=/*#__PURE__*/function(){function t(){}return t.createFromConfig=function(t){var n=null;return t.data&&(n=new Zt(t.data)),t.from&&(n=new Zt(this.tableElementToArray(t.from)),t.from.style.display="none"),t.server&&(n=new Jt(t.server)),n||Vt.error("Could not determine the storage type",!0),n},t.tableElementToArray=function(t){for(var n,e,r=[],o=a(t.querySelector("tbody").querySelectorAll("tr"));!(n=o()).done;){for(var i,u=[],s=a(n.value.querySelectorAll("td"));!(i=s()).done;){var l=i.value;1===l.childNodes.length&&l.childNodes[0].nodeType===Node.TEXT_NODE?u.push((e=l.innerHTML,(new DOMParser).parseFromString(e,"text/html").documentElement.textContent)):u.push(G(l.innerHTML))}r.push(u)}return r},t}(),Yt="undefined"!=typeof Symbol?Symbol.iterator||(Symbol.iterator=Symbol("Symbol.iterator")):"@@iterator";function tn(t,n,e){if(!t.s){if(e instanceof nn){if(!e.s)return void(e.o=tn.bind(null,t,n));1&n&&(n=e.s),e=e.v}if(e&&e.then)return void e.then(tn.bind(null,t,n),tn.bind(null,t,2));t.s=n,t.v=e;var r=t.o;r&&r(t)}}var nn=/*#__PURE__*/function(){function t(){}return t.prototype.then=function(n,e){var r=new t,o=this.s;if(o){var i=1&o?n:e;if(i){try{tn(r,1,i(this.v))}catch(t){tn(r,2,t)}return r}return this}return this.o=function(t){try{var o=t.v;1&t.s?tn(r,1,n?n(o):o):e?tn(r,1,e(o)):tn(r,2,o)}catch(t){tn(r,2,t)}},r},t}();function en(t){return t instanceof nn&&1&t.s}var rn=/*#__PURE__*/function(t){function n(n){var e;return(e=t.call(this)||this)._steps=new Map,e.cache=new Map,e.lastProcessorIndexUpdated=-1,n&&n.forEach(function(t){return e.register(t)}),e}o(n,t);var r=n.prototype;return r.clearCache=function(){this.cache=new Map,this.lastProcessorIndexUpdated=-1},r.register=function(t,n){if(void 0===n&&(n=null),!t)throw Error("Processor is not defined");if(null===t.type)throw Error("Processor type is not defined");if(this.findProcessorIndexByID(t.id)>-1)throw Error("Processor ID "+t.id+" is already defined");return t.on("propsUpdated",this.processorPropsUpdated.bind(this)),this.addProcessorByPriority(t,n),this.afterRegistered(t),t},r.tryRegister=function(t,n){void 0===n&&(n=null);try{return this.register(t,n)}catch(t){}},r.unregister=function(t){if(t&&-1!==this.findProcessorIndexByID(t.id)){var n=this._steps.get(t.type);n&&n.length&&(this._steps.set(t.type,n.filter(function(n){return n!=t})),this.emit("updated",t))}},r.addProcessorByPriority=function(t,n){var e=this._steps.get(t.type);if(!e){var r=[];this._steps.set(t.type,r),e=r}if(null===n||n<0)e.push(t);else if(e[n]){var o=e.slice(0,n-1),i=e.slice(n+1);this._steps.set(t.type,o.concat(t).concat(i))}else e[n]=t},r.getStepsByType=function(t){return this.steps.filter(function(n){return n.type===t})},r.getSortedProcessorTypes=function(){return Object.keys(K).filter(function(t){return!isNaN(Number(t))}).map(function(t){return Number(t)})},r.process=function(t){try{var n=function(t){return e.lastProcessorIndexUpdated=o.length,e.emit("afterProcess",i),i},e=this,r=e.lastProcessorIndexUpdated,o=e.steps,i=t,u=function(t,n){try{var u=function(t,n,e){if("function"==typeof t[Yt]){var r,o,i,u=t[Yt]();if(function t(e){try{for(;!(r=u.next()).done;)if((e=n(r.value))&&e.then){if(!en(e))return void e.then(t,i||(i=tn.bind(null,o=new nn,2)));e=e.v}o?tn(o,1,e):o=e}catch(t){tn(o||(o=new nn),2,t)}}(),u.return){var s=function(t){try{r.done||u.return()}catch(t){}return t};if(o&&o.then)return o.then(s,function(t){throw s(t)});s()}return o}if(!("length"in t))throw new TypeError("Object is not iterable");for(var a=[],l=0;l=r)return Promise.resolve(t.process(i)).then(function(n){e.cache.set(t.id,i=n)});i=e.cache.get(t.id)}();if(o&&o.then)return o.then(function(){})})}catch(t){return n(t)}return u&&u.then?u.then(void 0,n):u}(0,function(t){throw Vt.error(t),e.emit("error",i),t});return Promise.resolve(u&&u.then?u.then(n):n())}catch(t){return Promise.reject(t)}},r.findProcessorIndexByID=function(t){return this.steps.findIndex(function(n){return n.id==t})},r.setLastProcessorIndex=function(t){var n=this.findProcessorIndexByID(t.id);this.lastProcessorIndexUpdated>n&&(this.lastProcessorIndexUpdated=n)},r.processorPropsUpdated=function(t){this.setLastProcessorIndex(t),this.emit("propsUpdated"),this.emit("updated",t)},r.afterRegistered=function(t){this.setLastProcessorIndex(t),this.emit("afterRegister"),this.emit("updated",t)},e(n,[{key:"steps",get:function(){for(var t,n=[],e=a(this.getSortedProcessorTypes());!(t=e()).done;){var r=this._steps.get(t.value);r&&r.length&&(n=n.concat(r))}return n.filter(function(t){return t})}}]),n}(Q),on=/*#__PURE__*/function(t){function n(){return t.apply(this,arguments)||this}return o(n,t),n.prototype._process=function(t){try{return Promise.resolve(this.props.storage.get(t))}catch(t){return Promise.reject(t)}},e(n,[{key:"type",get:function(){return K.Extractor}}]),n}(tt),un=/*#__PURE__*/function(t){function n(){return t.apply(this,arguments)||this}return o(n,t),n.prototype._process=function(t){var n=J.fromArray(t.data);return n.length=t.total,n},e(n,[{key:"type",get:function(){return K.Transformer}}]),n}(tt),sn=/*#__PURE__*/function(t){function n(){return t.apply(this,arguments)||this}return o(n,t),n.prototype._process=function(){return Object.entries(this.props.serverStorageOptions).filter(function(t){return"function"!=typeof t[1]}).reduce(function(t,n){var e;return r({},t,((e={})[n[0]]=n[1],e))},{})},e(n,[{key:"type",get:function(){return K.Initiator}}]),n}(tt),an=/*#__PURE__*/function(t){function n(){return t.apply(this,arguments)||this}o(n,t);var r=n.prototype;return r.castData=function(t){if(!t||!t.length)return[];if(!this.props.header||!this.props.header.columns)return t;var n=Kt.leafColumns(this.props.header.columns);return t[0]instanceof Array?t.map(function(t){var e=0;return n.map(function(n,r){return void 0!==n.data?(e++,"function"==typeof n.data?n.data(t):n.data):t[r-e]})}):"object"!=typeof t[0]||t[0]instanceof Array?[]:t.map(function(t){return n.map(function(n,e){return void 0!==n.data?"function"==typeof n.data?n.data(t):n.data:n.id?t[n.id]:(Vt.error("Could not find the correct cell for column at position "+e+".\n Make sure either 'id' or 'selector' is defined for all columns."),null)})})},r._process=function(t){return{data:this.castData(t.data),total:t.total}},e(n,[{key:"type",get:function(){return K.Transformer}}]),n}(tt),ln=/*#__PURE__*/function(){function t(){}return t.createFromConfig=function(t){var n=new rn;return t.storage instanceof Jt&&n.register(new sn({serverStorageOptions:t.server})),n.register(new on({storage:t.storage})),n.register(new an({header:t.header})),n.register(new un),n},t}(),cn=function(t){var n=this;this.state=void 0,this.listeners=[],this.isDispatching=!1,this.getState=function(){return n.state},this.getListeners=function(){return n.listeners},this.dispatch=function(t){if("function"!=typeof t)throw new Error("Reducer is not a function");if(n.isDispatching)throw new Error("Reducers may not dispatch actions");n.isDispatching=!0;var e=n.state;try{n.state=t(n.state)}finally{n.isDispatching=!1}for(var r,o=a(n.listeners);!(r=o()).done;)(0,r.value)(n.state,e);return n.state},this.subscribe=function(t){if("function"!=typeof t)throw new Error("Listener is not a function");return n.listeners=[].concat(n.listeners,[t]),function(){return n.listeners=n.listeners.filter(function(n){return n!==t})}},this.state=t},fn=function(t,n){var e={__c:n="__cC"+m++,__:null,Consumer:function(t,n){return t.children(n)},Provider:function(t){var e,r;return this.getChildContext||(e=[],(r={})[n]=this,this.getChildContext=function(){return r},this.shouldComponentUpdate=function(t){this.props.value!==t.value&&e.some(E)},this.sub=function(t){e.push(t);var n=t.componentWillUnmount;t.componentWillUnmount=function(){e.splice(e.indexOf(t),1),n&&n.call(t)}}),t.children}};return e.Provider.__=e.Consumer.contextType=e}(),pn=/*#__PURE__*/function(){function n(){Object.assign(this,n.defaultConfig())}var e=n.prototype;return e.assign=function(t){return Object.assign(this,t)},e.update=function(t){return t?(this.assign(n.fromPartialConfig(r({},this,t))),this):this},n.defaultConfig=function(){return{store:new cn({status:l.Init,header:void 0,data:null}),plugin:new $t,tableRef:{current:null},width:"100%",height:"auto",processingThrottleMs:100,autoWidth:!0,style:{},className:{}}},n.fromPartialConfig=function(e){var r=(new n).assign(e);return"boolean"==typeof e.sort&&e.sort&&r.assign({sort:{multiColumn:!0}}),r.assign({header:Kt.createFromConfig(r)}),r.assign({storage:Qt.createFromConfig(r)}),r.assign({pipeline:ln.createFromConfig(r)}),r.assign({translator:new Lt(r.language)}),r.plugin=new $t,r.search&&r.plugin.add({id:"search",position:t.PluginPosition.Header,component:Dt}),r.pagination&&r.plugin.add({id:"pagination",position:t.PluginPosition.Footer,component:Ft}),r.plugins&&r.plugins.forEach(function(t){return r.plugin.add(t)}),r},n}();function dn(t){var n,e=It();return x("td",r({role:t.role,colSpan:t.colSpan,"data-column-id":t.column&&t.column.id,className:rt(et("td"),t.className,e.className.td),style:r({},t.style,e.style.td),onClick:function(n){t.messageCell||e.eventEmitter.emit("cellClick",n,t.cell,t.column,t.row)}},(n=t.column)?"function"==typeof n.attributes?n.attributes(t.cell.data,t.row,t.column):n.attributes:{}),t.column&&"function"==typeof t.column.formatter?t.column.formatter(t.cell.data,t.row,t.column):t.column&&t.column.plugin?x(Gt,{pluginId:t.column.id,props:{column:t.column,cell:t.cell,row:t.row}}):t.cell.data)}function hn(t){var n=It(),e=Ht(function(t){return t.header});return x("tr",{className:rt(et("tr"),n.className.tr),onClick:function(e){t.messageRow||n.eventEmitter.emit("rowClick",e,t.row)}},t.children?t.children:t.row.cells.map(function(n,r){var o=function(t){if(e){var n=Kt.leafColumns(e.columns);if(n)return n[t]}return null}(r);return o&&o.hidden?null:x(dn,{key:n.id,cell:n,row:t.row,column:o})}))}function _n(t){return x(hn,{messageRow:!0},x(dn,{role:"alert",colSpan:t.colSpan,messageCell:!0,cell:new X(t.message),className:rt(et("message"),t.className?t.className:null)}))}function mn(){var t=It(),n=Ht(function(t){return t.data}),e=Ht(function(t){return t.status}),r=Ht(function(t){return t.header}),o=At(),i=function(){return r?r.visibleColumns.length:0};return x("tbody",{className:rt(et("tbody"),t.className.tbody)},n&&n.rows.map(function(t){return x(hn,{key:t.id,row:t})}),e===l.Loading&&(!n||0===n.length)&&x(_n,{message:o("loading"),colSpan:i(),className:rt(et("loading"),t.className.loading)}),e===l.Rendered&&n&&0===n.length&&x(_n,{message:o("noRecordsFound"),colSpan:i(),className:rt(et("notfound"),t.className.notfound)}),e===l.Error&&x(_n,{message:o("error"),colSpan:i(),className:rt(et("error"),t.className.error)}))}var vn=/*#__PURE__*/function(t){function n(){return t.apply(this,arguments)||this}o(n,t);var r=n.prototype;return r.validateProps=function(){for(var t,n=a(this.props.columns);!(t=n()).done;){var e=t.value;void 0===e.direction&&(e.direction=1),1!==e.direction&&-1!==e.direction&&Vt.error("Invalid sort direction "+e.direction)}},r.compare=function(t,n){return t>n?1:t1&&(f=!0,c=!0):0===a?c=!0:a>0&&!e?(c=!0,f=!0):a>0&&e&&(c=!0),f&&(s=[]),c)s.push({index:t,direction:n,compare:o});else if(d){var h=s.indexOf(l);s[h].direction=n}else if(p){var _=s.indexOf(l);s.splice(_,1)}return r({},i,{sort:{columns:s}})}},yn=function(t,n,e){return function(o){var i=(o.sort?[].concat(o.sort.columns):[]).find(function(n){return n.index===t});return r({},o,i?gn(t,1===i.direction?-1:1,n,e)(o):gn(t,1,n,e)(o))}},bn=/*#__PURE__*/function(t){function n(){return t.apply(this,arguments)||this}return o(n,t),n.prototype._process=function(t){var n={};return this.props.url&&(n.url=this.props.url(t.url,this.props.columns)),this.props.body&&(n.body=this.props.body(t.body,this.props.columns)),r({},t,n)},e(n,[{key:"type",get:function(){return K.ServerSort}}]),n}(tt);function wn(t){var n=It(),e=jt().dispatch,o=At(),i=gt(0),u=i[0],s=i[1],a=n.sort,l=Ht(function(t){return t.sort}),c="object"==typeof(null==a?void 0:a.server)?K.ServerSort:K.Sort,f=function(){var t=n.pipeline.getStepsByType(c);if(t.length)return t[0]};return yt(function(){var t=f()||(c===K.ServerSort?new bn(r({columns:l?l.columns:[]},a.server)):new vn({columns:l?l.columns:[]}));return n.pipeline.tryRegister(t),function(){return n.pipeline.unregister(t)}},[n]),yt(function(){if(l){var n,e=l.columns.find(function(n){return n.index===t.index});e?(0===u&&(e.direction=null!=(n=t.direction)?n:1),s(e.direction)):s(0)}},[l]),yt(function(){var t=f();t&&l&&t.setProps({columns:l.columns})},[l]),x("button",{tabIndex:-1,"aria-label":o("sort.sort"+(1===u?"Desc":"Asc")),title:o("sort.sort"+(1===u?"Desc":"Asc")),className:rt(et("sort"),et("sort",function(t){return 1===t?"asc":-1===t?"desc":"neutral"}(u)),n.className.sort),onClick:function(n){n.preventDefault(),n.stopPropagation(),e(yn(t.index,!0===n.shiftKey&&a.multiColumn,t.compare))}})}var xn=function(t,n){var e;void 0===n&&(n=100);var r=Date.now(),o=function(){r=Date.now(),t.apply(void 0,[].slice.call(arguments))};return function(){var t=[].slice.call(arguments),i=Date.now(),u=i-r;u>=n?o.apply(void 0,t):(e&&clearTimeout(e),e=setTimeout(function(){o.apply(void 0,t),e=null},n-u))}};function kn(t){var n,e=function(t){return t instanceof MouseEvent?Math.floor(t.pageX):Math.floor(t.changedTouches[0].pageX)},r=function(r){r.stopPropagation();var u=parseInt(t.thRef.current.style.width,10)-e(r);n=xn(function(t){return o(t,u)},10),document.addEventListener("mouseup",i),document.addEventListener("touchend",i),document.addEventListener("mousemove",n),document.addEventListener("touchmove",n)},o=function(n,r){n.stopPropagation();var o=t.thRef.current;r+e(n)>=parseInt(o.style.minWidth,10)&&(o.style.width=r+e(n)+"px")},i=function t(e){e.stopPropagation(),document.removeEventListener("mouseup",t),document.removeEventListener("mousemove",n),document.removeEventListener("touchmove",n),document.removeEventListener("touchend",t)};return x("div",{className:rt(et("th"),et("resizable")),onMouseDown:r,onTouchStart:r,onClick:function(t){return t.stopPropagation()}})}function Pn(t){var n=It(),e=bt(null),o=gt({}),i=o[0],u=o[1],s=jt().dispatch;yt(function(){if(n.fixedHeader&&e.current){var t=e.current.offsetTop;"number"==typeof t&&u({top:t})}},[e]);var a,l=function(){return null!=t.column.sort},c=function(e){e.stopPropagation(),l()&&s(yn(t.index,!0===e.shiftKey&&n.sort.multiColumn,t.column.sort.compare))};return x("th",r({ref:e,"data-column-id":t.column&&t.column.id,className:rt(et("th"),l()?et("th","sort"):null,n.fixedHeader?et("th","fixed"):null,n.className.th),onClick:c,style:r({},n.style.th,{minWidth:t.column.minWidth,width:t.column.width},i,t.style),onKeyDown:function(t){l()&&13===t.which&&c(t)},rowSpan:t.rowSpan>1?t.rowSpan:void 0,colSpan:t.colSpan>1?t.colSpan:void 0},(a=t.column)?"function"==typeof a.attributes?a.attributes(null,null,t.column):a.attributes:{},l()?{tabIndex:0}:{}),x("div",{className:et("th","content")},void 0!==t.column.name?t.column.name:void 0!==t.column.plugin?x(Gt,{pluginId:t.column.plugin.id,props:{column:t.column}}):null),l()&&x(wn,r({index:t.index},t.column.sort)),t.column.resizable&&t.index0?(Vt.error("The container element "+t+" is not empty. Make sure the container is empty and call render() again"),this):(this.config.container=t,q(this.createElement(),t),this)},n}(Q);t.Cell=X,t.Component=S,t.Config=pn,t.Grid=Ln,t.Row=Z,t.className=et,t.createElement=x,t.createRef=function(){return{current:null}},t.h=x,t.html=G,t.useConfig=It,t.useEffect=yt,t.useRef=bt,t.useSelector=Ht,t.useState=gt,t.useStore=jt,t.useTranslator=At}); +//# sourceMappingURL=gridjs.umd.js.map diff --git a/web/vendor/gridjs/mermaid.min.css b/web/vendor/gridjs/mermaid.min.css new file mode 100644 index 0000000..21332c7 --- /dev/null +++ b/web/vendor/gridjs/mermaid.min.css @@ -0,0 +1 @@ +.gridjs-footer button,.gridjs-head button{background-color:transparent;background-image:none;border:none;cursor:pointer;margin:0;outline:none;padding:0}.gridjs-temp{position:relative}.gridjs-head{margin-bottom:5px;padding:5px 1px;width:100%}.gridjs-head:after{clear:both;content:"";display:block}.gridjs-head:empty{border:none;padding:0}.gridjs-container{color:#000;display:inline-block;overflow:hidden;padding:2px;position:relative;z-index:0}.gridjs-footer{background-color:#fff;border-bottom-width:1px;border-color:#e5e7eb;border-radius:0 0 8px 8px;border-top:1px solid #e5e7eb;box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.26);display:block;padding:12px 24px;position:relative;width:100%;z-index:5}.gridjs-footer:empty{border:none;padding:0}input.gridjs-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border:1px solid #d2d6dc;border-radius:5px;font-size:14px;line-height:1.45;outline:none;padding:10px 13px}input.gridjs-input:focus{border-color:#9bc2f7;box-shadow:0 0 0 3px rgba(149,189,243,.5)}.gridjs-pagination{color:#3d4044}.gridjs-pagination:after{clear:both;content:"";display:block}.gridjs-pagination .gridjs-summary{float:left;margin-top:5px}.gridjs-pagination .gridjs-pages{float:right}.gridjs-pagination .gridjs-pages button{background-color:#fff;border:1px solid #d2d6dc;border-right:none;outline:none;padding:5px 14px;-webkit-user-select:none;-moz-user-select:none;user-select:none}.gridjs-pagination .gridjs-pages button:focus{border-right:1px solid #d2d6dc;box-shadow:0 0 0 2px rgba(149,189,243,.5);margin-right:-1px;position:relative}.gridjs-pagination .gridjs-pages button:hover{background-color:#f7f7f7;color:#3c4257;outline:none}.gridjs-pagination .gridjs-pages button:disabled,.gridjs-pagination .gridjs-pages button:hover:disabled,.gridjs-pagination .gridjs-pages button[disabled]{background-color:#fff;color:#6b7280;cursor:default}.gridjs-pagination .gridjs-pages button.gridjs-spread{background-color:#fff;box-shadow:none;cursor:default}.gridjs-pagination .gridjs-pages button.gridjs-currentPage{background-color:#f7f7f7;font-weight:700}.gridjs-pagination .gridjs-pages button:last-child{border-bottom-right-radius:6px;border-right:1px solid #d2d6dc;border-top-right-radius:6px}.gridjs-pagination .gridjs-pages button:first-child{border-bottom-left-radius:6px;border-top-left-radius:6px}.gridjs-pagination .gridjs-pages button:last-child:focus{margin-right:0}button.gridjs-sort{background-color:transparent;background-position-x:center;background-repeat:no-repeat;background-size:contain;border:none;cursor:pointer;float:right;height:24px;margin:0;outline:none;padding:0;width:13px}button.gridjs-sort-neutral{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MDEuOTk4IiBoZWlnaHQ9IjQwMS45OTgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQwMS45OTggNDAxLjk5OCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBhdGggZD0iTTczLjA5MiAxNjQuNDUyaDI1NS44MTNjNC45NDkgMCA5LjIzMy0xLjgwNyAxMi44NDgtNS40MjQgMy42MTMtMy42MTYgNS40MjctNy44OTggNS40MjctMTIuODQ3cy0xLjgxMy05LjIyOS01LjQyNy0xMi44NUwyMTMuODQ2IDUuNDI0QzIxMC4yMzIgMS44MTIgMjA1Ljk1MSAwIDIwMC45OTkgMHMtOS4yMzMgMS44MTItMTIuODUgNS40MjRMNjAuMjQyIDEzMy4zMzFjLTMuNjE3IDMuNjE3LTUuNDI0IDcuOTAxLTUuNDI0IDEyLjg1IDAgNC45NDggMS44MDcgOS4yMzEgNS40MjQgMTIuODQ3IDMuNjIxIDMuNjE3IDcuOTAyIDUuNDI0IDEyLjg1IDUuNDI0ek0zMjguOTA1IDIzNy41NDlINzMuMDkyYy00Ljk1MiAwLTkuMjMzIDEuODA4LTEyLjg1IDUuNDIxLTMuNjE3IDMuNjE3LTUuNDI0IDcuODk4LTUuNDI0IDEyLjg0N3MxLjgwNyA5LjIzMyA1LjQyNCAxMi44NDhMMTg4LjE0OSAzOTYuNTdjMy42MjEgMy42MTcgNy45MDIgNS40MjggMTIuODUgNS40MjhzOS4yMzMtMS44MTEgMTIuODQ3LTUuNDI4bDEyNy45MDctMTI3LjkwNmMzLjYxMy0zLjYxNCA1LjQyNy03Ljg5OCA1LjQyNy0xMi44NDggMC00Ljk0OC0xLjgxMy05LjIyOS01LjQyNy0xMi44NDctMy42MTQtMy42MTYtNy44OTktNS40Mi0xMi44NDgtNS40MnoiLz48L3N2Zz4=");background-position-y:center;opacity:.3}button.gridjs-sort-asc{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyOTIuMzYyIiBoZWlnaHQ9IjI5Mi4zNjEiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDI5Mi4zNjIgMjkyLjM2MSIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBhdGggZD0iTTI4Ni45MzUgMTk3LjI4NyAxNTkuMDI4IDY5LjM4MWMtMy42MTMtMy42MTctNy44OTUtNS40MjQtMTIuODQ3LTUuNDI0cy05LjIzMyAxLjgwNy0xMi44NSA1LjQyNEw1LjQyNCAxOTcuMjg3QzEuODA3IDIwMC45MDQgMCAyMDUuMTg2IDAgMjEwLjEzNHMxLjgwNyA5LjIzMyA1LjQyNCAxMi44NDdjMy42MjEgMy42MTcgNy45MDIgNS40MjUgMTIuODUgNS40MjVoMjU1LjgxM2M0Ljk0OSAwIDkuMjMzLTEuODA4IDEyLjg0OC01LjQyNSAzLjYxMy0zLjYxMyA1LjQyNy03Ljg5OCA1LjQyNy0xMi44NDdzLTEuODE0LTkuMjMtNS40MjctMTIuODQ3eiIvPjwvc3ZnPg==");background-position-y:35%;background-size:10px}button.gridjs-sort-desc{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyOTIuMzYyIiBoZWlnaHQ9IjI5Mi4zNjIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDI5Mi4zNjIgMjkyLjM2MiIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBhdGggZD0iTTI4Ni45MzUgNjkuMzc3Yy0zLjYxNC0zLjYxNy03Ljg5OC01LjQyNC0xMi44NDgtNS40MjRIMTguMjc0Yy00Ljk1MiAwLTkuMjMzIDEuODA3LTEyLjg1IDUuNDI0QzEuODA3IDcyLjk5OCAwIDc3LjI3OSAwIDgyLjIyOGMwIDQuOTQ4IDEuODA3IDkuMjI5IDUuNDI0IDEyLjg0N2wxMjcuOTA3IDEyNy45MDdjMy42MjEgMy42MTcgNy45MDIgNS40MjggMTIuODUgNS40MjhzOS4yMzMtMS44MTEgMTIuODQ3LTUuNDI4TDI4Ni45MzUgOTUuMDc0YzMuNjEzLTMuNjE3IDUuNDI3LTcuODk4IDUuNDI3LTEyLjg0NyAwLTQuOTQ4LTEuODE0LTkuMjI5LTUuNDI3LTEyLjg1eiIvPjwvc3ZnPg==");background-position-y:65%;background-size:10px}button.gridjs-sort:focus{outline:none}table.gridjs-table{border-collapse:collapse;display:table;margin:0;max-width:100%;overflow:auto;padding:0;table-layout:fixed;text-align:left;width:100%}.gridjs-tbody,td.gridjs-td{background-color:#fff}td.gridjs-td{border:1px solid #e5e7eb;box-sizing:content-box;padding:12px 24px}td.gridjs-td:first-child{border-left:none}td.gridjs-td:last-child{border-right:none}td.gridjs-message{text-align:center}th.gridjs-th{background-color:#f9fafb;border:1px solid #e5e7eb;border-top:none;box-sizing:border-box;color:#6b7280;outline:none;padding:14px 24px;position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;white-space:nowrap}th.gridjs-th .gridjs-th-content{float:left;overflow:hidden;text-overflow:ellipsis;width:100%}th.gridjs-th-sort{cursor:pointer}th.gridjs-th-sort .gridjs-th-content{width:calc(100% - 15px)}th.gridjs-th-sort:focus,th.gridjs-th-sort:hover{background-color:#e5e7eb}th.gridjs-th-fixed{box-shadow:0 1px 0 0 #e5e7eb;position:sticky}@supports (-moz-appearance:none){th.gridjs-th-fixed{box-shadow:0 0 0 1px #e5e7eb}}th.gridjs-th:first-child{border-left:none}th.gridjs-th:last-child{border-right:none}.gridjs-tr{border:none}.gridjs-tr-selected td{background-color:#ebf5ff}.gridjs-tr:last-child td{border-bottom:0}.gridjs *,.gridjs :after,.gridjs :before{box-sizing:border-box}.gridjs-wrapper{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;border-color:#e5e7eb;border-radius:8px 8px 0 0;border-top-width:1px;box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.26);display:block;overflow:auto;position:relative;width:100%;z-index:1}.gridjs-wrapper:nth-last-of-type(2){border-bottom-width:1px;border-radius:8px}.gridjs-search{float:left}.gridjs-search-input{width:250px}.gridjs-loading-bar{background-color:#fff;opacity:.5;z-index:10}.gridjs-loading-bar,.gridjs-loading-bar:after{bottom:0;left:0;position:absolute;right:0;top:0}.gridjs-loading-bar:after{animation:shimmer 2s infinite;background-image:linear-gradient(90deg,hsla(0,0%,80%,0),hsla(0,0%,80%,.2) 20%,hsla(0,0%,80%,.5) 60%,hsla(0,0%,80%,0));content:"";transform:translateX(-100%)}@keyframes shimmer{to{transform:translateX(100%)}}.gridjs-td .gridjs-checkbox{cursor:pointer;display:block;margin:auto}.gridjs-resizable{bottom:0;position:absolute;right:0;top:0;width:5px}.gridjs-resizable:hover{background-color:#9bc2f7;cursor:ew-resize} \ No newline at end of file diff --git a/web/vendor/gridjs/plugins/selection/selection.umd.js b/web/vendor/gridjs/plugins/selection/selection.umd.js new file mode 100644 index 0000000..5c61aac --- /dev/null +++ b/web/vendor/gridjs/plugins/selection/selection.umd.js @@ -0,0 +1,2 @@ +!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports,require("gridjs")):"function"==typeof define&&define.amd?define(["exports","gridjs"],n):n(((e||self).gridjs=e.gridjs||{},e.gridjs.plugins=e.gridjs.plugins||{},e.gridjs.plugins.selection={}),e.gridjs)}(this,function(e,n){var t,r,o;function l(e,n,t,l,i){var c={type:e,props:n,key:t,ref:l,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==i?++o:i};return null==i&&null!=r.vnode&&r.vnode(c),c}function i(){return i=Object.assign?Object.assign.bind():function(e){for(var n=1;n-1?n:i({},n,{rowSelection:{rowIds:[e].concat(r)}})}},u=function(e){return function(n){var t,r=(null==(t=n.rowSelection)?void 0:t.rowIds)||[],o=r.indexOf(e);if(-1===o)return n;var l=[].concat(r);return l.splice(o,1),i({},n,{rowSelection:{rowIds:l}})}},s={__proto__:null,CheckRow:c,UncheckRow:u};e.RowSelection=function(e){var r=this,o=n.useStore().dispatch,i=n.useSelector(function(e){return e.rowSelection}),s=n.useState(!1),a=s[0],d=s[1],f=n.className("tr","selected"),p=n.className("checkbox"),_=function(e){return void 0!==e.row};n.useEffect(function(){var n;null!=(n=e.cell)&&n.data&&_(e)&&v()},[]),n.useEffect(function(){var n=r.base&&r.base.parentElement&&r.base.parentElement.parentElement;if(n){var t=((null==i?void 0:i.rowIds)||[]).indexOf(e.row.id)>-1;d(t),t?n.classList.add(f):n.classList.remove(f)}},[i]);var v=function(){var n;o(c(e.row.id)),null==(n=e.cell)||n.update(!0)};return _(e)?function(e,n,r){var o,i,c,u={};for(c in n)"key"==c?o=n[c]:"ref"==c?i=n[c]:u[c]=n[c];if(arguments.length>2&&(u.children=arguments.length>3?t.call(arguments,2):r),"function"==typeof e&&null!=e.defaultProps)for(c in e.defaultProps)void 0===u[c]&&(u[c]=e.defaultProps[c]);return l(e,u,o,i,null)}("input",{type:"checkbox",checked:a,onChange:function(){var n;a?(o(u(e.row.id)),null==(n=e.cell)||n.update(!1)):v()},className:p}):null},e.RowSelectionActions=s}); +//# sourceMappingURL=selection.umd.js.map diff --git a/web/vendor/multi-select/MultiSelect.css b/web/vendor/multi-select/MultiSelect.css new file mode 100644 index 0000000..e6f1fe8 --- /dev/null +++ b/web/vendor/multi-select/MultiSelect.css @@ -0,0 +1,206 @@ +:root { + --spacing-smaller: 3px; + --spacing-small: 5px; + --spacing-medium: 7px; + --spacing-large: 12px; + --font-size: 12px; + --font-size-large: 14px; + --font-size-larger: 16px; + --line-height: 16px; + --line-height-larger: 20px; + --primary-color: #40c979; + --text-color-dark: #212529; + --text-color: #585858; + --text-color-light: #65727e; + --border-color: #bebebe; + --border-color-light: #f1f3f5; + --input-placeholder: #65727e; + --input-background: #e9e9ed; + --input-border: #dee2e6; + --input-border-active: #c1c9d0; + --input-border-invalid: #e44e4e; + --input-outline-invalid: rgba(219, 138, 138, 0.5); + --input-color: #e9e9ed; + --input-disabled: #f7f7f7; + --input-min-height: 45px; + --options-height: 40dvh; + --option-background: #f3f4f7; + --border-radius: 5px; + --icon-size: 12px; + --icon-space: 30px; + --checkbox-size: 16px; + --checkbox-radius: 4px; + --checkbox-border: #ced4da; + --checkbox-background: #fff; + --checkbox-active: #fff; + --checkbox-thickness: 2px; +} +.multi-select { + display: flex; + box-sizing: border-box; + flex-direction: column; + position: relative; + width: 100%; + user-select: none; +} +.multi-select .multi-select-header { + border: 1px solid var(--input-border); + border-radius: var(--border-radius); + padding: var(--spacing-medium) var(--spacing-large); + padding-right: var(--icon-space); + overflow: hidden; + gap: var(--spacing-medium); + min-height: var(--input-min-height); +} +.multi-select .multi-select-header::after { + content: ""; + display: block; + position: absolute; + top: 50%; + right: 15px; + transform: translateY(-50%); + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23949ba3' viewBox='0 0 16 16'%3E%3Cpath d='M8 13.1l-8-8 2.1-2.2 5.9 5.9 5.9-5.9 2.1 2.2z'/%3E%3C/svg%3E"); + height: var(--icon-size); + width: var(--icon-size); +} +.multi-select .multi-select-header.multi-select-header-active { + border-color: var(--input-border-active); +} +.multi-select .multi-select-header.multi-select-header-active::after { + transform: translateY(-50%) rotate(180deg); +} +.multi-select .multi-select-header.multi-select-header-active + .multi-select-options { + display: flex; +} +.multi-select .multi-select-header .multi-select-header-placeholder { + color: var(--text-color-light); +} +.multi-select .multi-select-header .multi-select-header-option { + display: inline-flex; + align-items: center; + background-color: var(--option-background); + font-size: var(--font-size-large); + padding: var(--spacing-smaller) var(--spacing-small); + border-radius: var(--border-radius); +} +.multi-select .multi-select-header .multi-select-header-max { + font-size: var(--font-size-large); + color: var(--text-color-light); +} +.multi-select .multi-select-options { + display: none; + box-sizing: border-box; + flex-flow: wrap; + position: absolute; + top: 100%; + left: 0; + right: 0; + z-index: 999; + margin-top: var(--spacing-small); + padding: var(--spacing-small); + background-color: #fff; + border-radius: var(--border-radius); + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + max-height: var(--options-height); + overflow-y: auto; + overflow-x: hidden; +} +.multi-select .multi-select-options::-webkit-scrollbar { + width: 5px; +} +.multi-select .multi-select-options::-webkit-scrollbar-track { + background: #f0f1f3; +} +.multi-select .multi-select-options::-webkit-scrollbar-thumb { + background: #cdcfd1; +} +.multi-select .multi-select-options::-webkit-scrollbar-thumb:hover { + background: #b2b6b9; +} +.multi-select .multi-select-options .multi-select-option, +.multi-select .multi-select-options .multi-select-all { + padding: var(--spacing-large); +} +.multi-select .multi-select-options .multi-select-option .multi-select-option-radio, +.multi-select .multi-select-options .multi-select-all .multi-select-option-radio { + background: var(--checkbox-background); + margin-right: var(--spacing-large); + height: var(--checkbox-size); + width: var(--checkbox-size); + border: 1px solid var(--checkbox-border); + border-radius: var(--checkbox-radius); +} +.multi-select .multi-select-options .multi-select-option .multi-select-option-text, +.multi-select .multi-select-options .multi-select-all .multi-select-option-text { + box-sizing: border-box; + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: inherit; + font-size: var(--font-size-larger); + line-height: var(--line-height); +} +.multi-select .multi-select-options .multi-select-option.multi-select-selected .multi-select-option-radio, +.multi-select .multi-select-options .multi-select-all.multi-select-selected .multi-select-option-radio { + border-color: var(--primary-color); + background-color: var(--primary-color); +} +.multi-select .multi-select-options .multi-select-option.multi-select-selected .multi-select-option-radio::after, +.multi-select .multi-select-options .multi-select-all.multi-select-selected .multi-select-option-radio::after { + content: ""; + display: block; + width: calc(var(--checkbox-size) / 4); + height: calc(var(--checkbox-size) / 2); + border: solid var(--checkbox-active); + border-width: 0 var(--checkbox-thickness) var(--checkbox-thickness) 0; + transform: rotate(45deg) translate(50%, -25%); +} +.multi-select .multi-select-options .multi-select-option.multi-select-selected .multi-select-option-text, +.multi-select .multi-select-options .multi-select-all.multi-select-selected .multi-select-option-text { + color: var(--text-color-dark); +} +.multi-select .multi-select-options .multi-select-option:hover, .multi-select .multi-select-options .multi-select-option:active, +.multi-select .multi-select-options .multi-select-all:hover, .multi-select .multi-select-options .multi-select-all:active { + background-color: var(--option-background); +} +.multi-select .multi-select-options .multi-select-all { + border-bottom: 1px solid var(--border-color-light); + border-radius: 0; +} +.multi-select .multi-select-options .multi-select-search { + padding: var(--spacing-medium) var(--spacing-large); + border: 1px solid var(--input-border); + border-radius: var(--border-radius); + margin: 10px 10px 5px 10px; + width: 100%; + outline: none; + font-size: var(--font-size-larger); +} +.multi-select .multi-select-options .multi-select-search::placeholder { + color: var(--text-color-light); +} +.multi-select .multi-select-header, +.multi-select .multi-select-option, +.multi-select .multi-select-all { + display: flex; + flex-wrap: wrap; + box-sizing: border-box; + align-items: center; + border-radius: var(--border-radius); + cursor: pointer; + display: flex; + align-items: center; + width: 100%; + font-size: var(--font-size-larger); + color: var(--text-color-dark); +} +.multi-select.disabled { + opacity: 0.6; + pointer-events: none; + background-color: var(--input-disabled); +} +.multi-select.multi-select-invalid .multi-select-header { + border-color: var(--input-border-invalid); + outline: var(--input-outline-invalid) solid 1px; +} diff --git a/web/vendor/multi-select/MultiSelect.js b/web/vendor/multi-select/MultiSelect.js new file mode 100644 index 0000000..a92c0b9 --- /dev/null +++ b/web/vendor/multi-select/MultiSelect.js @@ -0,0 +1,399 @@ +/* + * Created by David Adams + * https://codeshack.io/multi-select-dropdown-html-javascript/ + * + * Released under the MIT license + */ +class MultiSelect { + + constructor(element, options = {}) { + let defaults = { + placeholder: 'Select item(s)', + max: null, + min: null, + disabled: false, + search: true, + searchPlaceholder: 'Search...', + selectAll: true, + selectAllLabel: 'Select all', + selectedLabel: 'selected', + listAll: true, + closeListOnItemSelect: false, + name: '', + width: '', + height: '', + dropdownWidth: '', + dropdownHeight: '', + data: [], + onChange: function() {}, + onSelect: function() {}, + onUnselect: function() {}, + onMaxReached: function() {} + }; + this.options = Object.assign(defaults, options); + this.selectElement = typeof element === 'string' ? document.querySelector(element) : element; + this.originalSelectElement = this.selectElement.cloneNode(true); + for(const prop in this.selectElement.dataset) { + if (this.options[prop] !== undefined) { + if (typeof this.options[prop] === 'boolean') { + this.options[prop] = this.selectElement.dataset[prop] === 'true'; + } else { + this.options[prop] = this.selectElement.dataset[prop]; + } + } + } + this.name = this.selectElement.getAttribute('name') ? this.selectElement.getAttribute('name') : 'multi-select-' + Math.floor(Math.random() * 1000000); + this.form = this.selectElement.getAttribute('form') ? this.selectElement.getAttribute('form') : ''; + if (!this.options.data.length) { + let options = this.selectElement.querySelectorAll('option'); + for (let i = 0; i < options.length; i++) { + this.options.data.push({ + value: options[i].value, + text: options[i].innerHTML, + selected: options[i].selected, + html: options[i].getAttribute('data-html') + }); + } + } + this.originalData = JSON.parse(JSON.stringify(this.options.data)); + this.element = this._template(); + this.selectElement.replaceWith(this.element); + this.outsideClickHandler = this._outsideClick.bind(this); + this._bulkSelect = false; + this._updateSelected(); + this._eventHandlers(); + if (this.options.disabled) { + this.disable(); + } + } + + _template() { + let optionsHTML = ''; + for (let i = 0; i < this.data.length; i++) { + const isSelected = this.data[i].selected; + optionsHTML += ` +
      + + ${this.data[i].html ? this.data[i].html : this.data[i].text} +
      + `; + } + let selectAllHTML = ''; + if (this.options.selectAll) { + selectAllHTML = `
      + + ${this.options.selectAllLabel} +
      `; + } + let template = ` + + `; + let element = document.createElement('div'); + element.innerHTML = template; + return element.firstElementChild; + } + + _eventHandlers() { + let headerElement = this.element.querySelector('.multi-select-header'); + const toggleDropdown = (forceClose = false) => { + if (this.element.classList.contains('disabled')) return; + if (forceClose || headerElement.classList.contains('multi-select-header-active')) { + headerElement.classList.remove('multi-select-header-active'); + this.element.setAttribute('aria-expanded', 'false'); + } else { + headerElement.classList.add('multi-select-header-active'); + this.element.setAttribute('aria-expanded', 'true'); + } + }; + this.element.querySelectorAll('.multi-select-option').forEach(option => { + option.onclick = (e) => { + e.stopPropagation(); + if (this.element.classList.contains('disabled')) return; + let selected = true; + if (!option.classList.contains('multi-select-selected')) { + if (this.options.max && this.selectedValues.length >= this.options.max) { + this.options.onMaxReached(this.options.max); + return; + } + option.classList.add('multi-select-selected'); + option.setAttribute('aria-selected', 'true'); + this.element.insertAdjacentHTML('afterbegin', ``); + this.data.find(data => data.value == option.dataset.value).selected = true; + } else { + option.classList.remove('multi-select-selected'); + option.setAttribute('aria-selected', 'false'); + this.element.querySelector(`input[value="${option.dataset.value}"]`).remove(); + this.data.find(data => data.value == option.dataset.value).selected = false; + selected = false; + } + this._updateHeader(); + if (this.options.search) { + this.element.querySelector('.multi-select-search').value = ''; + this.element.querySelectorAll('.multi-select-option').forEach(opt => opt.style.display = 'flex'); + } + if (this.options.closeListOnItemSelect) { + toggleDropdown(true); + } + this.options.onChange(option.dataset.value, option.querySelector('.multi-select-option-text').innerHTML, option); + if (selected) { + this.options.onSelect(option.dataset.value, option.querySelector('.multi-select-option-text').innerHTML, option); + } else { + this.options.onUnselect(option.dataset.value, option.querySelector('.multi-select-option-text').innerHTML, option); + } + this._validate(); + if (!this._bulkSelect) { + this._emitChange(); + } + }; + }); + headerElement.onclick = () => toggleDropdown(); + if (this.options.search) { + let search = this.element.querySelector('.multi-select-search'); + search.oninput = () => { + this.element.querySelectorAll('.multi-select-option').forEach(option => { + const text = option.querySelector('.multi-select-option-text').innerHTML.toLowerCase(); + option.style.display = text.includes(search.value.toLowerCase()) ? 'flex' : 'none'; + }); + }; + } + if (this.options.selectAll) { + let selectAllButton = this.element.querySelector('.multi-select-all'); + selectAllButton.onclick = (e) => { + e.stopPropagation(); + if (this.element.classList.contains('disabled')) return; + let allSelected = selectAllButton.classList.contains('multi-select-selected'); + this._bulkSelect = true; + this.element.querySelectorAll('.multi-select-option').forEach(option => { + let dataItem = this.data.find(data => data.value == option.dataset.value); + if (dataItem && ((allSelected && dataItem.selected) || (!allSelected && !dataItem.selected))) { + option.click(); + } + }); + this._bulkSelect = false; + selectAllButton.classList.toggle('multi-select-selected'); + this._emitChange(); + }; + } + if (this.selectElement.id && document.querySelector('label[for="' + this.selectElement.id + '"]')) { + document.querySelector('label[for="' + this.selectElement.id + '"]').onclick = () => { + toggleDropdown(); + }; + } + document.addEventListener('click', this.outsideClickHandler); + headerElement.addEventListener('keydown', (e) => { + if (['Enter', ' ', 'ArrowDown', 'ArrowUp'].includes(e.key)) { + e.preventDefault(); + toggleDropdown(); + const firstElement = this.element.querySelector('[role="searchbox"]') || this.element.querySelector('[role="option"]'); + if (firstElement) firstElement.focus(); + } + }); + this.element.addEventListener('keydown', (e) => { + if (e.key === 'Escape') { + toggleDropdown(true); + headerElement.focus(); + } + }); + const optionsContainer = this.element.querySelector('.multi-select-options'); + optionsContainer.addEventListener('keydown', (e) => { + const currentFocused = document.activeElement; + if (currentFocused.closest('.multi-select-options')) { + if (['ArrowDown', 'ArrowUp'].includes(e.key)) { + e.preventDefault(); + const direction = e.key === 'ArrowDown' ? 'nextElementSibling' : 'previousElementSibling'; + let nextElement = currentFocused[direction]; + while (nextElement && (nextElement.style.display === 'none' || !nextElement.matches('[role="option"], [role="searchbox"]'))) { + nextElement = nextElement[direction]; + } + if (nextElement) nextElement.focus(); + } else if (['Enter', ' '].includes(e.key) && currentFocused.matches('[role="option"]')) { + e.preventDefault(); + currentFocused.click(); + } + } + }); + } + + _updateHeader() { + this.element.querySelectorAll('.multi-select-header-option, .multi-select-header-placeholder').forEach(el => el.remove()); + if (this.selectedValues.length > 0) { + if (this.options.listAll) { + this.selectedItems.forEach(item => { + const el = document.createElement('span'); + el.className = 'multi-select-header-option'; + el.dataset.value = item.value; + el.innerHTML = item.text; + this.element.querySelector('.multi-select-header').prepend(el); + }); + } else { + const template = this.options.selectedLabel || 'selected'; + let label = template; + if (template.includes('{count}')) { + label = template.replace('{count}', this.selectedValues.length); + } else if (template.includes('%d')) { + label = template.replace('%d', this.selectedValues.length); + } else { + label = `${this.selectedValues.length} ${template}`; + } + this.element.querySelector('.multi-select-header').insertAdjacentHTML('afterbegin', `${label}`); + } + } else { + this.element.querySelector('.multi-select-header').insertAdjacentHTML('beforeend', `${this.placeholder}`); + } + if (this.options.max) { + this.element.querySelector('.multi-select-header-max').innerHTML = this.selectedValues.length + '/' + this.options.max; + } + } + + _updateSelected() { this._updateHeader(); } + + _emitChange() { + this.element.dispatchEvent(new CustomEvent('multi-select:change', { + detail: { values: this.selectedValues } + })); + } + + _validate() { + if (this.options.min && this.selectedValues.length < this.options.min) { + this.element.classList.add('multi-select-invalid'); + } else { + this.element.classList.remove('multi-select-invalid'); + } + } + + _outsideClick(event) { + if (!this.element.contains(event.target) && !event.target.closest('label[for="' + this.selectElement.id + '"]')) { + let headerElement = this.element.querySelector('.multi-select-header'); + if (headerElement.classList.contains('multi-select-header-active')) { + headerElement.classList.remove('multi-select-header-active'); + this.element.setAttribute('aria-expanded', 'false'); + } + } + } + + select(value) { + const option = this.element.querySelector(`.multi-select-option[data-value="${value}"]`); + if (option && !option.classList.contains('multi-select-selected')) { + option.click(); + } + } + + unselect(value) { + const option = this.element.querySelector(`.multi-select-option[data-value="${value}"]`); + if (option && option.classList.contains('multi-select-selected')) { + option.click(); + } + } + + setValues(values) { + this.data.forEach(item => { + item.selected = values.includes(item.value); + }); + this.refresh(); + } + + disable() { + this.element.classList.add('disabled'); + this.element.querySelector('.multi-select-header').removeAttribute('tabindex'); + const searchInput = this.element.querySelector('.multi-select-search'); + if (searchInput) searchInput.disabled = true; + } + + enable() { + this.element.classList.remove('disabled'); + this.element.querySelector('.multi-select-header').setAttribute('tabindex', '0'); + const searchInput = this.element.querySelector('.multi-select-search'); + if (searchInput) searchInput.disabled = false; + } + + destroy() { + this.element.replaceWith(this.originalSelectElement); + document.removeEventListener('click', this.outsideClickHandler); + } + + refresh() { + const newElement = this._template(); + this.element.replaceWith(newElement); + this.element = newElement; + this._updateSelected(); + this._eventHandlers(); + this._validate(); + } + + addItem(item) { + this.options.data.push(item); + this.refresh(); + } + + addItems(items) { + this.options.data.push(...items); + this.refresh(); + } + + async fetch(url, options = {}) { + const response = await fetch(url, options); + const data = await response.json(); + this.addItems(data); + if (this.options.onload) { + this.options.onload(data, this.options); + } + } + + removeItem(value) { + this.options.data = this.options.data.filter(item => item.value !== value); + this.refresh(); + } + + clear() { + this.options.data = []; + this.refresh(); + } + + reset() { + this.data = JSON.parse(JSON.stringify(this.originalData)); + this.refresh(); + } + + selectAll() { + this.data.forEach(item => item.selected = true); + this.refresh(); + } + + get selectedValues() { return this.data.filter(d => d.selected).map(d => d.value); } + get selectedItems() { return this.data.filter(d => d.selected); } + get data() { return this.options.data; } + set data(value) { this.options.data = value; } + + set selectElement(value) { this.options.selectElement = value; } + get selectElement() { return this.options.selectElement; } + + set element(value) { this.options.element = value; } + get element() { return this.options.element; } + + set placeholder(value) { this.options.placeholder = value; } + get placeholder() { return this.options.placeholder; } + + set name(value) { this.options.name = value; } + get name() { return this.options.name; } + + set width(value) { this.options.width = value; } + get width() { return this.options.width; } + + set height(value) { this.options.height = value; } + get height() { return this.options.height; } + +} +if (typeof window !== 'undefined') { + window.MultiSelect = window.MultiSelect || MultiSelect; +}