first commit
This commit is contained in:
22
public/assets/sweetalert2/LICENSE
Normal file
22
public/assets/sweetalert2/LICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Tristan Edwards & Limon Monte
|
||||
|
||||
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.
|
||||
|
||||
95
public/assets/sweetalert2/README.md
Normal file
95
public/assets/sweetalert2/README.md
Normal file
@@ -0,0 +1,95 @@
|
||||
<a href="https://sweetalert2.github.io/">
|
||||
<img src="./assets/swal2-logo.png" width="498" alt="SweetAlert2">
|
||||
</a>
|
||||
|
||||
A beautiful, responsive, customizable, accessible (WAI-ARIA) replacement <br> for JavaScript's popup boxes. Zero dependencies.
|
||||
|
||||
---
|
||||
|
||||
### [Installation](https://sweetalert2.github.io/#download) | [Usage](https://sweetalert2.github.io/#usage) | [Examples](https://sweetalert2.github.io/#examples) | [Recipe gallery](https://sweetalert2.github.io/recipe-gallery/) | [React](https://github.com/sweetalert2/sweetalert2-react-content) | [Angular](https://github.com/sweetalert2/ngx-sweetalert2) | [Laravel](https://github.com/sweetalert2/sweetalert2-laravel)
|
||||
|
||||
---
|
||||
|
||||
✨ 🚀 ✨ Get 20% discount on Hostiger Web Hosting: https://hostinger.com/?REFERRALCODE=BKZHOSTINDAB
|
||||
|
||||
# Sponsors
|
||||
|
||||
For all questions related to sponsorship please get in touch with me via email sweetalert2@gmail.com
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="SPONSORS.md#sponsors"><img src="https://sweetalert2.github.io/images/plus.png" width="80"><br>Become a sponsor</a></td>
|
||||
<td align="center"><a href="https://kryptot.fi/"><img src="https://sweetalert2.github.io/images/sponsors/kryptot.png" width="80"><br>Kryptot</a></td>
|
||||
<td align="center"><a href="https://www.inksonic.com/"><img src="https://sweetalert2.github.io/images/sponsors/inksonic.png" width="80"><br>InkSonic</a></td>
|
||||
<td align="center"><a href="https://bluehive.com/?utm_source=sweetalert2&utm_medium=sponsored&utm_campaign=listing"><img src="https://sweetalert2.github.io/images/sponsors/bluehive.png" width="80"><br>Occupational Healthcare</a></td>
|
||||
<td align="center"><a href="https://boilerplatehub.com/?utm_source=sweetalert2"><img src="https://sweetalert2.github.io/images/sponsors/boilerplatehub.jpg" width="80"><br>Build your SaaS or App</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://ssmarket.net/buy-youtube-views"><img src="https://sweetalert2.github.io/images/sponsors/ssmarket.png" width="80"><br>Buy Youtube Views</a></td>
|
||||
<td align="center"><a href="https://github.com/tiagostutz"><img src="https://avatars0.githubusercontent.com/u/3986989?s=80&v=4" width="80"><br>Tiago de Oliveira Stutz</a></td>
|
||||
<td align="center"><a href="https://roboflow.com/"><img src="https://sweetalert2.github.io/images/sponsors/roboflow.png" width="80"><br>Roboflow</a></td>
|
||||
<td align="center"><a href="https://www.zezelife.com/"><img src="https://sweetalert2.github.io/images/sponsors/zezelife.png" width="80"><br>ZezeLife</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
# NSFW Sponsors
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="SPONSORS.md#sponsors"><img src="https://sweetalert2.github.io/images/plus.png" width="80"><br>Become a NSFW sponsor</a></td>
|
||||
<td align="center"><a href="https://www.xndoll.com/"><img src="https://sweetalert2.github.io/images/sponsors/xndoll.png" width="80"><br>XNDOLL</a></td>
|
||||
<td align="center"><a href="https://www.pidoll.com/"><img src="https://sweetalert2.github.io/images/sponsors/pidoll.png" width="80"><br>PIDOLL</a></td>
|
||||
<td align="center"><a href="https://www.palstoy.com/"><img src="https://sweetalert2.github.io/images/sponsors/palstoy.png" width="80"><br>PalsToy</a></td>
|
||||
<td align="center"><a href="https://www.bestblowjobmachines.com/"><img src="https://sweetalert2.github.io/images/sponsors/bestblowjobmachines.png" width="80"><br>Mark Mitchell</a></td>
|
||||
<td align="center"><a href="https://pleasuremenow.com/"><img src="https://sweetalert2.github.io/images/sponsors/pleasuremenow.png" width="80"><br>Pleasure Me Now</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://www.venuslovedolls.com/"><img src="https://sweetalert2.github.io/images/sponsors/venuslovedolls.png" width="80"><br>Venus Love Dolls</a></td>
|
||||
<td align="center"><a href="https://www.sosexdoll.com/cheap-sex-doll"><img src="https://sweetalert2.github.io/images/sponsors/sosexdoll.png" width="80"><br>SoSexDoll</a></td>
|
||||
<td align="center"><a href="https://www.hismith.co.uk/"><img src="https://sweetalert2.github.io/images/sponsors/hismith.png" width="80"><br>Hismith</a></td>
|
||||
<td align="center"><a href="https://www.sexdollpartner.com/"><img src="https://sweetalert2.github.io/images/sponsors/sexdollpartner.jpg" width="80"><br>SexDollPartner</a></td>
|
||||
<td align="center"><a href="https://www.xspacecup.com/"><img src="https://sweetalert2.github.io/images/sponsors/xspacecup.png" width="80"><br>XspaceCup</a></td>
|
||||
<td align="center"><a href="https://nakedoll.com/"><img src="https://sweetalert2.github.io/images/sponsors/nakedoll.png" width="80"><br>NakeDoll</a></td>
|
||||
<td align="center"><a href="https://www.onahole.com/"><img src="https://sweetalert2.github.io/images/sponsors/onahole.png" width="80"><br>hentai sex toys</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://vsdoll.net/"><img src="https://sweetalert2.github.io/images/sponsors/vsdoll.png" width="80"><br>VSDoll</a></td>
|
||||
<td align="center"><a href="https://www.sextorso.com/"><img src="https://sweetalert2.github.io/images/sponsors/sextorso.png" width="80"><br>sexdoll torso</a></td>
|
||||
<td align="center"><a href="https://www.minisexdoll.com/anime-sexdoll/"><img src="https://sweetalert2.github.io/images/sponsors/minisexdoll.png" width="80"><br>anime sexdoll</a></td>
|
||||
<td align="center"><a href="https://www.myminisexdoll.com/under-300/"><img src="https://sweetalert2.github.io/images/sponsors/myminisexdoll.png" width="80"><br>cheap sexdoll</a></td>
|
||||
<td align="center"><a href="https://www.hugedildo.com/"><img src="https://sweetalert2.github.io/images/sponsors/hugedildo.png" width="80"><br>huge dildo</a></td>
|
||||
<td align="center"><a href="https://www.uusexdoll.com/"><img src="https://sweetalert2.github.io/images/sponsors/uusexdoll.png" width="80"><br>sexdoll</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://cutesexdoll.com/"><img src="https://sweetalert2.github.io/images/sponsors/cutesexdoll.jpg" width="80"><br>Cute Sex Doll</a></td>
|
||||
<td align="center"><a href="https://www.uusextoy.com/best-pocket-pussy/"><img src="https://sweetalert2.github.io/images/sponsors/uusextoy.png" width="80"><br>best pocket pussy</a></td>
|
||||
<td align="center"><a href="https://www.lovedolltorso.com/female-torso-sex-doll/"><img src="https://sweetalert2.github.io/images/sponsors/lovedolltorso.png" width="80"><br>female torso sex doll</a></td>
|
||||
<td align="center"><a href="https://www.mymasturbators.com/"><img src="https://sweetalert2.github.io/images/sponsors/mymasturbators.png" width="80"><br>male masturbator</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://www.buypenispump.com/"><img src="https://sweetalert2.github.io/images/sponsors/buypenispump.png" width="80"><br>penis pump</a></td>
|
||||
<td align="center"><a href="https://www.bestrealdoll.com/collections/us-warehouse"><img src="https://sweetalert2.github.io/images/sponsors/bestrealdoll.jpeg" width="80"><br>BestRealDoll</a></td>
|
||||
<td align="center"><a href="https://www.sexdolltech.com/product-category/us-warehouse/"><img src="https://sweetalert2.github.io/images/sponsors/sexdolltech.jpeg" width="80"><br>SexDollTech</a></td>
|
||||
<td align="center"><a href="https://www.sexdollsoff.com/"><img src="https://sweetalert2.github.io/images/sponsors/sexdollsoff.png" width="80"><br>SexDollsOff</a></td>
|
||||
<td align="center"><a href="https://realsexdoll.com/"><img src="https://sweetalert2.github.io/images/sponsors/realsexdoll.png" width="80"><br>RealSexDoll</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://www.yourdoll.com/"><img src="https://sweetalert2.github.io/images/sponsors/yourdoll.jpg" width="80"><br>Your Doll</a></td>
|
||||
<td align="center"><a href="https://anniesdollhouse.com/"><img src="https://sweetalert2.github.io/images/sponsors/annies-dollhouse.png" width="80"><br>Annie's Dollhouse</a></td>
|
||||
<td align="center"><a href="https://sextoycollective.com/"><img src="https://sweetalert2.github.io/images/sponsors/sextoycollective.jpg" width="80"><br>STC</a></td>
|
||||
<td align="center"><a href="https://doctorclimax.com/"><img src="https://sweetalert2.github.io/images/sponsors/doctorclimax.png" width="80"><br>DoctorClimax</a></td>
|
||||
<td align="center"><a href="https://www.bsdoll.com/"><img src="https://sweetalert2.github.io/images/sponsors/bsdoll.jpg" width="80"><br>BSDoll</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
4825
public/assets/sweetalert2/dist/sweetalert2.all.js
vendored
Normal file
4825
public/assets/sweetalert2/dist/sweetalert2.all.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
public/assets/sweetalert2/dist/sweetalert2.all.min.js
vendored
Normal file
6
public/assets/sweetalert2/dist/sweetalert2.all.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1233
public/assets/sweetalert2/dist/sweetalert2.css
vendored
Normal file
1233
public/assets/sweetalert2/dist/sweetalert2.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4816
public/assets/sweetalert2/dist/sweetalert2.esm.all.js
vendored
Normal file
4816
public/assets/sweetalert2/dist/sweetalert2.esm.all.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
public/assets/sweetalert2/dist/sweetalert2.esm.all.min.js
vendored
Normal file
6
public/assets/sweetalert2/dist/sweetalert2.esm.all.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4815
public/assets/sweetalert2/dist/sweetalert2.esm.js
vendored
Normal file
4815
public/assets/sweetalert2/dist/sweetalert2.esm.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5
public/assets/sweetalert2/dist/sweetalert2.esm.min.js
vendored
Normal file
5
public/assets/sweetalert2/dist/sweetalert2.esm.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4824
public/assets/sweetalert2/dist/sweetalert2.js
vendored
Normal file
4824
public/assets/sweetalert2/dist/sweetalert2.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
public/assets/sweetalert2/dist/sweetalert2.min.css
vendored
Normal file
1
public/assets/sweetalert2/dist/sweetalert2.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
5
public/assets/sweetalert2/dist/sweetalert2.min.js
vendored
Normal file
5
public/assets/sweetalert2/dist/sweetalert2.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
87
public/assets/sweetalert2/package.json
Normal file
87
public/assets/sweetalert2/package.json
Normal file
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"name": "sweetalert2",
|
||||
"version": "11.26.18",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sweetalert2/sweetalert2.git"
|
||||
},
|
||||
"homepage": "https://sweetalert2.github.io/",
|
||||
"description": "A beautiful, responsive, customizable and accessible (WAI-ARIA) replacement for JavaScript's popup boxes, supported fork of sweetalert",
|
||||
"main": "dist/sweetalert2.all.js",
|
||||
"browser": "dist/sweetalert2.all.js",
|
||||
"module": "dist/sweetalert2.esm.all.js",
|
||||
"types": "sweetalert2.d.ts",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.19.6",
|
||||
"@babel/preset-env": "^7.19.4",
|
||||
"@rollup/plugin-babel": "^6.0.2",
|
||||
"@rollup/plugin-terser": "^0.4.0",
|
||||
"@sweetalert2/eslint-config": "^1.0.11",
|
||||
"@sweetalert2/stylelint-config": "^3.0.0",
|
||||
"cypress": "^15.0.0",
|
||||
"eslint": "^9.0.0",
|
||||
"eslint-plugin-cypress": "^5.0.0",
|
||||
"eslint-plugin-jsdoc": "^62.0.1",
|
||||
"eslint-plugin-no-unsanitized": "^4.0.1",
|
||||
"jquery": "^3.6.1",
|
||||
"playwright-webkit": "^1.37.1",
|
||||
"prettier": "^3.0.0",
|
||||
"rollup": "^4.0.0",
|
||||
"sass": "^1.83.0",
|
||||
"stylelint": "^17.0.0",
|
||||
"typescript": "4.8.4",
|
||||
"vite": "^7.0.0",
|
||||
"zx": "^8.0.0"
|
||||
},
|
||||
"devDependenciesComments": {
|
||||
"typescript": "Do not upgrade TS, tests will verify that types work with the very first version of TS >= 4.8.4"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"src",
|
||||
"themes",
|
||||
"sweetalert2.d.ts"
|
||||
],
|
||||
"author": "Limon Monte (https://limonte.github.io)",
|
||||
"contributors": [
|
||||
"Matthew Francis Brunetti <zenflow87@gmail.com> (https://github.com/zenflow)",
|
||||
"Morgan Touverey-Quilling <mtouverey@alembic-dev.com> (https://github.com/toverux)",
|
||||
"Giuseppe Verni (https://github.com/gverni)",
|
||||
"Sam Turrell <sam@samturrell.co.uk> (https://github.com/samturrell)",
|
||||
"Joseph Schultz (https://github.com/acupofjose)",
|
||||
"Johan Fagerberg (https://github.com/birjolaxew)"
|
||||
],
|
||||
"keywords": [
|
||||
"sweetalert",
|
||||
"sweetalert2",
|
||||
"alert",
|
||||
"modal",
|
||||
"popup",
|
||||
"prompt",
|
||||
"confirm",
|
||||
"toast",
|
||||
"accessible"
|
||||
],
|
||||
"scripts": {
|
||||
"dev": "vite test/sandbox --open",
|
||||
"lint": "stylelint src/*.scss themes/*.css && eslint src cypress tools *.js *.ts && prettier --check src/**/*.js cypress/**/*.js *.js",
|
||||
"build": "zx tools/build.mjs",
|
||||
"test": "cypress run --headless",
|
||||
"check-types": "npx -p typescript@latest tsc --noEmit --lib dom,es2018 -p jsconfig.json",
|
||||
"cypress:open": "cypress open",
|
||||
"webpack-build": "webpack --config=test/webpack/webpack.config.js"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/limonte"
|
||||
},
|
||||
"prettier": {
|
||||
"printWidth": 120,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"quoteProps": "consistent",
|
||||
"trailingComma": "es5"
|
||||
},
|
||||
"bugs": "https://github.com/sweetalert2/sweetalert2/issues",
|
||||
"license": "MIT"
|
||||
}
|
||||
355
public/assets/sweetalert2/src/SweetAlert.js
Normal file
355
public/assets/sweetalert2/src/SweetAlert.js
Normal file
@@ -0,0 +1,355 @@
|
||||
import { handleCancelButtonClick, handleConfirmButtonClick, handleDenyButtonClick } from './buttons-handlers.js'
|
||||
import globalState from './globalState.js'
|
||||
import * as instanceMethods from './instanceMethods.js'
|
||||
import { addKeydownHandler, setFocus } from './keydown-handler.js'
|
||||
import { handlePopupClick } from './popup-click-handler.js'
|
||||
import privateMethods from './privateMethods.js'
|
||||
import privateProps from './privateProps.js'
|
||||
import * as staticMethods from './staticMethods.js'
|
||||
import { DismissReason } from './utils/DismissReason.js'
|
||||
import Timer from './utils/Timer.js'
|
||||
import { unsetAriaHidden } from './utils/aria.js'
|
||||
import * as dom from './utils/dom/index.js'
|
||||
import { handleInputOptionsAndValue } from './utils/dom/inputUtils.js'
|
||||
import { getTemplateParams } from './utils/getTemplateParams.js'
|
||||
import { openPopup } from './utils/openPopup.js'
|
||||
import defaultParams, { showWarningsForParams } from './utils/params.js'
|
||||
import setParameters from './utils/setParameters.js'
|
||||
import { callIfFunction, warnAboutDeprecation } from './utils/utils.js'
|
||||
|
||||
/** @type {SweetAlert} */
|
||||
let currentInstance
|
||||
|
||||
export class SweetAlert {
|
||||
/**
|
||||
* @type {Promise<SweetAlertResult>}
|
||||
*/
|
||||
#promise = /** @type {Promise<SweetAlertResult>} */ (Promise.resolve({ isConfirmed: false, isDenied: false, isDismissed: true }))
|
||||
|
||||
/**
|
||||
* @param {...(SweetAlertOptions | string)} args
|
||||
* @this {SweetAlert}
|
||||
*/
|
||||
constructor(...args) {
|
||||
// Prevent run in Node env
|
||||
if (typeof window === 'undefined') {
|
||||
return
|
||||
}
|
||||
|
||||
currentInstance = this
|
||||
|
||||
// @ts-ignore
|
||||
const outerParams = Object.freeze(this.constructor.argsToParams(args))
|
||||
|
||||
/** @type {Readonly<SweetAlertOptions>} */
|
||||
this.params = outerParams
|
||||
|
||||
/** @type {boolean} */
|
||||
this.isAwaitingPromise = false
|
||||
|
||||
this.#promise = this._main(currentInstance.params)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} userParams
|
||||
* @param {any} mixinParams
|
||||
*/
|
||||
_main(userParams, mixinParams = {}) {
|
||||
showWarningsForParams(Object.assign({}, mixinParams, userParams))
|
||||
|
||||
if (globalState.currentInstance) {
|
||||
const swalPromiseResolve = privateMethods.swalPromiseResolve.get(globalState.currentInstance)
|
||||
const { isAwaitingPromise } = globalState.currentInstance
|
||||
globalState.currentInstance._destroy()
|
||||
if (!isAwaitingPromise) {
|
||||
swalPromiseResolve({ isDismissed: true })
|
||||
}
|
||||
if (dom.isModal()) {
|
||||
unsetAriaHidden()
|
||||
}
|
||||
}
|
||||
|
||||
globalState.currentInstance = currentInstance
|
||||
|
||||
const innerParams = prepareParams(userParams, mixinParams)
|
||||
setParameters(innerParams)
|
||||
Object.freeze(innerParams)
|
||||
|
||||
// clear the previous timer
|
||||
if (globalState.timeout) {
|
||||
globalState.timeout.stop()
|
||||
delete globalState.timeout
|
||||
}
|
||||
|
||||
// clear the restore focus timeout
|
||||
clearTimeout(globalState.restoreFocusTimeout)
|
||||
|
||||
const domCache = populateDomCache(currentInstance)
|
||||
|
||||
dom.render(currentInstance, innerParams)
|
||||
|
||||
privateProps.innerParams.set(currentInstance, innerParams)
|
||||
|
||||
return swalPromise(currentInstance, domCache, innerParams)
|
||||
}
|
||||
|
||||
// `catch` cannot be the name of a module export, so we define our thenable methods here instead
|
||||
/**
|
||||
* @param {any} onFulfilled
|
||||
*/
|
||||
then(onFulfilled) {
|
||||
return this.#promise.then(onFulfilled)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} onFinally
|
||||
*/
|
||||
finally(onFinally) {
|
||||
return this.#promise.finally(onFinally)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {DomCache} domCache
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
* @returns {Promise<SweetAlertResult>}
|
||||
*/
|
||||
const swalPromise = (instance, domCache, innerParams) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// functions to handle all closings/dismissals
|
||||
/**
|
||||
* @param {DismissReason} dismiss
|
||||
*/
|
||||
const dismissWith = (dismiss) => {
|
||||
instance.close({ isDismissed: true, dismiss, isConfirmed: false, isDenied: false })
|
||||
}
|
||||
|
||||
privateMethods.swalPromiseResolve.set(instance, resolve)
|
||||
privateMethods.swalPromiseReject.set(instance, reject)
|
||||
|
||||
domCache.confirmButton.onclick = () => {
|
||||
handleConfirmButtonClick(instance)
|
||||
}
|
||||
|
||||
domCache.denyButton.onclick = () => {
|
||||
handleDenyButtonClick(instance)
|
||||
}
|
||||
|
||||
domCache.cancelButton.onclick = () => {
|
||||
handleCancelButtonClick(instance, dismissWith)
|
||||
}
|
||||
|
||||
domCache.closeButton.onclick = () => {
|
||||
dismissWith(DismissReason.close)
|
||||
}
|
||||
|
||||
handlePopupClick(innerParams, domCache, dismissWith)
|
||||
|
||||
addKeydownHandler(globalState, innerParams, dismissWith)
|
||||
|
||||
handleInputOptionsAndValue(instance, innerParams)
|
||||
|
||||
openPopup(innerParams)
|
||||
|
||||
setupTimer(globalState, innerParams, dismissWith)
|
||||
|
||||
initFocus(domCache, innerParams)
|
||||
|
||||
// Scroll container to top on open (#1247, #1946)
|
||||
setTimeout(() => {
|
||||
domCache.container.scrollTop = 0
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlertOptions} userParams
|
||||
* @param {SweetAlertOptions} mixinParams
|
||||
* @returns {SweetAlertOptions}
|
||||
*/
|
||||
const prepareParams = (userParams, mixinParams) => {
|
||||
const templateParams = getTemplateParams(userParams)
|
||||
const params = Object.assign({}, defaultParams, mixinParams, templateParams, userParams) // precedence is described in #2131
|
||||
params.showClass = Object.assign({}, defaultParams.showClass, params.showClass)
|
||||
params.hideClass = Object.assign({}, defaultParams.hideClass, params.hideClass)
|
||||
if (params.animation === false) {
|
||||
params.showClass = {
|
||||
backdrop: 'swal2-noanimation',
|
||||
}
|
||||
params.hideClass = {}
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @returns {DomCache}
|
||||
*/
|
||||
const populateDomCache = (instance) => {
|
||||
const domCache = /** @type {DomCache} */ ({
|
||||
popup: /** @type {HTMLElement} */ (dom.getPopup()),
|
||||
container: /** @type {HTMLElement} */ (dom.getContainer()),
|
||||
actions: /** @type {HTMLElement} */ (dom.getActions()),
|
||||
confirmButton: /** @type {HTMLElement} */ (dom.getConfirmButton()),
|
||||
denyButton: /** @type {HTMLElement} */ (dom.getDenyButton()),
|
||||
cancelButton: /** @type {HTMLElement} */ (dom.getCancelButton()),
|
||||
loader: /** @type {HTMLElement} */ (dom.getLoader()),
|
||||
closeButton: /** @type {HTMLElement} */ (dom.getCloseButton()),
|
||||
validationMessage: /** @type {HTMLElement} */ (dom.getValidationMessage()),
|
||||
progressSteps: /** @type {HTMLElement} */ (dom.getProgressSteps()),
|
||||
})
|
||||
privateProps.domCache.set(instance, domCache)
|
||||
|
||||
return domCache
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GlobalState} globalState
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
* @param {(dismiss: DismissReason) => void} dismissWith
|
||||
*/
|
||||
const setupTimer = (globalState, innerParams, dismissWith) => {
|
||||
const timerProgressBar = dom.getTimerProgressBar()
|
||||
dom.hide(timerProgressBar)
|
||||
if (innerParams.timer) {
|
||||
globalState.timeout = new Timer(() => {
|
||||
dismissWith('timer')
|
||||
delete globalState.timeout
|
||||
}, innerParams.timer)
|
||||
if (innerParams.timerProgressBar && timerProgressBar) {
|
||||
dom.show(timerProgressBar)
|
||||
dom.applyCustomClass(timerProgressBar, innerParams, 'timerProgressBar')
|
||||
setTimeout(() => {
|
||||
if (globalState.timeout && globalState.timeout.running) {
|
||||
// timer can be already stopped or unset at this point
|
||||
dom.animateTimerProgressBar(/** @type {number} */ (innerParams.timer))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize focus in the popup:
|
||||
*
|
||||
* 1. If `toast` is `true`, don't steal focus from the document.
|
||||
* 2. Else if there is an [autofocus] element, focus it.
|
||||
* 3. Else if `focusConfirm` is `true` and confirm button is visible, focus it.
|
||||
* 4. Else if `focusDeny` is `true` and deny button is visible, focus it.
|
||||
* 5. Else if `focusCancel` is `true` and cancel button is visible, focus it.
|
||||
* 6. Else focus the first focusable element in a popup (if any).
|
||||
*
|
||||
* @param {DomCache} domCache
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
*/
|
||||
const initFocus = (domCache, innerParams) => {
|
||||
if (innerParams.toast) {
|
||||
return
|
||||
}
|
||||
// TODO: this is dumb, remove `allowEnterKey` param in the next major version
|
||||
if (!callIfFunction(innerParams.allowEnterKey)) {
|
||||
warnAboutDeprecation('allowEnterKey')
|
||||
blurActiveElement()
|
||||
return
|
||||
}
|
||||
|
||||
if (focusAutofocus(domCache)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (focusButton(domCache, innerParams)) {
|
||||
return
|
||||
}
|
||||
|
||||
setFocus(-1, 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DomCache} domCache
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const focusAutofocus = (domCache) => {
|
||||
const autofocusElements = Array.from(domCache.popup.querySelectorAll('[autofocus]'))
|
||||
for (const autofocusElement of autofocusElements) {
|
||||
if (autofocusElement instanceof HTMLElement && dom.isVisible(autofocusElement)) {
|
||||
autofocusElement.focus()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DomCache} domCache
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const focusButton = (domCache, innerParams) => {
|
||||
if (innerParams.focusDeny && dom.isVisible(domCache.denyButton)) {
|
||||
domCache.denyButton.focus()
|
||||
return true
|
||||
}
|
||||
|
||||
if (innerParams.focusCancel && dom.isVisible(domCache.cancelButton)) {
|
||||
domCache.cancelButton.focus()
|
||||
return true
|
||||
}
|
||||
|
||||
if (innerParams.focusConfirm && dom.isVisible(domCache.confirmButton)) {
|
||||
domCache.confirmButton.focus()
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
const blurActiveElement = () => {
|
||||
if (document.activeElement instanceof HTMLElement && typeof document.activeElement.blur === 'function') {
|
||||
document.activeElement.blur()
|
||||
}
|
||||
}
|
||||
|
||||
// Assign instance methods from src/instanceMethods/*.js to prototype
|
||||
SweetAlert.prototype.disableButtons = instanceMethods.disableButtons
|
||||
SweetAlert.prototype.enableButtons = instanceMethods.enableButtons
|
||||
SweetAlert.prototype.getInput = instanceMethods.getInput
|
||||
SweetAlert.prototype.disableInput = instanceMethods.disableInput
|
||||
SweetAlert.prototype.enableInput = instanceMethods.enableInput
|
||||
SweetAlert.prototype.hideLoading = instanceMethods.hideLoading
|
||||
SweetAlert.prototype.disableLoading = instanceMethods.disableLoading
|
||||
SweetAlert.prototype.showValidationMessage = instanceMethods.showValidationMessage
|
||||
SweetAlert.prototype.resetValidationMessage = instanceMethods.resetValidationMessage
|
||||
SweetAlert.prototype.close = instanceMethods.close
|
||||
SweetAlert.prototype.closePopup = instanceMethods.closePopup
|
||||
SweetAlert.prototype.closeModal = instanceMethods.closeModal
|
||||
SweetAlert.prototype.closeToast = instanceMethods.closeToast
|
||||
SweetAlert.prototype.rejectPromise = instanceMethods.rejectPromise
|
||||
SweetAlert.prototype.update = instanceMethods.update
|
||||
SweetAlert.prototype._destroy = instanceMethods._destroy
|
||||
|
||||
// Assign static methods from src/staticMethods/*.js to constructor
|
||||
Object.assign(SweetAlert, staticMethods)
|
||||
|
||||
// Proxy to instance methods to constructor, for now, for backwards compatibility
|
||||
Object.keys(instanceMethods).forEach((key) => {
|
||||
/**
|
||||
* @param {...(SweetAlertOptions | string | undefined)} args
|
||||
* @returns {SweetAlertResult | Promise<SweetAlertResult> | undefined}
|
||||
*/
|
||||
// @ts-ignore: Dynamic property assignment for backwards compatibility
|
||||
SweetAlert[key] = function (...args) {
|
||||
// @ts-ignore
|
||||
if (currentInstance && currentInstance[key]) {
|
||||
// @ts-ignore
|
||||
return currentInstance[key](...args)
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
})
|
||||
|
||||
SweetAlert.DismissReason = DismissReason
|
||||
|
||||
SweetAlert.version = '11.26.18'
|
||||
|
||||
export default SweetAlert
|
||||
177
public/assets/sweetalert2/src/buttons-handlers.js
Normal file
177
public/assets/sweetalert2/src/buttons-handlers.js
Normal file
@@ -0,0 +1,177 @@
|
||||
import { handleAwaitingPromise } from './instanceMethods/close.js'
|
||||
import privateProps from './privateProps.js'
|
||||
import { showLoading } from './staticMethods/showLoading.js'
|
||||
import { DismissReason } from './utils/DismissReason.js'
|
||||
import { isVisible } from './utils/dom/domUtils.js'
|
||||
import { getDenyButton, getValidationMessage } from './utils/dom/getters.js'
|
||||
import { getInputValue } from './utils/dom/inputUtils.js'
|
||||
import { asPromise, capitalizeFirstLetter, error } from './utils/utils.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
*/
|
||||
export const handleConfirmButtonClick = (instance) => {
|
||||
const innerParams = privateProps.innerParams.get(instance)
|
||||
instance.disableButtons()
|
||||
if (innerParams.input) {
|
||||
handleConfirmOrDenyWithInput(instance, 'confirm')
|
||||
} else {
|
||||
confirm(instance, true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
*/
|
||||
export const handleDenyButtonClick = (instance) => {
|
||||
const innerParams = privateProps.innerParams.get(instance)
|
||||
instance.disableButtons()
|
||||
if (innerParams.returnInputValueOnDeny) {
|
||||
handleConfirmOrDenyWithInput(instance, 'deny')
|
||||
} else {
|
||||
deny(instance, false)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {(dismiss: DismissReason) => void} dismissWith
|
||||
*/
|
||||
export const handleCancelButtonClick = (instance, dismissWith) => {
|
||||
instance.disableButtons()
|
||||
dismissWith(DismissReason.cancel)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {'confirm' | 'deny'} type
|
||||
*/
|
||||
const handleConfirmOrDenyWithInput = (instance, type) => {
|
||||
const innerParams = privateProps.innerParams.get(instance)
|
||||
if (!innerParams.input) {
|
||||
error(`The "input" parameter is needed to be set when using returnInputValueOn${capitalizeFirstLetter(type)}`)
|
||||
return
|
||||
}
|
||||
const input = instance.getInput()
|
||||
const inputValue = getInputValue(instance, innerParams)
|
||||
if (innerParams.inputValidator) {
|
||||
handleInputValidator(instance, inputValue, type)
|
||||
} else if (input && !input.checkValidity()) {
|
||||
instance.enableButtons()
|
||||
instance.showValidationMessage(innerParams.validationMessage || input.validationMessage)
|
||||
} else if (type === 'deny') {
|
||||
deny(instance, inputValue)
|
||||
} else {
|
||||
confirm(instance, inputValue)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {SweetAlertInputValue} inputValue
|
||||
* @param {'confirm' | 'deny'} type
|
||||
*/
|
||||
const handleInputValidator = (instance, inputValue, type) => {
|
||||
const innerParams = privateProps.innerParams.get(instance)
|
||||
instance.disableInput()
|
||||
const validationPromise = Promise.resolve().then(() =>
|
||||
asPromise(innerParams.inputValidator(inputValue, innerParams.validationMessage))
|
||||
)
|
||||
validationPromise.then((validationMessage) => {
|
||||
instance.enableButtons()
|
||||
instance.enableInput()
|
||||
if (validationMessage) {
|
||||
instance.showValidationMessage(validationMessage)
|
||||
} else if (type === 'deny') {
|
||||
deny(instance, inputValue)
|
||||
} else {
|
||||
confirm(instance, inputValue)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {*} value
|
||||
*/
|
||||
const deny = (instance, value) => {
|
||||
const innerParams = privateProps.innerParams.get(instance)
|
||||
|
||||
if (innerParams.showLoaderOnDeny) {
|
||||
showLoading(getDenyButton())
|
||||
}
|
||||
|
||||
if (innerParams.preDeny) {
|
||||
instance.isAwaitingPromise = true // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesn't get destroyed until the result from this preDeny's promise is received
|
||||
const preDenyPromise = Promise.resolve().then(() =>
|
||||
asPromise(innerParams.preDeny(value, innerParams.validationMessage))
|
||||
)
|
||||
preDenyPromise
|
||||
.then((preDenyValue) => {
|
||||
if (preDenyValue === false) {
|
||||
instance.hideLoading()
|
||||
handleAwaitingPromise(instance)
|
||||
} else {
|
||||
instance.close(
|
||||
/** @type SweetAlertResult */ ({
|
||||
isDenied: true,
|
||||
value: typeof preDenyValue === 'undefined' ? value : preDenyValue,
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
.catch((error) => rejectWith(instance, error))
|
||||
} else {
|
||||
instance.close(/** @type SweetAlertResult */ ({ isDenied: true, value }))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {*} value
|
||||
*/
|
||||
const succeedWith = (instance, value) => {
|
||||
instance.close(/** @type SweetAlertResult */ ({ isConfirmed: true, value }))
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {SweetAlert} instance
|
||||
* @param {string} error
|
||||
*/
|
||||
const rejectWith = (instance, error) => {
|
||||
instance.rejectPromise(error)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {SweetAlert} instance
|
||||
* @param {*} value
|
||||
*/
|
||||
const confirm = (instance, value) => {
|
||||
const innerParams = privateProps.innerParams.get(instance)
|
||||
|
||||
if (innerParams.showLoaderOnConfirm) {
|
||||
showLoading()
|
||||
}
|
||||
|
||||
if (innerParams.preConfirm) {
|
||||
instance.resetValidationMessage()
|
||||
instance.isAwaitingPromise = true // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesn't get destroyed until the result from this preConfirm's promise is received
|
||||
const preConfirmPromise = Promise.resolve().then(() =>
|
||||
asPromise(innerParams.preConfirm(value, innerParams.validationMessage))
|
||||
)
|
||||
preConfirmPromise
|
||||
.then((preConfirmValue) => {
|
||||
if (isVisible(getValidationMessage()) || preConfirmValue === false) {
|
||||
instance.hideLoading()
|
||||
handleAwaitingPromise(instance)
|
||||
} else {
|
||||
succeedWith(instance, typeof preConfirmValue === 'undefined' ? value : preConfirmValue)
|
||||
}
|
||||
})
|
||||
.catch((error) => rejectWith(instance, error))
|
||||
} else {
|
||||
succeedWith(instance, value)
|
||||
}
|
||||
}
|
||||
1
public/assets/sweetalert2/src/constants.js
Normal file
1
public/assets/sweetalert2/src/constants.js
Normal file
@@ -0,0 +1 @@
|
||||
export const RESTORE_FOCUS_TIMEOUT = 100
|
||||
38
public/assets/sweetalert2/src/globalState.js
Normal file
38
public/assets/sweetalert2/src/globalState.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import { RESTORE_FOCUS_TIMEOUT } from './constants.js'
|
||||
|
||||
/** @type {GlobalState} */
|
||||
const globalState = {}
|
||||
|
||||
export default globalState
|
||||
|
||||
const focusPreviousActiveElement = () => {
|
||||
if (globalState.previousActiveElement instanceof HTMLElement) {
|
||||
globalState.previousActiveElement.focus()
|
||||
globalState.previousActiveElement = null
|
||||
} else if (document.body) {
|
||||
document.body.focus()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore previous active (focused) element
|
||||
*
|
||||
* @param {boolean} returnFocus
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export const restoreActiveElement = (returnFocus) => {
|
||||
return new Promise((resolve) => {
|
||||
if (!returnFocus) {
|
||||
return resolve()
|
||||
}
|
||||
const x = window.scrollX
|
||||
const y = window.scrollY
|
||||
|
||||
globalState.restoreFocusTimeout = setTimeout(() => {
|
||||
focusPreviousActiveElement()
|
||||
resolve()
|
||||
}, RESTORE_FOCUS_TIMEOUT) // issues/900
|
||||
|
||||
window.scrollTo(x, y)
|
||||
})
|
||||
}
|
||||
7
public/assets/sweetalert2/src/instanceMethods.js
Normal file
7
public/assets/sweetalert2/src/instanceMethods.js
Normal file
@@ -0,0 +1,7 @@
|
||||
export * from './instanceMethods/hideLoading.js'
|
||||
export * from './instanceMethods/getInput.js'
|
||||
export * from './instanceMethods/close.js'
|
||||
export * from './instanceMethods/enable-disable-elements.js'
|
||||
export * from './instanceMethods/validation-message.js'
|
||||
export * from './instanceMethods/update.js'
|
||||
export * from './instanceMethods/_destroy.js'
|
||||
104
public/assets/sweetalert2/src/instanceMethods/_destroy.js
Normal file
104
public/assets/sweetalert2/src/instanceMethods/_destroy.js
Normal file
@@ -0,0 +1,104 @@
|
||||
import globalState from '../globalState.js'
|
||||
import privateMethods from '../privateMethods.js'
|
||||
import privateProps from '../privateProps.js'
|
||||
|
||||
/**
|
||||
* Dispose the current SweetAlert2 instance
|
||||
* @this {SweetAlert}
|
||||
*/
|
||||
export function _destroy() {
|
||||
const domCache = privateProps.domCache.get(this)
|
||||
const innerParams = privateProps.innerParams.get(this)
|
||||
|
||||
if (!innerParams) {
|
||||
disposeWeakMaps(this) // The WeakMaps might have been partly destroyed, we must recall it to dispose any remaining WeakMaps #2335
|
||||
return // This instance has already been destroyed
|
||||
}
|
||||
|
||||
// Check if there is another Swal closing
|
||||
if (domCache.popup && globalState.swalCloseEventFinishedCallback) {
|
||||
globalState.swalCloseEventFinishedCallback()
|
||||
delete globalState.swalCloseEventFinishedCallback
|
||||
}
|
||||
|
||||
if (typeof innerParams.didDestroy === 'function') {
|
||||
innerParams.didDestroy()
|
||||
}
|
||||
globalState.eventEmitter?.emit('didDestroy')
|
||||
disposeSwal(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
*/
|
||||
const disposeSwal = (instance) => {
|
||||
disposeWeakMaps(instance)
|
||||
// Unset this.params so GC will dispose it (#1569)
|
||||
// @ts-ignore
|
||||
delete instance.params
|
||||
// Unset globalState props so GC will dispose globalState (#1569)
|
||||
delete globalState.keydownHandler
|
||||
delete globalState.keydownTarget
|
||||
// Unset currentInstance
|
||||
delete globalState.currentInstance
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
*/
|
||||
const disposeWeakMaps = (instance) => {
|
||||
// If the current instance is awaiting a promise result, we keep the privateMethods to call them once the promise result is retrieved #2335
|
||||
if (instance.isAwaitingPromise) {
|
||||
unsetWeakMaps(privateProps, instance)
|
||||
instance.isAwaitingPromise = true
|
||||
} else {
|
||||
unsetWeakMaps(privateMethods, instance)
|
||||
unsetWeakMaps(privateProps, instance)
|
||||
|
||||
// @ts-ignore
|
||||
delete instance.isAwaitingPromise
|
||||
// Unset instance methods
|
||||
// @ts-ignore
|
||||
delete instance.disableButtons
|
||||
// @ts-ignore
|
||||
delete instance.enableButtons
|
||||
// @ts-ignore
|
||||
delete instance.getInput
|
||||
// @ts-ignore
|
||||
delete instance.disableInput
|
||||
// @ts-ignore
|
||||
delete instance.enableInput
|
||||
// @ts-ignore
|
||||
delete instance.hideLoading
|
||||
// @ts-ignore
|
||||
delete instance.disableLoading
|
||||
// @ts-ignore
|
||||
delete instance.showValidationMessage
|
||||
// @ts-ignore
|
||||
delete instance.resetValidationMessage
|
||||
// @ts-ignore
|
||||
delete instance.close
|
||||
// @ts-ignore
|
||||
delete instance.closePopup
|
||||
// @ts-ignore
|
||||
delete instance.closeModal
|
||||
// @ts-ignore
|
||||
delete instance.closeToast
|
||||
// @ts-ignore
|
||||
delete instance.rejectPromise
|
||||
// @ts-ignore
|
||||
delete instance.update
|
||||
// @ts-ignore
|
||||
delete instance._destroy
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Record<string, WeakMap<any, any>>} obj
|
||||
* @param {SweetAlert} instance
|
||||
*/
|
||||
const unsetWeakMaps = (obj, instance) => {
|
||||
for (const i in obj) {
|
||||
obj[i].delete(instance)
|
||||
}
|
||||
}
|
||||
229
public/assets/sweetalert2/src/instanceMethods/close.js
Normal file
229
public/assets/sweetalert2/src/instanceMethods/close.js
Normal file
@@ -0,0 +1,229 @@
|
||||
import globalState, { restoreActiveElement } from '../globalState.js'
|
||||
import { removeKeydownHandler } from '../keydown-handler.js'
|
||||
import privateMethods from '../privateMethods.js'
|
||||
import privateProps from '../privateProps.js'
|
||||
import { unsetAriaHidden } from '../utils/aria.js'
|
||||
import { swalClasses } from '../utils/classes.js'
|
||||
import * as dom from '../utils/dom/index.js'
|
||||
import { undoIOSfix } from '../utils/iosFix.js'
|
||||
import { undoReplaceScrollbarWithPadding } from '../utils/scrollbar.js'
|
||||
import { isSafariOrIOS } from '../utils/iosFix.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {HTMLElement} container
|
||||
* @param {boolean} returnFocus
|
||||
* @param {(() => void) | undefined} didClose
|
||||
*/
|
||||
function removePopupAndResetState(instance, container, returnFocus, didClose) {
|
||||
if (dom.isToast()) {
|
||||
triggerDidCloseAndDispose(instance, didClose)
|
||||
} else {
|
||||
restoreActiveElement(returnFocus).then(() => triggerDidCloseAndDispose(instance, didClose))
|
||||
removeKeydownHandler(globalState)
|
||||
}
|
||||
|
||||
// workaround for https://github.com/sweetalert2/sweetalert2/issues/2088
|
||||
// for some reason removing the container in Safari will scroll the document to bottom
|
||||
if (isSafariOrIOS) {
|
||||
container.setAttribute('style', 'display:none !important')
|
||||
container.removeAttribute('class')
|
||||
container.innerHTML = ''
|
||||
} else {
|
||||
container.remove()
|
||||
}
|
||||
|
||||
if (dom.isModal()) {
|
||||
undoReplaceScrollbarWithPadding()
|
||||
undoIOSfix()
|
||||
unsetAriaHidden()
|
||||
}
|
||||
|
||||
removeBodyClasses()
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove SweetAlert2 classes from body
|
||||
*/
|
||||
function removeBodyClasses() {
|
||||
dom.removeClass(
|
||||
[document.documentElement, document.body],
|
||||
[swalClasses.shown, swalClasses['height-auto'], swalClasses['no-backdrop'], swalClasses['toast-shown']]
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Instance method to close sweetAlert
|
||||
*
|
||||
* @param {SweetAlertResult | undefined} resolveValue
|
||||
* @this {SweetAlert}
|
||||
*/
|
||||
export function close(resolveValue) {
|
||||
resolveValue = prepareResolveValue(resolveValue)
|
||||
|
||||
const swalPromiseResolve = privateMethods.swalPromiseResolve.get(this)
|
||||
|
||||
const didClose = triggerClosePopup(this)
|
||||
|
||||
if (this.isAwaitingPromise) {
|
||||
// A swal awaiting for a promise (after a click on Confirm or Deny) cannot be dismissed anymore #2335
|
||||
if (!resolveValue.isDismissed) {
|
||||
handleAwaitingPromise(this)
|
||||
swalPromiseResolve(resolveValue)
|
||||
}
|
||||
} else if (didClose) {
|
||||
// Resolve Swal promise
|
||||
swalPromiseResolve(resolveValue)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const triggerClosePopup = (instance) => {
|
||||
const popup = dom.getPopup()
|
||||
|
||||
if (!popup) {
|
||||
return false
|
||||
}
|
||||
|
||||
const innerParams = privateProps.innerParams.get(instance)
|
||||
if (!innerParams || dom.hasClass(popup, innerParams.hideClass.popup)) {
|
||||
return false
|
||||
}
|
||||
|
||||
dom.removeClass(popup, innerParams.showClass.popup)
|
||||
dom.addClass(popup, innerParams.hideClass.popup)
|
||||
|
||||
const backdrop = dom.getContainer()
|
||||
dom.removeClass(backdrop, innerParams.showClass.backdrop)
|
||||
dom.addClass(backdrop, innerParams.hideClass.backdrop)
|
||||
|
||||
handlePopupAnimation(instance, popup, innerParams)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Error | string} error
|
||||
* @this {SweetAlert}
|
||||
*/
|
||||
export function rejectPromise(error) {
|
||||
const rejectPromise = privateMethods.swalPromiseReject.get(this)
|
||||
handleAwaitingPromise(this)
|
||||
if (rejectPromise) {
|
||||
// Reject Swal promise
|
||||
rejectPromise(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
*/
|
||||
export const handleAwaitingPromise = (instance) => {
|
||||
if (instance.isAwaitingPromise) {
|
||||
// @ts-ignore
|
||||
delete instance.isAwaitingPromise
|
||||
// The instance might have been previously partly destroyed, we must resume the destroy process in this case #2335
|
||||
if (!privateProps.innerParams.get(instance)) {
|
||||
instance._destroy()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlertResult | undefined} resolveValue
|
||||
* @returns {SweetAlertResult}
|
||||
*/
|
||||
const prepareResolveValue = (resolveValue) => {
|
||||
// When user calls Swal.close()
|
||||
if (typeof resolveValue === 'undefined') {
|
||||
return {
|
||||
isConfirmed: false,
|
||||
isDenied: false,
|
||||
isDismissed: true,
|
||||
}
|
||||
}
|
||||
|
||||
return Object.assign(
|
||||
{
|
||||
isConfirmed: false,
|
||||
isDenied: false,
|
||||
isDismissed: false,
|
||||
},
|
||||
resolveValue
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {HTMLElement} popup
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
*/
|
||||
const handlePopupAnimation = (instance, popup, innerParams) => {
|
||||
const container = dom.getContainer()
|
||||
// If animation is supported, animate
|
||||
const animationIsSupported = dom.hasCssAnimation(popup)
|
||||
|
||||
if (typeof innerParams.willClose === 'function') {
|
||||
innerParams.willClose(popup)
|
||||
}
|
||||
globalState.eventEmitter?.emit('willClose', popup)
|
||||
|
||||
if (animationIsSupported && container) {
|
||||
animatePopup(instance, popup, container, Boolean(innerParams.returnFocus), innerParams.didClose)
|
||||
} else if (container) {
|
||||
// Otherwise, remove immediately
|
||||
removePopupAndResetState(instance, container, Boolean(innerParams.returnFocus), innerParams.didClose)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {HTMLElement} popup
|
||||
* @param {HTMLElement} container
|
||||
* @param {boolean} returnFocus
|
||||
* @param {(() => void) | undefined} didClose
|
||||
*/
|
||||
const animatePopup = (instance, popup, container, returnFocus, didClose) => {
|
||||
globalState.swalCloseEventFinishedCallback = removePopupAndResetState.bind(
|
||||
null,
|
||||
instance,
|
||||
container,
|
||||
returnFocus,
|
||||
didClose
|
||||
)
|
||||
/**
|
||||
* @param {AnimationEvent | TransitionEvent} e
|
||||
*/
|
||||
const swalCloseAnimationFinished = function (e) {
|
||||
if (e.target === popup) {
|
||||
globalState.swalCloseEventFinishedCallback?.()
|
||||
delete globalState.swalCloseEventFinishedCallback
|
||||
popup.removeEventListener('animationend', swalCloseAnimationFinished)
|
||||
popup.removeEventListener('transitionend', swalCloseAnimationFinished)
|
||||
}
|
||||
}
|
||||
popup.addEventListener('animationend', swalCloseAnimationFinished)
|
||||
popup.addEventListener('transitionend', swalCloseAnimationFinished)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {(() => void) | undefined} didClose
|
||||
*/
|
||||
const triggerDidCloseAndDispose = (instance, didClose) => {
|
||||
setTimeout(() => {
|
||||
if (typeof didClose === 'function') {
|
||||
didClose.bind(instance.params)()
|
||||
}
|
||||
globalState.eventEmitter?.emit('didClose')
|
||||
// instance might have been destroyed already
|
||||
if (instance._destroy) {
|
||||
instance._destroy()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export { close as closePopup, close as closeModal, close as closeToast }
|
||||
@@ -0,0 +1,67 @@
|
||||
import * as dom from '../utils/dom/index.js'
|
||||
import privateProps from '../privateProps.js'
|
||||
import { swalClasses } from '../utils/classes.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {string[]} buttons
|
||||
* @param {boolean} disabled
|
||||
*/
|
||||
function setButtonsDisabled(instance, buttons, disabled) {
|
||||
const domCache = privateProps.domCache.get(instance)
|
||||
buttons.forEach((button) => {
|
||||
domCache[button].disabled = disabled
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLInputElement | null} input
|
||||
* @param {boolean} disabled
|
||||
*/
|
||||
function setInputDisabled(input, disabled) {
|
||||
const popup = dom.getPopup()
|
||||
if (!popup || !input) {
|
||||
return
|
||||
}
|
||||
if (input.type === 'radio') {
|
||||
/** @type {NodeListOf<HTMLInputElement>} */
|
||||
const radios = popup.querySelectorAll(`[name="${swalClasses.radio}"]`)
|
||||
for (let i = 0; i < radios.length; i++) {
|
||||
radios[i].disabled = disabled
|
||||
}
|
||||
} else {
|
||||
input.disabled = disabled
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable all the buttons
|
||||
* @this {SweetAlert}
|
||||
*/
|
||||
export function enableButtons() {
|
||||
setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable all the buttons
|
||||
* @this {SweetAlert}
|
||||
*/
|
||||
export function disableButtons() {
|
||||
setButtonsDisabled(this, ['confirmButton', 'denyButton', 'cancelButton'], true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the input field
|
||||
* @this {SweetAlert}
|
||||
*/
|
||||
export function enableInput() {
|
||||
setInputDisabled(this.getInput(), false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the input field
|
||||
* @this {SweetAlert}
|
||||
*/
|
||||
export function disableInput() {
|
||||
setInputDisabled(this.getInput(), true)
|
||||
}
|
||||
17
public/assets/sweetalert2/src/instanceMethods/getInput.js
Normal file
17
public/assets/sweetalert2/src/instanceMethods/getInput.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import privateProps from '../privateProps.js'
|
||||
import * as dom from '../utils/dom/index.js'
|
||||
|
||||
/**
|
||||
* Gets the input DOM node, this method works with input parameter.
|
||||
*
|
||||
* @returns {HTMLInputElement | null}
|
||||
* @this {SweetAlert}
|
||||
*/
|
||||
export function getInput() {
|
||||
const innerParams = privateProps.innerParams.get(this)
|
||||
const domCache = privateProps.domCache.get(this)
|
||||
if (!domCache) {
|
||||
return null
|
||||
}
|
||||
return dom.getInput(domCache.popup, innerParams.input)
|
||||
}
|
||||
45
public/assets/sweetalert2/src/instanceMethods/hideLoading.js
Normal file
45
public/assets/sweetalert2/src/instanceMethods/hideLoading.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import privateProps from '../privateProps.js'
|
||||
import { swalClasses } from '../utils/classes.js'
|
||||
import * as dom from '../utils/dom/index.js'
|
||||
|
||||
/**
|
||||
* Hides loader and shows back the button which was hidden by .showLoading()
|
||||
* @this {SweetAlert}
|
||||
*/
|
||||
function hideLoading() {
|
||||
// do nothing if popup is closed
|
||||
const innerParams = privateProps.innerParams.get(this)
|
||||
if (!innerParams) {
|
||||
return
|
||||
}
|
||||
const domCache = privateProps.domCache.get(this)
|
||||
dom.hide(domCache.loader)
|
||||
if (dom.isToast()) {
|
||||
if (innerParams.icon) {
|
||||
dom.show(dom.getIcon())
|
||||
}
|
||||
} else {
|
||||
showRelatedButton(domCache)
|
||||
}
|
||||
dom.removeClass([domCache.popup, domCache.actions], swalClasses.loading)
|
||||
domCache.popup.removeAttribute('aria-busy')
|
||||
domCache.popup.removeAttribute('data-loading')
|
||||
domCache.confirmButton.disabled = false
|
||||
domCache.denyButton.disabled = false
|
||||
domCache.cancelButton.disabled = false
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DomCache} domCache
|
||||
*/
|
||||
const showRelatedButton = (domCache) => {
|
||||
const dataButtonToReplace = domCache.loader.getAttribute('data-button-to-replace')
|
||||
const buttonToReplace = dataButtonToReplace ? domCache.popup.getElementsByClassName(dataButtonToReplace) : []
|
||||
if (buttonToReplace.length) {
|
||||
dom.show(/** @type {HTMLElement} */ (buttonToReplace[0]), 'inline-block')
|
||||
} else if (dom.allButtonsAreHidden()) {
|
||||
dom.hide(domCache.actions)
|
||||
}
|
||||
}
|
||||
|
||||
export { hideLoading, hideLoading as disableLoading }
|
||||
60
public/assets/sweetalert2/src/instanceMethods/update.js
Normal file
60
public/assets/sweetalert2/src/instanceMethods/update.js
Normal file
@@ -0,0 +1,60 @@
|
||||
import * as dom from '../../src/utils/dom/index.js'
|
||||
import { isUpdatableParameter, showWarningsForParams } from '../../src/utils/params.js'
|
||||
import { warn } from '../../src/utils/utils.js'
|
||||
import privateProps from '../privateProps.js'
|
||||
|
||||
/**
|
||||
* Updates popup parameters.
|
||||
*
|
||||
* @this {any}
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export function update(params) {
|
||||
const container = dom.getContainer()
|
||||
const popup = dom.getPopup()
|
||||
const innerParams = privateProps.innerParams.get(this)
|
||||
|
||||
if (!popup || dom.hasClass(popup, innerParams.hideClass.popup)) {
|
||||
warn(
|
||||
`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.`
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const validUpdatableParams = filterValidParams(params)
|
||||
|
||||
const updatedParams = Object.assign({}, innerParams, validUpdatableParams)
|
||||
showWarningsForParams(updatedParams)
|
||||
|
||||
if (container) {
|
||||
container.dataset['swal2Theme'] = updatedParams.theme
|
||||
}
|
||||
dom.render(this, updatedParams)
|
||||
|
||||
privateProps.innerParams.set(this, updatedParams)
|
||||
Object.defineProperties(this, {
|
||||
params: {
|
||||
value: Object.assign({}, this.params, params),
|
||||
writable: false,
|
||||
enumerable: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlertOptions} params
|
||||
* @returns {SweetAlertOptions}
|
||||
*/
|
||||
const filterValidParams = (params) => {
|
||||
/** @type {Record<string, any>} */
|
||||
const validUpdatableParams = {}
|
||||
Object.keys(params).forEach((param) => {
|
||||
if (isUpdatableParameter(param)) {
|
||||
const typedParams = /** @type {Record<string, any>} */ (params)
|
||||
validUpdatableParams[param] = typedParams[param]
|
||||
} else {
|
||||
warn(`Invalid parameter to update: ${param}`)
|
||||
}
|
||||
})
|
||||
return validUpdatableParams
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import privateProps from '../privateProps.js'
|
||||
import { swalClasses } from '../utils/classes.js'
|
||||
import * as dom from '../utils/dom/index.js'
|
||||
|
||||
/**
|
||||
* Show block with validation message
|
||||
*
|
||||
* @param {string} error
|
||||
* @this {SweetAlert}
|
||||
*/
|
||||
export function showValidationMessage(error) {
|
||||
const domCache = privateProps.domCache.get(this)
|
||||
const params = privateProps.innerParams.get(this)
|
||||
dom.setInnerHtml(domCache.validationMessage, error)
|
||||
domCache.validationMessage.className = swalClasses['validation-message']
|
||||
if (params.customClass && params.customClass.validationMessage) {
|
||||
dom.addClass(domCache.validationMessage, params.customClass.validationMessage)
|
||||
}
|
||||
dom.show(domCache.validationMessage)
|
||||
|
||||
const input = this.getInput()
|
||||
if (input) {
|
||||
input.setAttribute('aria-invalid', 'true')
|
||||
input.setAttribute('aria-describedby', swalClasses['validation-message'])
|
||||
dom.focusInput(input)
|
||||
dom.addClass(input, swalClasses.inputerror)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide block with validation message
|
||||
*
|
||||
* @this {SweetAlert}
|
||||
*/
|
||||
export function resetValidationMessage() {
|
||||
const domCache = privateProps.domCache.get(this)
|
||||
if (domCache.validationMessage) {
|
||||
dom.hide(domCache.validationMessage)
|
||||
}
|
||||
|
||||
const input = this.getInput()
|
||||
if (input) {
|
||||
input.removeAttribute('aria-invalid')
|
||||
input.removeAttribute('aria-describedby')
|
||||
dom.removeClass(input, swalClasses.inputerror)
|
||||
}
|
||||
}
|
||||
222
public/assets/sweetalert2/src/keydown-handler.js
Normal file
222
public/assets/sweetalert2/src/keydown-handler.js
Normal file
@@ -0,0 +1,222 @@
|
||||
import { clickConfirm } from './staticMethods/dom.js'
|
||||
import { DismissReason } from './utils/DismissReason.js'
|
||||
import * as dom from './utils/dom/index.js'
|
||||
import { callIfFunction } from './utils/utils.js'
|
||||
|
||||
/**
|
||||
* @param {GlobalState} globalState
|
||||
*/
|
||||
export const removeKeydownHandler = (globalState) => {
|
||||
if (globalState.keydownTarget && globalState.keydownHandlerAdded && globalState.keydownHandler) {
|
||||
const handler = /** @type {EventListenerOrEventListenerObject} */ (/** @type {unknown} */ (globalState.keydownHandler))
|
||||
globalState.keydownTarget.removeEventListener('keydown', handler, {
|
||||
capture: globalState.keydownListenerCapture,
|
||||
})
|
||||
globalState.keydownHandlerAdded = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GlobalState} globalState
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
* @param {(dismiss: DismissReason) => void} dismissWith
|
||||
*/
|
||||
export const addKeydownHandler = (globalState, innerParams, dismissWith) => {
|
||||
removeKeydownHandler(globalState)
|
||||
if (!innerParams.toast) {
|
||||
/** @type {(this: HTMLElement, event: KeyboardEvent) => void} */
|
||||
const handler = (e) => keydownHandler(innerParams, e, dismissWith)
|
||||
globalState.keydownHandler = handler
|
||||
const target = innerParams.keydownListenerCapture ? window : dom.getPopup()
|
||||
if (target) {
|
||||
globalState.keydownTarget = target
|
||||
globalState.keydownListenerCapture = innerParams.keydownListenerCapture
|
||||
const eventHandler = /** @type {EventListenerOrEventListenerObject} */ (/** @type {unknown} */ (handler))
|
||||
globalState.keydownTarget.addEventListener('keydown', eventHandler, {
|
||||
capture: globalState.keydownListenerCapture,
|
||||
})
|
||||
globalState.keydownHandlerAdded = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} index
|
||||
* @param {number} increment
|
||||
*/
|
||||
export const setFocus = (index, increment) => {
|
||||
const focusableElements = dom.getFocusableElements()
|
||||
// search for visible elements and select the next possible match
|
||||
if (focusableElements.length) {
|
||||
index = index + increment
|
||||
|
||||
// shift + tab when .swal2-popup is focused
|
||||
if (index === -2) {
|
||||
index = focusableElements.length - 1
|
||||
}
|
||||
|
||||
// rollover to first item
|
||||
if (index === focusableElements.length) {
|
||||
index = 0
|
||||
|
||||
// go to last item
|
||||
} else if (index === -1) {
|
||||
index = focusableElements.length - 1
|
||||
}
|
||||
|
||||
focusableElements[index].focus()
|
||||
return
|
||||
}
|
||||
// no visible focusable elements, focus the popup
|
||||
dom.getPopup()?.focus()
|
||||
}
|
||||
|
||||
const arrowKeysNextButton = ['ArrowRight', 'ArrowDown']
|
||||
|
||||
const arrowKeysPreviousButton = ['ArrowLeft', 'ArrowUp']
|
||||
|
||||
/**
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
* @param {KeyboardEvent} event
|
||||
* @param {(dismiss: DismissReason) => void} dismissWith
|
||||
*/
|
||||
const keydownHandler = (innerParams, event, dismissWith) => {
|
||||
if (!innerParams) {
|
||||
return // This instance has already been destroyed
|
||||
}
|
||||
|
||||
// Ignore keydown during IME composition
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Document/keydown_event#ignoring_keydown_during_ime_composition
|
||||
// https://github.com/sweetalert2/sweetalert2/issues/720
|
||||
// https://github.com/sweetalert2/sweetalert2/issues/2406
|
||||
if (event.isComposing || event.keyCode === 229) {
|
||||
return
|
||||
}
|
||||
|
||||
if (innerParams.stopKeydownPropagation) {
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
// ENTER
|
||||
if (event.key === 'Enter') {
|
||||
handleEnter(event, innerParams)
|
||||
}
|
||||
|
||||
// TAB
|
||||
else if (event.key === 'Tab') {
|
||||
handleTab(event)
|
||||
}
|
||||
|
||||
// ARROWS - switch focus between buttons
|
||||
else if ([...arrowKeysNextButton, ...arrowKeysPreviousButton].includes(event.key)) {
|
||||
handleArrows(event.key)
|
||||
}
|
||||
|
||||
// ESC
|
||||
else if (event.key === 'Escape') {
|
||||
handleEsc(event, innerParams, dismissWith)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {KeyboardEvent} event
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
*/
|
||||
const handleEnter = (event, innerParams) => {
|
||||
// https://github.com/sweetalert2/sweetalert2/issues/2386
|
||||
if (!callIfFunction(innerParams.allowEnterKey)) {
|
||||
return
|
||||
}
|
||||
|
||||
const popup = dom.getPopup()
|
||||
if (!popup || !innerParams.input) {
|
||||
return
|
||||
}
|
||||
|
||||
const input = dom.getInput(popup, innerParams.input)
|
||||
|
||||
if (event.target && input && event.target instanceof HTMLElement && event.target.outerHTML === input.outerHTML) {
|
||||
if (['textarea', 'file'].includes(innerParams.input)) {
|
||||
return // do not submit
|
||||
}
|
||||
|
||||
clickConfirm()
|
||||
event.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {KeyboardEvent} event
|
||||
*/
|
||||
const handleTab = (event) => {
|
||||
const targetElement = event.target
|
||||
|
||||
const focusableElements = dom.getFocusableElements()
|
||||
let btnIndex = -1
|
||||
for (let i = 0; i < focusableElements.length; i++) {
|
||||
if (targetElement === focusableElements[i]) {
|
||||
btnIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Cycle to the next button
|
||||
if (!event.shiftKey) {
|
||||
setFocus(btnIndex, 1)
|
||||
}
|
||||
|
||||
// Cycle to the prev button
|
||||
else {
|
||||
setFocus(btnIndex, -1)
|
||||
}
|
||||
|
||||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} key
|
||||
*/
|
||||
const handleArrows = (key) => {
|
||||
const actions = dom.getActions()
|
||||
const confirmButton = dom.getConfirmButton()
|
||||
const denyButton = dom.getDenyButton()
|
||||
const cancelButton = dom.getCancelButton()
|
||||
if (!actions || !confirmButton || !denyButton || !cancelButton) {
|
||||
return
|
||||
}
|
||||
/** @type HTMLElement[] */
|
||||
const buttons = [confirmButton, denyButton, cancelButton]
|
||||
if (document.activeElement instanceof HTMLElement && !buttons.includes(document.activeElement)) {
|
||||
return
|
||||
}
|
||||
const sibling = arrowKeysNextButton.includes(key) ? 'nextElementSibling' : 'previousElementSibling'
|
||||
let buttonToFocus = document.activeElement
|
||||
if (!buttonToFocus) {
|
||||
return
|
||||
}
|
||||
for (let i = 0; i < actions.children.length; i++) {
|
||||
buttonToFocus = buttonToFocus[sibling]
|
||||
if (!buttonToFocus) {
|
||||
return
|
||||
}
|
||||
if (buttonToFocus instanceof HTMLButtonElement && dom.isVisible(buttonToFocus)) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (buttonToFocus instanceof HTMLButtonElement) {
|
||||
buttonToFocus.focus()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {KeyboardEvent} event
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
* @param {(dismiss: DismissReason) => void} dismissWith
|
||||
*/
|
||||
const handleEsc = (event, innerParams, dismissWith) => {
|
||||
event.preventDefault()
|
||||
if (callIfFunction(innerParams.allowEscapeKey)) {
|
||||
dismissWith(DismissReason.esc)
|
||||
}
|
||||
}
|
||||
104
public/assets/sweetalert2/src/popup-click-handler.js
Normal file
104
public/assets/sweetalert2/src/popup-click-handler.js
Normal file
@@ -0,0 +1,104 @@
|
||||
import { DismissReason } from './utils/DismissReason.js'
|
||||
import { callIfFunction } from './utils/utils.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
* @param {DomCache} domCache
|
||||
* @param {(dismiss: DismissReason) => void} dismissWith
|
||||
*/
|
||||
export const handlePopupClick = (innerParams, domCache, dismissWith) => {
|
||||
if (innerParams.toast) {
|
||||
handleToastClick(innerParams, domCache, dismissWith)
|
||||
} else {
|
||||
// Ignore click events that had mousedown on the popup but mouseup on the container
|
||||
// This can happen when the user drags a slider
|
||||
handleModalMousedown(domCache)
|
||||
|
||||
// Ignore click events that had mousedown on the container but mouseup on the popup
|
||||
handleContainerMousedown(domCache)
|
||||
|
||||
handleModalClick(innerParams, domCache, dismissWith)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
* @param {DomCache} domCache
|
||||
* @param {(dismiss: DismissReason) => void} dismissWith
|
||||
*/
|
||||
const handleToastClick = (innerParams, domCache, dismissWith) => {
|
||||
// Closing toast by internal click
|
||||
domCache.popup.onclick = () => {
|
||||
if (innerParams && (isAnyButtonShown(innerParams) || innerParams.timer || innerParams.input)) {
|
||||
return
|
||||
}
|
||||
dismissWith(DismissReason.close)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isAnyButtonShown = (innerParams) => {
|
||||
return Boolean(
|
||||
innerParams.showConfirmButton ||
|
||||
innerParams.showDenyButton ||
|
||||
innerParams.showCancelButton ||
|
||||
innerParams.showCloseButton
|
||||
)
|
||||
}
|
||||
|
||||
let ignoreOutsideClick = false
|
||||
|
||||
/**
|
||||
* @param {DomCache} domCache
|
||||
*/
|
||||
const handleModalMousedown = (domCache) => {
|
||||
domCache.popup.onmousedown = () => {
|
||||
domCache.container.onmouseup = function (e) {
|
||||
domCache.container.onmouseup = () => {}
|
||||
// We only check if the mouseup target is the container because usually it doesn't
|
||||
// have any other direct children aside of the popup
|
||||
if (e.target === domCache.container) {
|
||||
ignoreOutsideClick = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DomCache} domCache
|
||||
*/
|
||||
const handleContainerMousedown = (domCache) => {
|
||||
domCache.container.onmousedown = (e) => {
|
||||
// prevent the modal text from being selected on double click on the container (allowOutsideClick: false)
|
||||
if (e.target === domCache.container) {
|
||||
e.preventDefault()
|
||||
}
|
||||
domCache.popup.onmouseup = function (e) {
|
||||
domCache.popup.onmouseup = () => {}
|
||||
// We also need to check if the mouseup target is a child of the popup
|
||||
if (e.target === domCache.popup || (e.target instanceof HTMLElement && domCache.popup.contains(e.target))) {
|
||||
ignoreOutsideClick = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
* @param {DomCache} domCache
|
||||
* @param {(dismiss: DismissReason) => void} dismissWith
|
||||
*/
|
||||
const handleModalClick = (innerParams, domCache, dismissWith) => {
|
||||
domCache.container.onclick = (e) => {
|
||||
if (ignoreOutsideClick) {
|
||||
ignoreOutsideClick = false
|
||||
return
|
||||
}
|
||||
if (e.target === domCache.container && callIfFunction(innerParams.allowOutsideClick)) {
|
||||
dismissWith(DismissReason.backdrop)
|
||||
}
|
||||
}
|
||||
}
|
||||
14
public/assets/sweetalert2/src/privateMethods.js
Normal file
14
public/assets/sweetalert2/src/privateMethods.js
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* This module contains `WeakMap`s for each effectively-"private property" that a `Swal` has.
|
||||
* For example, to set the private property "foo" of `this` to "bar", you can `privateProps.foo.set(this, 'bar')`
|
||||
* This is the approach that Babel will probably take to implement private methods/fields
|
||||
* https://github.com/tc39/proposal-private-methods
|
||||
* https://github.com/babel/babel/pull/7555
|
||||
* Once we have the changes from that PR in Babel, and our core class fits reasonable in *one module*
|
||||
* then we can use that language feature.
|
||||
*/
|
||||
|
||||
export default {
|
||||
swalPromiseResolve: new WeakMap(),
|
||||
swalPromiseReject: new WeakMap(),
|
||||
}
|
||||
14
public/assets/sweetalert2/src/privateProps.js
Normal file
14
public/assets/sweetalert2/src/privateProps.js
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* This module contains `WeakMap`s for each effectively-"private property" that a `Swal` has.
|
||||
* For example, to set the private property "foo" of `this` to "bar", you can `privateProps.foo.set(this, 'bar')`
|
||||
* This is the approach that Babel will probably take to implement private methods/fields
|
||||
* https://github.com/tc39/proposal-private-methods
|
||||
* https://github.com/babel/babel/pull/7555
|
||||
* Once we have the changes from that PR in Babel, and our core class fits reasonable in *one module*
|
||||
* then we can use that language feature.
|
||||
*/
|
||||
|
||||
export default {
|
||||
innerParams: new WeakMap(),
|
||||
domCache: new WeakMap(),
|
||||
}
|
||||
9
public/assets/sweetalert2/src/staticMethods.js
Normal file
9
public/assets/sweetalert2/src/staticMethods.js
Normal file
@@ -0,0 +1,9 @@
|
||||
export * from './staticMethods/argsToParams.js'
|
||||
export * from './staticMethods/dom.js'
|
||||
export * from './staticMethods/fire.js'
|
||||
export * from './staticMethods/mixin.js'
|
||||
export * from './staticMethods/showLoading.js'
|
||||
export * from './staticMethods/timer.js'
|
||||
export * from './staticMethods/bindClickHandler.js'
|
||||
export * from './staticMethods/eventHandlers.js'
|
||||
export { isValidParameter, isUpdatableParameter, isDeprecatedParameter } from './utils/params.js'
|
||||
35
public/assets/sweetalert2/src/staticMethods/argsToParams.js
Normal file
35
public/assets/sweetalert2/src/staticMethods/argsToParams.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import { error } from '../utils/utils.js'
|
||||
|
||||
/**
|
||||
* @param {unknown} elem
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isJqueryElement = (elem) => typeof elem === 'object' && elem !== null && 'jquery' in elem
|
||||
|
||||
/**
|
||||
* @param {unknown} elem
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isElement = (elem) => elem instanceof Element || isJqueryElement(elem)
|
||||
|
||||
/**
|
||||
* @param {ReadonlyArray<unknown>} args
|
||||
* @returns {SweetAlertOptions}
|
||||
*/
|
||||
export const argsToParams = (args) => {
|
||||
/** @type {Record<string, unknown>} */
|
||||
const params = {}
|
||||
if (typeof args[0] === 'object' && !isElement(args[0])) {
|
||||
Object.assign(params, args[0])
|
||||
} else {
|
||||
;['title', 'html', 'icon'].forEach((name, index) => {
|
||||
const arg = args[index]
|
||||
if (typeof arg === 'string' || isElement(arg)) {
|
||||
params[name] = arg
|
||||
} else if (arg !== undefined) {
|
||||
error(`Unexpected type of ${name}! Expected "string" or "Element", got ${typeof arg}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
return /** @type {SweetAlertOptions} */ (params)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
let bodyClickListenerAdded = false
|
||||
/** @type {Record<string, any>} */
|
||||
const clickHandlers = {}
|
||||
|
||||
/**
|
||||
* @this {any}
|
||||
* @param {string} attr
|
||||
*/
|
||||
export function bindClickHandler(attr = 'data-swal-template') {
|
||||
clickHandlers[attr] = this
|
||||
|
||||
if (!bodyClickListenerAdded) {
|
||||
document.body.addEventListener('click', bodyClickListener)
|
||||
bodyClickListenerAdded = true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event
|
||||
*/
|
||||
const bodyClickListener = (event) => {
|
||||
for (let el = /** @type {any} */ (event.target); el && el !== document; el = el.parentNode) {
|
||||
for (const attr in clickHandlers) {
|
||||
const template = el.getAttribute && el.getAttribute(attr)
|
||||
if (template) {
|
||||
clickHandlers[attr].fire({ template })
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
public/assets/sweetalert2/src/staticMethods/dom.js
Normal file
47
public/assets/sweetalert2/src/staticMethods/dom.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import * as domUtils from '../utils/dom/domUtils.js'
|
||||
import * as dom from '../utils/dom/index.js'
|
||||
|
||||
export {
|
||||
getContainer,
|
||||
getPopup,
|
||||
getTitle,
|
||||
getHtmlContainer,
|
||||
getImage,
|
||||
getIcon,
|
||||
getIconContent,
|
||||
getInputLabel,
|
||||
getCloseButton,
|
||||
getActions,
|
||||
getConfirmButton,
|
||||
getDenyButton,
|
||||
getCancelButton,
|
||||
getLoader,
|
||||
getFooter,
|
||||
getTimerProgressBar,
|
||||
getFocusableElements,
|
||||
getValidationMessage,
|
||||
getProgressSteps,
|
||||
isLoading,
|
||||
} from '../utils/dom/index.js'
|
||||
|
||||
/*
|
||||
* Global function to determine if SweetAlert2 popup is shown
|
||||
*/
|
||||
export const isVisible = () => {
|
||||
return domUtils.isVisible(dom.getPopup())
|
||||
}
|
||||
|
||||
/*
|
||||
* Global function to click 'Confirm' button
|
||||
*/
|
||||
export const clickConfirm = () => dom.getConfirmButton()?.click()
|
||||
|
||||
/*
|
||||
* Global function to click 'Deny' button
|
||||
*/
|
||||
export const clickDeny = () => dom.getDenyButton()?.click()
|
||||
|
||||
/*
|
||||
* Global function to click 'Cancel' button
|
||||
*/
|
||||
export const clickCancel = () => dom.getCancelButton()?.click()
|
||||
48
public/assets/sweetalert2/src/staticMethods/eventHandlers.js
Normal file
48
public/assets/sweetalert2/src/staticMethods/eventHandlers.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import globalState from '../globalState.js'
|
||||
import EventEmitter from '../utils/EventEmitter.js'
|
||||
|
||||
globalState.eventEmitter = new EventEmitter()
|
||||
|
||||
/**
|
||||
* @param {string} eventName
|
||||
* @param {EventHandler} eventHandler
|
||||
*/
|
||||
export const on = (eventName, eventHandler) => {
|
||||
if (globalState.eventEmitter) {
|
||||
globalState.eventEmitter.on(eventName, eventHandler)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} eventName
|
||||
* @param {EventHandler} eventHandler
|
||||
*/
|
||||
export const once = (eventName, eventHandler) => {
|
||||
if (globalState.eventEmitter) {
|
||||
globalState.eventEmitter.once(eventName, eventHandler)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} [eventName]
|
||||
* @param {EventHandler} [eventHandler]
|
||||
*/
|
||||
export const off = (eventName, eventHandler) => {
|
||||
if (!globalState.eventEmitter) {
|
||||
return
|
||||
}
|
||||
|
||||
// Remove all handlers for all events
|
||||
if (!eventName) {
|
||||
globalState.eventEmitter.reset()
|
||||
return
|
||||
}
|
||||
|
||||
if (eventHandler) {
|
||||
// Remove a specific handler
|
||||
globalState.eventEmitter.removeListener(eventName, eventHandler)
|
||||
} else {
|
||||
// Remove all handlers for a specific event
|
||||
globalState.eventEmitter.removeAllListeners(eventName)
|
||||
}
|
||||
}
|
||||
10
public/assets/sweetalert2/src/staticMethods/fire.js
Normal file
10
public/assets/sweetalert2/src/staticMethods/fire.js
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Main method to create a new SweetAlert2 popup
|
||||
*
|
||||
* @this {new (...args: any[]) => any}
|
||||
* @param {...SweetAlertOptions} args
|
||||
* @returns {Promise<SweetAlertResult>}
|
||||
*/
|
||||
export function fire(...args) {
|
||||
return new this(...args)
|
||||
}
|
||||
34
public/assets/sweetalert2/src/staticMethods/mixin.js
Normal file
34
public/assets/sweetalert2/src/staticMethods/mixin.js
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Returns an extended version of `Swal` containing `params` as defaults.
|
||||
* Useful for reusing Swal configuration.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* Before:
|
||||
* const textPromptOptions = { input: 'text', showCancelButton: true }
|
||||
* const {value: firstName} = await Swal.fire({ ...textPromptOptions, title: 'What is your first name?' })
|
||||
* const {value: lastName} = await Swal.fire({ ...textPromptOptions, title: 'What is your last name?' })
|
||||
*
|
||||
* After:
|
||||
* const TextPrompt = Swal.mixin({ input: 'text', showCancelButton: true })
|
||||
* const {value: firstName} = await TextPrompt('What is your first name?')
|
||||
* const {value: lastName} = await TextPrompt('What is your last name?')
|
||||
*
|
||||
* @param {SweetAlertOptions} mixinParams
|
||||
* @returns {SweetAlert}
|
||||
* @this {typeof import('../SweetAlert.js').SweetAlert}
|
||||
*/
|
||||
export function mixin(mixinParams) {
|
||||
// @ts-ignore: 'this' refers to the SweetAlert constructor
|
||||
class MixinSwal extends this {
|
||||
/**
|
||||
* @param {any} params
|
||||
* @param {any} priorityMixinParams
|
||||
*/
|
||||
_main(params, priorityMixinParams) {
|
||||
return super._main(params, Object.assign({}, mixinParams, priorityMixinParams))
|
||||
}
|
||||
}
|
||||
// @ts-ignore
|
||||
return MixinSwal
|
||||
}
|
||||
58
public/assets/sweetalert2/src/staticMethods/showLoading.js
Normal file
58
public/assets/sweetalert2/src/staticMethods/showLoading.js
Normal file
@@ -0,0 +1,58 @@
|
||||
import Swal from '../sweetalert2.js'
|
||||
import { swalClasses } from '../utils/classes.js'
|
||||
import * as dom from '../utils/dom/index.js'
|
||||
|
||||
/**
|
||||
* Shows loader (spinner), this is useful with AJAX requests.
|
||||
* By default the loader be shown instead of the "Confirm" button.
|
||||
*
|
||||
* @param {HTMLButtonElement | null} [buttonToReplace]
|
||||
*/
|
||||
const showLoading = (buttonToReplace) => {
|
||||
let popup = dom.getPopup()
|
||||
if (!popup) {
|
||||
new Swal()
|
||||
}
|
||||
popup = dom.getPopup()
|
||||
if (!popup) {
|
||||
return
|
||||
}
|
||||
const loader = dom.getLoader()
|
||||
|
||||
if (dom.isToast()) {
|
||||
dom.hide(dom.getIcon())
|
||||
} else {
|
||||
replaceButton(popup, buttonToReplace)
|
||||
}
|
||||
dom.show(loader)
|
||||
|
||||
popup.setAttribute('data-loading', 'true')
|
||||
popup.setAttribute('aria-busy', 'true')
|
||||
popup.focus()
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} popup
|
||||
* @param {HTMLButtonElement | null} [buttonToReplace]
|
||||
*/
|
||||
const replaceButton = (popup, buttonToReplace) => {
|
||||
const actions = dom.getActions()
|
||||
const loader = dom.getLoader()
|
||||
if (!actions || !loader) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!buttonToReplace && dom.isVisible(dom.getConfirmButton())) {
|
||||
buttonToReplace = dom.getConfirmButton()
|
||||
}
|
||||
|
||||
dom.show(actions)
|
||||
if (buttonToReplace) {
|
||||
dom.hide(buttonToReplace)
|
||||
loader.setAttribute('data-button-to-replace', buttonToReplace.className)
|
||||
actions.insertBefore(loader, buttonToReplace)
|
||||
}
|
||||
dom.addClass([popup, actions], swalClasses.loading)
|
||||
}
|
||||
|
||||
export { showLoading, showLoading as enableLoading }
|
||||
76
public/assets/sweetalert2/src/staticMethods/timer.js
Normal file
76
public/assets/sweetalert2/src/staticMethods/timer.js
Normal file
@@ -0,0 +1,76 @@
|
||||
import globalState from '../globalState.js'
|
||||
import { animateTimerProgressBar, stopTimerProgressBar } from '../utils/dom/domUtils.js'
|
||||
|
||||
/**
|
||||
* If `timer` parameter is set, returns number of milliseconds of timer remained.
|
||||
* Otherwise, returns undefined.
|
||||
*
|
||||
* @returns {number | undefined}
|
||||
*/
|
||||
export const getTimerLeft = () => {
|
||||
return globalState.timeout && globalState.timeout.getTimerLeft()
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop timer. Returns number of milliseconds of timer remained.
|
||||
* If `timer` parameter isn't set, returns undefined.
|
||||
*
|
||||
* @returns {number | undefined}
|
||||
*/
|
||||
export const stopTimer = () => {
|
||||
if (globalState.timeout) {
|
||||
stopTimerProgressBar()
|
||||
return globalState.timeout.stop()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume timer. Returns number of milliseconds of timer remained.
|
||||
* If `timer` parameter isn't set, returns undefined.
|
||||
*
|
||||
* @returns {number | undefined}
|
||||
*/
|
||||
export const resumeTimer = () => {
|
||||
if (globalState.timeout) {
|
||||
const remaining = globalState.timeout.start()
|
||||
animateTimerProgressBar(remaining)
|
||||
return remaining
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume timer. Returns number of milliseconds of timer remained.
|
||||
* If `timer` parameter isn't set, returns undefined.
|
||||
*
|
||||
* @returns {number | undefined}
|
||||
*/
|
||||
export const toggleTimer = () => {
|
||||
const timer = globalState.timeout
|
||||
return timer && (timer.running ? stopTimer() : resumeTimer())
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase timer. Returns number of milliseconds of an updated timer.
|
||||
* If `timer` parameter isn't set, returns undefined.
|
||||
*
|
||||
* @param {number} ms
|
||||
* @returns {number | undefined}
|
||||
*/
|
||||
export const increaseTimer = (ms) => {
|
||||
if (globalState.timeout) {
|
||||
const remaining = globalState.timeout.increase(ms)
|
||||
animateTimerProgressBar(remaining, true)
|
||||
return remaining
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if timer is running. Returns true if timer is running
|
||||
* or false if timer is paused or stopped.
|
||||
* If `timer` parameter isn't set, returns undefined
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const isTimerRunning = () => {
|
||||
return Boolean(globalState.timeout && globalState.timeout.isRunning())
|
||||
}
|
||||
7
public/assets/sweetalert2/src/sweetalert2.js
Normal file
7
public/assets/sweetalert2/src/sweetalert2.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import SweetAlert from './SweetAlert.js'
|
||||
|
||||
const Swal = SweetAlert
|
||||
// @ts-ignore
|
||||
Swal.default = Swal
|
||||
|
||||
export default Swal
|
||||
1793
public/assets/sweetalert2/src/sweetalert2.scss
Normal file
1793
public/assets/sweetalert2/src/sweetalert2.scss
Normal file
File diff suppressed because it is too large
Load Diff
125
public/assets/sweetalert2/src/types.js
Normal file
125
public/assets/sweetalert2/src/types.js
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* @typedef { import('./SweetAlert').SweetAlert } SweetAlert
|
||||
* @typedef { import('sweetalert2').SweetAlertOptions } SweetAlertOptions
|
||||
* @typedef { import('sweetalert2').SweetAlertCustomClass } SweetAlertCustomClass
|
||||
* @typedef { import('sweetalert2').SweetAlertIcon } SweetAlertIcon
|
||||
* @typedef { import('sweetalert2').SweetAlertInput } SweetAlertInput
|
||||
* @typedef { import('sweetalert2').SweetAlertResult } SweetAlertResult
|
||||
* @typedef { import('sweetalert2').SweetAlertOptions['inputValue'] } SweetAlertInputValue
|
||||
* @typedef { import('sweetalert2').DismissReason } DismissReason
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef { import('./utils/Timer').default } Timer
|
||||
* @typedef { import('./utils/EventEmitter').default } EventEmitter
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef GlobalState
|
||||
* @property {SweetAlert} [currentInstance]
|
||||
* @property {Element | null} [previousActiveElement]
|
||||
* @property {Timer} [timeout]
|
||||
* @property {EventEmitter} [eventEmitter]
|
||||
* @property {NodeJS.Timeout} [restoreFocusTimeout]
|
||||
* @property {(this: HTMLElement, event: KeyboardEvent) => void} [keydownHandler]
|
||||
* @property {HTMLElement | (Window & typeof globalThis)} [keydownTarget]
|
||||
* @property {boolean} [keydownHandlerAdded]
|
||||
* @property {boolean} [keydownListenerCapture]
|
||||
* @property {() => void} [swalCloseEventFinishedCallback]
|
||||
* @property {boolean} [isRTL]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef DomCache
|
||||
* @property {HTMLElement} popup
|
||||
* @property {HTMLElement} container
|
||||
* @property {HTMLElement} actions
|
||||
* @property {HTMLElement} confirmButton
|
||||
* @property {HTMLElement} denyButton
|
||||
* @property {HTMLElement} cancelButton
|
||||
* @property {HTMLElement} loader
|
||||
* @property {HTMLElement} closeButton
|
||||
* @property {HTMLElement} validationMessage
|
||||
* @property {HTMLElement} progressSteps
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef
|
||||
* { | 'container'
|
||||
* | 'shown'
|
||||
* | 'height-auto'
|
||||
* | 'iosfix'
|
||||
* | 'popup'
|
||||
* | 'modal'
|
||||
* | 'no-backdrop'
|
||||
* | 'no-transition'
|
||||
* | 'toast'
|
||||
* | 'toast-shown'
|
||||
* | 'show'
|
||||
* | 'hide'
|
||||
* | 'close'
|
||||
* | 'title'
|
||||
* | 'html-container'
|
||||
* | 'actions'
|
||||
* | 'confirm'
|
||||
* | 'deny'
|
||||
* | 'cancel'
|
||||
* | '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'
|
||||
* | 'draggable'
|
||||
* | 'dragging'
|
||||
* } SwalClass
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {(eventName: string) => void} EventHandler
|
||||
* @typedef {EventHandler[]} EventHandlers
|
||||
* @typedef {Record<string, EventHandlers>} Events
|
||||
*/
|
||||
8
public/assets/sweetalert2/src/utils/DismissReason.js
Normal file
8
public/assets/sweetalert2/src/utils/DismissReason.js
Normal file
@@ -0,0 +1,8 @@
|
||||
/** @type {Record<DismissReason, DismissReason>} */
|
||||
export const DismissReason = Object.freeze({
|
||||
cancel: 'cancel',
|
||||
backdrop: 'backdrop',
|
||||
close: 'close',
|
||||
esc: 'esc',
|
||||
timer: 'timer',
|
||||
})
|
||||
94
public/assets/sweetalert2/src/utils/EventEmitter.js
Normal file
94
public/assets/sweetalert2/src/utils/EventEmitter.js
Normal file
@@ -0,0 +1,94 @@
|
||||
// Source: https://gist.github.com/mudge/5830382?permalink_comment_id=2691957#gistcomment-2691957
|
||||
|
||||
export default class EventEmitter {
|
||||
constructor() {
|
||||
/** @type {Events} */
|
||||
this.events = {}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} eventName
|
||||
* @returns {EventHandlers}
|
||||
*/
|
||||
_getHandlersByEventName(eventName) {
|
||||
if (typeof this.events[eventName] === 'undefined') {
|
||||
// not Set because we need to keep the FIFO order
|
||||
// https://github.com/sweetalert2/sweetalert2/pull/2763#discussion_r1748990334
|
||||
this.events[eventName] = []
|
||||
}
|
||||
return this.events[eventName]
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} eventName
|
||||
* @param {EventHandler} eventHandler
|
||||
*/
|
||||
on(eventName, eventHandler) {
|
||||
const currentHandlers = this._getHandlersByEventName(eventName)
|
||||
if (!currentHandlers.includes(eventHandler)) {
|
||||
currentHandlers.push(eventHandler)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} eventName
|
||||
* @param {EventHandler} eventHandler
|
||||
*/
|
||||
once(eventName, eventHandler) {
|
||||
/**
|
||||
* @param {...any} args
|
||||
*/
|
||||
const onceFn = (...args) => {
|
||||
this.removeListener(eventName, onceFn)
|
||||
// @ts-ignore
|
||||
eventHandler.apply(this, args)
|
||||
}
|
||||
this.on(eventName, onceFn)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} eventName
|
||||
* @param {...any} args
|
||||
*/
|
||||
emit(eventName, ...args) {
|
||||
this._getHandlersByEventName(eventName).forEach(
|
||||
/**
|
||||
* @param {EventHandler} eventHandler
|
||||
*/
|
||||
(eventHandler) => {
|
||||
try {
|
||||
// @ts-ignore
|
||||
eventHandler.apply(this, args)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} eventName
|
||||
* @param {EventHandler} eventHandler
|
||||
*/
|
||||
removeListener(eventName, eventHandler) {
|
||||
const currentHandlers = this._getHandlersByEventName(eventName)
|
||||
const index = currentHandlers.indexOf(eventHandler)
|
||||
if (index > -1) {
|
||||
currentHandlers.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} eventName
|
||||
*/
|
||||
removeAllListeners(eventName) {
|
||||
if (this.events[eventName] !== undefined) {
|
||||
// https://github.com/sweetalert2/sweetalert2/pull/2763#discussion_r1749239222
|
||||
this.events[eventName].length = 0
|
||||
}
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.events = {}
|
||||
}
|
||||
}
|
||||
71
public/assets/sweetalert2/src/utils/Timer.js
Normal file
71
public/assets/sweetalert2/src/utils/Timer.js
Normal file
@@ -0,0 +1,71 @@
|
||||
export default class Timer {
|
||||
/**
|
||||
* @param {() => void} callback
|
||||
* @param {number} delay
|
||||
*/
|
||||
constructor(callback, delay) {
|
||||
this.callback = callback
|
||||
this.remaining = delay
|
||||
this.running = false
|
||||
|
||||
this.start()
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
start() {
|
||||
if (!this.running) {
|
||||
this.running = true
|
||||
this.started = new Date()
|
||||
this.id = setTimeout(this.callback, this.remaining)
|
||||
}
|
||||
return this.remaining
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
stop() {
|
||||
if (this.started && this.running) {
|
||||
this.running = false
|
||||
clearTimeout(this.id)
|
||||
this.remaining -= new Date().getTime() - this.started.getTime()
|
||||
}
|
||||
return this.remaining
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} n
|
||||
* @returns {number}
|
||||
*/
|
||||
increase(n) {
|
||||
const running = this.running
|
||||
if (running) {
|
||||
this.stop()
|
||||
}
|
||||
this.remaining += n
|
||||
if (running) {
|
||||
this.start()
|
||||
}
|
||||
return this.remaining
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
getTimerLeft() {
|
||||
if (this.running) {
|
||||
this.stop()
|
||||
this.start()
|
||||
}
|
||||
return this.remaining
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isRunning() {
|
||||
return this.running
|
||||
}
|
||||
}
|
||||
33
public/assets/sweetalert2/src/utils/aria.js
Normal file
33
public/assets/sweetalert2/src/utils/aria.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import { getContainer } from './dom/getters.js'
|
||||
|
||||
// From https://developer.paciellogroup.com/blog/2018/06/the-current-state-of-modal-dialog-accessibility/
|
||||
// Adding aria-hidden="true" to elements outside of the active modal dialog ensures that
|
||||
// elements not within the active modal dialog will not be surfaced if a user opens a screen
|
||||
// reader’s list of elements (headings, form controls, landmarks, etc.) in the document.
|
||||
|
||||
export const setAriaHidden = () => {
|
||||
const container = getContainer()
|
||||
const bodyChildren = Array.from(document.body.children)
|
||||
bodyChildren.forEach((el) => {
|
||||
if (el.contains(container)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (el.hasAttribute('aria-hidden')) {
|
||||
el.setAttribute('data-previous-aria-hidden', el.getAttribute('aria-hidden') || '')
|
||||
}
|
||||
el.setAttribute('aria-hidden', 'true')
|
||||
})
|
||||
}
|
||||
|
||||
export const unsetAriaHidden = () => {
|
||||
const bodyChildren = Array.from(document.body.children)
|
||||
bodyChildren.forEach((el) => {
|
||||
if (el.hasAttribute('data-previous-aria-hidden')) {
|
||||
el.setAttribute('aria-hidden', el.getAttribute('data-previous-aria-hidden') || '')
|
||||
el.removeAttribute('data-previous-aria-hidden')
|
||||
} else {
|
||||
el.removeAttribute('aria-hidden')
|
||||
}
|
||||
})
|
||||
}
|
||||
97
public/assets/sweetalert2/src/utils/classes.js
Normal file
97
public/assets/sweetalert2/src/utils/classes.js
Normal file
@@ -0,0 +1,97 @@
|
||||
export const swalPrefix = 'swal2-'
|
||||
|
||||
/**
|
||||
* @typedef {Record<SwalClass, string>} SwalClasses
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {'success' | 'warning' | 'info' | 'question' | 'error'} SwalIcon
|
||||
* @typedef {Record<SwalIcon, string>} SwalIcons
|
||||
*/
|
||||
|
||||
/** @type {SwalClass[]} */
|
||||
const classNames = [
|
||||
'container',
|
||||
'shown',
|
||||
'height-auto',
|
||||
'iosfix',
|
||||
'popup',
|
||||
'modal',
|
||||
'no-backdrop',
|
||||
'no-transition',
|
||||
'toast',
|
||||
'toast-shown',
|
||||
'show',
|
||||
'hide',
|
||||
'close',
|
||||
'title',
|
||||
'html-container',
|
||||
'actions',
|
||||
'confirm',
|
||||
'deny',
|
||||
'cancel',
|
||||
'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',
|
||||
'draggable',
|
||||
'dragging',
|
||||
]
|
||||
|
||||
export const swalClasses = classNames.reduce((acc, className) => {
|
||||
acc[className] = swalPrefix + className
|
||||
return acc
|
||||
}, /** @type {SwalClasses} */ ({}))
|
||||
|
||||
/** @type {SwalIcon[]} */
|
||||
const icons = ['success', 'warning', 'info', 'question', 'error']
|
||||
|
||||
export const iconTypes = icons.reduce((acc, icon) => {
|
||||
acc[icon] = swalPrefix + icon
|
||||
return acc
|
||||
}, /** @type {SwalIcons} */ ({}))
|
||||
@@ -0,0 +1,23 @@
|
||||
export default {
|
||||
/**
|
||||
* @param {string} string
|
||||
* @param {string} [validationMessage]
|
||||
* @returns {Promise<string | void>}
|
||||
*/
|
||||
email: (string, validationMessage) => {
|
||||
return /^[a-zA-Z0-9.+_'-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]+$/.test(string)
|
||||
? Promise.resolve()
|
||||
: Promise.resolve(validationMessage || 'Invalid email address')
|
||||
},
|
||||
/**
|
||||
* @param {string} string
|
||||
* @param {string} [validationMessage]
|
||||
* @returns {Promise<string | void>}
|
||||
*/
|
||||
url: (string, validationMessage) => {
|
||||
// taken from https://stackoverflow.com/a/3809435 with a small change from #1306 and #2013
|
||||
return /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-z]{2,63}\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$/.test(string)
|
||||
? Promise.resolve()
|
||||
: Promise.resolve(validationMessage || 'Invalid URL')
|
||||
},
|
||||
}
|
||||
365
public/assets/sweetalert2/src/utils/dom/domUtils.js
Normal file
365
public/assets/sweetalert2/src/utils/dom/domUtils.js
Normal file
@@ -0,0 +1,365 @@
|
||||
import { iconTypes, swalClasses } from '../classes.js'
|
||||
import { warn } from '../utils.js'
|
||||
import { getCancelButton, getConfirmButton, getDenyButton, getTimerProgressBar } from './getters.js'
|
||||
|
||||
/**
|
||||
* Securely set innerHTML of an element
|
||||
* https://github.com/sweetalert2/sweetalert2/issues/1926
|
||||
*
|
||||
* @param {HTMLElement} elem
|
||||
* @param {string} html
|
||||
*/
|
||||
export const setInnerHtml = (elem, html) => {
|
||||
elem.textContent = ''
|
||||
if (html) {
|
||||
const parser = new DOMParser()
|
||||
const parsed = parser.parseFromString(html, `text/html`)
|
||||
const head = parsed.querySelector('head')
|
||||
if (head) {
|
||||
Array.from(head.childNodes).forEach((child) => {
|
||||
elem.appendChild(child)
|
||||
})
|
||||
}
|
||||
const body = parsed.querySelector('body')
|
||||
if (body) {
|
||||
Array.from(body.childNodes).forEach((child) => {
|
||||
if (child instanceof HTMLVideoElement || child instanceof HTMLAudioElement) {
|
||||
elem.appendChild(child.cloneNode(true)) // https://github.com/sweetalert2/sweetalert2/issues/2507
|
||||
} else {
|
||||
elem.appendChild(child)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} elem
|
||||
* @param {string} className
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const hasClass = (elem, className) => {
|
||||
if (!className) {
|
||||
return false
|
||||
}
|
||||
const classList = className.split(/\s+/)
|
||||
for (let i = 0; i < classList.length; i++) {
|
||||
if (!elem.classList.contains(classList[i])) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} elem
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
const removeCustomClasses = (elem, params) => {
|
||||
Array.from(elem.classList).forEach((className) => {
|
||||
if (
|
||||
!Object.values(swalClasses).includes(className) &&
|
||||
!Object.values(iconTypes).includes(className) &&
|
||||
!Object.values(params.showClass || {}).includes(className)
|
||||
) {
|
||||
elem.classList.remove(className)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} elem
|
||||
* @param {SweetAlertOptions} params
|
||||
* @param {string} className
|
||||
*/
|
||||
export const applyCustomClass = (elem, params, className) => {
|
||||
removeCustomClasses(elem, params)
|
||||
|
||||
if (!params.customClass) {
|
||||
return
|
||||
}
|
||||
|
||||
const customClass = params.customClass[/** @type {keyof SweetAlertCustomClass} */ (className)]
|
||||
|
||||
if (!customClass) {
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof customClass !== 'string' && !customClass.forEach) {
|
||||
warn(`Invalid type of customClass.${className}! Expected string or iterable object, got "${typeof customClass}"`)
|
||||
return
|
||||
}
|
||||
|
||||
addClass(elem, customClass)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} popup
|
||||
* @param {import('./renderers/renderInput').InputClass | SweetAlertInput} inputClass
|
||||
* @returns {HTMLInputElement | null}
|
||||
*/
|
||||
export const getInput = (popup, inputClass) => {
|
||||
if (!inputClass) {
|
||||
return null
|
||||
}
|
||||
switch (inputClass) {
|
||||
case 'select':
|
||||
case 'textarea':
|
||||
case 'file':
|
||||
return popup.querySelector(`.${swalClasses.popup} > .${swalClasses[inputClass]}`)
|
||||
case 'checkbox':
|
||||
return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.checkbox} input`)
|
||||
case 'radio':
|
||||
return (
|
||||
popup.querySelector(`.${swalClasses.popup} > .${swalClasses.radio} input:checked`) ||
|
||||
popup.querySelector(`.${swalClasses.popup} > .${swalClasses.radio} input:first-child`)
|
||||
)
|
||||
case 'range':
|
||||
return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.range} input`)
|
||||
default:
|
||||
return popup.querySelector(`.${swalClasses.popup} > .${swalClasses.input}`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement} input
|
||||
*/
|
||||
export const focusInput = (input) => {
|
||||
input.focus()
|
||||
|
||||
// place cursor at end of text in text input
|
||||
if (input.type !== 'file') {
|
||||
// http://stackoverflow.com/a/2345915
|
||||
const val = input.value
|
||||
input.value = ''
|
||||
input.value = val
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement | HTMLElement[] | null} target
|
||||
* @param {string | string[] | readonly string[] | undefined} classList
|
||||
* @param {boolean} condition
|
||||
*/
|
||||
export const toggleClass = (target, classList, condition) => {
|
||||
if (!target || !classList) {
|
||||
return
|
||||
}
|
||||
if (typeof classList === 'string') {
|
||||
classList = classList.split(/\s+/).filter(Boolean)
|
||||
}
|
||||
classList.forEach((className) => {
|
||||
if (Array.isArray(target)) {
|
||||
target.forEach((elem) => {
|
||||
if (condition) {
|
||||
elem.classList.add(className)
|
||||
} else {
|
||||
elem.classList.remove(className)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
if (condition) {
|
||||
target.classList.add(className)
|
||||
} else {
|
||||
target.classList.remove(className)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement | HTMLElement[] | null} target
|
||||
* @param {string | string[] | readonly string[] | undefined} classList
|
||||
*/
|
||||
export const addClass = (target, classList) => {
|
||||
toggleClass(target, classList, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement | HTMLElement[] | null} target
|
||||
* @param {string | string[] | readonly string[] | undefined} classList
|
||||
*/
|
||||
export const removeClass = (target, classList) => {
|
||||
toggleClass(target, classList, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get direct child of an element by class name
|
||||
*
|
||||
* @param {HTMLElement} elem
|
||||
* @param {string} className
|
||||
* @returns {HTMLElement | undefined}
|
||||
*/
|
||||
export const getDirectChildByClass = (elem, className) => {
|
||||
const children = Array.from(elem.children)
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const child = children[i]
|
||||
if (child instanceof HTMLElement && hasClass(child, className)) {
|
||||
return child
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} elem
|
||||
* @param {string} property
|
||||
* @param {string | number | null | undefined} value
|
||||
*/
|
||||
export const applyNumericalStyle = (elem, property, value) => {
|
||||
if (value === `${parseInt(`${value}`)}`) {
|
||||
value = parseInt(value)
|
||||
}
|
||||
if (value || parseInt(`${value}`) === 0) {
|
||||
elem.style.setProperty(property, typeof value === 'number' ? `${value}px` : /** @type {string} */ (value))
|
||||
} else {
|
||||
elem.style.removeProperty(property)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement | null} elem
|
||||
* @param {string} display
|
||||
*/
|
||||
export const show = (elem, display = 'flex') => {
|
||||
if (!elem) {
|
||||
return
|
||||
}
|
||||
|
||||
elem.style.display = display
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement | null} elem
|
||||
*/
|
||||
export const hide = (elem) => {
|
||||
if (!elem) {
|
||||
return
|
||||
}
|
||||
|
||||
elem.style.display = 'none'
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement | null} elem
|
||||
* @param {string} display
|
||||
*/
|
||||
export const showWhenInnerHtmlPresent = (elem, display = 'block') => {
|
||||
if (!elem) {
|
||||
return
|
||||
}
|
||||
new MutationObserver(() => {
|
||||
toggle(elem, elem.innerHTML, display)
|
||||
}).observe(elem, { childList: true, subtree: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} parent
|
||||
* @param {string} selector
|
||||
* @param {string} property
|
||||
* @param {string} value
|
||||
*/
|
||||
export const setStyle = (parent, selector, property, value) => {
|
||||
/** @type {HTMLElement | null} */
|
||||
const el = parent.querySelector(selector)
|
||||
if (el) {
|
||||
el.style.setProperty(property, value)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} elem
|
||||
* @param {boolean | string | null | undefined} condition
|
||||
* @param {string} display
|
||||
*/
|
||||
export const toggle = (elem, condition, display = 'flex') => {
|
||||
if (condition) {
|
||||
show(elem, display)
|
||||
} else {
|
||||
hide(elem)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* borrowed from jquery $(elem).is(':visible') implementation
|
||||
*
|
||||
* @param {HTMLElement | null} elem
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const isVisible = (elem) => Boolean(elem && (elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length))
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const allButtonsAreHidden = () =>
|
||||
!isVisible(getConfirmButton()) && !isVisible(getDenyButton()) && !isVisible(getCancelButton())
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} elem
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const isScrollable = (elem) => Boolean(elem.scrollHeight > elem.clientHeight)
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} element
|
||||
* @param {HTMLElement} stopElement
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const selfOrParentIsScrollable = (element, stopElement) => {
|
||||
let parent = /** @type {HTMLElement | null} */ (element)
|
||||
while (parent && parent !== stopElement) {
|
||||
if (isScrollable(parent)) {
|
||||
return true
|
||||
}
|
||||
parent = parent.parentElement
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* borrowed from https://stackoverflow.com/a/46352119
|
||||
*
|
||||
* @param {HTMLElement} elem
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const hasCssAnimation = (elem) => {
|
||||
const style = window.getComputedStyle(elem)
|
||||
|
||||
const animDuration = parseFloat(style.getPropertyValue('animation-duration') || '0')
|
||||
const transDuration = parseFloat(style.getPropertyValue('transition-duration') || '0')
|
||||
|
||||
return animDuration > 0 || transDuration > 0
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} timer
|
||||
* @param {boolean} reset
|
||||
*/
|
||||
export const animateTimerProgressBar = (timer, reset = false) => {
|
||||
const timerProgressBar = getTimerProgressBar()
|
||||
if (!timerProgressBar) {
|
||||
return
|
||||
}
|
||||
if (isVisible(timerProgressBar)) {
|
||||
if (reset) {
|
||||
timerProgressBar.style.transition = 'none'
|
||||
timerProgressBar.style.width = '100%'
|
||||
}
|
||||
setTimeout(() => {
|
||||
timerProgressBar.style.transition = `width ${timer / 1000}s linear`
|
||||
timerProgressBar.style.width = '0%'
|
||||
}, 10)
|
||||
}
|
||||
}
|
||||
|
||||
export const stopTimerProgressBar = () => {
|
||||
const timerProgressBar = getTimerProgressBar()
|
||||
if (!timerProgressBar) {
|
||||
return
|
||||
}
|
||||
const timerProgressBarWidth = parseInt(window.getComputedStyle(timerProgressBar).width)
|
||||
timerProgressBar.style.removeProperty('transition')
|
||||
timerProgressBar.style.width = '100%'
|
||||
const timerProgressBarFullWidth = parseInt(window.getComputedStyle(timerProgressBar).width)
|
||||
const timerProgressBarPercent = (timerProgressBarWidth / timerProgressBarFullWidth) * 100
|
||||
timerProgressBar.style.width = `${timerProgressBarPercent}%`
|
||||
}
|
||||
198
public/assets/sweetalert2/src/utils/dom/getters.js
Normal file
198
public/assets/sweetalert2/src/utils/dom/getters.js
Normal file
@@ -0,0 +1,198 @@
|
||||
import { swalClasses } from '../classes.js'
|
||||
import { hasClass, isVisible } from './domUtils.js'
|
||||
|
||||
/**
|
||||
* Gets the popup container which contains the backdrop and the popup itself.
|
||||
*
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
export const getContainer = () => document.body.querySelector(`.${swalClasses.container}`)
|
||||
|
||||
/**
|
||||
* @param {string} selectorString
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
export const elementBySelector = (selectorString) => {
|
||||
const container = getContainer()
|
||||
return container ? container.querySelector(selectorString) : null
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} className
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
const elementByClass = (className) => {
|
||||
return elementBySelector(`.${className}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
export const getPopup = () => elementByClass(swalClasses.popup)
|
||||
|
||||
/**
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
export const getIcon = () => elementByClass(swalClasses.icon)
|
||||
|
||||
/**
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
export const getIconContent = () => elementByClass(swalClasses['icon-content'])
|
||||
|
||||
/**
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
export const getTitle = () => elementByClass(swalClasses.title)
|
||||
|
||||
/**
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
export const getHtmlContainer = () => elementByClass(swalClasses['html-container'])
|
||||
|
||||
/**
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
export const getImage = () => elementByClass(swalClasses.image)
|
||||
|
||||
/**
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
export const getProgressSteps = () => elementByClass(swalClasses['progress-steps'])
|
||||
|
||||
/**
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
export const getValidationMessage = () => elementByClass(swalClasses['validation-message'])
|
||||
|
||||
/**
|
||||
* @returns {HTMLButtonElement | null}
|
||||
*/
|
||||
export const getConfirmButton = () =>
|
||||
/** @type {HTMLButtonElement} */ (elementBySelector(`.${swalClasses.actions} .${swalClasses.confirm}`))
|
||||
|
||||
/**
|
||||
* @returns {HTMLButtonElement | null}
|
||||
*/
|
||||
export const getCancelButton = () =>
|
||||
/** @type {HTMLButtonElement} */ (elementBySelector(`.${swalClasses.actions} .${swalClasses.cancel}`))
|
||||
|
||||
/**
|
||||
* @returns {HTMLButtonElement | null}
|
||||
*/
|
||||
export const getDenyButton = () =>
|
||||
/** @type {HTMLButtonElement} */ (elementBySelector(`.${swalClasses.actions} .${swalClasses.deny}`))
|
||||
|
||||
/**
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
export const getInputLabel = () => elementByClass(swalClasses['input-label'])
|
||||
|
||||
/**
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
export const getLoader = () => elementBySelector(`.${swalClasses.loader}`)
|
||||
|
||||
/**
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
export const getActions = () => elementByClass(swalClasses.actions)
|
||||
|
||||
/**
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
export const getFooter = () => elementByClass(swalClasses.footer)
|
||||
|
||||
/**
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
export const getTimerProgressBar = () => elementByClass(swalClasses['timer-progress-bar'])
|
||||
|
||||
/**
|
||||
* @returns {HTMLElement | null}
|
||||
*/
|
||||
export const getCloseButton = () => elementByClass(swalClasses.close)
|
||||
|
||||
// https://github.com/jkup/focusable/blob/master/index.js
|
||||
const focusable = `
|
||||
a[href],
|
||||
area[href],
|
||||
input:not([disabled]),
|
||||
select:not([disabled]),
|
||||
textarea:not([disabled]),
|
||||
button:not([disabled]),
|
||||
iframe,
|
||||
object,
|
||||
embed,
|
||||
[tabindex="0"],
|
||||
[contenteditable],
|
||||
audio[controls],
|
||||
video[controls],
|
||||
summary
|
||||
`
|
||||
/**
|
||||
* @returns {HTMLElement[]}
|
||||
*/
|
||||
export const getFocusableElements = () => {
|
||||
const popup = getPopup()
|
||||
if (!popup) {
|
||||
return []
|
||||
}
|
||||
/** @type {NodeListOf<HTMLElement>} */
|
||||
const focusableElementsWithTabindex = popup.querySelectorAll('[tabindex]:not([tabindex="-1"]):not([tabindex="0"])')
|
||||
const focusableElementsWithTabindexSorted = Array.from(focusableElementsWithTabindex)
|
||||
// sort according to tabindex
|
||||
.sort((a, b) => {
|
||||
const tabindexA = parseInt(a.getAttribute('tabindex') || '0')
|
||||
const tabindexB = parseInt(b.getAttribute('tabindex') || '0')
|
||||
if (tabindexA > tabindexB) {
|
||||
return 1
|
||||
} else if (tabindexA < tabindexB) {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
})
|
||||
|
||||
/** @type {NodeListOf<HTMLElement>} */
|
||||
const otherFocusableElements = popup.querySelectorAll(focusable)
|
||||
const otherFocusableElementsFiltered = Array.from(otherFocusableElements).filter(
|
||||
(el) => el.getAttribute('tabindex') !== '-1'
|
||||
)
|
||||
|
||||
return [...new Set(focusableElementsWithTabindexSorted.concat(otherFocusableElementsFiltered))].filter((el) =>
|
||||
isVisible(el)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const isModal = () => {
|
||||
return (
|
||||
hasClass(document.body, swalClasses.shown) &&
|
||||
!hasClass(document.body, swalClasses['toast-shown']) &&
|
||||
!hasClass(document.body, swalClasses['no-backdrop'])
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const isToast = () => {
|
||||
const popup = getPopup()
|
||||
if (!popup) {
|
||||
return false
|
||||
}
|
||||
return hasClass(popup, swalClasses.toast)
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const isLoading = () => {
|
||||
const popup = getPopup()
|
||||
if (!popup) {
|
||||
return false
|
||||
}
|
||||
return popup.hasAttribute('data-loading')
|
||||
}
|
||||
5
public/assets/sweetalert2/src/utils/dom/index.js
Normal file
5
public/assets/sweetalert2/src/utils/dom/index.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export * from './domUtils.js'
|
||||
export * from './init.js'
|
||||
export * from './getters.js'
|
||||
export * from './parseHtmlToContainer.js'
|
||||
export * from './renderers/render.js'
|
||||
193
public/assets/sweetalert2/src/utils/dom/init.js
Normal file
193
public/assets/sweetalert2/src/utils/dom/init.js
Normal file
@@ -0,0 +1,193 @@
|
||||
import globalState from '../../globalState.js'
|
||||
import { swalClasses } from '../classes.js'
|
||||
import { isNodeEnv } from '../isNodeEnv.js'
|
||||
import { error } from '../utils.js'
|
||||
import { addClass, getDirectChildByClass, removeClass, setInnerHtml } from './domUtils.js'
|
||||
import { getContainer, getPopup } from './getters.js'
|
||||
|
||||
const sweetHTML = `
|
||||
<div aria-labelledby="${swalClasses.title}" aria-describedby="${swalClasses['html-container']}" class="${swalClasses.popup}" tabindex="-1">
|
||||
<button type="button" class="${swalClasses.close}"></button>
|
||||
<ul class="${swalClasses['progress-steps']}"></ul>
|
||||
<div class="${swalClasses.icon}"></div>
|
||||
<img class="${swalClasses.image}" />
|
||||
<h2 class="${swalClasses.title}" id="${swalClasses.title}"></h2>
|
||||
<div class="${swalClasses['html-container']}" id="${swalClasses['html-container']}"></div>
|
||||
<input class="${swalClasses.input}" id="${swalClasses.input}" />
|
||||
<input type="file" class="${swalClasses.file}" />
|
||||
<div class="${swalClasses.range}">
|
||||
<input type="range" />
|
||||
<output></output>
|
||||
</div>
|
||||
<select class="${swalClasses.select}" id="${swalClasses.select}"></select>
|
||||
<div class="${swalClasses.radio}"></div>
|
||||
<label class="${swalClasses.checkbox}">
|
||||
<input type="checkbox" id="${swalClasses.checkbox}" />
|
||||
<span class="${swalClasses.label}"></span>
|
||||
</label>
|
||||
<textarea class="${swalClasses.textarea}" id="${swalClasses.textarea}"></textarea>
|
||||
<div class="${swalClasses['validation-message']}" id="${swalClasses['validation-message']}"></div>
|
||||
<div class="${swalClasses.actions}">
|
||||
<div class="${swalClasses.loader}"></div>
|
||||
<button type="button" class="${swalClasses.confirm}"></button>
|
||||
<button type="button" class="${swalClasses.deny}"></button>
|
||||
<button type="button" class="${swalClasses.cancel}"></button>
|
||||
</div>
|
||||
<div class="${swalClasses.footer}"></div>
|
||||
<div class="${swalClasses['timer-progress-bar-container']}">
|
||||
<div class="${swalClasses['timer-progress-bar']}"></div>
|
||||
</div>
|
||||
</div>
|
||||
`.replace(/(^|\n)\s*/g, '')
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const resetOldContainer = () => {
|
||||
const oldContainer = getContainer()
|
||||
if (!oldContainer) {
|
||||
return false
|
||||
}
|
||||
|
||||
oldContainer.remove()
|
||||
removeClass(
|
||||
[document.documentElement, document.body],
|
||||
[
|
||||
swalClasses['no-backdrop'],
|
||||
swalClasses['toast-shown'],
|
||||
// @ts-ignore: 'has-column' is not defined in swalClasses but may be set dynamically
|
||||
swalClasses['has-column'],
|
||||
]
|
||||
)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
const resetValidationMessage = () => {
|
||||
if (globalState.currentInstance) {
|
||||
globalState.currentInstance.resetValidationMessage()
|
||||
}
|
||||
}
|
||||
|
||||
const addInputChangeListeners = () => {
|
||||
const popup = getPopup()
|
||||
if (!popup) {
|
||||
return
|
||||
}
|
||||
|
||||
const input = getDirectChildByClass(popup, swalClasses.input)
|
||||
const file = getDirectChildByClass(popup, swalClasses.file)
|
||||
/** @type {HTMLInputElement | null} */
|
||||
const range = popup.querySelector(`.${swalClasses.range} input`)
|
||||
/** @type {HTMLOutputElement | null} */
|
||||
const rangeOutput = popup.querySelector(`.${swalClasses.range} output`)
|
||||
const select = getDirectChildByClass(popup, swalClasses.select)
|
||||
/** @type {HTMLInputElement | null} */
|
||||
const checkbox = popup.querySelector(`.${swalClasses.checkbox} input`)
|
||||
const textarea = getDirectChildByClass(popup, swalClasses.textarea)
|
||||
|
||||
if (input) {
|
||||
input.oninput = resetValidationMessage
|
||||
}
|
||||
if (file) {
|
||||
file.onchange = resetValidationMessage
|
||||
}
|
||||
if (select) {
|
||||
select.onchange = resetValidationMessage
|
||||
}
|
||||
if (checkbox) {
|
||||
checkbox.onchange = resetValidationMessage
|
||||
}
|
||||
if (textarea) {
|
||||
textarea.oninput = resetValidationMessage
|
||||
}
|
||||
|
||||
if (range && rangeOutput) {
|
||||
range.oninput = () => {
|
||||
resetValidationMessage()
|
||||
rangeOutput.value = range.value
|
||||
}
|
||||
|
||||
range.onchange = () => {
|
||||
resetValidationMessage()
|
||||
rangeOutput.value = range.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string | HTMLElement} target
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
const getTarget = (target) => {
|
||||
if (typeof target === 'string') {
|
||||
const element = document.querySelector(target)
|
||||
if (!element) {
|
||||
throw new Error(`Target element "${target}" not found`)
|
||||
}
|
||||
return /** @type {HTMLElement} */ (element)
|
||||
}
|
||||
return target
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
const setupAccessibility = (params) => {
|
||||
const popup = getPopup()
|
||||
if (!popup) {
|
||||
return
|
||||
}
|
||||
|
||||
popup.setAttribute('role', params.toast ? 'alert' : 'dialog')
|
||||
popup.setAttribute('aria-live', params.toast ? 'polite' : 'assertive')
|
||||
if (!params.toast) {
|
||||
popup.setAttribute('aria-modal', 'true')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} targetElement
|
||||
*/
|
||||
const setupRTL = (targetElement) => {
|
||||
if (window.getComputedStyle(targetElement).direction === 'rtl') {
|
||||
addClass(getContainer(), swalClasses.rtl)
|
||||
globalState.isRTL = true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add modal + backdrop to DOM
|
||||
*
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export const init = (params) => {
|
||||
// Clean up the old popup container if it exists
|
||||
const oldContainerExisted = resetOldContainer()
|
||||
|
||||
if (isNodeEnv()) {
|
||||
error('SweetAlert2 requires document to initialize')
|
||||
return
|
||||
}
|
||||
|
||||
const container = document.createElement('div')
|
||||
container.className = swalClasses.container
|
||||
if (oldContainerExisted) {
|
||||
addClass(container, swalClasses['no-transition'])
|
||||
}
|
||||
setInnerHtml(container, sweetHTML)
|
||||
|
||||
container.dataset['swal2Theme'] = params.theme
|
||||
|
||||
const targetElement = getTarget(params.target || 'body')
|
||||
targetElement.appendChild(container)
|
||||
|
||||
if (params.topLayer) {
|
||||
container.setAttribute('popover', '')
|
||||
container.showPopover()
|
||||
}
|
||||
|
||||
setupAccessibility(params)
|
||||
setupRTL(targetElement)
|
||||
addInputChangeListeners()
|
||||
}
|
||||
239
public/assets/sweetalert2/src/utils/dom/inputUtils.js
Normal file
239
public/assets/sweetalert2/src/utils/dom/inputUtils.js
Normal file
@@ -0,0 +1,239 @@
|
||||
import { showLoading } from '../../staticMethods/showLoading.js'
|
||||
import { swalClasses } from '../classes.js'
|
||||
import { asPromise, error, hasToPromiseFn, isPromise } from '../utils.js'
|
||||
import { getDirectChildByClass } from './domUtils.js'
|
||||
import * as dom from './index.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export const handleInputOptionsAndValue = (instance, params) => {
|
||||
if (params.input === 'select' || params.input === 'radio') {
|
||||
handleInputOptions(instance, params)
|
||||
} else if (
|
||||
['text', 'email', 'number', 'tel', 'textarea'].some((i) => i === params.input) &&
|
||||
(hasToPromiseFn(params.inputValue) || isPromise(params.inputValue))
|
||||
) {
|
||||
showLoading(dom.getConfirmButton())
|
||||
handleInputValue(instance, params)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
* @returns {SweetAlertInputValue}
|
||||
*/
|
||||
export const getInputValue = (instance, innerParams) => {
|
||||
const input = instance.getInput()
|
||||
if (!input) {
|
||||
return null
|
||||
}
|
||||
switch (innerParams.input) {
|
||||
case 'checkbox':
|
||||
return getCheckboxValue(input)
|
||||
case 'radio':
|
||||
return getRadioValue(input)
|
||||
case 'file':
|
||||
return getFileValue(input)
|
||||
default:
|
||||
return innerParams.inputAutoTrim ? input.value.trim() : input.value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLInputElement} input
|
||||
* @returns {number}
|
||||
*/
|
||||
const getCheckboxValue = (input) => (input.checked ? 1 : 0)
|
||||
|
||||
/**
|
||||
* @param {HTMLInputElement} input
|
||||
* @returns {string | null}
|
||||
*/
|
||||
const getRadioValue = (input) => (input.checked ? input.value : null)
|
||||
|
||||
/**
|
||||
* @param {HTMLInputElement} input
|
||||
* @returns {FileList | File | null}
|
||||
*/
|
||||
const getFileValue = (input) =>
|
||||
input.files && input.files.length ? (input.getAttribute('multiple') !== null ? input.files : input.files[0]) : null
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
const handleInputOptions = (instance, params) => {
|
||||
const popup = dom.getPopup()
|
||||
if (!popup) {
|
||||
return
|
||||
}
|
||||
/**
|
||||
* @param {*} inputOptions
|
||||
*/
|
||||
const processInputOptions = (inputOptions) => {
|
||||
if (params.input === 'select') {
|
||||
populateSelectOptions(popup, formatInputOptions(inputOptions), params)
|
||||
} else if (params.input === 'radio') {
|
||||
populateRadioOptions(popup, formatInputOptions(inputOptions), params)
|
||||
}
|
||||
}
|
||||
if (hasToPromiseFn(params.inputOptions) || isPromise(params.inputOptions)) {
|
||||
showLoading(dom.getConfirmButton())
|
||||
asPromise(params.inputOptions).then((inputOptions) => {
|
||||
instance.hideLoading()
|
||||
processInputOptions(inputOptions)
|
||||
})
|
||||
} else if (typeof params.inputOptions === 'object') {
|
||||
processInputOptions(params.inputOptions)
|
||||
} else {
|
||||
error(`Unexpected type of inputOptions! Expected object, Map or Promise, got ${typeof params.inputOptions}`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
const handleInputValue = (instance, params) => {
|
||||
const input = instance.getInput()
|
||||
if (!input) {
|
||||
return
|
||||
}
|
||||
dom.hide(input)
|
||||
asPromise(params.inputValue)
|
||||
.then((inputValue) => {
|
||||
input.value = params.input === 'number' ? `${parseFloat(inputValue) || 0}` : `${inputValue}`
|
||||
dom.show(input)
|
||||
input.focus()
|
||||
instance.hideLoading()
|
||||
})
|
||||
.catch((err) => {
|
||||
error(`Error in inputValue promise: ${err}`)
|
||||
input.value = ''
|
||||
dom.show(input)
|
||||
input.focus()
|
||||
instance.hideLoading()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} popup
|
||||
* @param {InputOptionFlattened[]} inputOptions
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
function populateSelectOptions(popup, inputOptions, params) {
|
||||
const select = getDirectChildByClass(popup, swalClasses.select)
|
||||
if (!select) {
|
||||
return
|
||||
}
|
||||
/**
|
||||
* @param {HTMLElement} parent
|
||||
* @param {string} optionLabel
|
||||
* @param {string} optionValue
|
||||
*/
|
||||
const renderOption = (parent, optionLabel, optionValue) => {
|
||||
const option = document.createElement('option')
|
||||
option.value = optionValue
|
||||
dom.setInnerHtml(option, optionLabel)
|
||||
option.selected = isSelected(optionValue, params.inputValue)
|
||||
parent.appendChild(option)
|
||||
}
|
||||
inputOptions.forEach((inputOption) => {
|
||||
const optionValue = inputOption[0]
|
||||
const optionLabel = inputOption[1]
|
||||
// <optgroup> spec:
|
||||
// https://www.w3.org/TR/html401/interact/forms.html#h-17.6
|
||||
// "...all OPTGROUP elements must be specified directly within a SELECT element (i.e., groups may not be nested)..."
|
||||
// check whether this is a <optgroup>
|
||||
if (Array.isArray(optionLabel)) {
|
||||
// if it is an array, then it is an <optgroup>
|
||||
const optgroup = document.createElement('optgroup')
|
||||
optgroup.label = optionValue
|
||||
optgroup.disabled = false // not configurable for now
|
||||
select.appendChild(optgroup)
|
||||
optionLabel.forEach((o) => renderOption(optgroup, o[1], o[0]))
|
||||
} else {
|
||||
// case of <option>
|
||||
renderOption(select, optionLabel, optionValue)
|
||||
}
|
||||
})
|
||||
select.focus()
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} popup
|
||||
* @param {InputOptionFlattened[]} inputOptions
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
function populateRadioOptions(popup, inputOptions, params) {
|
||||
const radio = getDirectChildByClass(popup, swalClasses.radio)
|
||||
if (!radio) {
|
||||
return
|
||||
}
|
||||
inputOptions.forEach((inputOption) => {
|
||||
const radioValue = inputOption[0]
|
||||
const radioLabel = inputOption[1]
|
||||
const radioInput = document.createElement('input')
|
||||
const radioLabelElement = document.createElement('label')
|
||||
radioInput.type = 'radio'
|
||||
radioInput.name = swalClasses.radio
|
||||
radioInput.value = radioValue
|
||||
if (isSelected(radioValue, params.inputValue)) {
|
||||
radioInput.checked = true
|
||||
}
|
||||
const label = document.createElement('span')
|
||||
dom.setInnerHtml(label, radioLabel)
|
||||
label.className = swalClasses.label
|
||||
radioLabelElement.appendChild(radioInput)
|
||||
radioLabelElement.appendChild(label)
|
||||
radio.appendChild(radioLabelElement)
|
||||
})
|
||||
const radios = radio.querySelectorAll('input')
|
||||
if (radios.length) {
|
||||
radios[0].focus()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts `inputOptions` into an array of `[value, label]`s
|
||||
*
|
||||
* @param {*} inputOptions
|
||||
* @typedef {string[]} InputOptionFlattened
|
||||
* @returns {InputOptionFlattened[]}
|
||||
*/
|
||||
const formatInputOptions = (inputOptions) => {
|
||||
/** @type {InputOptionFlattened[]} */
|
||||
const result = []
|
||||
if (inputOptions instanceof Map) {
|
||||
inputOptions.forEach((value, key) => {
|
||||
let valueFormatted = value
|
||||
if (typeof valueFormatted === 'object') {
|
||||
// case of <optgroup>
|
||||
valueFormatted = formatInputOptions(valueFormatted)
|
||||
}
|
||||
result.push([key, valueFormatted])
|
||||
})
|
||||
} else {
|
||||
Object.keys(inputOptions).forEach((key) => {
|
||||
let valueFormatted = inputOptions[key]
|
||||
if (typeof valueFormatted === 'object') {
|
||||
// case of <optgroup>
|
||||
valueFormatted = formatInputOptions(valueFormatted)
|
||||
}
|
||||
result.push([key, valueFormatted])
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} optionValue
|
||||
* @param {SweetAlertInputValue} inputValue
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isSelected = (optionValue, inputValue) => {
|
||||
return Boolean(inputValue) && (inputValue !== null && inputValue !== undefined) && inputValue.toString() === optionValue.toString()
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import { setInnerHtml } from './domUtils.js'
|
||||
|
||||
/**
|
||||
* @param {HTMLElement | object | string} param
|
||||
* @param {HTMLElement} target
|
||||
*/
|
||||
export const parseHtmlToContainer = (param, target) => {
|
||||
// DOM element
|
||||
if (param instanceof HTMLElement) {
|
||||
target.appendChild(param)
|
||||
}
|
||||
|
||||
// Object
|
||||
else if (typeof param === 'object') {
|
||||
handleObject(param, target)
|
||||
}
|
||||
|
||||
// Plain string
|
||||
else if (param) {
|
||||
setInnerHtml(target, param)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} param
|
||||
* @param {HTMLElement} target
|
||||
*/
|
||||
const handleObject = (param, target) => {
|
||||
// JQuery element(s)
|
||||
if ('jquery' in param) {
|
||||
handleJqueryElem(target, param)
|
||||
}
|
||||
|
||||
// For other objects use their string representation
|
||||
else {
|
||||
setInnerHtml(target, param.toString())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} target
|
||||
* @param {any} elem
|
||||
*/
|
||||
const handleJqueryElem = (target, elem) => {
|
||||
target.textContent = ''
|
||||
if (0 in elem) {
|
||||
for (let i = 0; i in elem; i++) {
|
||||
target.appendChild(elem[i].cloneNode(true))
|
||||
}
|
||||
} else {
|
||||
target.appendChild(elem.cloneNode(true))
|
||||
}
|
||||
}
|
||||
37
public/assets/sweetalert2/src/utils/dom/renderers/render.js
Normal file
37
public/assets/sweetalert2/src/utils/dom/renderers/render.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import globalState from '../../../globalState.js'
|
||||
import { getPopup } from '../getters.js'
|
||||
import { renderActions } from './renderActions.js'
|
||||
import { renderCloseButton } from './renderCloseButton.js'
|
||||
import { renderContainer } from './renderContainer.js'
|
||||
import { renderContent } from './renderContent.js'
|
||||
import { renderFooter } from './renderFooter.js'
|
||||
import { renderIcon } from './renderIcon.js'
|
||||
import { renderImage } from './renderImage.js'
|
||||
import { renderPopup } from './renderPopup.js'
|
||||
import { renderProgressSteps } from './renderProgressSteps.js'
|
||||
import { renderTitle } from './renderTitle.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export const render = (instance, params) => {
|
||||
renderPopup(instance, params)
|
||||
renderContainer(instance, params)
|
||||
|
||||
renderProgressSteps(instance, params)
|
||||
renderIcon(instance, params)
|
||||
renderImage(instance, params)
|
||||
renderTitle(instance, params)
|
||||
renderCloseButton(instance, params)
|
||||
|
||||
renderContent(instance, params)
|
||||
renderActions(instance, params)
|
||||
renderFooter(instance, params)
|
||||
|
||||
const popup = getPopup()
|
||||
if (typeof params.didRender === 'function' && popup) {
|
||||
params.didRender(popup)
|
||||
}
|
||||
globalState.eventEmitter?.emit('didRender', popup)
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
import { swalClasses } from '../../classes.js'
|
||||
import * as dom from '../../dom/index.js'
|
||||
import { capitalizeFirstLetter } from '../../utils.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export const renderActions = (instance, params) => {
|
||||
const actions = dom.getActions()
|
||||
const loader = dom.getLoader()
|
||||
if (!actions || !loader) {
|
||||
return
|
||||
}
|
||||
|
||||
// Actions (buttons) wrapper
|
||||
if (!params.showConfirmButton && !params.showDenyButton && !params.showCancelButton) {
|
||||
dom.hide(actions)
|
||||
} else {
|
||||
dom.show(actions)
|
||||
}
|
||||
|
||||
// Custom class
|
||||
dom.applyCustomClass(actions, params, 'actions')
|
||||
|
||||
// Render all the buttons
|
||||
renderButtons(actions, loader, params)
|
||||
|
||||
// Loader
|
||||
dom.setInnerHtml(loader, params.loaderHtml || '')
|
||||
dom.applyCustomClass(loader, params, 'loader')
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} actions
|
||||
* @param {HTMLElement} loader
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
function renderButtons(actions, loader, params) {
|
||||
const confirmButton = dom.getConfirmButton()
|
||||
const denyButton = dom.getDenyButton()
|
||||
const cancelButton = dom.getCancelButton()
|
||||
if (!confirmButton || !denyButton || !cancelButton) {
|
||||
return
|
||||
}
|
||||
|
||||
// Render buttons
|
||||
renderButton(confirmButton, 'confirm', params)
|
||||
renderButton(denyButton, 'deny', params)
|
||||
renderButton(cancelButton, 'cancel', params)
|
||||
handleButtonsStyling(confirmButton, denyButton, cancelButton, params)
|
||||
|
||||
if (params.reverseButtons) {
|
||||
if (params.toast) {
|
||||
actions.insertBefore(cancelButton, confirmButton)
|
||||
actions.insertBefore(denyButton, confirmButton)
|
||||
} else {
|
||||
actions.insertBefore(cancelButton, loader)
|
||||
actions.insertBefore(denyButton, loader)
|
||||
actions.insertBefore(confirmButton, loader)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} confirmButton
|
||||
* @param {HTMLElement} denyButton
|
||||
* @param {HTMLElement} cancelButton
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
function handleButtonsStyling(confirmButton, denyButton, cancelButton, params) {
|
||||
if (!params.buttonsStyling) {
|
||||
dom.removeClass([confirmButton, denyButton, cancelButton], swalClasses.styled)
|
||||
return
|
||||
}
|
||||
|
||||
dom.addClass([confirmButton, denyButton, cancelButton], swalClasses.styled)
|
||||
|
||||
// Apply custom background colors to action buttons
|
||||
if (params.confirmButtonColor) {
|
||||
confirmButton.style.setProperty('--swal2-confirm-button-background-color', params.confirmButtonColor)
|
||||
}
|
||||
if (params.denyButtonColor) {
|
||||
denyButton.style.setProperty('--swal2-deny-button-background-color', params.denyButtonColor)
|
||||
}
|
||||
if (params.cancelButtonColor) {
|
||||
cancelButton.style.setProperty('--swal2-cancel-button-background-color', params.cancelButtonColor)
|
||||
}
|
||||
|
||||
// Apply the outline color to action buttons
|
||||
applyOutlineColor(confirmButton)
|
||||
applyOutlineColor(denyButton)
|
||||
applyOutlineColor(cancelButton)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} button
|
||||
*/
|
||||
function applyOutlineColor(button) {
|
||||
const buttonStyle = window.getComputedStyle(button)
|
||||
if (buttonStyle.getPropertyValue('--swal2-action-button-focus-box-shadow')) {
|
||||
// If the button already has a custom outline color, no need to change it
|
||||
return
|
||||
}
|
||||
const outlineColor = buttonStyle.backgroundColor.replace(/rgba?\((\d+), (\d+), (\d+).*/, 'rgba($1, $2, $3, 0.5)')
|
||||
button.style.setProperty(
|
||||
'--swal2-action-button-focus-box-shadow',
|
||||
buttonStyle.getPropertyValue('--swal2-outline').replace(/ rgba\(.*/, ` ${outlineColor}`)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} button
|
||||
* @param {'confirm' | 'deny' | 'cancel'} buttonType
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
function renderButton(button, buttonType, params) {
|
||||
const buttonName = /** @type {'Confirm' | 'Deny' | 'Cancel'} */ (capitalizeFirstLetter(buttonType))
|
||||
|
||||
dom.toggle(button, params[`show${buttonName}Button`], 'inline-block')
|
||||
dom.setInnerHtml(button, params[`${buttonType}ButtonText`] || '') // Set caption text
|
||||
button.setAttribute('aria-label', params[`${buttonType}ButtonAriaLabel`] || '') // ARIA label
|
||||
|
||||
// Add buttons custom classes
|
||||
button.className = swalClasses[buttonType]
|
||||
dom.applyCustomClass(button, params, `${buttonType}Button`)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import * as dom from '../../dom/index.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export const renderCloseButton = (instance, params) => {
|
||||
const closeButton = dom.getCloseButton()
|
||||
if (!closeButton) {
|
||||
return
|
||||
}
|
||||
|
||||
dom.setInnerHtml(closeButton, params.closeButtonHtml || '')
|
||||
|
||||
// Custom class
|
||||
dom.applyCustomClass(closeButton, params, 'closeButton')
|
||||
|
||||
dom.toggle(closeButton, params.showCloseButton)
|
||||
closeButton.setAttribute('aria-label', params.closeButtonAriaLabel || '')
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import { swalClasses } from '../../classes.js'
|
||||
import * as dom from '../../dom/index.js'
|
||||
import { warn } from '../../utils.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export const renderContainer = (instance, params) => {
|
||||
const container = dom.getContainer()
|
||||
|
||||
if (!container) {
|
||||
return
|
||||
}
|
||||
|
||||
handleBackdropParam(container, params.backdrop)
|
||||
|
||||
handlePositionParam(container, params.position)
|
||||
handleGrowParam(container, params.grow)
|
||||
|
||||
// Custom class
|
||||
dom.applyCustomClass(container, params, 'container')
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} container
|
||||
* @param {SweetAlertOptions['backdrop']} backdrop
|
||||
*/
|
||||
function handleBackdropParam(container, backdrop) {
|
||||
if (typeof backdrop === 'string') {
|
||||
container.style.background = backdrop
|
||||
} else if (!backdrop) {
|
||||
dom.addClass([document.documentElement, document.body], swalClasses['no-backdrop'])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} container
|
||||
* @param {SweetAlertOptions['position']} position
|
||||
*/
|
||||
function handlePositionParam(container, position) {
|
||||
if (!position) {
|
||||
return
|
||||
}
|
||||
if (position in swalClasses) {
|
||||
dom.addClass(container, swalClasses[position])
|
||||
} else {
|
||||
warn('The "position" parameter is not valid, defaulting to "center"')
|
||||
dom.addClass(container, swalClasses.center)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} container
|
||||
* @param {SweetAlertOptions['grow']} grow
|
||||
*/
|
||||
function handleGrowParam(container, grow) {
|
||||
if (!grow) {
|
||||
return
|
||||
}
|
||||
dom.addClass(container, swalClasses[`grow-${grow}`])
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import * as dom from '../../dom/index.js'
|
||||
import { renderInput } from './renderInput.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export const renderContent = (instance, params) => {
|
||||
const htmlContainer = dom.getHtmlContainer()
|
||||
if (!htmlContainer) {
|
||||
return
|
||||
}
|
||||
|
||||
dom.showWhenInnerHtmlPresent(htmlContainer)
|
||||
|
||||
dom.applyCustomClass(htmlContainer, params, 'htmlContainer')
|
||||
|
||||
// Content as HTML
|
||||
if (params.html) {
|
||||
dom.parseHtmlToContainer(params.html, htmlContainer)
|
||||
dom.show(htmlContainer, 'block')
|
||||
}
|
||||
|
||||
// Content as plain text
|
||||
else if (params.text) {
|
||||
htmlContainer.textContent = params.text
|
||||
dom.show(htmlContainer, 'block')
|
||||
}
|
||||
|
||||
// No content
|
||||
else {
|
||||
dom.hide(htmlContainer)
|
||||
}
|
||||
|
||||
renderInput(instance, params)
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import * as dom from '../../dom/index.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export const renderFooter = (instance, params) => {
|
||||
const footer = dom.getFooter()
|
||||
if (!footer) {
|
||||
return
|
||||
}
|
||||
|
||||
dom.showWhenInnerHtmlPresent(footer)
|
||||
|
||||
dom.toggle(footer, Boolean(params.footer), 'block')
|
||||
|
||||
if (params.footer) {
|
||||
dom.parseHtmlToContainer(params.footer, footer)
|
||||
}
|
||||
|
||||
// Custom class
|
||||
dom.applyCustomClass(footer, params, 'footer')
|
||||
}
|
||||
164
public/assets/sweetalert2/src/utils/dom/renderers/renderIcon.js
Normal file
164
public/assets/sweetalert2/src/utils/dom/renderers/renderIcon.js
Normal file
@@ -0,0 +1,164 @@
|
||||
import privateProps from '../../../privateProps.js'
|
||||
import { iconTypes, swalClasses } from '../../classes.js'
|
||||
import * as dom from '../../dom/index.js'
|
||||
import { error } from '../../utils.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export const renderIcon = (instance, params) => {
|
||||
const innerParams = privateProps.innerParams.get(instance)
|
||||
const icon = dom.getIcon()
|
||||
if (!icon) {
|
||||
return
|
||||
}
|
||||
|
||||
// if the given icon already rendered, apply the styling without re-rendering the icon
|
||||
if (innerParams && params.icon === innerParams.icon) {
|
||||
// Custom or default content
|
||||
setContent(icon, params)
|
||||
|
||||
applyStyles(icon, params)
|
||||
return
|
||||
}
|
||||
|
||||
if (!params.icon && !params.iconHtml) {
|
||||
dom.hide(icon)
|
||||
return
|
||||
}
|
||||
|
||||
if (params.icon && Object.keys(iconTypes).indexOf(params.icon) === -1) {
|
||||
error(`Unknown icon! Expected "success", "error", "warning", "info" or "question", got "${params.icon}"`)
|
||||
dom.hide(icon)
|
||||
return
|
||||
}
|
||||
|
||||
dom.show(icon)
|
||||
|
||||
// Custom or default content
|
||||
setContent(icon, params)
|
||||
|
||||
applyStyles(icon, params)
|
||||
|
||||
// Animate icon
|
||||
dom.addClass(icon, params.showClass && params.showClass.icon)
|
||||
|
||||
// Re-adjust the success icon on system theme change
|
||||
const colorSchemeQueryList = window.matchMedia('(prefers-color-scheme: dark)')
|
||||
colorSchemeQueryList.addEventListener('change', adjustSuccessIconBackgroundColor)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} icon
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
const applyStyles = (icon, params) => {
|
||||
for (const [iconType, iconClassName] of Object.entries(iconTypes)) {
|
||||
if (params.icon !== iconType) {
|
||||
dom.removeClass(icon, iconClassName)
|
||||
}
|
||||
}
|
||||
dom.addClass(icon, params.icon && iconTypes[params.icon])
|
||||
|
||||
// Icon color
|
||||
setColor(icon, params)
|
||||
|
||||
// Success icon background color
|
||||
adjustSuccessIconBackgroundColor()
|
||||
|
||||
// Custom class
|
||||
dom.applyCustomClass(icon, params, 'icon')
|
||||
}
|
||||
|
||||
// Adjust success icon background color to match the popup background color
|
||||
const adjustSuccessIconBackgroundColor = () => {
|
||||
const popup = dom.getPopup()
|
||||
if (!popup) {
|
||||
return
|
||||
}
|
||||
const popupBackgroundColor = window.getComputedStyle(popup).getPropertyValue('background-color')
|
||||
/** @type {NodeListOf<HTMLElement>} */
|
||||
const successIconParts = popup.querySelectorAll('[class^=swal2-success-circular-line], .swal2-success-fix')
|
||||
for (let i = 0; i < successIconParts.length; i++) {
|
||||
successIconParts[i].style.backgroundColor = popupBackgroundColor
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {SweetAlertOptions} params
|
||||
* @returns {string}
|
||||
*/
|
||||
const successIconHtml = (params) => `
|
||||
${params.animation ? '<div class="swal2-success-circular-line-left"></div>' : ''}
|
||||
<span class="swal2-success-line-tip"></span> <span class="swal2-success-line-long"></span>
|
||||
<div class="swal2-success-ring"></div>
|
||||
${params.animation ? '<div class="swal2-success-fix"></div>' : ''}
|
||||
${params.animation ? '<div class="swal2-success-circular-line-right"></div>' : ''}
|
||||
`
|
||||
|
||||
const errorIconHtml = `
|
||||
<span class="swal2-x-mark">
|
||||
<span class="swal2-x-mark-line-left"></span>
|
||||
<span class="swal2-x-mark-line-right"></span>
|
||||
</span>
|
||||
`
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} icon
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
const setContent = (icon, params) => {
|
||||
if (!params.icon && !params.iconHtml) {
|
||||
return
|
||||
}
|
||||
let oldContent = icon.innerHTML
|
||||
let newContent = ''
|
||||
if (params.iconHtml) {
|
||||
newContent = iconContent(params.iconHtml)
|
||||
} else if (params.icon === 'success') {
|
||||
newContent = successIconHtml(params)
|
||||
oldContent = oldContent.replace(/ style=".*?"/g, '') // undo adjustSuccessIconBackgroundColor()
|
||||
} else if (params.icon === 'error') {
|
||||
newContent = errorIconHtml
|
||||
} else if (params.icon) {
|
||||
const defaultIconHtml = {
|
||||
question: '?',
|
||||
warning: '!',
|
||||
info: 'i',
|
||||
}
|
||||
newContent = iconContent(defaultIconHtml[params.icon])
|
||||
}
|
||||
|
||||
if (oldContent.trim() !== newContent.trim()) {
|
||||
dom.setInnerHtml(icon, newContent)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} icon
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
const setColor = (icon, params) => {
|
||||
if (!params.iconColor) {
|
||||
return
|
||||
}
|
||||
icon.style.color = params.iconColor
|
||||
icon.style.borderColor = params.iconColor
|
||||
for (const sel of [
|
||||
'.swal2-success-line-tip',
|
||||
'.swal2-success-line-long',
|
||||
'.swal2-x-mark-line-left',
|
||||
'.swal2-x-mark-line-right',
|
||||
]) {
|
||||
dom.setStyle(icon, sel, 'background-color', params.iconColor)
|
||||
}
|
||||
dom.setStyle(icon, '.swal2-success-ring', 'border-color', params.iconColor)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} content
|
||||
* @returns {string}
|
||||
*/
|
||||
const iconContent = (content) => `<div class="${swalClasses['icon-content']}">${content}</div>`
|
||||
@@ -0,0 +1,32 @@
|
||||
import { swalClasses } from '../../classes.js'
|
||||
import * as dom from '../../dom/index.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export const renderImage = (instance, params) => {
|
||||
const image = dom.getImage()
|
||||
if (!image) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!params.imageUrl) {
|
||||
dom.hide(image)
|
||||
return
|
||||
}
|
||||
|
||||
dom.show(image, '')
|
||||
|
||||
// Src, alt
|
||||
image.setAttribute('src', params.imageUrl)
|
||||
image.setAttribute('alt', params.imageAlt || '')
|
||||
|
||||
// Width, height
|
||||
dom.applyNumericalStyle(image, 'width', params.imageWidth)
|
||||
dom.applyNumericalStyle(image, 'height', params.imageHeight)
|
||||
|
||||
// Class
|
||||
image.className = swalClasses.image
|
||||
dom.applyCustomClass(image, params, 'image')
|
||||
}
|
||||
353
public/assets/sweetalert2/src/utils/dom/renderers/renderInput.js
Normal file
353
public/assets/sweetalert2/src/utils/dom/renderers/renderInput.js
Normal file
@@ -0,0 +1,353 @@
|
||||
/// <reference path="../../../../sweetalert2.d.ts"/>
|
||||
|
||||
/**
|
||||
* @typedef { HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement } Input
|
||||
* @typedef { 'input' | 'file' | 'range' | 'select' | 'radio' | 'checkbox' | 'textarea' } InputClass
|
||||
*/
|
||||
import privateProps from '../../../privateProps.js'
|
||||
import { swalClasses } from '../../classes.js'
|
||||
import * as dom from '../../dom/index.js'
|
||||
import { error, isPromise, warn } from '../../utils.js'
|
||||
|
||||
/** @type {InputClass[]} */
|
||||
const inputClasses = ['input', 'file', 'range', 'select', 'radio', 'checkbox', 'textarea']
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export const renderInput = (instance, params) => {
|
||||
const popup = dom.getPopup()
|
||||
if (!popup) {
|
||||
return
|
||||
}
|
||||
const innerParams = privateProps.innerParams.get(instance)
|
||||
const rerender = !innerParams || params.input !== innerParams.input
|
||||
|
||||
inputClasses.forEach((inputClass) => {
|
||||
const inputContainer = dom.getDirectChildByClass(popup, swalClasses[inputClass])
|
||||
|
||||
if (!inputContainer) {
|
||||
return
|
||||
}
|
||||
|
||||
// set attributes
|
||||
setAttributes(inputClass, params.inputAttributes)
|
||||
|
||||
// set class
|
||||
inputContainer.className = swalClasses[inputClass]
|
||||
|
||||
if (rerender) {
|
||||
dom.hide(inputContainer)
|
||||
}
|
||||
})
|
||||
|
||||
if (params.input) {
|
||||
if (rerender) {
|
||||
showInput(params)
|
||||
}
|
||||
// set custom class
|
||||
setCustomClass(params)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
const showInput = (params) => {
|
||||
if (!params.input) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!renderInputType[params.input]) {
|
||||
error(`Unexpected type of input! Expected ${Object.keys(renderInputType).join(' | ')}, got "${params.input}"`)
|
||||
return
|
||||
}
|
||||
|
||||
const inputContainer = getInputContainer(params.input)
|
||||
if (!inputContainer) {
|
||||
return
|
||||
}
|
||||
|
||||
const input = renderInputType[params.input](inputContainer, params)
|
||||
dom.show(inputContainer)
|
||||
|
||||
// input autofocus
|
||||
if (params.inputAutoFocus) {
|
||||
setTimeout(() => {
|
||||
dom.focusInput(input)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLInputElement} input
|
||||
*/
|
||||
const removeAttributes = (input) => {
|
||||
for (let i = 0; i < input.attributes.length; i++) {
|
||||
const attrName = input.attributes[i].name
|
||||
if (!['id', 'type', 'value', 'style'].includes(attrName)) {
|
||||
input.removeAttribute(attrName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {InputClass} inputClass
|
||||
* @param {SweetAlertOptions['inputAttributes']} inputAttributes
|
||||
*/
|
||||
const setAttributes = (inputClass, inputAttributes) => {
|
||||
const popup = dom.getPopup()
|
||||
if (!popup) {
|
||||
return
|
||||
}
|
||||
|
||||
const input = dom.getInput(popup, inputClass)
|
||||
if (!input) {
|
||||
return
|
||||
}
|
||||
|
||||
removeAttributes(input)
|
||||
|
||||
for (const attr in inputAttributes) {
|
||||
input.setAttribute(attr, inputAttributes[attr])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
const setCustomClass = (params) => {
|
||||
if (!params.input) {
|
||||
return
|
||||
}
|
||||
const inputContainer = getInputContainer(params.input)
|
||||
if (inputContainer) {
|
||||
dom.applyCustomClass(inputContainer, params, 'input')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLInputElement | HTMLTextAreaElement} input
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
const setInputPlaceholder = (input, params) => {
|
||||
if (!input.placeholder && params.inputPlaceholder) {
|
||||
input.placeholder = params.inputPlaceholder
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Input} input
|
||||
* @param {Input} prependTo
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
const setInputLabel = (input, prependTo, params) => {
|
||||
if (params.inputLabel) {
|
||||
const label = document.createElement('label')
|
||||
const labelClass = swalClasses['input-label']
|
||||
label.setAttribute('for', input.id)
|
||||
label.className = labelClass
|
||||
if (typeof params.customClass === 'object') {
|
||||
dom.addClass(label, params.customClass.inputLabel)
|
||||
}
|
||||
label.innerText = params.inputLabel
|
||||
prependTo.insertAdjacentElement('beforebegin', label)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlertInput} inputType
|
||||
* @returns {HTMLElement | undefined}
|
||||
*/
|
||||
const getInputContainer = (inputType) => {
|
||||
const popup = dom.getPopup()
|
||||
if (!popup) {
|
||||
return
|
||||
}
|
||||
|
||||
return dom.getDirectChildByClass(popup, swalClasses[/** @type {SwalClass} */ (inputType)] || swalClasses.input)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLInputElement | HTMLOutputElement | HTMLTextAreaElement} input
|
||||
* @param {SweetAlertOptions['inputValue']} inputValue
|
||||
*/
|
||||
const checkAndSetInputValue = (input, inputValue) => {
|
||||
if (['string', 'number'].includes(typeof inputValue)) {
|
||||
input.value = `${inputValue}`
|
||||
} else if (!isPromise(inputValue)) {
|
||||
warn(`Unexpected type of inputValue! Expected "string", "number" or "Promise", got "${typeof inputValue}"`)
|
||||
}
|
||||
}
|
||||
|
||||
/** @type {Record<SweetAlertInput, (input: Input | HTMLElement, params: SweetAlertOptions) => Input>} */
|
||||
const renderInputType = {}
|
||||
|
||||
/**
|
||||
* @param {Input | HTMLElement} input
|
||||
* @param {SweetAlertOptions} params
|
||||
* @returns {Input}
|
||||
*/
|
||||
renderInputType.text =
|
||||
renderInputType.email =
|
||||
renderInputType.password =
|
||||
renderInputType.number =
|
||||
renderInputType.tel =
|
||||
renderInputType.url =
|
||||
renderInputType.search =
|
||||
renderInputType.date =
|
||||
renderInputType['datetime-local'] =
|
||||
renderInputType.time =
|
||||
renderInputType.week =
|
||||
renderInputType.month =
|
||||
/** @type {(input: Input | HTMLElement, params: SweetAlertOptions) => Input} */
|
||||
(input, params) => {
|
||||
const inputElement = /** @type {HTMLInputElement} */ (input)
|
||||
checkAndSetInputValue(inputElement, params.inputValue)
|
||||
setInputLabel(inputElement, inputElement, params)
|
||||
setInputPlaceholder(inputElement, params)
|
||||
inputElement.type = /** @type {string} */ (params.input)
|
||||
return inputElement
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Input | HTMLElement} input
|
||||
* @param {SweetAlertOptions} params
|
||||
* @returns {Input}
|
||||
*/
|
||||
renderInputType.file = (input, params) => {
|
||||
const inputElement = /** @type {HTMLInputElement} */ (input)
|
||||
setInputLabel(inputElement, inputElement, params)
|
||||
setInputPlaceholder(inputElement, params)
|
||||
return inputElement
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Input | HTMLElement} range
|
||||
* @param {SweetAlertOptions} params
|
||||
* @returns {Input}
|
||||
*/
|
||||
renderInputType.range = (range, params) => {
|
||||
const rangeContainer = /** @type {HTMLElement} */ (range)
|
||||
const rangeInput = rangeContainer.querySelector('input')
|
||||
const rangeOutput = rangeContainer.querySelector('output')
|
||||
if (rangeInput) {
|
||||
checkAndSetInputValue(rangeInput, params.inputValue)
|
||||
rangeInput.type = /** @type {string} */ (params.input)
|
||||
setInputLabel(rangeInput, /** @type {Input} */ (range), params)
|
||||
}
|
||||
if (rangeOutput) {
|
||||
checkAndSetInputValue(rangeOutput, params.inputValue)
|
||||
}
|
||||
return /** @type {Input} */ (range)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Input | HTMLElement} select
|
||||
* @param {SweetAlertOptions} params
|
||||
* @returns {Input}
|
||||
*/
|
||||
renderInputType.select = (select, params) => {
|
||||
const selectElement = /** @type {HTMLSelectElement} */ (select)
|
||||
selectElement.textContent = ''
|
||||
if (params.inputPlaceholder) {
|
||||
const placeholder = document.createElement('option')
|
||||
dom.setInnerHtml(placeholder, params.inputPlaceholder)
|
||||
placeholder.value = ''
|
||||
placeholder.disabled = true
|
||||
placeholder.selected = true
|
||||
selectElement.appendChild(placeholder)
|
||||
}
|
||||
setInputLabel(selectElement, selectElement, params)
|
||||
return selectElement
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Input | HTMLElement} radio
|
||||
* @returns {Input}
|
||||
*/
|
||||
renderInputType.radio = (radio) => {
|
||||
const radioElement = /** @type {HTMLElement} */ (radio)
|
||||
radioElement.textContent = ''
|
||||
return /** @type {Input} */ (radio)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Input | HTMLElement} checkboxContainer
|
||||
* @param {SweetAlertOptions} params
|
||||
* @returns {Input}
|
||||
*/
|
||||
renderInputType.checkbox = (checkboxContainer, params) => {
|
||||
const popup = dom.getPopup()
|
||||
if (!popup) {
|
||||
throw new Error('Popup not found')
|
||||
}
|
||||
const checkbox = dom.getInput(popup, 'checkbox')
|
||||
if (!checkbox) {
|
||||
throw new Error('Checkbox input not found')
|
||||
}
|
||||
checkbox.value = '1'
|
||||
checkbox.checked = Boolean(params.inputValue)
|
||||
const containerElement = /** @type {HTMLElement} */ (checkboxContainer)
|
||||
const label = containerElement.querySelector('span')
|
||||
if (label) {
|
||||
const placeholderOrLabel = params.inputPlaceholder || params.inputLabel
|
||||
if (placeholderOrLabel) {
|
||||
dom.setInnerHtml(label, placeholderOrLabel)
|
||||
}
|
||||
}
|
||||
return checkbox
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Input | HTMLElement} textarea
|
||||
* @param {SweetAlertOptions} params
|
||||
* @returns {Input}
|
||||
*/
|
||||
renderInputType.textarea = (textarea, params) => {
|
||||
const textareaElement = /** @type {HTMLTextAreaElement} */ (textarea)
|
||||
checkAndSetInputValue(textareaElement, params.inputValue)
|
||||
setInputPlaceholder(textareaElement, params)
|
||||
setInputLabel(textareaElement, textareaElement, params)
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} el
|
||||
* @returns {number}
|
||||
*/
|
||||
const getMargin = (el) =>
|
||||
parseInt(window.getComputedStyle(el).marginLeft) + parseInt(window.getComputedStyle(el).marginRight)
|
||||
|
||||
// https://github.com/sweetalert2/sweetalert2/issues/2291
|
||||
setTimeout(() => {
|
||||
// https://github.com/sweetalert2/sweetalert2/issues/1699
|
||||
if ('MutationObserver' in window) {
|
||||
const popup = dom.getPopup()
|
||||
if (!popup) {
|
||||
return
|
||||
}
|
||||
const initialPopupWidth = parseInt(window.getComputedStyle(popup).width)
|
||||
const textareaResizeHandler = () => {
|
||||
// check if texarea is still in document (i.e. popup wasn't closed in the meantime)
|
||||
if (!document.body.contains(textareaElement)) {
|
||||
return
|
||||
}
|
||||
const textareaWidth = textareaElement.offsetWidth + getMargin(textareaElement)
|
||||
const popupElement = dom.getPopup()
|
||||
if (popupElement) {
|
||||
if (textareaWidth > initialPopupWidth) {
|
||||
popupElement.style.width = `${textareaWidth}px`
|
||||
} else {
|
||||
dom.applyNumericalStyle(popupElement, 'width', params.width)
|
||||
}
|
||||
}
|
||||
}
|
||||
new MutationObserver(textareaResizeHandler).observe(textareaElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ['style'],
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return textareaElement
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import { swalClasses } from '../../classes.js'
|
||||
import { addDraggableListeners, removeDraggableListeners } from '../../draggable.js'
|
||||
import * as dom from '../../dom/index.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export const renderPopup = (instance, params) => {
|
||||
const container = dom.getContainer()
|
||||
const popup = dom.getPopup()
|
||||
if (!container || !popup) {
|
||||
return
|
||||
}
|
||||
|
||||
// Width
|
||||
// https://github.com/sweetalert2/sweetalert2/issues/2170
|
||||
if (params.toast) {
|
||||
dom.applyNumericalStyle(container, 'width', params.width)
|
||||
popup.style.width = '100%'
|
||||
const loader = dom.getLoader()
|
||||
if (loader) {
|
||||
popup.insertBefore(loader, dom.getIcon())
|
||||
}
|
||||
} else {
|
||||
dom.applyNumericalStyle(popup, 'width', params.width)
|
||||
}
|
||||
|
||||
// Padding
|
||||
dom.applyNumericalStyle(popup, 'padding', params.padding)
|
||||
|
||||
// Color
|
||||
if (params.color) {
|
||||
popup.style.color = params.color
|
||||
}
|
||||
|
||||
// Background
|
||||
if (params.background) {
|
||||
popup.style.background = params.background
|
||||
}
|
||||
|
||||
dom.hide(dom.getValidationMessage())
|
||||
|
||||
// Classes
|
||||
addClasses(popup, params)
|
||||
|
||||
if (params.draggable && !params.toast) {
|
||||
dom.addClass(popup, swalClasses.draggable)
|
||||
addDraggableListeners(popup)
|
||||
} else {
|
||||
dom.removeClass(popup, swalClasses.draggable)
|
||||
removeDraggableListeners(popup)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} popup
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
const addClasses = (popup, params) => {
|
||||
const showClass = params.showClass || {}
|
||||
// Default Class + showClass when updating Swal.update({})
|
||||
popup.className = `${swalClasses.popup} ${dom.isVisible(popup) ? showClass.popup : ''}`
|
||||
|
||||
if (params.toast) {
|
||||
dom.addClass([document.documentElement, document.body], swalClasses['toast-shown'])
|
||||
dom.addClass(popup, swalClasses.toast)
|
||||
} else {
|
||||
dom.addClass(popup, swalClasses.modal)
|
||||
}
|
||||
|
||||
// Custom class
|
||||
dom.applyCustomClass(popup, params, 'popup')
|
||||
// TODO: remove in the next major
|
||||
if (typeof params.customClass === 'string') {
|
||||
dom.addClass(popup, params.customClass)
|
||||
}
|
||||
|
||||
// Icon class (#1842)
|
||||
if (params.icon) {
|
||||
dom.addClass(popup, swalClasses[`icon-${params.icon}`])
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import { swalClasses } from '../../classes.js'
|
||||
import * as dom from '../../dom/index.js'
|
||||
import { warn } from '../../utils.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export const renderProgressSteps = (instance, params) => {
|
||||
const progressStepsContainer = dom.getProgressSteps()
|
||||
if (!progressStepsContainer) {
|
||||
return
|
||||
}
|
||||
|
||||
const { progressSteps, currentProgressStep } = params
|
||||
|
||||
if (!progressSteps || progressSteps.length === 0 || currentProgressStep === undefined) {
|
||||
dom.hide(progressStepsContainer)
|
||||
return
|
||||
}
|
||||
|
||||
dom.show(progressStepsContainer)
|
||||
progressStepsContainer.textContent = ''
|
||||
if (currentProgressStep >= progressSteps.length) {
|
||||
warn(
|
||||
'Invalid currentProgressStep parameter, it should be less than progressSteps.length ' +
|
||||
'(currentProgressStep like JS arrays starts from 0)'
|
||||
)
|
||||
}
|
||||
|
||||
progressSteps.forEach((step, index) => {
|
||||
const stepEl = createStepElement(step)
|
||||
progressStepsContainer.appendChild(stepEl)
|
||||
if (index === currentProgressStep) {
|
||||
dom.addClass(stepEl, swalClasses['active-progress-step'])
|
||||
}
|
||||
|
||||
if (index !== progressSteps.length - 1) {
|
||||
const lineEl = createLineElement(params)
|
||||
progressStepsContainer.appendChild(lineEl)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} step
|
||||
* @returns {HTMLLIElement}
|
||||
*/
|
||||
const createStepElement = (step) => {
|
||||
const stepEl = document.createElement('li')
|
||||
dom.addClass(stepEl, swalClasses['progress-step'])
|
||||
dom.setInnerHtml(stepEl, step)
|
||||
return stepEl
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlertOptions} params
|
||||
* @returns {HTMLLIElement}
|
||||
*/
|
||||
const createLineElement = (params) => {
|
||||
const lineEl = document.createElement('li')
|
||||
dom.addClass(lineEl, swalClasses['progress-step-line'])
|
||||
if (params.progressStepsDistance) {
|
||||
dom.applyNumericalStyle(lineEl, 'width', params.progressStepsDistance)
|
||||
}
|
||||
return lineEl
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import * as dom from '../../dom/index.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export const renderTitle = (instance, params) => {
|
||||
const title = dom.getTitle()
|
||||
if (!title) {
|
||||
return
|
||||
}
|
||||
|
||||
dom.showWhenInnerHtmlPresent(title)
|
||||
|
||||
dom.toggle(title, Boolean(params.title || params.titleText), 'block')
|
||||
|
||||
if (params.title) {
|
||||
dom.parseHtmlToContainer(params.title, title)
|
||||
}
|
||||
|
||||
if (params.titleText) {
|
||||
title.innerText = params.titleText
|
||||
}
|
||||
|
||||
// Custom class
|
||||
dom.applyCustomClass(title, params, 'title')
|
||||
}
|
||||
99
public/assets/sweetalert2/src/utils/draggable.js
Normal file
99
public/assets/sweetalert2/src/utils/draggable.js
Normal file
@@ -0,0 +1,99 @@
|
||||
import globalState from '../globalState.js'
|
||||
import * as dom from './dom/index.js'
|
||||
|
||||
let dragging = false
|
||||
let mousedownX = 0
|
||||
let mousedownY = 0
|
||||
let initialX = 0
|
||||
let initialY = 0
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} popup
|
||||
*/
|
||||
export const addDraggableListeners = (popup) => {
|
||||
popup.addEventListener('mousedown', down)
|
||||
document.body.addEventListener('mousemove', move)
|
||||
popup.addEventListener('mouseup', up)
|
||||
|
||||
popup.addEventListener('touchstart', down)
|
||||
document.body.addEventListener('touchmove', move)
|
||||
popup.addEventListener('touchend', up)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} popup
|
||||
*/
|
||||
export const removeDraggableListeners = (popup) => {
|
||||
popup.removeEventListener('mousedown', down)
|
||||
document.body.removeEventListener('mousemove', move)
|
||||
popup.removeEventListener('mouseup', up)
|
||||
|
||||
popup.removeEventListener('touchstart', down)
|
||||
document.body.removeEventListener('touchmove', move)
|
||||
popup.removeEventListener('touchend', up)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MouseEvent | TouchEvent} event
|
||||
*/
|
||||
const down = (event) => {
|
||||
const popup = dom.getPopup()
|
||||
|
||||
if (!popup) {
|
||||
return
|
||||
}
|
||||
|
||||
const icon = dom.getIcon()
|
||||
if (event.target === popup || (icon && icon.contains(/** @type {HTMLElement} */ (event.target)))) {
|
||||
dragging = true
|
||||
const clientXY = getClientXY(event)
|
||||
mousedownX = clientXY.clientX
|
||||
mousedownY = clientXY.clientY
|
||||
initialX = parseInt(popup.style.insetInlineStart) || 0
|
||||
initialY = parseInt(popup.style.insetBlockStart) || 0
|
||||
dom.addClass(popup, 'swal2-dragging')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MouseEvent | TouchEvent} event
|
||||
*/
|
||||
const move = (event) => {
|
||||
const popup = dom.getPopup()
|
||||
|
||||
if (!popup) {
|
||||
return
|
||||
}
|
||||
|
||||
if (dragging) {
|
||||
let { clientX, clientY } = getClientXY(event)
|
||||
const deltaX = clientX - mousedownX
|
||||
// In RTL mode, negate the horizontal delta since insetInlineStart refers to the right edge
|
||||
popup.style.insetInlineStart = `${initialX + (globalState.isRTL ? -deltaX : deltaX)}px`
|
||||
popup.style.insetBlockStart = `${initialY + (clientY - mousedownY)}px`
|
||||
}
|
||||
}
|
||||
|
||||
const up = () => {
|
||||
const popup = dom.getPopup()
|
||||
|
||||
dragging = false
|
||||
dom.removeClass(popup, 'swal2-dragging')
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MouseEvent | TouchEvent} event
|
||||
* @returns {{ clientX: number, clientY: number }}
|
||||
*/
|
||||
const getClientXY = (event) => {
|
||||
let clientX = 0,
|
||||
clientY = 0
|
||||
if (event.type.startsWith('mouse')) {
|
||||
clientX = /** @type {MouseEvent} */ (event).clientX
|
||||
clientY = /** @type {MouseEvent} */ (event).clientY
|
||||
} else if (event.type.startsWith('touch')) {
|
||||
clientX = /** @type {TouchEvent} */ (event).touches[0].clientX
|
||||
clientY = /** @type {TouchEvent} */ (event).touches[0].clientY
|
||||
}
|
||||
return { clientX, clientY }
|
||||
}
|
||||
265
public/assets/sweetalert2/src/utils/getTemplateParams.js
Normal file
265
public/assets/sweetalert2/src/utils/getTemplateParams.js
Normal file
@@ -0,0 +1,265 @@
|
||||
import defaultParams from './params.js'
|
||||
import { capitalizeFirstLetter, warn } from './utils.js'
|
||||
|
||||
const swalStringParams = ['swal-title', 'swal-html', 'swal-footer']
|
||||
|
||||
/**
|
||||
* @param {SweetAlertOptions} params
|
||||
* @returns {SweetAlertOptions}
|
||||
*/
|
||||
export const getTemplateParams = (params) => {
|
||||
const template =
|
||||
typeof params.template === 'string'
|
||||
? /** @type {HTMLTemplateElement} */ (document.querySelector(params.template))
|
||||
: params.template
|
||||
if (!template) {
|
||||
return {}
|
||||
}
|
||||
/** @type {DocumentFragment} */
|
||||
const templateContent = template.content
|
||||
|
||||
showWarningsForElements(templateContent)
|
||||
|
||||
const result = Object.assign(
|
||||
getSwalParams(templateContent),
|
||||
getSwalFunctionParams(templateContent),
|
||||
getSwalButtons(templateContent),
|
||||
getSwalImage(templateContent),
|
||||
getSwalIcon(templateContent),
|
||||
getSwalInput(templateContent),
|
||||
getSwalStringParams(templateContent, swalStringParams)
|
||||
)
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DocumentFragment} templateContent
|
||||
* @returns {Record<string, string | boolean | number>}
|
||||
*/
|
||||
const getSwalParams = (templateContent) => {
|
||||
/** @type {Record<string, string | boolean | number>} */
|
||||
const result = {}
|
||||
/** @type {HTMLElement[]} */
|
||||
const swalParams = Array.from(templateContent.querySelectorAll('swal-param'))
|
||||
swalParams.forEach((param) => {
|
||||
showWarningsForAttributes(param, ['name', 'value'])
|
||||
const paramName = /** @type {keyof SweetAlertOptions} */ (param.getAttribute('name'))
|
||||
const value = param.getAttribute('value')
|
||||
if (!paramName || !value) {
|
||||
return
|
||||
}
|
||||
if (
|
||||
paramName in defaultParams &&
|
||||
typeof defaultParams[/** @type {keyof typeof defaultParams} */ (paramName)] === 'boolean'
|
||||
) {
|
||||
result[paramName] = value !== 'false'
|
||||
} else if (
|
||||
paramName in defaultParams &&
|
||||
typeof defaultParams[/** @type {keyof typeof defaultParams} */ (paramName)] === 'object'
|
||||
) {
|
||||
result[paramName] = JSON.parse(value)
|
||||
} else {
|
||||
result[paramName] = value
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DocumentFragment} templateContent
|
||||
* @returns {Record<string, () => void>}
|
||||
*/
|
||||
const getSwalFunctionParams = (templateContent) => {
|
||||
/** @type {Record<string, () => void>} */
|
||||
const result = {}
|
||||
/** @type {HTMLElement[]} */
|
||||
const swalFunctions = Array.from(templateContent.querySelectorAll('swal-function-param'))
|
||||
swalFunctions.forEach((param) => {
|
||||
const paramName = /** @type {keyof SweetAlertOptions} */ param.getAttribute('name')
|
||||
const value = param.getAttribute('value')
|
||||
if (!paramName || !value) {
|
||||
return
|
||||
}
|
||||
result[paramName] = new Function(`return ${value}`)()
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DocumentFragment} templateContent
|
||||
* @returns {Record<string, string | boolean>}
|
||||
*/
|
||||
const getSwalButtons = (templateContent) => {
|
||||
/** @type {Record<string, string | boolean>} */
|
||||
const result = {}
|
||||
/** @type {HTMLElement[]} */
|
||||
const swalButtons = Array.from(templateContent.querySelectorAll('swal-button'))
|
||||
swalButtons.forEach((button) => {
|
||||
showWarningsForAttributes(button, ['type', 'color', 'aria-label'])
|
||||
const type = button.getAttribute('type')
|
||||
if (!type || !['confirm', 'cancel', 'deny'].includes(type)) {
|
||||
return
|
||||
}
|
||||
result[`${type}ButtonText`] = button.innerHTML
|
||||
result[`show${capitalizeFirstLetter(type)}Button`] = true
|
||||
if (button.hasAttribute('color')) {
|
||||
const color = button.getAttribute('color')
|
||||
if (color !== null) {
|
||||
result[`${type}ButtonColor`] = color
|
||||
}
|
||||
}
|
||||
if (button.hasAttribute('aria-label')) {
|
||||
const ariaLabel = button.getAttribute('aria-label')
|
||||
if (ariaLabel !== null) {
|
||||
result[`${type}ButtonAriaLabel`] = ariaLabel
|
||||
}
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DocumentFragment} templateContent
|
||||
* @returns {Pick<SweetAlertOptions, 'imageUrl' | 'imageWidth' | 'imageHeight' | 'imageAlt'>}
|
||||
*/
|
||||
const getSwalImage = (templateContent) => {
|
||||
const result = {}
|
||||
/** @type {HTMLElement | null} */
|
||||
const image = templateContent.querySelector('swal-image')
|
||||
if (image) {
|
||||
showWarningsForAttributes(image, ['src', 'width', 'height', 'alt'])
|
||||
if (image.hasAttribute('src')) {
|
||||
result.imageUrl = image.getAttribute('src') || undefined
|
||||
}
|
||||
if (image.hasAttribute('width')) {
|
||||
result.imageWidth = image.getAttribute('width') || undefined
|
||||
}
|
||||
if (image.hasAttribute('height')) {
|
||||
result.imageHeight = image.getAttribute('height') || undefined
|
||||
}
|
||||
if (image.hasAttribute('alt')) {
|
||||
result.imageAlt = image.getAttribute('alt') || undefined
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DocumentFragment} templateContent
|
||||
* @returns {object}
|
||||
*/
|
||||
const getSwalIcon = (templateContent) => {
|
||||
const result = {}
|
||||
/** @type {HTMLElement | null} */
|
||||
const icon = templateContent.querySelector('swal-icon')
|
||||
if (icon) {
|
||||
showWarningsForAttributes(icon, ['type', 'color'])
|
||||
if (icon.hasAttribute('type')) {
|
||||
result.icon = icon.getAttribute('type')
|
||||
}
|
||||
if (icon.hasAttribute('color')) {
|
||||
result.iconColor = icon.getAttribute('color')
|
||||
}
|
||||
result.iconHtml = icon.innerHTML
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DocumentFragment} templateContent
|
||||
* @returns {object}
|
||||
*/
|
||||
const getSwalInput = (templateContent) => {
|
||||
/** @type {Record<string, any>} */
|
||||
const result = {}
|
||||
/** @type {HTMLElement | null} */
|
||||
const input = templateContent.querySelector('swal-input')
|
||||
if (input) {
|
||||
showWarningsForAttributes(input, ['type', 'label', 'placeholder', 'value'])
|
||||
result.input = input.getAttribute('type') || 'text'
|
||||
if (input.hasAttribute('label')) {
|
||||
result.inputLabel = input.getAttribute('label')
|
||||
}
|
||||
if (input.hasAttribute('placeholder')) {
|
||||
result.inputPlaceholder = input.getAttribute('placeholder')
|
||||
}
|
||||
if (input.hasAttribute('value')) {
|
||||
result.inputValue = input.getAttribute('value')
|
||||
}
|
||||
}
|
||||
/** @type {HTMLElement[]} */
|
||||
const inputOptions = Array.from(templateContent.querySelectorAll('swal-input-option'))
|
||||
if (inputOptions.length) {
|
||||
result.inputOptions = {}
|
||||
inputOptions.forEach((option) => {
|
||||
showWarningsForAttributes(option, ['value'])
|
||||
const optionValue = option.getAttribute('value')
|
||||
if (!optionValue) {
|
||||
return
|
||||
}
|
||||
const optionName = option.innerHTML
|
||||
result.inputOptions[optionValue] = optionName
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DocumentFragment} templateContent
|
||||
* @param {string[]} paramNames
|
||||
* @returns {Record<string, string>}
|
||||
*/
|
||||
const getSwalStringParams = (templateContent, paramNames) => {
|
||||
/** @type {Record<string, string>} */
|
||||
const result = {}
|
||||
for (const i in paramNames) {
|
||||
const paramName = paramNames[i]
|
||||
/** @type {HTMLElement | null} */
|
||||
const tag = templateContent.querySelector(paramName)
|
||||
if (tag) {
|
||||
showWarningsForAttributes(tag, [])
|
||||
result[paramName.replace(/^swal-/, '')] = tag.innerHTML.trim()
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DocumentFragment} templateContent
|
||||
*/
|
||||
const showWarningsForElements = (templateContent) => {
|
||||
const allowedElements = swalStringParams.concat([
|
||||
'swal-param',
|
||||
'swal-function-param',
|
||||
'swal-button',
|
||||
'swal-image',
|
||||
'swal-icon',
|
||||
'swal-input',
|
||||
'swal-input-option',
|
||||
])
|
||||
Array.from(templateContent.children).forEach((el) => {
|
||||
const tagName = el.tagName.toLowerCase()
|
||||
if (!allowedElements.includes(tagName)) {
|
||||
warn(`Unrecognized element <${tagName}>`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} el
|
||||
* @param {string[]} allowedAttributes
|
||||
*/
|
||||
const showWarningsForAttributes = (el, allowedAttributes) => {
|
||||
Array.from(el.attributes).forEach((attribute) => {
|
||||
if (allowedAttributes.indexOf(attribute.name) === -1) {
|
||||
warn([
|
||||
`Unrecognized attribute "${attribute.name}" on <${el.tagName.toLowerCase()}>.`,
|
||||
`${
|
||||
allowedAttributes.length
|
||||
? `Allowed attributes are: ${allowedAttributes.join(', ')}`
|
||||
: 'To set the value, use HTML within the element.'
|
||||
}`,
|
||||
])
|
||||
}
|
||||
})
|
||||
}
|
||||
112
public/assets/sweetalert2/src/utils/iosFix.js
Normal file
112
public/assets/sweetalert2/src/utils/iosFix.js
Normal file
@@ -0,0 +1,112 @@
|
||||
import { swalClasses } from '../utils/classes.js'
|
||||
import * as dom from './dom/index.js'
|
||||
|
||||
// @ts-ignore
|
||||
export const isSafariOrIOS = typeof window !== 'undefined' && Boolean(window.GestureEvent) // true for Safari desktop + all iOS browsers https://stackoverflow.com/a/70585394
|
||||
|
||||
/**
|
||||
* Fix iOS scrolling
|
||||
* http://stackoverflow.com/q/39626302
|
||||
*/
|
||||
export const iOSfix = () => {
|
||||
if (isSafariOrIOS && !dom.hasClass(document.body, swalClasses.iosfix)) {
|
||||
const offset = document.body.scrollTop
|
||||
document.body.style.top = `${offset * -1}px`
|
||||
dom.addClass(document.body, swalClasses.iosfix)
|
||||
lockBodyScroll()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* https://github.com/sweetalert2/sweetalert2/issues/1246
|
||||
*/
|
||||
const lockBodyScroll = () => {
|
||||
const container = dom.getContainer()
|
||||
if (!container) {
|
||||
return
|
||||
}
|
||||
/** @type {boolean} */
|
||||
let preventTouchMove
|
||||
/**
|
||||
* @param {TouchEvent} event
|
||||
*/
|
||||
container.ontouchstart = (event) => {
|
||||
preventTouchMove = shouldPreventTouchMove(event)
|
||||
}
|
||||
/**
|
||||
* @param {TouchEvent} event
|
||||
*/
|
||||
container.ontouchmove = (event) => {
|
||||
if (preventTouchMove) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TouchEvent} event
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const shouldPreventTouchMove = (event) => {
|
||||
const target = event.target
|
||||
const container = dom.getContainer()
|
||||
const htmlContainer = dom.getHtmlContainer()
|
||||
if (!container || !htmlContainer) {
|
||||
return false
|
||||
}
|
||||
if (isStylus(event) || isZoom(event)) {
|
||||
return false
|
||||
}
|
||||
if (target === container) {
|
||||
return true
|
||||
}
|
||||
if (
|
||||
!dom.isScrollable(container) &&
|
||||
target instanceof HTMLElement &&
|
||||
!dom.selfOrParentIsScrollable(target, htmlContainer) && // #2823
|
||||
target.tagName !== 'INPUT' && // #1603
|
||||
target.tagName !== 'TEXTAREA' && // #2266
|
||||
!(
|
||||
dom.isScrollable(htmlContainer) && // #1944
|
||||
htmlContainer.contains(target)
|
||||
)
|
||||
) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* https://github.com/sweetalert2/sweetalert2/issues/1786
|
||||
*
|
||||
* @param {TouchEvent} event
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isStylus = (event) => {
|
||||
return Boolean(
|
||||
event.touches &&
|
||||
event.touches.length &&
|
||||
// @ts-ignore - touchType is not a standard property
|
||||
event.touches[0].touchType === 'stylus'
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* https://github.com/sweetalert2/sweetalert2/issues/1891
|
||||
*
|
||||
* @param {TouchEvent} event
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isZoom = (event) => {
|
||||
return event.touches && event.touches.length > 1
|
||||
}
|
||||
|
||||
export const undoIOSfix = () => {
|
||||
if (dom.hasClass(document.body, swalClasses.iosfix)) {
|
||||
const offset = parseInt(document.body.style.top, 10)
|
||||
dom.removeClass(document.body, swalClasses.iosfix)
|
||||
document.body.style.top = ''
|
||||
document.body.scrollTop = offset * -1
|
||||
}
|
||||
}
|
||||
6
public/assets/sweetalert2/src/utils/isNodeEnv.js
Normal file
6
public/assets/sweetalert2/src/utils/isNodeEnv.js
Normal file
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Detect Node env
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const isNodeEnv = () => typeof window === 'undefined' || typeof document === 'undefined'
|
||||
139
public/assets/sweetalert2/src/utils/openPopup.js
Normal file
139
public/assets/sweetalert2/src/utils/openPopup.js
Normal file
@@ -0,0 +1,139 @@
|
||||
import globalState from '../globalState.js'
|
||||
import { setAriaHidden } from './aria.js'
|
||||
import { swalClasses } from './classes.js'
|
||||
import * as dom from './dom/index.js'
|
||||
import { iOSfix } from './iosFix.js'
|
||||
import { replaceScrollbarWithPadding } from './scrollbar.js'
|
||||
|
||||
export const SHOW_CLASS_TIMEOUT = 10
|
||||
|
||||
/**
|
||||
* Open popup, add necessary classes and styles, fix scrollbar
|
||||
*
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export const openPopup = (params) => {
|
||||
const container = dom.getContainer()
|
||||
const popup = dom.getPopup()
|
||||
|
||||
if (!container || !popup) {
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof params.willOpen === 'function') {
|
||||
params.willOpen(popup)
|
||||
}
|
||||
globalState.eventEmitter?.emit('willOpen', popup)
|
||||
|
||||
const bodyStyles = window.getComputedStyle(document.body)
|
||||
const initialBodyOverflow = bodyStyles.overflowY
|
||||
addClasses(container, popup, params)
|
||||
|
||||
// scrolling is 'hidden' until animation is done, after that 'auto'
|
||||
setTimeout(() => {
|
||||
setScrollingVisibility(container, popup)
|
||||
}, SHOW_CLASS_TIMEOUT)
|
||||
|
||||
if (dom.isModal()) {
|
||||
// Using ternary instead of ?? operator for Webpack 4 compatibility
|
||||
fixScrollContainer(
|
||||
container,
|
||||
params.scrollbarPadding !== undefined ? params.scrollbarPadding : false,
|
||||
initialBodyOverflow
|
||||
)
|
||||
setAriaHidden()
|
||||
}
|
||||
|
||||
if (!dom.isToast() && !globalState.previousActiveElement) {
|
||||
globalState.previousActiveElement = document.activeElement
|
||||
}
|
||||
|
||||
if (typeof params.didOpen === 'function') {
|
||||
const didOpen = params.didOpen
|
||||
setTimeout(() => didOpen(popup))
|
||||
}
|
||||
globalState.eventEmitter?.emit('didOpen', popup)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Event} event
|
||||
*/
|
||||
const swalOpenAnimationFinished = (event) => {
|
||||
const popup = dom.getPopup()
|
||||
if (!popup || event.target !== popup) {
|
||||
return
|
||||
}
|
||||
const container = dom.getContainer()
|
||||
if (!container) {
|
||||
return
|
||||
}
|
||||
popup.removeEventListener('animationend', swalOpenAnimationFinished)
|
||||
popup.removeEventListener('transitionend', swalOpenAnimationFinished)
|
||||
container.style.overflowY = 'auto'
|
||||
|
||||
// no-transition is added in init() in case one swal is opened right after another
|
||||
dom.removeClass(container, swalClasses['no-transition'])
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} container
|
||||
* @param {HTMLElement} popup
|
||||
*/
|
||||
const setScrollingVisibility = (container, popup) => {
|
||||
if (dom.hasCssAnimation(popup)) {
|
||||
container.style.overflowY = 'hidden'
|
||||
popup.addEventListener('animationend', swalOpenAnimationFinished)
|
||||
popup.addEventListener('transitionend', swalOpenAnimationFinished)
|
||||
} else {
|
||||
container.style.overflowY = 'auto'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} container
|
||||
* @param {boolean} scrollbarPadding
|
||||
* @param {string} initialBodyOverflow
|
||||
*/
|
||||
const fixScrollContainer = (container, scrollbarPadding, initialBodyOverflow) => {
|
||||
iOSfix()
|
||||
|
||||
if (scrollbarPadding && initialBodyOverflow !== 'hidden') {
|
||||
replaceScrollbarWithPadding(initialBodyOverflow)
|
||||
}
|
||||
|
||||
// sweetalert2/issues/1247
|
||||
setTimeout(() => {
|
||||
container.scrollTop = 0
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} container
|
||||
* @param {HTMLElement} popup
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
const addClasses = (container, popup, params) => {
|
||||
if (params.showClass?.backdrop) {
|
||||
dom.addClass(container, params.showClass.backdrop)
|
||||
}
|
||||
if (params.animation) {
|
||||
// this workaround with opacity is needed for https://github.com/sweetalert2/sweetalert2/issues/2059
|
||||
popup.style.setProperty('opacity', '0', 'important')
|
||||
dom.show(popup, 'grid')
|
||||
setTimeout(() => {
|
||||
// Animate popup right after showing it
|
||||
if (params.showClass?.popup) {
|
||||
dom.addClass(popup, params.showClass.popup)
|
||||
}
|
||||
// and remove the opacity workaround
|
||||
popup.style.removeProperty('opacity')
|
||||
}, SHOW_CLASS_TIMEOUT) // 10ms in order to fix #2062
|
||||
} else {
|
||||
dom.show(popup, 'grid')
|
||||
}
|
||||
|
||||
dom.addClass([document.documentElement, document.body], swalClasses.shown)
|
||||
if (params.heightAuto && params.backdrop && !params.toast) {
|
||||
dom.addClass([document.documentElement, document.body], swalClasses['height-auto'])
|
||||
}
|
||||
}
|
||||
269
public/assets/sweetalert2/src/utils/params.js
Normal file
269
public/assets/sweetalert2/src/utils/params.js
Normal file
@@ -0,0 +1,269 @@
|
||||
import { warn, warnAboutDeprecation } from '../utils/utils.js'
|
||||
|
||||
export const defaultParams = {
|
||||
title: '',
|
||||
titleText: '',
|
||||
text: '',
|
||||
html: '',
|
||||
footer: '',
|
||||
icon: undefined,
|
||||
iconColor: undefined,
|
||||
iconHtml: undefined,
|
||||
template: undefined,
|
||||
toast: false,
|
||||
draggable: false,
|
||||
animation: true,
|
||||
theme: 'light',
|
||||
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: undefined,
|
||||
backdrop: true,
|
||||
heightAuto: true,
|
||||
allowOutsideClick: true,
|
||||
allowEscapeKey: true,
|
||||
allowEnterKey: true,
|
||||
stopKeydownPropagation: true,
|
||||
keydownListenerCapture: false,
|
||||
showConfirmButton: true,
|
||||
showDenyButton: false,
|
||||
showCancelButton: false,
|
||||
preConfirm: undefined,
|
||||
preDeny: undefined,
|
||||
confirmButtonText: 'OK',
|
||||
confirmButtonAriaLabel: '',
|
||||
confirmButtonColor: undefined,
|
||||
denyButtonText: 'No',
|
||||
denyButtonAriaLabel: '',
|
||||
denyButtonColor: undefined,
|
||||
cancelButtonText: 'Cancel',
|
||||
cancelButtonAriaLabel: '',
|
||||
cancelButtonColor: undefined,
|
||||
buttonsStyling: true,
|
||||
reverseButtons: false,
|
||||
focusConfirm: true,
|
||||
focusDeny: false,
|
||||
focusCancel: false,
|
||||
returnFocus: true,
|
||||
showCloseButton: false,
|
||||
closeButtonHtml: '×',
|
||||
closeButtonAriaLabel: 'Close this dialog',
|
||||
loaderHtml: '',
|
||||
showLoaderOnConfirm: false,
|
||||
showLoaderOnDeny: false,
|
||||
imageUrl: undefined,
|
||||
imageWidth: undefined,
|
||||
imageHeight: undefined,
|
||||
imageAlt: '',
|
||||
timer: undefined,
|
||||
timerProgressBar: false,
|
||||
width: undefined,
|
||||
padding: undefined,
|
||||
background: undefined,
|
||||
input: undefined,
|
||||
inputPlaceholder: '',
|
||||
inputLabel: '',
|
||||
inputValue: '',
|
||||
inputOptions: {},
|
||||
inputAutoFocus: true,
|
||||
inputAutoTrim: true,
|
||||
inputAttributes: {},
|
||||
inputValidator: undefined,
|
||||
returnInputValueOnDeny: false,
|
||||
validationMessage: undefined,
|
||||
grow: false,
|
||||
position: 'center',
|
||||
progressSteps: [],
|
||||
currentProgressStep: undefined,
|
||||
progressStepsDistance: undefined,
|
||||
willOpen: undefined,
|
||||
didOpen: undefined,
|
||||
didRender: undefined,
|
||||
willClose: undefined,
|
||||
didClose: undefined,
|
||||
didDestroy: undefined,
|
||||
scrollbarPadding: true,
|
||||
topLayer: false,
|
||||
}
|
||||
|
||||
export const updatableParams = [
|
||||
'allowEscapeKey',
|
||||
'allowOutsideClick',
|
||||
'background',
|
||||
'buttonsStyling',
|
||||
'cancelButtonAriaLabel',
|
||||
'cancelButtonColor',
|
||||
'cancelButtonText',
|
||||
'closeButtonAriaLabel',
|
||||
'closeButtonHtml',
|
||||
'color',
|
||||
'confirmButtonAriaLabel',
|
||||
'confirmButtonColor',
|
||||
'confirmButtonText',
|
||||
'currentProgressStep',
|
||||
'customClass',
|
||||
'denyButtonAriaLabel',
|
||||
'denyButtonColor',
|
||||
'denyButtonText',
|
||||
'didClose',
|
||||
'didDestroy',
|
||||
'draggable',
|
||||
'footer',
|
||||
'hideClass',
|
||||
'html',
|
||||
'icon',
|
||||
'iconColor',
|
||||
'iconHtml',
|
||||
'imageAlt',
|
||||
'imageHeight',
|
||||
'imageUrl',
|
||||
'imageWidth',
|
||||
'preConfirm',
|
||||
'preDeny',
|
||||
'progressSteps',
|
||||
'returnFocus',
|
||||
'reverseButtons',
|
||||
'showCancelButton',
|
||||
'showCloseButton',
|
||||
'showConfirmButton',
|
||||
'showDenyButton',
|
||||
'text',
|
||||
'title',
|
||||
'titleText',
|
||||
'theme',
|
||||
'willClose',
|
||||
]
|
||||
|
||||
/** @type {Record<string, string | undefined>} */
|
||||
export const deprecatedParams = {
|
||||
allowEnterKey: undefined,
|
||||
}
|
||||
|
||||
const toastIncompatibleParams = [
|
||||
'allowOutsideClick',
|
||||
'allowEnterKey',
|
||||
'backdrop',
|
||||
'draggable',
|
||||
'focusConfirm',
|
||||
'focusDeny',
|
||||
'focusCancel',
|
||||
'returnFocus',
|
||||
'heightAuto',
|
||||
'keydownListenerCapture',
|
||||
]
|
||||
|
||||
/**
|
||||
* Is valid parameter
|
||||
*
|
||||
* @param {string} paramName
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const isValidParameter = (paramName) => {
|
||||
return Object.prototype.hasOwnProperty.call(defaultParams, paramName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Is valid parameter for Swal.update() method
|
||||
*
|
||||
* @param {string} paramName
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const isUpdatableParameter = (paramName) => {
|
||||
return updatableParams.indexOf(paramName) !== -1
|
||||
}
|
||||
|
||||
/**
|
||||
* Is deprecated parameter
|
||||
*
|
||||
* @param {string} paramName
|
||||
* @returns {string | undefined}
|
||||
*/
|
||||
export const isDeprecatedParameter = (paramName) => {
|
||||
return deprecatedParams[paramName]
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} param
|
||||
*/
|
||||
const checkIfParamIsValid = (param) => {
|
||||
if (!isValidParameter(param)) {
|
||||
warn(`Unknown parameter "${param}"`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} param
|
||||
*/
|
||||
const checkIfToastParamIsValid = (param) => {
|
||||
if (toastIncompatibleParams.includes(param)) {
|
||||
warn(`The parameter "${param}" is incompatible with toasts`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} param
|
||||
*/
|
||||
const checkIfParamIsDeprecated = (param) => {
|
||||
const isDeprecated = isDeprecatedParameter(param)
|
||||
if (isDeprecated) {
|
||||
warnAboutDeprecation(param, isDeprecated)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show relevant warnings for given params
|
||||
*
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export const showWarningsForParams = (params) => {
|
||||
if (params.backdrop === false && params.allowOutsideClick) {
|
||||
warn('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`')
|
||||
}
|
||||
|
||||
if (
|
||||
params.theme &&
|
||||
![
|
||||
'light',
|
||||
'dark',
|
||||
'auto',
|
||||
'minimal',
|
||||
'borderless',
|
||||
'bootstrap-4',
|
||||
'bootstrap-4-light',
|
||||
'bootstrap-4-dark',
|
||||
'bootstrap-5',
|
||||
'bootstrap-5-light',
|
||||
'bootstrap-5-dark',
|
||||
'material-ui',
|
||||
'material-ui-light',
|
||||
'material-ui-dark',
|
||||
'embed-iframe',
|
||||
'bulma',
|
||||
'bulma-light',
|
||||
'bulma-dark',
|
||||
].includes(params.theme)
|
||||
) {
|
||||
warn(`Invalid theme "${params.theme}"`)
|
||||
}
|
||||
|
||||
for (const param in params) {
|
||||
checkIfParamIsValid(param)
|
||||
|
||||
if (params.toast) {
|
||||
checkIfToastParamIsValid(param)
|
||||
}
|
||||
|
||||
checkIfParamIsDeprecated(param)
|
||||
}
|
||||
}
|
||||
|
||||
export default defaultParams
|
||||
48
public/assets/sweetalert2/src/utils/scrollbar.js
Normal file
48
public/assets/sweetalert2/src/utils/scrollbar.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import { swalClasses } from './classes.js'
|
||||
|
||||
/**
|
||||
* Measure scrollbar width for padding body during modal show/hide
|
||||
* https://github.com/twbs/bootstrap/blob/master/js/src/modal.js
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
export const measureScrollbar = () => {
|
||||
const scrollDiv = document.createElement('div')
|
||||
scrollDiv.className = swalClasses['scrollbar-measure']
|
||||
document.body.appendChild(scrollDiv)
|
||||
const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth
|
||||
document.body.removeChild(scrollDiv)
|
||||
return scrollbarWidth
|
||||
}
|
||||
|
||||
/**
|
||||
* Remember state in cases where opening and handling a modal will fiddle with it.
|
||||
* @type {number | null}
|
||||
*/
|
||||
let previousBodyPadding = null
|
||||
|
||||
/**
|
||||
* @param {string} initialBodyOverflow
|
||||
*/
|
||||
export const replaceScrollbarWithPadding = (initialBodyOverflow) => {
|
||||
// for queues, do not do this more than once
|
||||
if (previousBodyPadding !== null) {
|
||||
return
|
||||
}
|
||||
// if the body has overflow
|
||||
if (
|
||||
document.body.scrollHeight > window.innerHeight ||
|
||||
initialBodyOverflow === 'scroll' // https://github.com/sweetalert2/sweetalert2/issues/2663
|
||||
) {
|
||||
// add padding so the content doesn't shift after removal of scrollbar
|
||||
previousBodyPadding = parseInt(window.getComputedStyle(document.body).getPropertyValue('padding-right'))
|
||||
document.body.style.paddingRight = `${previousBodyPadding + measureScrollbar()}px`
|
||||
}
|
||||
}
|
||||
|
||||
export const undoReplaceScrollbarWithPadding = () => {
|
||||
if (previousBodyPadding !== null) {
|
||||
document.body.style.paddingRight = `${previousBodyPadding}px`
|
||||
previousBodyPadding = null
|
||||
}
|
||||
}
|
||||
61
public/assets/sweetalert2/src/utils/setParameters.js
Normal file
61
public/assets/sweetalert2/src/utils/setParameters.js
Normal file
@@ -0,0 +1,61 @@
|
||||
import defaultInputValidators from './defaultInputValidators.js'
|
||||
import * as dom from './dom/index.js'
|
||||
import { warn } from './utils.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
function setDefaultInputValidators(params) {
|
||||
// Use default `inputValidator` for supported input types if not provided
|
||||
if (params.inputValidator) {
|
||||
return
|
||||
}
|
||||
if (params.input === 'email') {
|
||||
params.inputValidator = defaultInputValidators['email']
|
||||
}
|
||||
if (params.input === 'url') {
|
||||
params.inputValidator = defaultInputValidators['url']
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
function validateCustomTargetElement(params) {
|
||||
// Determine if the custom target element is valid
|
||||
if (
|
||||
!params.target ||
|
||||
(typeof params.target === 'string' && !document.querySelector(params.target)) ||
|
||||
(typeof params.target !== 'string' && !params.target.appendChild)
|
||||
) {
|
||||
warn('Target parameter is not valid, defaulting to "body"')
|
||||
params.target = 'body'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set type, text and actions on popup
|
||||
*
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export default function setParameters(params) {
|
||||
setDefaultInputValidators(params)
|
||||
|
||||
// showLoaderOnConfirm && preConfirm
|
||||
if (params.showLoaderOnConfirm && !params.preConfirm) {
|
||||
warn(
|
||||
'showLoaderOnConfirm is set to true, but preConfirm is not defined.\n' +
|
||||
'showLoaderOnConfirm should be used together with preConfirm, see usage example:\n' +
|
||||
'https://sweetalert2.github.io/#ajax-request'
|
||||
)
|
||||
}
|
||||
|
||||
validateCustomTargetElement(params)
|
||||
|
||||
// Replace newlines with <br> in title
|
||||
if (typeof params.title === 'string') {
|
||||
params.title = params.title.split('\n').join('<br />')
|
||||
}
|
||||
|
||||
dom.init(params)
|
||||
}
|
||||
88
public/assets/sweetalert2/src/utils/utils.js
Normal file
88
public/assets/sweetalert2/src/utils/utils.js
Normal file
@@ -0,0 +1,88 @@
|
||||
export const consolePrefix = 'SweetAlert2:'
|
||||
|
||||
/**
|
||||
* Capitalize the first letter of a string
|
||||
*
|
||||
* @param {string} str
|
||||
* @returns {string}
|
||||
*/
|
||||
export const capitalizeFirstLetter = (str) => str.charAt(0).toUpperCase() + str.slice(1)
|
||||
|
||||
/**
|
||||
* Standardize console warnings
|
||||
*
|
||||
* @param {string | string[]} message
|
||||
*/
|
||||
export const warn = (message) => {
|
||||
console.warn(`${consolePrefix} ${typeof message === 'object' ? message.join(' ') : message}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Standardize console errors
|
||||
*
|
||||
* @param {string} message
|
||||
*/
|
||||
export const error = (message) => {
|
||||
console.error(`${consolePrefix} ${message}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Private global state for `warnOnce`
|
||||
*
|
||||
* @type {string[]}
|
||||
* @private
|
||||
*/
|
||||
const previousWarnOnceMessages = []
|
||||
|
||||
/**
|
||||
* Show a console warning, but only if it hasn't already been shown
|
||||
*
|
||||
* @param {string} message
|
||||
*/
|
||||
export const warnOnce = (message) => {
|
||||
if (!previousWarnOnceMessages.includes(message)) {
|
||||
previousWarnOnceMessages.push(message)
|
||||
warn(message)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a one-time console warning about deprecated params/methods
|
||||
*
|
||||
* @param {string} deprecatedParam
|
||||
* @param {string?} useInstead
|
||||
*/
|
||||
export const warnAboutDeprecation = (deprecatedParam, useInstead = null) => {
|
||||
warnOnce(
|
||||
`"${deprecatedParam}" is deprecated and will be removed in the next major release.${
|
||||
useInstead ? ` Use "${useInstead}" instead.` : ''
|
||||
}`
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* If `arg` is a function, call it (with no arguments or context) and return the result.
|
||||
* Otherwise, just pass the value through
|
||||
*
|
||||
* @param {(() => *) | *} arg
|
||||
* @returns {*}
|
||||
*/
|
||||
export const callIfFunction = (arg) => (typeof arg === 'function' ? arg() : arg)
|
||||
|
||||
/**
|
||||
* @param {*} arg
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const hasToPromiseFn = (arg) => arg && typeof arg.toPromise === 'function'
|
||||
|
||||
/**
|
||||
* @param {*} arg
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export const asPromise = (arg) => (hasToPromiseFn(arg) ? arg.toPromise() : Promise.resolve(arg))
|
||||
|
||||
/**
|
||||
* @param {*} arg
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const isPromise = (arg) => arg && Promise.resolve(arg) === arg
|
||||
1315
public/assets/sweetalert2/sweetalert2.d.ts
vendored
Normal file
1315
public/assets/sweetalert2/sweetalert2.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
167
public/assets/sweetalert2/themes/bootstrap-4.css
vendored
Normal file
167
public/assets/sweetalert2/themes/bootstrap-4.css
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
[data-swal2-theme='bootstrap-4'],
|
||||
[data-swal2-theme='bootstrap-4-light'],
|
||||
[data-swal2-theme='bootstrap-4-dark'] {
|
||||
/* BACKDROP */
|
||||
--swal2-backdrop: rgba(0, 0, 0, 0.5);
|
||||
--swal2-backdrop-transition: opacity 0.15s linear;
|
||||
|
||||
/* POPUP */
|
||||
--swal2-width: 32rem;
|
||||
--swal2-padding: 1.5rem;
|
||||
--swal2-border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
--swal2-border-radius: 0.375rem;
|
||||
--swal2-background: #fff;
|
||||
--swal2-color: #212529;
|
||||
|
||||
/* ANIMATIONS */
|
||||
--swal2-show-animation: bootstrap-4-fade-in 0.15s ease-out;
|
||||
--swal2-hide-animation: bootstrap-4-fade-out 0.15s ease-in forwards;
|
||||
|
||||
/* TITLE */
|
||||
--swal2-title-padding: 0 0 0.75rem;
|
||||
|
||||
/* HTML CONTAINER */
|
||||
--swal2-html-container-padding: 0 0 1rem;
|
||||
|
||||
/* INPUT */
|
||||
--swal2-input-border: 1px solid #ced4da;
|
||||
--swal2-input-border-radius: 0.375rem;
|
||||
--swal2-input-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
--swal2-input-background: #fff;
|
||||
--swal2-input-transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||
|
||||
/* INPUT:HOVER */
|
||||
--swal2-input-hover-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
|
||||
/* INPUT:FOCUS */
|
||||
--swal2-input-focus-border: 1px solid #80bdff;
|
||||
--swal2-input-focus-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075), 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
||||
|
||||
/* PROGRESS STEPS */
|
||||
--swal2-progress-step-background: #007bff;
|
||||
|
||||
/* VALIDATION MESSAGE */
|
||||
--swal2-validation-message-background: #f8d7da;
|
||||
--swal2-validation-message-color: #721c24;
|
||||
|
||||
/* FOOTER */
|
||||
--swal2-footer-border-color: #dee2e6;
|
||||
--swal2-footer-background: #f8f9fa;
|
||||
--swal2-footer-color: #6c757d;
|
||||
|
||||
/* CLOSE BUTTON */
|
||||
--swal2-close-button-color: #6c757d;
|
||||
--swal2-close-button-transition: color 0.15s ease-in-out, opacity 0.15s ease-in-out;
|
||||
|
||||
/* ACTIONS */
|
||||
--swal2-actions-justify-content: flex-end;
|
||||
--swal2-actions-margin: 1rem -0.25rem 0;
|
||||
--swal2-actions-padding: 0;
|
||||
|
||||
/* COMMON VARIABLES FOR ALL ACTION BUTTONS */
|
||||
--swal2-action-button-transition:
|
||||
color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out,
|
||||
box-shadow 0.15s ease-in-out;
|
||||
--swal2-action-button-hover: rgba(0, 0, 0, 0.075);
|
||||
--swal2-action-button-active: rgba(0, 0, 0, 0.125);
|
||||
--swal2-action-button-focus-box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);
|
||||
|
||||
/* CONFIRM BUTTON */
|
||||
--swal2-confirm-button-border-radius: 0.375rem;
|
||||
--swal2-confirm-button-background-color: #007bff;
|
||||
--swal2-confirm-button-color: #fff;
|
||||
--swal2-confirm-button-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
|
||||
/* DENY BUTTON */
|
||||
--swal2-deny-button-border-radius: 0.375rem;
|
||||
--swal2-deny-button-background-color: #dc3545;
|
||||
--swal2-deny-button-color: #fff;
|
||||
--swal2-deny-button-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
|
||||
/* CANCEL BUTTON */
|
||||
--swal2-cancel-button-border-radius: 0.375rem;
|
||||
--swal2-cancel-button-background-color: #6c757d;
|
||||
--swal2-cancel-button-color: #fff;
|
||||
--swal2-cancel-button-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
|
||||
/* TOASTS */
|
||||
--swal2-toast-border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
--swal2-toast-box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
[data-swal2-theme='bootstrap-4'] {
|
||||
/* POPUP */
|
||||
--swal2-background: #343a40;
|
||||
--swal2-color: #f8f9fa;
|
||||
--swal2-border: 1px solid #495057;
|
||||
|
||||
/* INPUT */
|
||||
--swal2-input-background: #495057;
|
||||
--swal2-input-border: 1px solid #6c757d;
|
||||
--swal2-input-focus-border: 1px solid #80bdff;
|
||||
--swal2-input-focus-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075), 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
||||
|
||||
/* VALIDATION MESSAGE */
|
||||
--swal2-validation-message-background: #721c24;
|
||||
--swal2-validation-message-color: #f5c6cb;
|
||||
|
||||
/* FOOTER */
|
||||
--swal2-footer-border-color: #495057;
|
||||
--swal2-footer-background: #495057;
|
||||
--swal2-footer-color: #adb5bd;
|
||||
|
||||
/* CLOSE BUTTON */
|
||||
--swal2-close-button-color: #adb5bd;
|
||||
}
|
||||
}
|
||||
|
||||
[data-swal2-theme='bootstrap-4-dark'] {
|
||||
/* POPUP */
|
||||
--swal2-background: #343a40;
|
||||
--swal2-color: #f8f9fa;
|
||||
--swal2-border: 1px solid #495057;
|
||||
|
||||
/* INPUT */
|
||||
--swal2-input-background: #495057;
|
||||
--swal2-input-border: 1px solid #6c757d;
|
||||
--swal2-input-focus-border: 1px solid #80bdff;
|
||||
--swal2-input-focus-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075), 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
||||
|
||||
/* VALIDATION MESSAGE */
|
||||
--swal2-validation-message-background: #721c24;
|
||||
--swal2-validation-message-color: #f5c6cb;
|
||||
|
||||
/* FOOTER */
|
||||
--swal2-footer-border-color: #495057;
|
||||
--swal2-footer-background: #495057;
|
||||
--swal2-footer-color: #adb5bd;
|
||||
|
||||
/* CLOSE BUTTON */
|
||||
--swal2-close-button-color: #adb5bd;
|
||||
}
|
||||
|
||||
/* Bootstrap 4 Modal Animations */
|
||||
@keyframes bootstrap-4-fade-in {
|
||||
0% {
|
||||
transform: translate3d(0, -50px, 0) scale(0.9);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate3d(0, 0, 0) scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bootstrap-4-fade-out {
|
||||
0% {
|
||||
transform: translate3d(0, 0, 0) scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate3d(0, -50px, 0) scale(0.9);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
173
public/assets/sweetalert2/themes/bootstrap-5.css
vendored
Normal file
173
public/assets/sweetalert2/themes/bootstrap-5.css
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
[data-swal2-theme='bootstrap-5'],
|
||||
[data-swal2-theme='bootstrap-5-light'],
|
||||
[data-swal2-theme='bootstrap-5-dark'] {
|
||||
/* BACKDROP */
|
||||
--swal2-backdrop: rgba(0, 0, 0, 0.5);
|
||||
--swal2-backdrop-transition: opacity 0.15s linear;
|
||||
|
||||
/* POPUP */
|
||||
--swal2-width: 32rem;
|
||||
--swal2-padding: 1.5rem;
|
||||
--swal2-border: 1px solid var(--bs-border-color, rgba(0, 0, 0, 0.175));
|
||||
--swal2-border-radius: 0.5rem;
|
||||
--swal2-background: #fff;
|
||||
--swal2-color: #212529;
|
||||
|
||||
/* ANIMATIONS */
|
||||
--swal2-show-animation: bootstrap-5-fade-in 0.15s ease-out;
|
||||
--swal2-hide-animation: bootstrap-5-fade-out 0.15s ease-in forwards;
|
||||
|
||||
/* TITLE */
|
||||
--swal2-title-padding: 0 0 1rem;
|
||||
|
||||
/* HTML CONTAINER */
|
||||
--swal2-html-container-padding: 0 0 1rem;
|
||||
|
||||
/* INPUT */
|
||||
--swal2-input-border: 1px solid #dee2e6;
|
||||
--swal2-input-border-radius: 0.375rem;
|
||||
--swal2-input-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
--swal2-input-background: #fff;
|
||||
--swal2-input-transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||
|
||||
/* INPUT:HOVER */
|
||||
--swal2-input-hover-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
|
||||
/* INPUT:FOCUS */
|
||||
--swal2-input-focus-border: 1px solid #86b7fe;
|
||||
--swal2-input-focus-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075), 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
||||
|
||||
/* PROGRESS STEPS */
|
||||
--swal2-progress-step-background: #0d6efd;
|
||||
|
||||
/* VALIDATION MESSAGE */
|
||||
--swal2-validation-message-background: #f8d7da;
|
||||
--swal2-validation-message-color: #842029;
|
||||
|
||||
/* FOOTER */
|
||||
--swal2-footer-border-color: #dee2e6;
|
||||
--swal2-footer-background: #f8f9fa;
|
||||
--swal2-footer-color: #6c757d;
|
||||
|
||||
/* CLOSE BUTTON */
|
||||
--swal2-close-button-color: #000;
|
||||
--swal2-close-button-transition: color 0.15s ease-in-out, opacity 0.15s ease-in-out;
|
||||
|
||||
/* ACTIONS */
|
||||
--swal2-actions-justify-content: flex-end;
|
||||
--swal2-actions-margin: 1rem -0.25rem 0;
|
||||
--swal2-actions-padding: 0;
|
||||
|
||||
/* COMMON VARIABLES FOR ALL ACTION BUTTONS */
|
||||
--swal2-action-button-transition:
|
||||
color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out,
|
||||
box-shadow 0.15s ease-in-out;
|
||||
--swal2-action-button-hover: rgba(0, 0, 0, 0.075);
|
||||
--swal2-action-button-active: rgba(0, 0, 0, 0.125);
|
||||
--swal2-action-button-focus-box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
||||
|
||||
/* CONFIRM BUTTON */
|
||||
--swal2-confirm-button-border-radius: 0.375rem;
|
||||
--swal2-confirm-button-background-color: #0d6efd;
|
||||
--swal2-confirm-button-color: #fff;
|
||||
--swal2-confirm-button-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
|
||||
/* DENY BUTTON */
|
||||
--swal2-deny-button-border-radius: 0.375rem;
|
||||
--swal2-deny-button-background-color: #dc3545;
|
||||
--swal2-deny-button-color: #fff;
|
||||
--swal2-deny-button-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
|
||||
/* CANCEL BUTTON */
|
||||
--swal2-cancel-button-border-radius: 0.375rem;
|
||||
--swal2-cancel-button-background-color: #6c757d;
|
||||
--swal2-cancel-button-color: #fff;
|
||||
--swal2-cancel-button-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
|
||||
/* TOASTS */
|
||||
--swal2-toast-border: 1px solid rgba(0, 0, 0, 0.175);
|
||||
--swal2-toast-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
[data-swal2-theme='bootstrap-5'] {
|
||||
/* POPUP */
|
||||
--swal2-background: #212529;
|
||||
--swal2-color: #fff;
|
||||
--swal2-border: 1px solid #495057;
|
||||
|
||||
/* INPUT */
|
||||
--swal2-input-background: #2b3035;
|
||||
--swal2-input-border: 1px solid #495057;
|
||||
--swal2-input-focus-border: 1px solid #86b7fe;
|
||||
--swal2-input-focus-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075), 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
||||
|
||||
/* VALIDATION MESSAGE */
|
||||
--swal2-validation-message-background: #2c0b0e;
|
||||
--swal2-validation-message-color: #ea868f;
|
||||
|
||||
/* FOOTER */
|
||||
--swal2-footer-border-color: #495057;
|
||||
--swal2-footer-background: #343a40;
|
||||
--swal2-footer-color: #adb5bd;
|
||||
|
||||
/* CLOSE BUTTON */
|
||||
--swal2-close-button-color: #fff;
|
||||
|
||||
/* TOASTS */
|
||||
--swal2-toast-border: 1px solid #495057;
|
||||
}
|
||||
}
|
||||
|
||||
[data-swal2-theme='bootstrap-5-dark'] {
|
||||
/* POPUP */
|
||||
--swal2-background: #212529;
|
||||
--swal2-color: #fff;
|
||||
--swal2-border: 1px solid #495057;
|
||||
|
||||
/* INPUT */
|
||||
--swal2-input-background: #2b3035;
|
||||
--swal2-input-border: 1px solid #495057;
|
||||
--swal2-input-focus-border: 1px solid #86b7fe;
|
||||
--swal2-input-focus-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075), 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
||||
|
||||
/* VALIDATION MESSAGE */
|
||||
--swal2-validation-message-background: #2c0b0e;
|
||||
--swal2-validation-message-color: #ea868f;
|
||||
|
||||
/* FOOTER */
|
||||
--swal2-footer-border-color: #495057;
|
||||
--swal2-footer-background: #343a40;
|
||||
--swal2-footer-color: #adb5bd;
|
||||
|
||||
/* CLOSE BUTTON */
|
||||
--swal2-close-button-color: #fff;
|
||||
|
||||
/* TOASTS */
|
||||
--swal2-toast-border: 1px solid #495057;
|
||||
}
|
||||
|
||||
/* Bootstrap 5 Modal Animations */
|
||||
@keyframes bootstrap-5-fade-in {
|
||||
0% {
|
||||
transform: translate3d(0, -50px, 0) scale(0.9);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate3d(0, 0, 0) scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bootstrap-5-fade-out {
|
||||
0% {
|
||||
transform: translate3d(0, 0, 0) scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate3d(0, -50px, 0) scale(0.9);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
46
public/assets/sweetalert2/themes/borderless.css
Normal file
46
public/assets/sweetalert2/themes/borderless.css
Normal file
@@ -0,0 +1,46 @@
|
||||
[data-swal2-theme='borderless'] {
|
||||
/* BACKDROP */
|
||||
--swal2-backdrop: rgba(54, 70, 93, 0.99);
|
||||
|
||||
/* POPUP */
|
||||
--swal2-background: transparent;
|
||||
--swal2-color: white;
|
||||
|
||||
/* ANIMATIONS */
|
||||
--swal2-show-animation: opacity-show 0.3s;
|
||||
--swal2-hide-animation: opacity-hide 0.1s;
|
||||
|
||||
/* PROGRESS STEPS */
|
||||
--swal2-progress-step-background: color-mix(in srgb, var(--swal2-backdrop), white 30%);
|
||||
|
||||
/* VALIDATION MESSAGE */
|
||||
--swal2-validation-message-background: transparent;
|
||||
--swal2-validation-message-color: white;
|
||||
|
||||
/* FOOTER */
|
||||
--swal2-footer-border-color: rgba(255, 255, 255, 0.2);
|
||||
|
||||
/* CLOSE BUTTON */
|
||||
--swal2-close-button-position: fixed;
|
||||
--swal2-close-button-inset: 0;
|
||||
--swal2-close-button-font-size: 3em;
|
||||
--swal2-close-button-color: white;
|
||||
}
|
||||
|
||||
/* Appearance animation */
|
||||
@keyframes opacity-show {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disppearance animation */
|
||||
@keyframes opacity-hide {
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
94
public/assets/sweetalert2/themes/bulma.css
vendored
Normal file
94
public/assets/sweetalert2/themes/bulma.css
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
[data-swal2-theme='bulma'],
|
||||
[data-swal2-theme='bulma-light'],
|
||||
[data-swal2-theme='bulma-dark'] {
|
||||
/* BACKDROP */
|
||||
--swal2-backdrop: hsla(221deg, 14%, 4%, 0.86);
|
||||
|
||||
/* POPUP */
|
||||
--swal2-border-radius: 0.75rem;
|
||||
--swal2-padding: 1.25rem 0 0;
|
||||
|
||||
/* INPUT */
|
||||
--swal2-input-border: none;
|
||||
--swal2-input-box-shadow: 0 0 0 1px #d7d9e1 inset, 0 0 0 3px transparent;
|
||||
|
||||
/* INPUT:HOVER */
|
||||
--swal2-input-hover-box-shadow: 0 0 0 1px #b9beca inset, 0 0 0 3px transparent;
|
||||
|
||||
/* INPUT:FOCUS */
|
||||
--swal2-input-focus-border: none;
|
||||
--swal2-input-focus-box-shadow: 0 0 0 1px #4259ff inset, 0 0 0 3px hsla(233deg, 100%, 58%, 0.25);
|
||||
|
||||
/* CLOSE BUTTON */
|
||||
--swal2-close-button-position: fixed;
|
||||
--swal2-close-button-inset: 1em;
|
||||
--swal2-close-button-font-size: 1.6em;
|
||||
--swal2-close-button-color: white;
|
||||
|
||||
/* ACTIONS */
|
||||
--swal2-actions-justify-content: flex-start;
|
||||
--swal2-actions-width: 100%;
|
||||
--swal2-actions-padding: 2rem;
|
||||
--swal2-actions-border-radius: 0 0 0.75rem 0.75rem;
|
||||
--swal2-actions-background: #f9fafa;
|
||||
|
||||
/* COMMON VARIABLES FOR ALL ACTION BUTTONS */
|
||||
--swal2-action-button-hover: black 5%;
|
||||
--swal2-action-button-active: black 10%;
|
||||
--swal2-action-button-focus-box-shadow: 0 0 0 1px #4259ff inset, 0 0 0 3px hsla(233deg, 100%, 58%, 0.25);
|
||||
|
||||
/* CONFIRM BUTTON */
|
||||
--swal2-confirm-button-background-color: #47c78e;
|
||||
--swal2-confirm-button-color: #190005;
|
||||
|
||||
/* DENY BUTTON */
|
||||
--swal2-deny-button-background-color: #ff6684;
|
||||
--swal2-deny-button-color: #190005;
|
||||
|
||||
/* CANCEL BUTTON */
|
||||
--swal2-cancel-button-background-color: #fff;
|
||||
--swal2-cancel-button-color: #190005;
|
||||
--swal2-cancel-button-box-shadow: 0 0 0 1px #d7d9e1 inset;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
[data-swal2-theme='bulma'] {
|
||||
/* POPUP */
|
||||
--swal2-background: #14161a;
|
||||
--swal2-color: #ebecef;
|
||||
|
||||
/* INPUT */
|
||||
--swal2-input-box-shadow: 0 0 0 1px #353a46 inset, 0 0 0 3px transparent;
|
||||
|
||||
/* INPUT:HOVER */
|
||||
--swal2-input-hover-box-shadow: 0 0 0 1px #4b5262 inset, 0 0 0 3px transparent;
|
||||
|
||||
/* ACTIONS */
|
||||
--swal2-actions-background: #191b20;
|
||||
|
||||
/* CANCEL BUTTON */
|
||||
--swal2-cancel-button-background-color: #14161a;
|
||||
--swal2-cancel-button-color: #ebecef;
|
||||
--swal2-cancel-button-box-shadow: 0 0 0 1px #353a46 inset;
|
||||
}
|
||||
}
|
||||
|
||||
[data-swal2-theme='bulma-dark'] {
|
||||
/* POPUP */
|
||||
--swal2-background: #14161a;
|
||||
--swal2-color: #ebecef;
|
||||
|
||||
/* INPUT */
|
||||
--swal2-input-box-shadow: 0 0 0 1px #353a46 inset, 0 0 0 3px transparent;
|
||||
|
||||
/* INPUT:HOVER */
|
||||
--swal2-input-hover-box-shadow: 0 0 0 1px #4b5262 inset, 0 0 0 3px transparent;
|
||||
|
||||
/* ACTIONS */
|
||||
--swal2-actions-background: #191b20;
|
||||
|
||||
/* CANCEL BUTTON */
|
||||
--swal2-cancel-button-background-color: #14161a;
|
||||
--swal2-cancel-button-color: #ebecef;
|
||||
--swal2-cancel-button-box-shadow: 0 0 0 1px #353a46 inset;
|
||||
}
|
||||
29
public/assets/sweetalert2/themes/embed-iframe.css
Normal file
29
public/assets/sweetalert2/themes/embed-iframe.css
Normal file
@@ -0,0 +1,29 @@
|
||||
[data-swal2-theme='embed-iframe'] {
|
||||
/* POPUP */
|
||||
--swal2-padding: 0;
|
||||
--swal2-backdrop: rgba(54, 70, 93, 0.99);
|
||||
--swal2-border-radius: 0;
|
||||
|
||||
/* CLOSE BUTTON */
|
||||
--swal2-close-button-position: fixed;
|
||||
--swal2-close-button-inset: 0;
|
||||
--swal2-close-button-font-size: 3em;
|
||||
--swal2-close-button-color: white;
|
||||
--swal2-close-button-transition: transform 0.3s ease-out;
|
||||
--swal2-close-button-focus-box-shadow: none;
|
||||
|
||||
/* CLOSE BUTTON:HOVER */
|
||||
--swal2-close-button-hover-transform: rotate(90deg);
|
||||
|
||||
/* TITLE */
|
||||
--swal2-title-padding: 0.5em 1em;
|
||||
|
||||
/* HTML CONTAINER */
|
||||
--swal2-html-container-padding: 0;
|
||||
|
||||
iframe {
|
||||
aspect-ratio: 16 / 9;
|
||||
width: 100%;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
183
public/assets/sweetalert2/themes/material-ui.css
Normal file
183
public/assets/sweetalert2/themes/material-ui.css
Normal file
@@ -0,0 +1,183 @@
|
||||
[data-swal2-theme='material-ui'],
|
||||
[data-swal2-theme='material-ui-light'],
|
||||
[data-swal2-theme='material-ui-dark'] {
|
||||
/* BACKDROP */
|
||||
--swal2-backdrop: rgba(0, 0, 0, 0.5);
|
||||
--swal2-backdrop-transition: opacity 0.225s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
/* POPUP */
|
||||
--swal2-width: 35rem;
|
||||
--swal2-padding: 1.5rem;
|
||||
--swal2-border: none;
|
||||
--swal2-border-radius: 0.5rem;
|
||||
--swal2-background: #fff;
|
||||
--swal2-color: rgba(0, 0, 0, 0.87);
|
||||
|
||||
/* ANIMATIONS */
|
||||
--swal2-show-animation: material-ui-fade-in 0.225s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--swal2-hide-animation: material-ui-fade-out 0.195s cubic-bezier(0.4, 0, 1, 1) forwards;
|
||||
|
||||
/* TITLE */
|
||||
--swal2-title-padding: 0 0 1rem;
|
||||
|
||||
/* HTML CONTAINER */
|
||||
--swal2-html-container-padding: 0 0 1.5rem;
|
||||
|
||||
/* INPUT */
|
||||
--swal2-input-border: none;
|
||||
--swal2-input-border-radius: 0.25rem;
|
||||
--swal2-input-box-shadow: none;
|
||||
--swal2-input-background: rgba(0, 0, 0, 0.04);
|
||||
--swal2-input-transition:
|
||||
background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.15s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
/* INPUT:HOVER */
|
||||
--swal2-input-hover-box-shadow: none;
|
||||
|
||||
/* INPUT:FOCUS */
|
||||
--swal2-input-focus-border: none;
|
||||
--swal2-input-focus-box-shadow: inset 0 -2px 0 #1976d2;
|
||||
|
||||
/* PROGRESS STEPS */
|
||||
--swal2-progress-step-background: #1976d2;
|
||||
|
||||
/* VALIDATION MESSAGE */
|
||||
--swal2-validation-message-background: #ffebee;
|
||||
--swal2-validation-message-color: #c62828;
|
||||
|
||||
/* FOOTER */
|
||||
--swal2-footer-border-color: rgba(0, 0, 0, 0.12);
|
||||
--swal2-footer-background: transparent;
|
||||
--swal2-footer-color: rgba(0, 0, 0, 0.6);
|
||||
|
||||
/* CLOSE BUTTON */
|
||||
--swal2-close-button-color: rgba(0, 0, 0, 0.54);
|
||||
--swal2-close-button-transition:
|
||||
color 0.15s cubic-bezier(0.4, 0, 0.2, 1), transform 0.15s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
/* ACTIONS */
|
||||
--swal2-actions-justify-content: flex-end;
|
||||
--swal2-actions-margin: 0.5rem -0.5rem 0;
|
||||
--swal2-actions-padding: 0;
|
||||
|
||||
/* COMMON VARIABLES FOR ALL ACTION BUTTONS */
|
||||
--swal2-action-button-transition:
|
||||
background-color 0.25s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.25s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
border-color 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--swal2-action-button-hover: rgba(0, 0, 0, 0.04);
|
||||
--swal2-action-button-active: rgba(0, 0, 0, 0.12);
|
||||
--swal2-action-button-focus-box-shadow: none;
|
||||
|
||||
/* CONFIRM BUTTON */
|
||||
--swal2-confirm-button-border-radius: 0.25rem;
|
||||
--swal2-confirm-button-background-color: #1976d2;
|
||||
--swal2-confirm-button-color: #fff;
|
||||
--swal2-confirm-button-box-shadow:
|
||||
0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);
|
||||
|
||||
/* DENY BUTTON */
|
||||
--swal2-deny-button-border-radius: 0.25rem;
|
||||
--swal2-deny-button-background-color: #d32f2f;
|
||||
--swal2-deny-button-color: #fff;
|
||||
--swal2-deny-button-box-shadow:
|
||||
0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12);
|
||||
|
||||
/* CANCEL BUTTON */
|
||||
--swal2-cancel-button-border-radius: 0.25rem;
|
||||
--swal2-cancel-button-background-color: transparent;
|
||||
--swal2-cancel-button-color: #1976d2;
|
||||
--swal2-cancel-button-box-shadow: none;
|
||||
|
||||
/* TOASTS */
|
||||
--swal2-toast-border: none;
|
||||
--swal2-toast-box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
[data-swal2-theme='material-ui'] {
|
||||
/* POPUP */
|
||||
--swal2-background: #424242;
|
||||
--swal2-color: rgba(255, 255, 255, 0.87);
|
||||
|
||||
/* INPUT */
|
||||
--swal2-input-background: rgba(255, 255, 255, 0.09);
|
||||
--swal2-input-focus-box-shadow: inset 0 -2px 0 #90caf9;
|
||||
|
||||
/* VALIDATION MESSAGE */
|
||||
--swal2-validation-message-background: #ffcdd2;
|
||||
--swal2-validation-message-color: #d32f2f;
|
||||
|
||||
/* FOOTER */
|
||||
--swal2-footer-border-color: rgba(255, 255, 255, 0.12);
|
||||
--swal2-footer-color: rgba(255, 255, 255, 0.6);
|
||||
|
||||
/* CLOSE BUTTON */
|
||||
--swal2-close-button-color: rgba(255, 255, 255, 0.7);
|
||||
|
||||
/* COMMON VARIABLES FOR ALL ACTION BUTTONS */
|
||||
--swal2-action-button-hover: rgba(255, 255, 255, 0.08);
|
||||
--swal2-action-button-active: rgba(255, 255, 255, 0.16);
|
||||
|
||||
/* CONFIRM BUTTON */
|
||||
--swal2-confirm-button-background-color: #1e88e5;
|
||||
|
||||
/* CANCEL BUTTON */
|
||||
--swal2-cancel-button-color: #90caf9;
|
||||
}
|
||||
}
|
||||
|
||||
[data-swal2-theme='material-ui-dark'] {
|
||||
/* POPUP */
|
||||
--swal2-background: #424242;
|
||||
--swal2-color: rgba(255, 255, 255, 0.87);
|
||||
|
||||
/* INPUT */
|
||||
--swal2-input-background: rgba(255, 255, 255, 0.09);
|
||||
--swal2-input-focus-box-shadow: inset 0 -2px 0 #90caf9;
|
||||
|
||||
/* VALIDATION MESSAGE */
|
||||
--swal2-validation-message-background: #ffcdd2;
|
||||
--swal2-validation-message-color: #d32f2f;
|
||||
|
||||
/* FOOTER */
|
||||
--swal2-footer-border-color: rgba(255, 255, 255, 0.12);
|
||||
--swal2-footer-color: rgba(255, 255, 255, 0.6);
|
||||
|
||||
/* CLOSE BUTTON */
|
||||
--swal2-close-button-color: rgba(255, 255, 255, 0.7);
|
||||
|
||||
/* COMMON VARIABLES FOR ALL ACTION BUTTONS */
|
||||
--swal2-action-button-hover: rgba(255, 255, 255, 0.08);
|
||||
--swal2-action-button-active: rgba(255, 255, 255, 0.16);
|
||||
|
||||
/* CONFIRM BUTTON */
|
||||
--swal2-confirm-button-background-color: #1e88e5;
|
||||
|
||||
/* CANCEL BUTTON */
|
||||
--swal2-cancel-button-color: #90caf9;
|
||||
}
|
||||
|
||||
/* MaterialUI Modal Animations */
|
||||
@keyframes material-ui-fade-in {
|
||||
0% {
|
||||
transform: scale(0.8) translateY(-16px);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1) translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes material-ui-fade-out {
|
||||
0% {
|
||||
transform: scale(1) translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.8) translateY(-16px);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
40
public/assets/sweetalert2/themes/minimal.css
Normal file
40
public/assets/sweetalert2/themes/minimal.css
Normal file
@@ -0,0 +1,40 @@
|
||||
[data-swal2-theme='minimal'] {
|
||||
/* BACKDROP */
|
||||
--swal2-backdrop-transition: none;
|
||||
|
||||
/* POPUP */
|
||||
--swal2-border-radius: 0;
|
||||
|
||||
/* ANIMATIONS */
|
||||
--swal2-show-animation: none;
|
||||
--swal2-hide-animation: none;
|
||||
|
||||
/* ICONS */
|
||||
--swal2-icon-animations: false;
|
||||
|
||||
/* INPUT */
|
||||
--swal2-input-border-radius: 0;
|
||||
--swal2-input-box-shadow: none;
|
||||
--swal2-input-transition: none;
|
||||
|
||||
/* CLOSE BUTTON */
|
||||
--swal2-close-button-transition: none;
|
||||
|
||||
/* COMMON VARIABLES FOR ALL ACTION BUTTONS */
|
||||
--swal2-action-button-transition: none;
|
||||
|
||||
/* CONFIRM BUTTON */
|
||||
--swal2-confirm-button-border-radius: 0;
|
||||
|
||||
/* DENY BUTTON */
|
||||
--swal2-deny-button-border-radius: 0;
|
||||
|
||||
/* CANCEL BUTTON */
|
||||
--swal2-cancel-button-border-radius: 0;
|
||||
|
||||
/* TOASTS */
|
||||
--swal2-toast-show-animation: none;
|
||||
--swal2-toast-hide-animation: none;
|
||||
--swal2-toast-border: 1px solid rgba(0, 0, 0, 0.3);
|
||||
--swal2-toast-box-shadow: none;
|
||||
}
|
||||
Reference in New Issue
Block a user