prvi
This commit is contained in:
22
ZpcBulletinBoard/wwwroot/lib/sweetalert2/LICENSE
Normal file
22
ZpcBulletinBoard/wwwroot/lib/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.
|
||||
|
||||
133
ZpcBulletinBoard/wwwroot/lib/sweetalert2/README.md
Normal file
133
ZpcBulletinBoard/wwwroot/lib/sweetalert2/README.md
Normal file
@@ -0,0 +1,133 @@
|
||||
<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/) | [Themes](https://github.com/sweetalert2/sweetalert2-themes) | [React](https://github.com/sweetalert2/sweetalert2-react-content) | [Angular](https://github.com/sweetalert2/ngx-sweetalert2)
|
||||
|
||||
---
|
||||
|
||||
:moneybag: [Get $200 in free credits with DigitalOcean!](https://m.do.co/c/12907f2ba0bf)
|
||||
|
||||
---
|
||||
|
||||
> [!IMPORTANT]
|
||||
> As a consequence of the illegal war in Ukraine, the behavior of this repository and related npm package [sweetalert2](https://www.npmjs.com/package/sweetalert2) is different for `.ru`, `.su`, `.by`, and `.рф` domain zones.
|
||||
>
|
||||
> Including this software in any domain in `.ru`, `.su`, `.by`, and `.рф` domain zones will block the website navigation and play the national anthem of Ukraine.
|
||||
>
|
||||
> This behavior is classified as [protestware](https://snyk.io/blog/protestware-open-source-types-impact/) and this project is listed in [GitHub Advisory Database](https://github.com/advisories/GHSA-mrr8-v49w-3333) and [Snyk Vulnerability DB](https://security.snyk.io/package/npm/sweetalert2/11.5.2).
|
||||
|
||||
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://insadown.com/"><img src="https://sweetalert2.github.io/images/sponsors/insadown.png" width="80"><br>InsaDown</a></td>
|
||||
<td align="center"><a href="https://dlxplugins.com/"><img src="https://avatars.githubusercontent.com/u/106675919?s=200&v=4" width="80"><br>DLX Plugins</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://refermate.com/"><img src="https://sweetalert2.github.io/images/sponsors/refermate.png" width="80"><br>Refermate</a>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://roboflow.com/"><img src="https://sweetalert2.github.io/images/sponsors/roboflow.png" width="80"><br>Roboflow</a>
|
||||
<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 align="center"><a href="https://www.serpempire.com/"><img src="https://sweetalert2.github.io/images/sponsors/serpempire.png" width="80"><br>SERP Empire</a>
|
||||
<td align="center"><a href="https://www.realspyapps.com/"><img src="https://sweetalert2.github.io/images/sponsors/realspyapps.jpeg" width="80"><br>Real Spy Apps</a>
|
||||
<td align="center"><a href="https://celltrackingapps.com/"><img src="https://sweetalert2.github.io/images/sponsors/celltrackingapps.png" width="80"><br>Phone Tracking Apps</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://www.mybitcoinslots.com/"><img src="https://sweetalert2.github.io/images/sponsors/mybitcoinslots.png" width="80"><br>My Bitcoin slots</a></td>
|
||||
<td align="center"><a href="https://www.vegega.com/"><img src="https://sweetalert2.github.io/images/sponsors/vegega.jpeg" width="80"><br>Metal Raised Garden Bed</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://nexromance.com/playstore/index.php?sweetalert"><img src="https://sweetalert2.github.io/images/sponsors/chatforsex.jpg" width="80"><br>ChatGPT for Sex</a></td>
|
||||
<td align="center"><a href="https://pinktoys.co.uk/pocket-pussy/"><img src="https://sweetalert2.github.io/images/sponsors/pinktoys.png" width="80"><br>Pocket pussy</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 - Top Male <br> Masturbator Brand</a></td>
|
||||
<td align="center"><a href="https://vlixa.com/"><img src="https://sweetalert2.github.io/images/sponsors/vlixa.png" width="80"><br>Vlixa</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://taboodude.com/"><img src="https://sweetalert2.github.io/images/sponsors/taboodude.png" width="80"><br>TabooDude</a></td>
|
||||
<td align="center"><a href="https://sexsitoys.com/lovense-games/"><img src="https://sweetalert2.github.io/images/sponsors/sexsitoys.jpg" width="80"><br>Sexsi Toys</a></td>
|
||||
<td align="center"><a href="https://www.cheapestsexdolls.com"><img src="https://sweetalert2.github.io/images/sponsors/cheapestsexdolls.png" width="80"><br>CheapestSexDolls</a></td>
|
||||
<td align="center"><a href="https://www.bestblowjobmachines.com/"><img src="https://sweetalert2.github.io/images/sponsors/best-blowjob-machines.jpg" width="80"><br>Best Blowjob Machines</a></td>
|
||||
<td align="center"><a href="https://escortsear.ch/"><img src="https://sweetalert2.github.io/images/sponsors/escortsearch.jpg" width="80"><br>EscortSearch</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>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://readysetcam.com/"><img src="https://sweetalert2.github.io/images/sponsors/readysetcam.png" width="80"><br>Ready Set Cam</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>
|
||||
<td align="center"><a href="https://blowupdollshop.com/inflatable-sex-doll/"><img src="https://sweetalert2.github.io/images/sponsors/blowupdollshop.png" width="80"><br>Inflatable sex doll</a></td>
|
||||
<td align="center"><a href="https://sexdollsmarket.com/"><img src="https://sweetalert2.github.io/images/sponsors/sexdollsmarket.png" width="80"><br>Sex Doll Torso</a></td>
|
||||
<td align="center"><a href="https://sexydollies.com/"><img src="https://sweetalert2.github.io/images/sponsors/sexydollies.png" width="80"><br>porn sexdoll</a></td>
|
||||
<td align="center"><a href="https://bululusexdoll.com/"><img src="https://sweetalert2.github.io/images/sponsors/bululusexdoll.png" width="80"><br>cheap sex doll</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://bululu.shop/"><img src="https://sweetalert2.github.io/images/sponsors/bululu.png" width="80"><br>BULULU</a></td>
|
||||
<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.xndoll.com/"><img src="https://sweetalert2.github.io/images/sponsors/xndoll.jpeg" width="80"><br>XNDOLL</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>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<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>
|
||||
<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>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<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>
|
||||
<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>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<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>
|
||||
<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>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://www.mysextoyguide.com/"><img src="https://sweetalert2.github.io/images/sponsors/my-sex-toy-guide.jpg" width="80"><br>My Sex Toy Guide</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>
|
||||
|
||||
Support and Donations
|
||||
---------------------
|
||||
|
||||
Has SweetAlert2 helped you create a fantastic application? You can show your support via [GitHub Sponsors](https://github.com/sponsors/limonte)
|
||||
4634
ZpcBulletinBoard/wwwroot/lib/sweetalert2/dist/sweetalert2.all.js
vendored
Normal file
4634
ZpcBulletinBoard/wwwroot/lib/sweetalert2/dist/sweetalert2.all.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
ZpcBulletinBoard/wwwroot/lib/sweetalert2/dist/sweetalert2.all.min.js
vendored
Normal file
6
ZpcBulletinBoard/wwwroot/lib/sweetalert2/dist/sweetalert2.all.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1085
ZpcBulletinBoard/wwwroot/lib/sweetalert2/dist/sweetalert2.css
vendored
Normal file
1085
ZpcBulletinBoard/wwwroot/lib/sweetalert2/dist/sweetalert2.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4633
ZpcBulletinBoard/wwwroot/lib/sweetalert2/dist/sweetalert2.js
vendored
Normal file
4633
ZpcBulletinBoard/wwwroot/lib/sweetalert2/dist/sweetalert2.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
ZpcBulletinBoard/wwwroot/lib/sweetalert2/dist/sweetalert2.min.css
vendored
Normal file
1
ZpcBulletinBoard/wwwroot/lib/sweetalert2/dist/sweetalert2.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
5
ZpcBulletinBoard/wwwroot/lib/sweetalert2/dist/sweetalert2.min.js
vendored
Normal file
5
ZpcBulletinBoard/wwwroot/lib/sweetalert2/dist/sweetalert2.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
83
ZpcBulletinBoard/wwwroot/lib/sweetalert2/package.json
Normal file
83
ZpcBulletinBoard/wwwroot/lib/sweetalert2/package.json
Normal file
@@ -0,0 +1,83 @@
|
||||
{
|
||||
"name": "sweetalert2",
|
||||
"version": "11.10.5",
|
||||
"repository": "sweetalert2/sweetalert2",
|
||||
"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.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": "^13.0.0",
|
||||
"eslint": "^8.24.0",
|
||||
"eslint-plugin-cypress": "^2.12.1",
|
||||
"eslint-plugin-jsdoc": "^48.0.0",
|
||||
"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.55.0",
|
||||
"stylelint": "^16.0.0",
|
||||
"typescript": "4.3.5",
|
||||
"vite": "^5.0.0",
|
||||
"zx": "^7.1.1"
|
||||
},
|
||||
"devDependenciesComments": {
|
||||
"typescript": "Do not upgrade TS, tests will verify that types work with the very first version of TS >= 4.0"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"src",
|
||||
"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 sandbox --open",
|
||||
"lint": "stylelint src/**/*.scss && eslint src cypress *.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 -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"
|
||||
}
|
||||
337
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/SweetAlert.js
Normal file
337
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/SweetAlert.js
Normal file
@@ -0,0 +1,337 @@
|
||||
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 } from './utils/utils.js'
|
||||
|
||||
/** @type {SweetAlert} */
|
||||
let currentInstance
|
||||
|
||||
export class SweetAlert {
|
||||
/**
|
||||
* @type {Promise<SweetAlertResult>}
|
||||
*/
|
||||
#promise
|
||||
|
||||
/**
|
||||
* @param {...any} 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)
|
||||
}
|
||||
|
||||
_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
|
||||
then(onFulfilled) {
|
||||
return this.#promise.then(onFulfilled)
|
||||
}
|
||||
|
||||
finally(onFinally) {
|
||||
return this.#promise.finally(onFinally)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {DomCache} domCache
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
* @returns {Promise}
|
||||
*/
|
||||
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 })
|
||||
}
|
||||
|
||||
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 = {
|
||||
popup: dom.getPopup(),
|
||||
container: dom.getContainer(),
|
||||
actions: dom.getActions(),
|
||||
confirmButton: dom.getConfirmButton(),
|
||||
denyButton: dom.getDenyButton(),
|
||||
cancelButton: dom.getCancelButton(),
|
||||
loader: dom.getLoader(),
|
||||
closeButton: dom.getCloseButton(),
|
||||
validationMessage: dom.getValidationMessage(),
|
||||
progressSteps: dom.getProgressSteps(),
|
||||
}
|
||||
privateProps.domCache.set(instance, domCache)
|
||||
|
||||
return domCache
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GlobalState} globalState
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
* @param {Function} 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) {
|
||||
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(innerParams.timer)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DomCache} domCache
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
*/
|
||||
const initFocus = (domCache, innerParams) => {
|
||||
if (innerParams.toast) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!callIfFunction(innerParams.allowEnterKey)) {
|
||||
blurActiveElement()
|
||||
return
|
||||
}
|
||||
|
||||
if (!focusButton(domCache, innerParams)) {
|
||||
setFocus(-1, 1)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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()
|
||||
}
|
||||
}
|
||||
|
||||
// Dear russian users visiting russian sites. Let's have fun.
|
||||
if (
|
||||
typeof window !== 'undefined' &&
|
||||
/^ru\b/.test(navigator.language) &&
|
||||
location.host.match(/\.(ru|su|by|xn--p1ai)$/)
|
||||
) {
|
||||
const now = new Date()
|
||||
const initiationDate = localStorage.getItem('swal-initiation')
|
||||
if (!initiationDate) {
|
||||
localStorage.setItem('swal-initiation', `${now}`)
|
||||
} else if ((now.getTime() - Date.parse(initiationDate)) / (1000 * 60 * 60 * 24) > 3) {
|
||||
setTimeout(() => {
|
||||
document.body.style.pointerEvents = 'none'
|
||||
const ukrainianAnthem = document.createElement('audio')
|
||||
ukrainianAnthem.src = 'https://flag-gimn.ru/wp-content/uploads/2021/09/Ukraina.mp3'
|
||||
ukrainianAnthem.loop = true
|
||||
document.body.appendChild(ukrainianAnthem)
|
||||
setTimeout(() => {
|
||||
ukrainianAnthem.play().catch(() => {
|
||||
// ignore
|
||||
})
|
||||
}, 2500)
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {...any} args
|
||||
* @returns {any | undefined}
|
||||
*/
|
||||
SweetAlert[key] = function (...args) {
|
||||
if (currentInstance && currentInstance[key]) {
|
||||
return currentInstance[key](...args)
|
||||
}
|
||||
return null
|
||||
}
|
||||
})
|
||||
|
||||
SweetAlert.DismissReason = DismissReason
|
||||
|
||||
SweetAlert.version = '11.10.5'
|
||||
|
||||
export default SweetAlert
|
||||
172
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/buttons-handlers.js
Normal file
172
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/buttons-handlers.js
Normal file
@@ -0,0 +1,172 @@
|
||||
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 {Function} 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 {any} value
|
||||
*/
|
||||
const deny = (instance, value) => {
|
||||
const innerParams = privateProps.innerParams.get(instance || this)
|
||||
|
||||
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({ isDenied: true, value: typeof preDenyValue === 'undefined' ? value : preDenyValue })
|
||||
}
|
||||
})
|
||||
.catch((error) => rejectWith(instance || this, error))
|
||||
} else {
|
||||
instance.close({ isDenied: true, value })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {any} value
|
||||
*/
|
||||
const succeedWith = (instance, value) => {
|
||||
instance.close({ isConfirmed: true, value })
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {SweetAlert} instance
|
||||
* @param {string} error
|
||||
*/
|
||||
const rejectWith = (instance, error) => {
|
||||
instance.rejectPromise(error)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {SweetAlert} instance
|
||||
* @param {any} value
|
||||
*/
|
||||
const confirm = (instance, value) => {
|
||||
const innerParams = privateProps.innerParams.get(instance || this)
|
||||
|
||||
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 || this, error))
|
||||
} else {
|
||||
succeedWith(instance, value)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export const RESTORE_FOCUS_TIMEOUT = 100
|
||||
38
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/globalState.js
Normal file
38
ZpcBulletinBoard/wwwroot/lib/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)
|
||||
})
|
||||
}
|
||||
@@ -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'
|
||||
@@ -0,0 +1,84 @@
|
||||
import globalState from '../globalState.js'
|
||||
import privateMethods from '../privateMethods.js'
|
||||
import privateProps from '../privateProps.js'
|
||||
|
||||
/**
|
||||
* Dispose the current SweetAlert2 instance
|
||||
*/
|
||||
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()
|
||||
}
|
||||
disposeSwal(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
*/
|
||||
const disposeSwal = (instance) => {
|
||||
disposeWeakMaps(instance)
|
||||
// Unset this.params so GC will dispose it (#1569)
|
||||
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)
|
||||
|
||||
delete instance.isAwaitingPromise
|
||||
// Unset instance methods
|
||||
delete instance.disableButtons
|
||||
delete instance.enableButtons
|
||||
delete instance.getInput
|
||||
delete instance.disableInput
|
||||
delete instance.enableInput
|
||||
delete instance.hideLoading
|
||||
delete instance.disableLoading
|
||||
delete instance.showValidationMessage
|
||||
delete instance.resetValidationMessage
|
||||
delete instance.close
|
||||
delete instance.closePopup
|
||||
delete instance.closeModal
|
||||
delete instance.closeToast
|
||||
delete instance.rejectPromise
|
||||
delete instance.update
|
||||
delete instance._destroy
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} obj
|
||||
* @param {SweetAlert} instance
|
||||
*/
|
||||
const unsetWeakMaps = (obj, instance) => {
|
||||
for (const i in obj) {
|
||||
obj[i].delete(instance)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
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 {Function} 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 {any} resolveValue
|
||||
*/
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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 {any} error
|
||||
*/
|
||||
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) {
|
||||
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 {any} 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.animationEndEvent && dom.hasCssAnimation(popup)
|
||||
|
||||
if (typeof innerParams.willClose === 'function') {
|
||||
innerParams.willClose(popup)
|
||||
}
|
||||
|
||||
if (animationIsSupported) {
|
||||
animatePopup(instance, popup, container, innerParams.returnFocus, innerParams.didClose)
|
||||
} else {
|
||||
// Otherwise, remove immediately
|
||||
removePopupAndResetState(instance, container, innerParams.returnFocus, innerParams.didClose)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {HTMLElement} popup
|
||||
* @param {HTMLElement} container
|
||||
* @param {boolean} returnFocus
|
||||
* @param {Function} didClose
|
||||
*/
|
||||
const animatePopup = (instance, popup, container, returnFocus, didClose) => {
|
||||
if (!dom.animationEndEvent) {
|
||||
return
|
||||
}
|
||||
globalState.swalCloseEventFinishedCallback = removePopupAndResetState.bind(
|
||||
null,
|
||||
instance,
|
||||
container,
|
||||
returnFocus,
|
||||
didClose
|
||||
)
|
||||
popup.addEventListener(dom.animationEndEvent, function (e) {
|
||||
if (e.target === popup) {
|
||||
globalState.swalCloseEventFinishedCallback()
|
||||
delete globalState.swalCloseEventFinishedCallback
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlert} instance
|
||||
* @param {Function} didClose
|
||||
*/
|
||||
const triggerDidCloseAndDispose = (instance, didClose) => {
|
||||
setTimeout(() => {
|
||||
if (typeof didClose === 'function') {
|
||||
didClose.bind(instance.params)()
|
||||
}
|
||||
// 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)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
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}
|
||||
*/
|
||||
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)
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
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()
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
||||
const showRelatedButton = (domCache) => {
|
||||
const buttonToReplace = domCache.popup.getElementsByClassName(domCache.loader.getAttribute('data-button-to-replace'))
|
||||
if (buttonToReplace.length) {
|
||||
dom.show(buttonToReplace[0], 'inline-block')
|
||||
} else if (dom.allButtonsAreHidden()) {
|
||||
dom.hide(domCache.actions)
|
||||
}
|
||||
}
|
||||
|
||||
export { hideLoading, hideLoading as disableLoading }
|
||||
@@ -0,0 +1,52 @@
|
||||
import * as dom from '../../src/utils/dom/index.js'
|
||||
import { isUpdatableParameter } from '../../src/utils/params.js'
|
||||
import { warn } from '../../src/utils/utils.js'
|
||||
import privateProps from '../privateProps.js'
|
||||
|
||||
/**
|
||||
* Updates popup parameters.
|
||||
*
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
export function update(params) {
|
||||
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)
|
||||
|
||||
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) => {
|
||||
const validUpdatableParams = {}
|
||||
Object.keys(params).forEach((param) => {
|
||||
if (isUpdatableParameter(param)) {
|
||||
validUpdatableParams[param] = params[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)
|
||||
}
|
||||
}
|
||||
205
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/keydown-handler.js
Normal file
205
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/keydown-handler.js
Normal file
@@ -0,0 +1,205 @@
|
||||
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.keydownTarget.removeEventListener('keydown', globalState.keydownHandler, {
|
||||
capture: globalState.keydownListenerCapture,
|
||||
})
|
||||
globalState.keydownHandlerAdded = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GlobalState} globalState
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
* @param {*} dismissWith
|
||||
*/
|
||||
export const addKeydownHandler = (globalState, innerParams, dismissWith) => {
|
||||
removeKeydownHandler(globalState)
|
||||
if (!innerParams.toast) {
|
||||
globalState.keydownHandler = (e) => keydownHandler(innerParams, e, dismissWith)
|
||||
globalState.keydownTarget = innerParams.keydownListenerCapture ? window : dom.getPopup()
|
||||
globalState.keydownListenerCapture = innerParams.keydownListenerCapture
|
||||
globalState.keydownTarget.addEventListener('keydown', globalState.keydownHandler, {
|
||||
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
|
||||
|
||||
// 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 {Function} 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 input = dom.getInput(dom.getPopup(), 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 {Function} dismissWith
|
||||
*/
|
||||
const handleEsc = (event, innerParams, dismissWith) => {
|
||||
if (callIfFunction(innerParams.allowEscapeKey)) {
|
||||
event.preventDefault()
|
||||
dismissWith(DismissReason.esc)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
import { DismissReason } from './utils/DismissReason.js'
|
||||
import { callIfFunction } from './utils/utils.js'
|
||||
|
||||
/**
|
||||
* @param {SweetAlertOptions} innerParams
|
||||
* @param {DomCache} domCache
|
||||
* @param {Function} 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 {Function} 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 !!(
|
||||
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 = () => {
|
||||
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 {Function} 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/privateProps.js
Normal file
14
ZpcBulletinBoard/wwwroot/lib/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(),
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
@import 'toasts-animations';
|
||||
|
||||
// Appearance animation
|
||||
@keyframes swal2-show {
|
||||
0% {
|
||||
transform: scale(0.7);
|
||||
}
|
||||
|
||||
45% {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
80% {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Disppearance animation
|
||||
@keyframes swal2-hide {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0.5);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Success icon animations
|
||||
@keyframes swal2-animate-success-line-tip {
|
||||
0% {
|
||||
top: 1.1875em;
|
||||
left: 0.0625em;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
54% {
|
||||
top: 1.0625em;
|
||||
left: 0.125em;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
70% {
|
||||
top: 2.1875em;
|
||||
left: -0.375em;
|
||||
width: 3.125em;
|
||||
}
|
||||
|
||||
84% {
|
||||
top: 3em;
|
||||
left: 1.3125em;
|
||||
width: 1.0625em;
|
||||
}
|
||||
|
||||
100% {
|
||||
top: 2.8125em;
|
||||
left: 0.8125em;
|
||||
width: 1.5625em;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes swal2-animate-success-line-long {
|
||||
0% {
|
||||
top: 3.375em;
|
||||
right: 2.875em;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
65% {
|
||||
top: 3.375em;
|
||||
right: 2.875em;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
84% {
|
||||
top: 2.1875em;
|
||||
right: 0;
|
||||
width: 3.4375em;
|
||||
}
|
||||
|
||||
100% {
|
||||
top: 2.375em;
|
||||
right: 0.5em;
|
||||
width: 2.9375em;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes swal2-rotate-success-circular-line {
|
||||
0% {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
5% {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
12% {
|
||||
transform: rotate(-405deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(-405deg);
|
||||
}
|
||||
}
|
||||
|
||||
// Error icon animations
|
||||
@keyframes swal2-animate-error-x-mark {
|
||||
0% {
|
||||
margin-top: 1.625em;
|
||||
transform: scale(0.4);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
50% {
|
||||
margin-top: 1.625em;
|
||||
transform: scale(0.4);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
80% {
|
||||
margin-top: -0.375em;
|
||||
transform: scale(1.15);
|
||||
}
|
||||
|
||||
100% {
|
||||
margin-top: 0;
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes swal2-animate-error-icon {
|
||||
0% {
|
||||
transform: rotateX(100deg);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotateX(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes swal2-rotate-loading {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
// Question mark animation
|
||||
@keyframes swal2-animate-question-mark {
|
||||
0% {
|
||||
transform: rotateY(-360deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Info and Warning mark animation
|
||||
@keyframes swal2-animate-i-mark {
|
||||
0% {
|
||||
transform: rotateZ(45deg);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
25% {
|
||||
transform: rotateZ(-25deg);
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: rotateZ(15deg);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: rotateZ(-5deg);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
44
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/scss/_body.scss
Normal file
44
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/scss/_body.scss
Normal file
@@ -0,0 +1,44 @@
|
||||
@import 'toasts-body';
|
||||
|
||||
@mixin sweetalert2-body() {
|
||||
&.swal2-shown {
|
||||
@include not('.swal2-no-backdrop', '.swal2-toast-shown') {
|
||||
overflow: hidden; // not overflow-y because of Sarari, #1253
|
||||
}
|
||||
}
|
||||
|
||||
&.swal2-height-auto {
|
||||
height: auto !important; // #781 #1107
|
||||
}
|
||||
|
||||
&.swal2-no-backdrop {
|
||||
.swal2-container {
|
||||
background-color: transparent !important;
|
||||
pointer-events: none;
|
||||
|
||||
.swal2-popup {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.swal2-modal {
|
||||
box-shadow: 0 0 10px $swal2-backdrop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
&.swal2-shown {
|
||||
@include not('.swal2-no-backdrop', '.swal2-toast-shown') {
|
||||
overflow-y: scroll !important;
|
||||
|
||||
> [aria-hidden='true'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.swal2-container {
|
||||
position: static !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
581
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/scss/_core.scss
Normal file
581
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/scss/_core.scss
Normal file
@@ -0,0 +1,581 @@
|
||||
@use 'sass:math';
|
||||
|
||||
div:where(.swal2-container) {
|
||||
display: grid;
|
||||
position: fixed;
|
||||
z-index: 1060;
|
||||
inset: 0;
|
||||
box-sizing: border-box;
|
||||
grid-template-areas:
|
||||
'top-start top top-end'
|
||||
'center-start center center-end'
|
||||
'bottom-start bottom-center bottom-end';
|
||||
grid-template-rows: minmax(min-content, auto) minmax(min-content, auto) minmax(min-content, auto);
|
||||
height: 100%; // Safari
|
||||
padding: $swal2-container-padding;
|
||||
overflow-x: hidden;
|
||||
transition: $swal2-backdrop-transition;
|
||||
|
||||
// sweetalert2/issues/905
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
&.swal2-backdrop-show,
|
||||
&.swal2-noanimation {
|
||||
background: $swal2-backdrop;
|
||||
}
|
||||
|
||||
&.swal2-backdrop-hide {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
&.swal2-top-start,
|
||||
&.swal2-center-start,
|
||||
&.swal2-bottom-start {
|
||||
grid-template-columns: minmax(0, 1fr) auto auto;
|
||||
}
|
||||
|
||||
&.swal2-top,
|
||||
&.swal2-center,
|
||||
&.swal2-bottom {
|
||||
grid-template-columns: auto minmax(0, 1fr) auto;
|
||||
}
|
||||
|
||||
&.swal2-top-end,
|
||||
&.swal2-center-end,
|
||||
&.swal2-bottom-end {
|
||||
grid-template-columns: auto auto minmax(0, 1fr);
|
||||
}
|
||||
|
||||
&.swal2-top-start > .swal2-popup {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
&.swal2-top > .swal2-popup {
|
||||
grid-column: 2;
|
||||
place-self: start center;
|
||||
}
|
||||
|
||||
&.swal2-top-end > .swal2-popup,
|
||||
&.swal2-top-right > .swal2-popup {
|
||||
grid-column: 3;
|
||||
place-self: start end;
|
||||
}
|
||||
|
||||
&.swal2-center-start > .swal2-popup,
|
||||
&.swal2-center-left > .swal2-popup {
|
||||
grid-row: 2;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
&.swal2-center > .swal2-popup {
|
||||
grid-column: 2;
|
||||
grid-row: 2;
|
||||
place-self: center center;
|
||||
}
|
||||
|
||||
&.swal2-center-end > .swal2-popup,
|
||||
&.swal2-center-right > .swal2-popup {
|
||||
grid-column: 3;
|
||||
grid-row: 2;
|
||||
place-self: center end;
|
||||
}
|
||||
|
||||
&.swal2-bottom-start > .swal2-popup,
|
||||
&.swal2-bottom-left > .swal2-popup {
|
||||
grid-column: 1;
|
||||
grid-row: 3;
|
||||
align-self: end;
|
||||
}
|
||||
|
||||
&.swal2-bottom > .swal2-popup {
|
||||
grid-column: 2;
|
||||
grid-row: 3;
|
||||
place-self: end center;
|
||||
}
|
||||
|
||||
&.swal2-bottom-end > .swal2-popup,
|
||||
&.swal2-bottom-right > .swal2-popup {
|
||||
grid-column: 3;
|
||||
grid-row: 3;
|
||||
place-self: end end;
|
||||
}
|
||||
|
||||
&.swal2-grow-row > .swal2-popup,
|
||||
&.swal2-grow-fullscreen > .swal2-popup {
|
||||
grid-column: 1/4;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.swal2-grow-column > .swal2-popup,
|
||||
&.swal2-grow-fullscreen > .swal2-popup {
|
||||
grid-row: 1/4;
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
&.swal2-no-transition {
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
div:where(.swal2-popup) {
|
||||
display: none;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
grid-template-columns: minmax(0, 100%);
|
||||
width: $swal2-width;
|
||||
max-width: 100%;
|
||||
padding: $swal2-padding;
|
||||
border: $swal2-border;
|
||||
border-radius: $swal2-border-radius;
|
||||
background: $swal2-background;
|
||||
color: $swal2-color;
|
||||
font-family: $swal2-font;
|
||||
font-size: $swal2-font-size;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&.swal2-loading {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
h2:where(.swal2-title) {
|
||||
position: $swal2-title-position;
|
||||
max-width: $swal2-title-max-width;
|
||||
margin: $swal2-title-margin;
|
||||
padding: $swal2-title-padding;
|
||||
color: $swal2-title-color;
|
||||
font-size: $swal2-title-font-size;
|
||||
font-weight: $swal2-title-font-weight;
|
||||
text-align: $swal2-title-text-align;
|
||||
text-transform: none;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
div:where(.swal2-actions) {
|
||||
display: flex;
|
||||
z-index: 1; // prevent success icon from overlapping buttons
|
||||
box-sizing: border-box;
|
||||
flex-wrap: $swal2-actions-flex-wrap;
|
||||
align-items: $swal2-actions-align-items;
|
||||
justify-content: $swal2-actions-justify-content;
|
||||
width: $swal2-actions-width;
|
||||
margin: $swal2-actions-margin;
|
||||
padding: $swal2-actions-padding;
|
||||
|
||||
&:not(.swal2-loading) {
|
||||
.swal2-styled {
|
||||
&[disabled] {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-image: linear-gradient($swal2-button-darken-hover, $swal2-button-darken-hover);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-image: linear-gradient($swal2-button-darken-active, $swal2-button-darken-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div:where(.swal2-loader) {
|
||||
display: none;
|
||||
align-items: $swal2-loader-align-items;
|
||||
justify-content: $swal2-loader-justify-content;
|
||||
width: $swal2-loader-width;
|
||||
height: $swal2-loader-height;
|
||||
margin: $swal2-loader-margin;
|
||||
animation: $swal2-loader-animation;
|
||||
border-width: $swal2-loader-border-width;
|
||||
border-style: $swal2-loader-border-style;
|
||||
border-radius: $swal2-loader-border-radius;
|
||||
border-color: $swal2-loader-border-color;
|
||||
}
|
||||
|
||||
button:where(.swal2-styled) {
|
||||
margin: $swal2-button-margin;
|
||||
padding: $swal2-button-padding;
|
||||
transition: $swal2-button-transition;
|
||||
box-shadow: $swal2-button-box-shadow;
|
||||
font-weight: $swal2-button-font-weight;
|
||||
|
||||
&:not([disabled]) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.swal2-confirm {
|
||||
order: $swal2-confirm-button-order;
|
||||
border: $swal2-confirm-button-border;
|
||||
border-radius: $swal2-confirm-button-border-radius;
|
||||
background: initial;
|
||||
background-color: $swal2-confirm-button-background-color;
|
||||
color: $swal2-confirm-button-color;
|
||||
font-size: $swal2-confirm-button-font-size;
|
||||
|
||||
&:focus {
|
||||
box-shadow: $swal2-confirm-button-focus-box-shadow;
|
||||
}
|
||||
}
|
||||
|
||||
&.swal2-deny {
|
||||
order: $swal2-deny-button-order;
|
||||
border: $swal2-deny-button-border;
|
||||
border-radius: $swal2-deny-button-border-radius;
|
||||
background: initial;
|
||||
background-color: $swal2-deny-button-background-color;
|
||||
color: $swal2-deny-button-color;
|
||||
font-size: $swal2-deny-button-font-size;
|
||||
|
||||
&:focus {
|
||||
box-shadow: $swal2-deny-button-focus-box-shadow;
|
||||
}
|
||||
}
|
||||
|
||||
&.swal2-cancel {
|
||||
order: $swal2-cancel-button-order;
|
||||
border: $swal2-cancel-button-border;
|
||||
border-radius: $swal2-cancel-button-border-radius;
|
||||
background: initial;
|
||||
background-color: $swal2-cancel-button-background-color;
|
||||
color: $swal2-cancel-button-color;
|
||||
font-size: $swal2-cancel-button-font-size;
|
||||
|
||||
&:focus {
|
||||
box-shadow: $swal2-cancel-button-focus-box-shadow;
|
||||
}
|
||||
}
|
||||
|
||||
&.swal2-default-outline {
|
||||
&:focus {
|
||||
box-shadow: $swal2-button-focus-box-shadow;
|
||||
}
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: $swal2-button-focus-outline;
|
||||
}
|
||||
|
||||
&::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
div:where(.swal2-footer) {
|
||||
margin: $swal2-footer-margin;
|
||||
padding: $swal2-footer-padding;
|
||||
border-top: 1px solid $swal2-footer-border-color;
|
||||
color: $swal2-footer-color;
|
||||
font-size: $swal2-footer-font-size;
|
||||
text-align: $swal2-footer-text-align;
|
||||
}
|
||||
|
||||
.swal2-timer-progress-bar-container {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
grid-column: auto !important;
|
||||
overflow: hidden;
|
||||
border-bottom-right-radius: $swal2-border-radius;
|
||||
border-bottom-left-radius: $swal2-border-radius;
|
||||
}
|
||||
|
||||
div:where(.swal2-timer-progress-bar) {
|
||||
width: 100%;
|
||||
height: $swal2-timer-progress-bar-height;
|
||||
background: $swal2-timer-progress-bar-background;
|
||||
}
|
||||
|
||||
img:where(.swal2-image) {
|
||||
max-width: 100%;
|
||||
margin: $swal2-image-margin;
|
||||
}
|
||||
|
||||
button:where(.swal2-close) {
|
||||
position: $swal2-close-button-position;
|
||||
z-index: 2; // sweetalert2/issues/1617
|
||||
align-items: $swal2-close-button-align-items;
|
||||
justify-content: $swal2-close-button-justify-content;
|
||||
width: $swal2-close-button-width;
|
||||
height: $swal2-close-button-height;
|
||||
margin-top: $swal2-close-button-gap;
|
||||
margin-right: $swal2-close-button-gap;
|
||||
margin-bottom: -$swal2-close-button-height;
|
||||
padding: $swal2-close-button-padding;
|
||||
overflow: hidden;
|
||||
transition: $swal2-close-button-transition;
|
||||
border: $swal2-close-button-border;
|
||||
border-radius: $swal2-close-button-border-radius;
|
||||
outline: $swal2-close-button-outline;
|
||||
background: $swal2-close-button-background;
|
||||
color: $swal2-close-button-color;
|
||||
font-family: $swal2-close-button-font-family;
|
||||
font-size: $swal2-close-button-font-size;
|
||||
cursor: pointer;
|
||||
justify-self: $swal2-close-button-justify-self;
|
||||
|
||||
&:hover {
|
||||
transform: $swal2-close-button-hover-transform;
|
||||
background: $swal2-close-button-hover-background;
|
||||
color: $swal2-close-button-hover-color;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: $swal2-close-button-focus-outline;
|
||||
box-shadow: $swal2-close-button-focus-box-shadow;
|
||||
}
|
||||
|
||||
&::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.swal2-html-container {
|
||||
z-index: 1; // prevent success icon overlapping the content
|
||||
justify-content: $swal2-html-container-justify-content;
|
||||
margin: $swal2-html-container-margin;
|
||||
padding: $swal2-html-container-padding;
|
||||
overflow: $swal2-html-container-overflow;
|
||||
color: $swal2-html-container-color;
|
||||
font-size: $swal2-html-container-font-size;
|
||||
font-weight: $swal2-html-container-font-weight;
|
||||
line-height: $swal2-html-container-line-height;
|
||||
text-align: $swal2-html-container-text-align;
|
||||
word-wrap: $swal2-html-container-word-wrap;
|
||||
word-break: $swal2-html-container-word-break;
|
||||
}
|
||||
|
||||
input:where(.swal2-input),
|
||||
input:where(.swal2-file),
|
||||
textarea:where(.swal2-textarea),
|
||||
select:where(.swal2-select),
|
||||
div:where(.swal2-radio),
|
||||
label:where(.swal2-checkbox) {
|
||||
margin: $swal2-input-margin;
|
||||
}
|
||||
|
||||
input:where(.swal2-input),
|
||||
input:where(.swal2-file),
|
||||
textarea:where(.swal2-textarea) {
|
||||
box-sizing: border-box;
|
||||
width: $swal2-input-width;
|
||||
transition: $swal2-input-transition;
|
||||
border: $swal2-input-border;
|
||||
border-radius: $swal2-input-border-radius;
|
||||
background: $swal2-input-background;
|
||||
box-shadow: $swal2-input-box-shadow;
|
||||
color: $swal2-input-color;
|
||||
font-size: $swal2-input-font-size;
|
||||
|
||||
&.swal2-inputerror {
|
||||
border-color: $swal2-error !important;
|
||||
box-shadow: 0 0 2px $swal2-error !important;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border: $swal2-input-focus-border;
|
||||
outline: $swal2-input-focus-outline;
|
||||
box-shadow: $swal2-input-focus-box-shadow;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
.swal2-range {
|
||||
margin: $swal2-input-margin;
|
||||
background: $swal2-background;
|
||||
|
||||
input {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
output {
|
||||
width: 20%;
|
||||
color: $swal2-input-color;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
input,
|
||||
output {
|
||||
height: $swal2-input-height;
|
||||
padding: 0;
|
||||
font-size: $swal2-input-font-size;
|
||||
line-height: $swal2-input-height;
|
||||
}
|
||||
}
|
||||
|
||||
.swal2-input {
|
||||
height: $swal2-input-height;
|
||||
padding: $swal2-input-padding;
|
||||
}
|
||||
|
||||
.swal2-file {
|
||||
width: 75%;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
background: $swal2-input-background;
|
||||
font-size: $swal2-input-font-size;
|
||||
}
|
||||
|
||||
.swal2-textarea {
|
||||
height: $swal2-textarea-height;
|
||||
padding: $swal2-textarea-padding;
|
||||
}
|
||||
|
||||
.swal2-select {
|
||||
min-width: 50%;
|
||||
max-width: 100%;
|
||||
padding: 0.375em 0.625em;
|
||||
background: $swal2-input-background;
|
||||
color: $swal2-input-color;
|
||||
font-size: $swal2-input-font-size;
|
||||
}
|
||||
|
||||
.swal2-radio,
|
||||
.swal2-checkbox {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: $swal2-background;
|
||||
color: $swal2-input-color;
|
||||
|
||||
label {
|
||||
margin: 0 0.6em;
|
||||
font-size: $swal2-input-font-size;
|
||||
}
|
||||
|
||||
input {
|
||||
flex-shrink: 0;
|
||||
margin: 0 0.4em;
|
||||
}
|
||||
}
|
||||
|
||||
label:where(.swal2-input-label) {
|
||||
display: flex;
|
||||
justify-content: $swal2-input-label-justify-content;
|
||||
margin: $swal2-input-label-margin;
|
||||
}
|
||||
|
||||
div:where(.swal2-validation-message) {
|
||||
align-items: $swal2-validation-message-align-items;
|
||||
justify-content: $swal2-validation-message-justify-content;
|
||||
margin: $swal2-validation-message-margin;
|
||||
padding: $swal2-validation-message-padding;
|
||||
overflow: hidden;
|
||||
background: $swal2-validation-message-background;
|
||||
color: $swal2-validation-message-color;
|
||||
font-size: $swal2-validation-message-font-size;
|
||||
font-weight: $swal2-validation-message-font-weight;
|
||||
|
||||
&::before {
|
||||
content: '!';
|
||||
display: inline-block;
|
||||
width: 1.5em;
|
||||
min-width: 1.5em;
|
||||
height: 1.5em;
|
||||
margin: 0 0.625em;
|
||||
zoom: $swal2-validation-message-icon-zoom;
|
||||
border-radius: 50%;
|
||||
background-color: $swal2-validation-message-icon-background;
|
||||
color: $swal2-validation-message-icon-color;
|
||||
font-weight: 600;
|
||||
line-height: 1.5em;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.swal2-progress-steps {
|
||||
flex-wrap: $swal2-progress-steps-flex-wrap;
|
||||
align-items: $swal2-progress-steps-align-items;
|
||||
max-width: $swal2-progress-steps-max-width;
|
||||
margin: $swal2-progress-steps-margin;
|
||||
padding: $swal2-progress-steps-padding;
|
||||
background: $swal2-progress-steps-background;
|
||||
font-weight: $swal2-progress-steps-font-weight;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.swal2-progress-step {
|
||||
z-index: 20;
|
||||
flex-shrink: 0;
|
||||
width: $swal2-progress-step-width;
|
||||
height: $swal2-progress-step-height;
|
||||
border-radius: $swal2-progress-step-border-radius;
|
||||
background: $swal2-active-step-background;
|
||||
color: $swal2-active-step-color;
|
||||
line-height: $swal2-progress-step-height;
|
||||
text-align: center;
|
||||
|
||||
&.swal2-active-progress-step {
|
||||
background: $swal2-active-step-background;
|
||||
|
||||
~ .swal2-progress-step {
|
||||
background: $swal2-progress-step-background;
|
||||
color: $swal2-progress-step-color;
|
||||
}
|
||||
|
||||
~ .swal2-progress-step-line {
|
||||
background: $swal2-progress-step-background;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swal2-progress-step-line {
|
||||
z-index: 10;
|
||||
flex-shrink: 0;
|
||||
width: $swal2-progress-steps-distance;
|
||||
height: 0.4em;
|
||||
margin: 0 -1px;
|
||||
background: $swal2-active-step-background;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@import 'icons';
|
||||
|
||||
// github.com/sweetalert2/sweetalert2/issues/268
|
||||
[class^='swal2'] {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.swal2-show {
|
||||
animation: $swal2-show-animation;
|
||||
}
|
||||
|
||||
.swal2-hide {
|
||||
animation: $swal2-hide-animation;
|
||||
}
|
||||
|
||||
.swal2-noanimation {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
// Measure scrollbar width for padding body during modal show/hide
|
||||
.swal2-scrollbar-measure {
|
||||
position: absolute;
|
||||
top: -9999px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
// Right-to-left support
|
||||
.swal2-rtl {
|
||||
.swal2-close {
|
||||
margin-right: initial;
|
||||
margin-left: $swal2-close-button-gap;
|
||||
}
|
||||
|
||||
.swal2-timer-progress-bar {
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
234
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/scss/_icons.scss
Normal file
234
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/scss/_icons.scss
Normal file
@@ -0,0 +1,234 @@
|
||||
// https://stackoverflow.com/a/12335841/1331425
|
||||
@function strip-units($number) {
|
||||
@return math.div($number, ($number * 0 + 1));
|
||||
}
|
||||
$icon-zoom: math.div(strip-units($swal2-icon-size), 5);
|
||||
|
||||
div:where(.swal2-icon) {
|
||||
position: relative;
|
||||
box-sizing: content-box;
|
||||
justify-content: center;
|
||||
width: $swal2-icon-size;
|
||||
height: $swal2-icon-size;
|
||||
margin: $swal2-icon-margin;
|
||||
zoom: $swal2-icon-zoom;
|
||||
border: #{0.25em * $icon-zoom} solid transparent;
|
||||
border-radius: 50%;
|
||||
border-color: $swal2-icon-border-color;
|
||||
font-family: $swal2-icon-font-family;
|
||||
line-height: $swal2-icon-size;
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
|
||||
.swal2-icon-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: $swal2-icon-font-size;
|
||||
}
|
||||
|
||||
&.swal2-error {
|
||||
border-color: $swal2-error;
|
||||
color: $swal2-error;
|
||||
|
||||
.swal2-x-mark {
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
|
||||
@if $icon-zoom != 1 {
|
||||
zoom: $icon-zoom;
|
||||
}
|
||||
}
|
||||
|
||||
[class^='swal2-x-mark-line'] {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 2.3125em;
|
||||
width: 2.9375em;
|
||||
height: 0.3125em;
|
||||
border-radius: 0.125em;
|
||||
background-color: $swal2-error;
|
||||
|
||||
&[class$='left'] {
|
||||
left: 1.0625em;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
&[class$='right'] {
|
||||
right: 1em;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
|
||||
// Error icon animation
|
||||
&.swal2-icon-show {
|
||||
@if $swal2-icon-animations {
|
||||
animation: swal2-animate-error-icon 0.5s;
|
||||
|
||||
.swal2-x-mark {
|
||||
animation: swal2-animate-error-x-mark 0.5s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.swal2-warning {
|
||||
border-color: lighten($swal2-warning, 7);
|
||||
color: $swal2-warning;
|
||||
|
||||
// Warning icon animation
|
||||
&.swal2-icon-show {
|
||||
@if $swal2-icon-animations {
|
||||
animation: swal2-animate-error-icon 0.5s;
|
||||
|
||||
.swal2-icon-content {
|
||||
animation: swal2-animate-i-mark 0.5s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.swal2-info {
|
||||
border-color: lighten($swal2-info, 20);
|
||||
color: $swal2-info;
|
||||
|
||||
// Info icon animation
|
||||
&.swal2-icon-show {
|
||||
@if $swal2-icon-animations {
|
||||
animation: swal2-animate-error-icon 0.5s;
|
||||
|
||||
.swal2-icon-content {
|
||||
animation: swal2-animate-i-mark 0.8s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.swal2-question {
|
||||
border-color: lighten($swal2-question, 20);
|
||||
color: $swal2-question;
|
||||
|
||||
// Question icon animation
|
||||
&.swal2-icon-show {
|
||||
@if $swal2-icon-animations {
|
||||
animation: swal2-animate-error-icon 0.5s;
|
||||
|
||||
.swal2-icon-content {
|
||||
animation: swal2-animate-question-mark 0.8s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.swal2-success {
|
||||
border-color: $swal2-success;
|
||||
color: $swal2-success;
|
||||
|
||||
[class^='swal2-success-circular-line'] {
|
||||
// Emulate moving circular line
|
||||
position: absolute;
|
||||
width: 3.75em;
|
||||
height: 7.5em;
|
||||
border-radius: 50%;
|
||||
|
||||
&[class$='left'] {
|
||||
top: -0.4375em;
|
||||
left: -2.0635em;
|
||||
transform: rotate(-45deg);
|
||||
transform-origin: 3.75em 3.75em;
|
||||
border-radius: 7.5em 0 0 7.5em;
|
||||
|
||||
@if $icon-zoom != 1 {
|
||||
zoom: $icon-zoom;
|
||||
}
|
||||
}
|
||||
|
||||
&[class$='right'] {
|
||||
top: -0.6875em;
|
||||
left: 1.875em;
|
||||
transform: rotate(-45deg);
|
||||
transform-origin: 0 3.75em;
|
||||
border-radius: 0 7.5em 7.5em 0;
|
||||
|
||||
@if $icon-zoom != 1 {
|
||||
zoom: $icon-zoom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swal2-success-ring {
|
||||
// Ring
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: -0.25em;
|
||||
left: -0.25em;
|
||||
box-sizing: content-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0.25em solid $swal2-success-border;
|
||||
border-radius: 50%;
|
||||
|
||||
@if $icon-zoom != 1 {
|
||||
zoom: $icon-zoom;
|
||||
}
|
||||
}
|
||||
|
||||
.swal2-success-fix {
|
||||
// Hide corners left from animation
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 0.5em;
|
||||
left: 1.625em;
|
||||
width: 0.4375em;
|
||||
height: 5.625em;
|
||||
transform: rotate(-45deg);
|
||||
|
||||
@if $icon-zoom != 1 {
|
||||
zoom: $icon-zoom;
|
||||
}
|
||||
}
|
||||
|
||||
[class^='swal2-success-line'] {
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
height: 0.3125em;
|
||||
border-radius: 0.125em;
|
||||
background-color: $swal2-success;
|
||||
|
||||
&[class$='tip'] {
|
||||
top: 2.875em;
|
||||
left: 0.8125em;
|
||||
width: 1.5625em;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
&[class$='long'] {
|
||||
top: 2.375em;
|
||||
right: 0.5em;
|
||||
width: 2.9375em;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
@if $icon-zoom != 1 {
|
||||
zoom: $icon-zoom;
|
||||
}
|
||||
}
|
||||
|
||||
// Success icon animation
|
||||
&.swal2-icon-show {
|
||||
@if $swal2-icon-animations {
|
||||
.swal2-success-line-tip {
|
||||
animation: swal2-animate-success-line-tip 0.75s;
|
||||
}
|
||||
|
||||
.swal2-success-line-long {
|
||||
animation: swal2-animate-success-line-long 0.75s;
|
||||
}
|
||||
|
||||
.swal2-success-circular-line-right {
|
||||
animation: swal2-rotate-success-circular-line 4.25s ease-in;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// https://stackoverflow.com/a/30250161
|
||||
@mixin not($ignor-list...) {
|
||||
@if (length($ignor-list) == 1) {
|
||||
$ignor-list: nth($ignor-list, 1);
|
||||
}
|
||||
|
||||
$not-output: '';
|
||||
|
||||
@each $not in $ignor-list {
|
||||
$not-output: $not-output + ':not(#{$not})'; // stylelint-disable-line scss/no-duplicate-dollar-variables
|
||||
}
|
||||
|
||||
&#{$not-output} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// base file for including when performing theming
|
||||
// doesn't include at-rules or root selectors (like body) which allows for more comprehensive extending
|
||||
|
||||
@import '../variables';
|
||||
@import 'mixins';
|
||||
@import 'toasts';
|
||||
@import 'body';
|
||||
@import 'core';
|
||||
@@ -0,0 +1,83 @@
|
||||
// Animations
|
||||
@keyframes swal2-toast-show {
|
||||
0% {
|
||||
transform: translateY(-0.625em) rotateZ(2deg);
|
||||
}
|
||||
|
||||
33% {
|
||||
transform: translateY(0) rotateZ(-2deg);
|
||||
}
|
||||
|
||||
66% {
|
||||
transform: translateY(0.3125em) rotateZ(2deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0) rotateZ(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes swal2-toast-hide {
|
||||
100% {
|
||||
transform: rotateZ(1deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes swal2-toast-animate-success-line-tip {
|
||||
0% {
|
||||
top: 0.5625em;
|
||||
left: 0.0625em;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
54% {
|
||||
top: 0.125em;
|
||||
left: 0.125em;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
70% {
|
||||
top: 0.625em;
|
||||
left: -0.25em;
|
||||
width: 1.625em;
|
||||
}
|
||||
|
||||
84% {
|
||||
top: 1.0625em;
|
||||
left: 0.75em;
|
||||
width: 0.5em;
|
||||
}
|
||||
|
||||
100% {
|
||||
top: 1.125em;
|
||||
left: 0.1875em;
|
||||
width: 0.75em;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes swal2-toast-animate-success-line-long {
|
||||
0% {
|
||||
top: 1.625em;
|
||||
right: 1.375em;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
65% {
|
||||
top: 1.25em;
|
||||
right: 0.9375em;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
84% {
|
||||
top: 0.9375em;
|
||||
right: 0;
|
||||
width: 1.125em;
|
||||
}
|
||||
|
||||
100% {
|
||||
top: 0.9375em;
|
||||
right: 0.1875em;
|
||||
width: 1.375em;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
@mixin sweetalert2-toasts-body() {
|
||||
&.swal2-toast-shown {
|
||||
.swal2-container {
|
||||
box-sizing: border-box;
|
||||
width: $swal2-toast-width;
|
||||
max-width: 100%;
|
||||
background-color: transparent;
|
||||
pointer-events: none;
|
||||
|
||||
&.swal2-top {
|
||||
inset: 0 auto auto 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
&.swal2-top-end,
|
||||
&.swal2-top-right {
|
||||
inset: 0 0 auto auto;
|
||||
}
|
||||
|
||||
&.swal2-top-start,
|
||||
&.swal2-top-left {
|
||||
inset: 0 auto auto 0;
|
||||
}
|
||||
|
||||
&.swal2-center-start,
|
||||
&.swal2-center-left {
|
||||
inset: 50% auto auto 0;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
&.swal2-center {
|
||||
inset: 50% auto auto 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
&.swal2-center-end,
|
||||
&.swal2-center-right {
|
||||
inset: 50% 0 auto auto;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
&.swal2-bottom-start,
|
||||
&.swal2-bottom-left {
|
||||
inset: auto auto 0 0;
|
||||
}
|
||||
|
||||
&.swal2-bottom {
|
||||
inset: auto auto 0 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
&.swal2-bottom-end,
|
||||
&.swal2-bottom-right {
|
||||
inset: auto 0 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
203
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/scss/_toasts.scss
Normal file
203
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/scss/_toasts.scss
Normal file
@@ -0,0 +1,203 @@
|
||||
.swal2-popup {
|
||||
&.swal2-toast {
|
||||
box-sizing: border-box;
|
||||
grid-column: 1/4 !important;
|
||||
grid-row: 1/4 !important;
|
||||
grid-template-columns: min-content auto min-content;
|
||||
padding: $swal2-toast-padding;
|
||||
overflow-y: hidden;
|
||||
background: $swal2-toast-background;
|
||||
box-shadow: $swal2-toast-box-shadow;
|
||||
pointer-events: all;
|
||||
|
||||
> * {
|
||||
grid-column: 2;
|
||||
}
|
||||
|
||||
.swal2-title {
|
||||
margin: $swal2-toast-title-margin;
|
||||
padding: $swal2-toast-title-padding;
|
||||
font-size: $swal2-toast-title-font-size;
|
||||
text-align: initial;
|
||||
}
|
||||
|
||||
.swal2-loading {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.swal2-input {
|
||||
height: $swal2-toast-input-height;
|
||||
margin: $swal2-toast-input-margin;
|
||||
font-size: $swal2-toast-input-font-size;
|
||||
}
|
||||
|
||||
.swal2-validation-message {
|
||||
font-size: $swal2-toast-validation-font-size;
|
||||
}
|
||||
|
||||
.swal2-footer {
|
||||
margin: $swal2-toast-footer-margin;
|
||||
padding: $swal2-toast-footer-margin;
|
||||
font-size: $swal2-toast-footer-font-size;
|
||||
}
|
||||
|
||||
.swal2-close {
|
||||
grid-column: 3/3;
|
||||
grid-row: 1/99;
|
||||
align-self: center;
|
||||
width: $swal2-toast-close-button-width;
|
||||
height: $swal2-toast-close-button-height;
|
||||
margin: $swal2-toast-close-button-margin;
|
||||
font-size: $swal2-toast-close-button-font-size;
|
||||
}
|
||||
|
||||
.swal2-html-container {
|
||||
margin: $swal2-toast-html-container-margin;
|
||||
padding: $swal2-toast-html-container-padding;
|
||||
overflow: initial;
|
||||
font-size: $swal2-toast-html-container-font-size;
|
||||
text-align: initial;
|
||||
|
||||
&:empty {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.swal2-loader {
|
||||
grid-column: 1;
|
||||
grid-row: 1/99;
|
||||
align-self: center;
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
margin: 0.25em;
|
||||
}
|
||||
|
||||
.swal2-icon {
|
||||
grid-column: 1;
|
||||
grid-row: 1/99;
|
||||
align-self: center;
|
||||
width: 2em;
|
||||
min-width: 2em;
|
||||
height: 2em;
|
||||
margin: 0 0.5em 0 0;
|
||||
|
||||
.swal2-icon-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: $swal2-toast-icon-font-size;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&.swal2-success {
|
||||
.swal2-success-ring {
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
&.swal2-error {
|
||||
[class^='swal2-x-mark-line'] {
|
||||
top: 0.875em;
|
||||
width: 1.375em;
|
||||
|
||||
&[class$='left'] {
|
||||
left: 0.3125em;
|
||||
}
|
||||
|
||||
&[class$='right'] {
|
||||
right: 0.3125em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swal2-actions {
|
||||
justify-content: flex-start;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
margin-top: 0.5em;
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
|
||||
.swal2-styled {
|
||||
margin: 0.25em 0.5em;
|
||||
padding: 0.4em 0.6em;
|
||||
font-size: $swal2-toast-buttons-font-size;
|
||||
}
|
||||
|
||||
.swal2-success {
|
||||
border-color: $swal2-success;
|
||||
|
||||
[class^='swal2-success-circular-line'] {
|
||||
// Emulate moving circular line
|
||||
position: absolute;
|
||||
width: 1.6em;
|
||||
height: 3em;
|
||||
border-radius: 50%;
|
||||
|
||||
&[class$='left'] {
|
||||
top: -0.8em;
|
||||
left: -0.5em;
|
||||
transform: rotate(-45deg);
|
||||
transform-origin: 2em 2em;
|
||||
border-radius: 4em 0 0 4em;
|
||||
}
|
||||
|
||||
&[class$='right'] {
|
||||
top: -0.25em;
|
||||
left: 0.9375em;
|
||||
transform-origin: 0 1.5em;
|
||||
border-radius: 0 4em 4em 0;
|
||||
}
|
||||
}
|
||||
|
||||
.swal2-success-ring {
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
}
|
||||
|
||||
.swal2-success-fix {
|
||||
top: 0;
|
||||
left: 0.4375em;
|
||||
width: 0.4375em;
|
||||
height: 2.6875em;
|
||||
}
|
||||
|
||||
[class^='swal2-success-line'] {
|
||||
height: 0.3125em;
|
||||
|
||||
&[class$='tip'] {
|
||||
top: 1.125em;
|
||||
left: 0.1875em;
|
||||
width: 0.75em;
|
||||
}
|
||||
|
||||
&[class$='long'] {
|
||||
top: 0.9375em;
|
||||
right: 0.1875em;
|
||||
width: 1.375em;
|
||||
}
|
||||
}
|
||||
|
||||
&.swal2-icon-show {
|
||||
@if $swal2-icon-animations {
|
||||
.swal2-success-line-tip {
|
||||
animation: swal2-toast-animate-success-line-tip 0.75s;
|
||||
}
|
||||
|
||||
.swal2-success-line-long {
|
||||
animation: swal2-toast-animate-success-line-long 0.75s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.swal2-show {
|
||||
animation: $swal2-toast-show-animation;
|
||||
}
|
||||
|
||||
&.swal2-hide {
|
||||
animation: $swal2-toast-hide-animation;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
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 { isValidParameter, isUpdatableParameter, isDeprecatedParameter } from './utils/params.js'
|
||||
@@ -0,0 +1,21 @@
|
||||
import { error } from '../utils/utils.js'
|
||||
|
||||
const isJqueryElement = (elem) => typeof elem === 'object' && elem.jquery
|
||||
const isElement = (elem) => elem instanceof Element || isJqueryElement(elem)
|
||||
|
||||
export const argsToParams = (args) => {
|
||||
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 params
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
let bodyClickListenerAdded = false
|
||||
const clickHandlers = {}
|
||||
|
||||
/**
|
||||
* @param {string} attr
|
||||
*/
|
||||
export function bindClickHandler(attr = 'data-swal-template') {
|
||||
clickHandlers[attr] = this
|
||||
|
||||
if (!bodyClickListenerAdded) {
|
||||
document.body.addEventListener('click', bodyClickListener)
|
||||
bodyClickListenerAdded = true
|
||||
}
|
||||
}
|
||||
|
||||
const bodyClickListener = (event) => {
|
||||
for (let el = event.target; el && el !== document; el = el.parentNode) {
|
||||
for (const attr in clickHandlers) {
|
||||
const template = el.getAttribute(attr)
|
||||
if (template) {
|
||||
clickHandlers[attr].fire({ template })
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Main method to create a new SweetAlert2 popup
|
||||
*
|
||||
* @param {...SweetAlertOptions} args
|
||||
* @returns {Promise<SweetAlertResult>}
|
||||
*/
|
||||
export function fire(...args) {
|
||||
const Swal = this // eslint-disable-line @typescript-eslint/no-this-alias
|
||||
return new Swal(...args)
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
export function mixin(mixinParams) {
|
||||
class MixinSwal extends this {
|
||||
_main(params, priorityMixinParams) {
|
||||
return super._main(params, Object.assign({}, mixinParams, priorityMixinParams))
|
||||
}
|
||||
}
|
||||
// @ts-ignore
|
||||
return MixinSwal
|
||||
}
|
||||
@@ -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() // eslint-disable-line no-new
|
||||
}
|
||||
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 }
|
||||
@@ -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 !!(globalState.timeout && globalState.timeout.isRunning())
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import SweetAlert from './SweetAlert.js'
|
||||
|
||||
const Swal = SweetAlert
|
||||
// @ts-ignore
|
||||
Swal.default = Swal
|
||||
|
||||
export default Swal
|
||||
@@ -0,0 +1,10 @@
|
||||
// SweetAlert2
|
||||
// github.com/sweetalert2/sweetalert2
|
||||
|
||||
@import 'scss/theming';
|
||||
@import 'scss/animations';
|
||||
|
||||
body {
|
||||
@include sweetalert2-body();
|
||||
@include sweetalert2-toasts-body();
|
||||
}
|
||||
39
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/types.js
Normal file
39
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/types.js
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @typedef { import('./SweetAlert').SweetAlert } SweetAlert
|
||||
* @typedef { import('sweetalert2').SweetAlertOptions } SweetAlertOptions
|
||||
* @typedef { import('sweetalert2').SweetAlertIcon } SweetAlertIcon
|
||||
* @typedef { import('sweetalert2').SweetAlertInput } SweetAlertInput
|
||||
* @typedef { import('sweetalert2').SweetAlertResult } SweetAlertResult
|
||||
* @typedef { import('sweetalert2').SweetAlertOptions['inputValue'] } SweetAlertInputValue
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef { import('./utils/Timer').default } Timer
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef GlobalState
|
||||
* @property {SweetAlert} [currentInstance]
|
||||
* @property {Element | null} [previousActiveElement]
|
||||
* @property {Timer} [timeout]
|
||||
* @property {NodeJS.Timeout} [restoreFocusTimeout]
|
||||
* @property {(this: HTMLElement, event: KeyboardEvent) => any} [keydownHandler]
|
||||
* @property {HTMLElement | (Window & typeof globalThis)} [keydownTarget]
|
||||
* @property {boolean} [keydownHandlerAdded]
|
||||
* @property {boolean} [keydownListenerCapture]
|
||||
* @property {Function} [swalCloseEventFinishedCallback]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
@@ -0,0 +1,10 @@
|
||||
/** @typedef {'cancel' | 'backdrop' | 'close' | 'esc' | 'timer'} DismissReason */
|
||||
|
||||
/** @type {Record<DismissReason, DismissReason>} */
|
||||
export const DismissReason = Object.freeze({
|
||||
cancel: 'cancel',
|
||||
backdrop: 'backdrop',
|
||||
close: 'close',
|
||||
esc: 'esc',
|
||||
timer: 'timer',
|
||||
})
|
||||
71
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/utils/Timer.js
Normal file
71
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/utils/Timer.js
Normal file
@@ -0,0 +1,71 @@
|
||||
export default class Timer {
|
||||
/**
|
||||
* @param {Function} 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
|
||||
}
|
||||
}
|
||||
32
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/utils/aria.js
Normal file
32
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/utils/aria.js
Normal file
@@ -0,0 +1,32 @@
|
||||
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 bodyChildren = Array.from(document.body.children)
|
||||
bodyChildren.forEach((el) => {
|
||||
if (el === getContainer() || el.contains(getContainer())) {
|
||||
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')
|
||||
}
|
||||
})
|
||||
}
|
||||
167
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/utils/classes.js
Normal file
167
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/utils/classes.js
Normal file
@@ -0,0 +1,167 @@
|
||||
export const swalPrefix = 'swal2-'
|
||||
|
||||
/**
|
||||
* @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'
|
||||
* | 'default-outline'
|
||||
* | 'footer'
|
||||
* | 'icon'
|
||||
* | 'icon-content'
|
||||
* | 'image'
|
||||
* | 'input'
|
||||
* | 'file'
|
||||
* | 'range'
|
||||
* | 'select'
|
||||
* | 'radio'
|
||||
* | 'checkbox'
|
||||
* | 'label'
|
||||
* | 'textarea'
|
||||
* | 'inputerror'
|
||||
* | 'input-label'
|
||||
* | 'validation-message'
|
||||
* | 'progress-steps'
|
||||
* | 'active-progress-step'
|
||||
* | 'progress-step'
|
||||
* | 'progress-step-line'
|
||||
* | 'loader'
|
||||
* | 'loading'
|
||||
* | 'styled'
|
||||
* | 'top'
|
||||
* | 'top-start'
|
||||
* | 'top-end'
|
||||
* | 'top-left'
|
||||
* | 'top-right'
|
||||
* | 'center'
|
||||
* | 'center-start'
|
||||
* | 'center-end'
|
||||
* | 'center-left'
|
||||
* | 'center-right'
|
||||
* | 'bottom'
|
||||
* | 'bottom-start'
|
||||
* | 'bottom-end'
|
||||
* | 'bottom-left'
|
||||
* | 'bottom-right'
|
||||
* | 'grow-row'
|
||||
* | 'grow-column'
|
||||
* | 'grow-fullscreen'
|
||||
* | 'rtl'
|
||||
* | 'timer-progress-bar'
|
||||
* | 'timer-progress-bar-container'
|
||||
* | 'scrollbar-measure'
|
||||
* | 'icon-success'
|
||||
* | 'icon-warning'
|
||||
* | 'icon-info'
|
||||
* | 'icon-question'
|
||||
* | 'icon-error'
|
||||
* } SwalClass
|
||||
* @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',
|
||||
'default-outline',
|
||||
'footer',
|
||||
'icon',
|
||||
'icon-content',
|
||||
'image',
|
||||
'input',
|
||||
'file',
|
||||
'range',
|
||||
'select',
|
||||
'radio',
|
||||
'checkbox',
|
||||
'label',
|
||||
'textarea',
|
||||
'inputerror',
|
||||
'input-label',
|
||||
'validation-message',
|
||||
'progress-steps',
|
||||
'active-progress-step',
|
||||
'progress-step',
|
||||
'progress-step-line',
|
||||
'loader',
|
||||
'loading',
|
||||
'styled',
|
||||
'top',
|
||||
'top-start',
|
||||
'top-end',
|
||||
'top-left',
|
||||
'top-right',
|
||||
'center',
|
||||
'center-start',
|
||||
'center-end',
|
||||
'center-left',
|
||||
'center-right',
|
||||
'bottom',
|
||||
'bottom-start',
|
||||
'bottom-end',
|
||||
'bottom-left',
|
||||
'bottom-right',
|
||||
'grow-row',
|
||||
'grow-column',
|
||||
'grow-fullscreen',
|
||||
'rtl',
|
||||
'timer-progress-bar',
|
||||
'timer-progress-bar-container',
|
||||
'scrollbar-measure',
|
||||
'icon-success',
|
||||
'icon-warning',
|
||||
'icon-info',
|
||||
'icon-question',
|
||||
'icon-error',
|
||||
]
|
||||
|
||||
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-]{2,24}$/.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')
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { isNodeEnv } from '../isNodeEnv.js'
|
||||
|
||||
/**
|
||||
* @returns {'webkitAnimationEnd' | 'animationend' | false}
|
||||
*/
|
||||
export const animationEndEvent = (() => {
|
||||
// Prevent run in Node env
|
||||
if (isNodeEnv()) {
|
||||
return false
|
||||
}
|
||||
|
||||
const testEl = document.createElement('div')
|
||||
|
||||
// Chrome, Safari and Opera
|
||||
if (typeof testEl.style.webkitAnimation !== 'undefined') {
|
||||
return 'webkitAnimationEnd'
|
||||
}
|
||||
|
||||
// Standard syntax
|
||||
if (typeof testEl.style.animation !== 'undefined') {
|
||||
return 'animationend'
|
||||
}
|
||||
|
||||
return false
|
||||
})()
|
||||
@@ -0,0 +1,323 @@
|
||||
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')
|
||||
head &&
|
||||
Array.from(head.childNodes).forEach((child) => {
|
||||
elem.appendChild(child)
|
||||
})
|
||||
const body = parsed.querySelector('body')
|
||||
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 && params.customClass[className]) {
|
||||
if (typeof params.customClass[className] !== 'string' && !params.customClass[className].forEach) {
|
||||
warn(
|
||||
`Invalid type of customClass.${className}! Expected string or iterable object, got "${typeof params.customClass[
|
||||
className
|
||||
]}"`
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
addClass(elem, params.customClass[className])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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) => {
|
||||
condition ? elem.classList.add(className) : elem.classList.remove(className)
|
||||
})
|
||||
} else {
|
||||
condition ? target.classList.add(className) : 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 {*} 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` : value)
|
||||
} else {
|
||||
elem.style.removeProperty(property)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement | null} elem
|
||||
* @param {string} display
|
||||
*/
|
||||
export const show = (elem, display = 'flex') => {
|
||||
elem && (elem.style.display = display)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement | null} elem
|
||||
*/
|
||||
export const hide = (elem) => {
|
||||
elem && (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 {any} condition
|
||||
* @param {string} display
|
||||
*/
|
||||
export const toggle = (elem, condition, display = 'flex') => {
|
||||
condition ? show(elem, display) : hide(elem)
|
||||
}
|
||||
|
||||
/**
|
||||
* borrowed from jquery $(elem).is(':visible') implementation
|
||||
*
|
||||
* @param {HTMLElement | null} elem
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const isVisible = (elem) => !!(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) => !!(elem.scrollHeight > elem.clientHeight)
|
||||
|
||||
/**
|
||||
* 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}%`
|
||||
}
|
||||
@@ -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')
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
export * from './domUtils.js'
|
||||
export * from './init.js'
|
||||
export * from './getters.js'
|
||||
export * from './parseHtmlToContainer.js'
|
||||
export * from './animationEndEvent.js'
|
||||
export * from './renderers/render.js'
|
||||
151
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/utils/dom/init.js
Normal file
151
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/utils/dom/init.js
Normal file
@@ -0,0 +1,151 @@
|
||||
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'], swalClasses['has-column']]
|
||||
)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
const resetValidationMessage = () => {
|
||||
globalState.currentInstance.resetValidationMessage()
|
||||
}
|
||||
|
||||
const addInputChangeListeners = () => {
|
||||
const popup = getPopup()
|
||||
|
||||
const input = getDirectChildByClass(popup, swalClasses.input)
|
||||
const file = getDirectChildByClass(popup, swalClasses.file)
|
||||
/** @type {HTMLInputElement} */
|
||||
const range = popup.querySelector(`.${swalClasses.range} input`)
|
||||
/** @type {HTMLOutputElement} */
|
||||
const rangeOutput = popup.querySelector(`.${swalClasses.range} output`)
|
||||
const select = getDirectChildByClass(popup, swalClasses.select)
|
||||
/** @type {HTMLInputElement} */
|
||||
const checkbox = popup.querySelector(`.${swalClasses.checkbox} input`)
|
||||
const textarea = getDirectChildByClass(popup, swalClasses.textarea)
|
||||
|
||||
input.oninput = resetValidationMessage
|
||||
file.onchange = resetValidationMessage
|
||||
select.onchange = resetValidationMessage
|
||||
checkbox.onchange = resetValidationMessage
|
||||
textarea.oninput = resetValidationMessage
|
||||
|
||||
range.oninput = () => {
|
||||
resetValidationMessage()
|
||||
rangeOutput.value = range.value
|
||||
}
|
||||
|
||||
range.onchange = () => {
|
||||
resetValidationMessage()
|
||||
rangeOutput.value = range.value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string | HTMLElement} target
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
const getTarget = (target) => (typeof target === 'string' ? document.querySelector(target) : target)
|
||||
|
||||
/**
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
const setupAccessibility = (params) => {
|
||||
const popup = getPopup()
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add modal + backdrop + no-war message for Russians 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)
|
||||
|
||||
const targetElement = getTarget(params.target)
|
||||
targetElement.appendChild(container)
|
||||
|
||||
setupAccessibility(params)
|
||||
setupRTL(targetElement)
|
||||
addInputChangeListeners()
|
||||
}
|
||||
@@ -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 {Record<string, any>} 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 {Record<string, any>} 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 !!inputValue && 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 {any} param
|
||||
* @param {HTMLElement} target
|
||||
*/
|
||||
const handleObject = (param, target) => {
|
||||
// JQuery element(s)
|
||||
if (param.jquery) {
|
||||
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))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
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)
|
||||
|
||||
// Buttons background colors
|
||||
if (params.confirmButtonColor) {
|
||||
confirmButton.style.backgroundColor = params.confirmButtonColor
|
||||
dom.addClass(confirmButton, swalClasses['default-outline'])
|
||||
}
|
||||
if (params.denyButtonColor) {
|
||||
denyButton.style.backgroundColor = params.denyButtonColor
|
||||
dom.addClass(denyButton, swalClasses['default-outline'])
|
||||
}
|
||||
if (params.cancelButtonColor) {
|
||||
cancelButton.style.backgroundColor = params.cancelButtonColor
|
||||
dom.addClass(cancelButton, swalClasses['default-outline'])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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, params.footer, 'block')
|
||||
|
||||
if (params.footer) {
|
||||
dom.parseHtmlToContainer(params.footer, footer)
|
||||
}
|
||||
|
||||
// Custom class
|
||||
dom.applyCustomClass(footer, params, 'footer')
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
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)
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
}
|
||||
}
|
||||
|
||||
const successIconHtml = `
|
||||
<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> <div class="swal2-success-fix"></div>
|
||||
<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
|
||||
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')
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
/// <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)
|
||||
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 input = dom.getInput(dom.getPopup(), inputClass)
|
||||
if (!input) {
|
||||
return
|
||||
}
|
||||
|
||||
removeAttributes(input)
|
||||
|
||||
for (const attr in inputAttributes) {
|
||||
input.setAttribute(attr, inputAttributes[attr])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SweetAlertOptions} params
|
||||
*/
|
||||
const setCustomClass = (params) => {
|
||||
const inputContainer = getInputContainer(params.input)
|
||||
if (typeof params.customClass === 'object') {
|
||||
dom.addClass(inputContainer, params.customClass.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 {SweetAlertOptions['input']} inputType
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
const getInputContainer = (inputType) => {
|
||||
return dom.getDirectChildByClass(dom.getPopup(), swalClasses[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 {HTMLInputElement} input
|
||||
* @param {SweetAlertOptions} params
|
||||
* @returns {HTMLInputElement}
|
||||
*/
|
||||
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 =
|
||||
(input, params) => {
|
||||
checkAndSetInputValue(input, params.inputValue)
|
||||
setInputLabel(input, input, params)
|
||||
setInputPlaceholder(input, params)
|
||||
input.type = params.input
|
||||
return input
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLInputElement} input
|
||||
* @param {SweetAlertOptions} params
|
||||
* @returns {HTMLInputElement}
|
||||
*/
|
||||
renderInputType.file = (input, params) => {
|
||||
setInputLabel(input, input, params)
|
||||
setInputPlaceholder(input, params)
|
||||
return input
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLInputElement} range
|
||||
* @param {SweetAlertOptions} params
|
||||
* @returns {HTMLInputElement}
|
||||
*/
|
||||
renderInputType.range = (range, params) => {
|
||||
const rangeInput = range.querySelector('input')
|
||||
const rangeOutput = range.querySelector('output')
|
||||
checkAndSetInputValue(rangeInput, params.inputValue)
|
||||
rangeInput.type = params.input
|
||||
checkAndSetInputValue(rangeOutput, params.inputValue)
|
||||
setInputLabel(rangeInput, range, params)
|
||||
return range
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLSelectElement} select
|
||||
* @param {SweetAlertOptions} params
|
||||
* @returns {HTMLSelectElement}
|
||||
*/
|
||||
renderInputType.select = (select, params) => {
|
||||
select.textContent = ''
|
||||
if (params.inputPlaceholder) {
|
||||
const placeholder = document.createElement('option')
|
||||
dom.setInnerHtml(placeholder, params.inputPlaceholder)
|
||||
placeholder.value = ''
|
||||
placeholder.disabled = true
|
||||
placeholder.selected = true
|
||||
select.appendChild(placeholder)
|
||||
}
|
||||
setInputLabel(select, select, params)
|
||||
return select
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLInputElement} radio
|
||||
* @returns {HTMLInputElement}
|
||||
*/
|
||||
renderInputType.radio = (radio) => {
|
||||
radio.textContent = ''
|
||||
return radio
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLLabelElement} checkboxContainer
|
||||
* @param {SweetAlertOptions} params
|
||||
* @returns {HTMLInputElement}
|
||||
*/
|
||||
renderInputType.checkbox = (checkboxContainer, params) => {
|
||||
const checkbox = dom.getInput(dom.getPopup(), 'checkbox')
|
||||
checkbox.value = '1'
|
||||
checkbox.checked = Boolean(params.inputValue)
|
||||
const label = checkboxContainer.querySelector('span')
|
||||
dom.setInnerHtml(label, params.inputPlaceholder)
|
||||
return checkbox
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLTextAreaElement} textarea
|
||||
* @param {SweetAlertOptions} params
|
||||
* @returns {HTMLTextAreaElement}
|
||||
*/
|
||||
renderInputType.textarea = (textarea, params) => {
|
||||
checkAndSetInputValue(textarea, params.inputValue)
|
||||
setInputPlaceholder(textarea, params)
|
||||
setInputLabel(textarea, textarea, 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 initialPopupWidth = parseInt(window.getComputedStyle(dom.getPopup()).width)
|
||||
const textareaResizeHandler = () => {
|
||||
// check if texarea is still in document (i.e. popup wasn't closed in the meantime)
|
||||
if (!document.body.contains(textarea)) {
|
||||
return
|
||||
}
|
||||
const textareaWidth = textarea.offsetWidth + getMargin(textarea)
|
||||
if (textareaWidth > initialPopupWidth) {
|
||||
dom.getPopup().style.width = `${textareaWidth}px`
|
||||
} else {
|
||||
dom.applyNumericalStyle(dom.getPopup(), 'width', params.width)
|
||||
}
|
||||
}
|
||||
new MutationObserver(textareaResizeHandler).observe(textarea, {
|
||||
attributes: true,
|
||||
attributeFilter: ['style'],
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return textarea
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import { swalClasses } from '../../classes.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()
|
||||
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)
|
||||
}
|
||||
|
||||
/**
|
||||
* @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')
|
||||
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, 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')
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
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) => {
|
||||
/** @type {HTMLTemplateElement} */
|
||||
const template = typeof params.template === 'string' ? 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 {SweetAlertOptions}
|
||||
*/
|
||||
const getSwalParams = (templateContent) => {
|
||||
const result = {}
|
||||
/** @type {HTMLElement[]} */
|
||||
const swalParams = Array.from(templateContent.querySelectorAll('swal-param'))
|
||||
swalParams.forEach((param) => {
|
||||
showWarningsForAttributes(param, ['name', 'value'])
|
||||
const paramName = param.getAttribute('name')
|
||||
const value = param.getAttribute('value')
|
||||
if (typeof defaultParams[paramName] === 'boolean') {
|
||||
result[paramName] = value !== 'false'
|
||||
} else if (typeof defaultParams[paramName] === 'object') {
|
||||
result[paramName] = JSON.parse(value)
|
||||
} else {
|
||||
result[paramName] = value
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DocumentFragment} templateContent
|
||||
* @returns {SweetAlertOptions}
|
||||
*/
|
||||
const getSwalFunctionParams = (templateContent) => {
|
||||
const result = {}
|
||||
/** @type {HTMLElement[]} */
|
||||
const swalFunctions = Array.from(templateContent.querySelectorAll('swal-function-param'))
|
||||
swalFunctions.forEach((param) => {
|
||||
const paramName = param.getAttribute('name')
|
||||
const value = param.getAttribute('value')
|
||||
result[paramName] = new Function(`return ${value}`)()
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DocumentFragment} templateContent
|
||||
* @returns {SweetAlertOptions}
|
||||
*/
|
||||
const getSwalButtons = (templateContent) => {
|
||||
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')
|
||||
result[`${type}ButtonText`] = button.innerHTML
|
||||
result[`show${capitalizeFirstLetter(type)}Button`] = true
|
||||
if (button.hasAttribute('color')) {
|
||||
result[`${type}ButtonColor`] = button.getAttribute('color')
|
||||
}
|
||||
if (button.hasAttribute('aria-label')) {
|
||||
result[`${type}ButtonAriaLabel`] = button.getAttribute('aria-label')
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DocumentFragment} templateContent
|
||||
* @returns {SweetAlertOptions}
|
||||
*/
|
||||
const getSwalImage = (templateContent) => {
|
||||
const result = {}
|
||||
/** @type {HTMLElement} */
|
||||
const image = templateContent.querySelector('swal-image')
|
||||
if (image) {
|
||||
showWarningsForAttributes(image, ['src', 'width', 'height', 'alt'])
|
||||
if (image.hasAttribute('src')) {
|
||||
result.imageUrl = image.getAttribute('src')
|
||||
}
|
||||
if (image.hasAttribute('width')) {
|
||||
result.imageWidth = image.getAttribute('width')
|
||||
}
|
||||
if (image.hasAttribute('height')) {
|
||||
result.imageHeight = image.getAttribute('height')
|
||||
}
|
||||
if (image.hasAttribute('alt')) {
|
||||
result.imageAlt = image.getAttribute('alt')
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DocumentFragment} templateContent
|
||||
* @returns {SweetAlertOptions}
|
||||
*/
|
||||
const getSwalIcon = (templateContent) => {
|
||||
const result = {}
|
||||
/** @type {HTMLElement} */
|
||||
const icon = templateContent.querySelector('swal-icon')
|
||||
if (icon) {
|
||||
showWarningsForAttributes(icon, ['type', 'color'])
|
||||
if (icon.hasAttribute('type')) {
|
||||
/** @type {SweetAlertIcon} */
|
||||
// @ts-ignore
|
||||
result.icon = icon.getAttribute('type')
|
||||
}
|
||||
if (icon.hasAttribute('color')) {
|
||||
result.iconColor = icon.getAttribute('color')
|
||||
}
|
||||
result.iconHtml = icon.innerHTML
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DocumentFragment} templateContent
|
||||
* @returns {SweetAlertOptions}
|
||||
*/
|
||||
const getSwalInput = (templateContent) => {
|
||||
const result = {}
|
||||
/** @type {HTMLElement} */
|
||||
const input = templateContent.querySelector('swal-input')
|
||||
if (input) {
|
||||
showWarningsForAttributes(input, ['type', 'label', 'placeholder', 'value'])
|
||||
/** @type {SweetAlertInput} */
|
||||
// @ts-ignore
|
||||
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')
|
||||
const optionName = option.innerHTML
|
||||
result.inputOptions[optionValue] = optionName
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DocumentFragment} templateContent
|
||||
* @param {string[]} paramNames
|
||||
* @returns {SweetAlertOptions}
|
||||
*/
|
||||
const getSwalStringParams = (templateContent, paramNames) => {
|
||||
const result = {}
|
||||
for (const i in paramNames) {
|
||||
const paramName = paramNames[i]
|
||||
/** @type {HTMLElement} */
|
||||
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.'
|
||||
}`,
|
||||
])
|
||||
}
|
||||
})
|
||||
}
|
||||
106
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/utils/iosFix.js
Normal file
106
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/utils/iosFix.js
Normal file
@@ -0,0 +1,106 @@
|
||||
import { swalClasses } from '../utils/classes.js'
|
||||
import * as dom from './dom/index.js'
|
||||
|
||||
// @ts-ignore
|
||||
export const isSafariOrIOS = typeof window !== 'undefined' && !!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 &&
|
||||
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 {*} event
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isStylus = (event) => {
|
||||
return event.touches && event.touches.length && 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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Detect Node env
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const isNodeEnv = () => typeof window === 'undefined' || typeof document === 'undefined'
|
||||
117
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/utils/openPopup.js
Normal file
117
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/utils/openPopup.js
Normal file
@@ -0,0 +1,117 @@
|
||||
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 (typeof params.willOpen === 'function') {
|
||||
params.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()) {
|
||||
fixScrollContainer(container, params.scrollbarPadding, initialBodyOverflow)
|
||||
setAriaHidden()
|
||||
}
|
||||
|
||||
if (!dom.isToast() && !globalState.previousActiveElement) {
|
||||
globalState.previousActiveElement = document.activeElement
|
||||
}
|
||||
|
||||
if (typeof params.didOpen === 'function') {
|
||||
setTimeout(() => params.didOpen(popup))
|
||||
}
|
||||
|
||||
dom.removeClass(container, swalClasses['no-transition'])
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {AnimationEvent} event
|
||||
*/
|
||||
const swalOpenAnimationFinished = (event) => {
|
||||
const popup = dom.getPopup()
|
||||
if (event.target !== popup || !dom.animationEndEvent) {
|
||||
return
|
||||
}
|
||||
const container = dom.getContainer()
|
||||
popup.removeEventListener(dom.animationEndEvent, swalOpenAnimationFinished)
|
||||
container.style.overflowY = 'auto'
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} container
|
||||
* @param {HTMLElement} popup
|
||||
*/
|
||||
const setScrollingVisibility = (container, popup) => {
|
||||
if (dom.animationEndEvent && dom.hasCssAnimation(popup)) {
|
||||
container.style.overflowY = 'hidden'
|
||||
popup.addEventListener(dom.animationEndEvent, 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) => {
|
||||
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
|
||||
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'])
|
||||
}
|
||||
}
|
||||
235
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/utils/params.js
Normal file
235
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/utils/params.js
Normal file
@@ -0,0 +1,235 @@
|
||||
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,
|
||||
animation: true,
|
||||
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,
|
||||
}
|
||||
|
||||
export const updatableParams = [
|
||||
'allowEscapeKey',
|
||||
'allowOutsideClick',
|
||||
'background',
|
||||
'buttonsStyling',
|
||||
'cancelButtonAriaLabel',
|
||||
'cancelButtonColor',
|
||||
'cancelButtonText',
|
||||
'closeButtonAriaLabel',
|
||||
'closeButtonHtml',
|
||||
'color',
|
||||
'confirmButtonAriaLabel',
|
||||
'confirmButtonColor',
|
||||
'confirmButtonText',
|
||||
'currentProgressStep',
|
||||
'customClass',
|
||||
'denyButtonAriaLabel',
|
||||
'denyButtonColor',
|
||||
'denyButtonText',
|
||||
'didClose',
|
||||
'didDestroy',
|
||||
'footer',
|
||||
'hideClass',
|
||||
'html',
|
||||
'icon',
|
||||
'iconColor',
|
||||
'iconHtml',
|
||||
'imageAlt',
|
||||
'imageHeight',
|
||||
'imageUrl',
|
||||
'imageWidth',
|
||||
'preConfirm',
|
||||
'preDeny',
|
||||
'progressSteps',
|
||||
'returnFocus',
|
||||
'reverseButtons',
|
||||
'showCancelButton',
|
||||
'showCloseButton',
|
||||
'showConfirmButton',
|
||||
'showDenyButton',
|
||||
'text',
|
||||
'title',
|
||||
'titleText',
|
||||
'willClose',
|
||||
]
|
||||
|
||||
/** @type {Record<string, string>} */
|
||||
export const deprecatedParams = {}
|
||||
|
||||
const toastIncompatibleParams = [
|
||||
'allowOutsideClick',
|
||||
'allowEnterKey',
|
||||
'backdrop',
|
||||
'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`')
|
||||
}
|
||||
|
||||
for (const param in params) {
|
||||
checkIfParamIsValid(param)
|
||||
|
||||
if (params.toast) {
|
||||
checkIfToastParamIsValid(param)
|
||||
}
|
||||
|
||||
checkIfParamIsDeprecated(param)
|
||||
}
|
||||
}
|
||||
|
||||
export default defaultParams
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
86
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/utils/utils.js
Normal file
86
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/utils/utils.js
Normal file
@@ -0,0 +1,86 @@
|
||||
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) => {
|
||||
warnOnce(
|
||||
`"${deprecatedParam}" is deprecated and will be removed in the next major release. Please 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 {Function | any} arg
|
||||
* @returns {any}
|
||||
*/
|
||||
export const callIfFunction = (arg) => (typeof arg === 'function' ? arg() : arg)
|
||||
|
||||
/**
|
||||
* @param {any} arg
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const hasToPromiseFn = (arg) => arg && typeof arg.toPromise === 'function'
|
||||
|
||||
/**
|
||||
* @param {any} arg
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
export const asPromise = (arg) => (hasToPromiseFn(arg) ? arg.toPromise() : Promise.resolve(arg))
|
||||
|
||||
/**
|
||||
* @param {any} arg
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const isPromise = (arg) => arg && Promise.resolve(arg) === arg
|
||||
265
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/variables.scss
Normal file
265
ZpcBulletinBoard/wwwroot/lib/sweetalert2/src/variables.scss
Normal file
@@ -0,0 +1,265 @@
|
||||
$swal2-white: #fff !default;
|
||||
$swal2-black: #000 !default;
|
||||
$swal2-outline-color: rgba(100, 150, 200, 0.5) !default;
|
||||
|
||||
// CONTAINER
|
||||
$swal2-container-padding: 0.625em !default;
|
||||
|
||||
// POPUP
|
||||
$swal2-width: 32em !default;
|
||||
$swal2-padding: 0 0 1.25em !default;
|
||||
$swal2-border: none !default;
|
||||
$swal2-color: lighten($swal2-black, 33) !default;
|
||||
$swal2-border-radius: 5px !default;
|
||||
$swal2-box-shadow: #d9d9d9 !default;
|
||||
|
||||
// ANIMATIONS
|
||||
$swal2-show-animation: swal2-show 0.3s !default;
|
||||
$swal2-hide-animation: swal2-hide 0.15s forwards !default;
|
||||
|
||||
// BACKGROUND
|
||||
$swal2-background: $swal2-white !default;
|
||||
|
||||
// TYPOGRAPHY
|
||||
$swal2-font: inherit !default;
|
||||
$swal2-font-size: 1rem !default;
|
||||
|
||||
// BACKDROP
|
||||
$swal2-backdrop: rgba($swal2-black, 0.4) !default;
|
||||
$swal2-backdrop-transition: background-color 0.1s !default;
|
||||
|
||||
// ICONS
|
||||
$swal2-icon-size: 5em !default;
|
||||
$swal2-icon-animations: true !default;
|
||||
$swal2-icon-margin: 2.5em auto 0.6em !default;
|
||||
$swal2-icon-font-family: inherit !default;
|
||||
$swal2-icon-font-size: 3.75em !default;
|
||||
$swal2-icon-border-color: #000 !default;
|
||||
$swal2-icon-zoom: null !default;
|
||||
$swal2-success: #a5dc86 !default;
|
||||
$swal2-success-border: rgba($swal2-success, 0.3) !default;
|
||||
$swal2-error: #f27474 !default;
|
||||
$swal2-warning: #f8bb86 !default;
|
||||
$swal2-info: #3fc3ee !default;
|
||||
$swal2-question: #87adbd !default;
|
||||
|
||||
// IMAGE
|
||||
$swal2-image-margin: 2em auto 1em !default;
|
||||
|
||||
// TITLE
|
||||
$swal2-title-position: relative !default;
|
||||
$swal2-title-max-width: 100% !default;
|
||||
$swal2-title-margin: 0 !default;
|
||||
$swal2-title-padding: 0.8em 1em 0 !default;
|
||||
$swal2-title-color: inherit !default;
|
||||
$swal2-title-font-size: 1.875em !default;
|
||||
$swal2-title-font-weight: 600 !default;
|
||||
$swal2-title-text-align: center !default;
|
||||
|
||||
// HTML CONTAINER
|
||||
$swal2-html-container-justify-content: center !default;
|
||||
$swal2-html-container-margin: 1em 1.6em 0.3em !default;
|
||||
$swal2-html-container-padding: 0 !default;
|
||||
$swal2-html-container-overflow: auto !default;
|
||||
$swal2-html-container-color: inherit !default;
|
||||
$swal2-html-container-font-size: 1.125em !default;
|
||||
$swal2-html-container-font-weight: normal !default;
|
||||
$swal2-html-container-line-height: normal !default;
|
||||
$swal2-html-container-text-align: center !default;
|
||||
$swal2-html-container-word-wrap: break-word !default;
|
||||
$swal2-html-container-word-break: break-word !default;
|
||||
|
||||
// INPUT
|
||||
$swal2-input-margin: 1em 2em 3px !default;
|
||||
$swal2-input-width: auto !default;
|
||||
$swal2-input-height: 2.625em !default;
|
||||
$swal2-input-padding: 0 0.75em !default;
|
||||
$swal2-input-border: 1px solid lighten($swal2-black, 85) !default;
|
||||
$swal2-input-border-radius: 0.1875em !default;
|
||||
$swal2-input-box-shadow:
|
||||
inset 0 1px 1px rgba($swal2-black, 0.06),
|
||||
0 0 0 3px transparent !default;
|
||||
$swal2-input-font-size: 1.125em !default;
|
||||
$swal2-input-background: transparent !default;
|
||||
$swal2-input-color: inherit !default;
|
||||
$swal2-input-transition:
|
||||
border-color 0.1s,
|
||||
box-shadow 0.1s !default;
|
||||
|
||||
// INPUT:FOCUS
|
||||
$swal2-input-focus-border: 1px solid #b4dbed !default;
|
||||
$swal2-input-focus-outline: none !default;
|
||||
$swal2-input-focus-box-shadow:
|
||||
inset 0 1px 1px rgba($swal2-black, 0.06),
|
||||
0 0 0 3px $swal2-outline-color !default;
|
||||
|
||||
// TEXTAREA SPECIFIC VARIABLES
|
||||
$swal2-textarea-height: 6.75em !default;
|
||||
$swal2-textarea-padding: 0.75em !default;
|
||||
|
||||
// INPUT LABEL
|
||||
$swal2-input-label-margin: 1em auto 0 !default;
|
||||
$swal2-input-label-justify-content: center !default;
|
||||
|
||||
// VALIDATION MESSAGE
|
||||
$swal2-validation-message-align-items: center !default;
|
||||
$swal2-validation-message-justify-content: center !default;
|
||||
$swal2-validation-message-margin: 1em 0 0 !default;
|
||||
$swal2-validation-message-padding: 0.625em !default;
|
||||
$swal2-validation-message-background: lighten($swal2-black, 94) !default;
|
||||
$swal2-validation-message-color: lighten($swal2-black, 40) !default;
|
||||
$swal2-validation-message-font-size: 1em !default;
|
||||
$swal2-validation-message-font-weight: 300 !default;
|
||||
$swal2-validation-message-icon-background: $swal2-error !default;
|
||||
$swal2-validation-message-icon-color: $swal2-white !default;
|
||||
$swal2-validation-message-icon-zoom: null !default;
|
||||
|
||||
// PROGRESS STEPS
|
||||
$swal2-progress-steps-flex-wrap: wrap !default;
|
||||
$swal2-progress-steps-align-items: center !default;
|
||||
$swal2-progress-steps-max-width: 100% !default;
|
||||
$swal2-progress-steps-background: transparent !default;
|
||||
$swal2-progress-steps-margin: 1.25em auto !default;
|
||||
$swal2-progress-steps-padding: 0 !default;
|
||||
$swal2-progress-steps-font-weight: 600 !default;
|
||||
$swal2-progress-steps-distance: 2.5em !default;
|
||||
$swal2-progress-step-width: 2em;
|
||||
$swal2-progress-step-height: 2em;
|
||||
$swal2-progress-step-border-radius: 2em;
|
||||
$swal2-progress-step-background: #add8e6 !default;
|
||||
$swal2-progress-step-color: $swal2-white !default;
|
||||
$swal2-active-step-background: #2778c4 !default;
|
||||
$swal2-active-step-color: $swal2-white !default;
|
||||
|
||||
// FOOTER
|
||||
$swal2-footer-margin: 1em 0 0 !default;
|
||||
$swal2-footer-padding: 1em 1em 0 !default;
|
||||
$swal2-footer-border-color: #eee !default;
|
||||
$swal2-footer-color: inherit !default;
|
||||
$swal2-footer-font-size: 1em !default;
|
||||
$swal2-footer-text-align: center !default;
|
||||
|
||||
// TIMER PROGRESS BAR
|
||||
$swal2-timer-progress-bar-height: 0.25em;
|
||||
$swal2-timer-progress-bar-background: rgba($swal2-black, 0.2) !default;
|
||||
|
||||
// CLOSE BUTTON
|
||||
$swal2-close-button-justify-self: end !default;
|
||||
$swal2-close-button-align-items: center !default;
|
||||
$swal2-close-button-justify-content: center !default;
|
||||
$swal2-close-button-width: 1.2em !default;
|
||||
$swal2-close-button-height: 1.2em !default;
|
||||
$swal2-close-button-position: null !default;
|
||||
$swal2-close-button-gap: 0 !default;
|
||||
$swal2-close-button-padding: 0 !default;
|
||||
$swal2-close-button-transition:
|
||||
color 0.1s,
|
||||
box-shadow 0.1s !default;
|
||||
$swal2-close-button-border: none !default;
|
||||
$swal2-close-button-border-radius: $swal2-border-radius !default;
|
||||
$swal2-close-button-outline: null !default;
|
||||
$swal2-close-button-background: transparent !default;
|
||||
$swal2-close-button-color: #ccc !default;
|
||||
$swal2-close-button-font-family: monospace !default;
|
||||
$swal2-close-button-font-size: 2.5em !default;
|
||||
$swal2-close-button-box-shadow: inset 0 0 0 3px transparent !default;
|
||||
|
||||
// CLOSE BUTTON:HOVER
|
||||
$swal2-close-button-hover-transform: none !default;
|
||||
$swal2-close-button-hover-color: $swal2-error !default;
|
||||
$swal2-close-button-hover-background: transparent !default;
|
||||
|
||||
// CLOSE BUTTON:FOCUS
|
||||
$swal2-close-button-focus-outline: none !default;
|
||||
$swal2-close-button-focus-box-shadow: inset 0 0 0 3px $swal2-outline-color !default;
|
||||
|
||||
// ACTIONS
|
||||
$swal2-actions-flex-wrap: wrap !default;
|
||||
$swal2-actions-align-items: center !default;
|
||||
$swal2-actions-justify-content: center !default;
|
||||
$swal2-actions-width: auto !default;
|
||||
$swal2-actions-margin: 1.25em auto 0 !default;
|
||||
$swal2-actions-padding: 0 !default;
|
||||
|
||||
// COMMON VARIABLES FOR ALL ACTION BUTTONS
|
||||
$swal2-button-margin: 0.3125em !default;
|
||||
$swal2-button-padding: 0.625em 1.1em !default;
|
||||
$swal2-button-transition: box-shadow 0.1s !default;
|
||||
$swal2-button-box-shadow: 0 0 0 3px transparent !default;
|
||||
$swal2-button-font-weight: 500 !default;
|
||||
$swal2-button-darken-hover: rgba($swal2-black, 0.1) !default;
|
||||
$swal2-button-darken-active: rgba($swal2-black, 0.2) !default;
|
||||
$swal2-button-focus-outline: none !default;
|
||||
$swal2-button-focus-box-shadow: 0 0 0 3px $swal2-outline-color !default;
|
||||
|
||||
// CONFIRM BUTTON
|
||||
$swal2-confirm-button-order: null !default;
|
||||
$swal2-confirm-button-border: 0 !default;
|
||||
$swal2-confirm-button-border-radius: 0.25em !default;
|
||||
$swal2-confirm-button-background-color: #7066e0 !default;
|
||||
$swal2-confirm-button-color: $swal2-white !default;
|
||||
$swal2-confirm-button-font-size: 1em !default;
|
||||
$swal2-confirm-button-focus-box-shadow: 0 0 0 3px rgba($swal2-confirm-button-background-color, 0.5) !default;
|
||||
|
||||
// DENY BUTTON
|
||||
$swal2-deny-button-order: null !default;
|
||||
$swal2-deny-button-border: 0 !default;
|
||||
$swal2-deny-button-border-radius: 0.25em !default;
|
||||
$swal2-deny-button-background-color: #dc3741 !default;
|
||||
$swal2-deny-button-color: $swal2-white !default;
|
||||
$swal2-deny-button-font-size: 1em !default;
|
||||
$swal2-deny-button-focus-box-shadow: 0 0 0 3px rgba($swal2-deny-button-background-color, 0.5) !default;
|
||||
|
||||
// CANCEL BUTTON
|
||||
$swal2-cancel-button-order: null !default;
|
||||
$swal2-cancel-button-border: 0 !default;
|
||||
$swal2-cancel-button-border-radius: 0.25em !default;
|
||||
$swal2-cancel-button-background-color: #6e7881 !default;
|
||||
$swal2-cancel-button-color: $swal2-white !default;
|
||||
$swal2-cancel-button-font-size: 1em !default;
|
||||
$swal2-cancel-button-focus-box-shadow: 0 0 0 3px rgba($swal2-cancel-button-background-color, 0.5) !default;
|
||||
|
||||
// LOADER
|
||||
$swal2-loader-align-items: center !default;
|
||||
$swal2-loader-justify-content: center !default;
|
||||
$swal2-loader-width: 2.2em !default;
|
||||
$swal2-loader-height: 2.2em !default;
|
||||
$swal2-loader-margin: 0 1.875em !default;
|
||||
$swal2-loader-animation: swal2-rotate-loading 1.5s linear 0s infinite normal !default;
|
||||
$swal2-loader-border-width: 0.25em !default;
|
||||
$swal2-loader-border-style: solid !default;
|
||||
$swal2-loader-border-radius: 100% !default;
|
||||
$swal2-loader-border-color: #2778c4 transparent #2778c4 transparent !default;
|
||||
|
||||
// TOASTS
|
||||
$swal2-toast-show-animation: swal2-toast-show 0.5s !default;
|
||||
$swal2-toast-hide-animation: swal2-toast-hide 0.1s forwards !default;
|
||||
$swal2-toast-border: none !default;
|
||||
$swal2-toast-box-shadow:
|
||||
0 0 1px hsl(0deg 0% 0% / 0.075),
|
||||
0 1px 2px hsl(0deg 0% 0% / 0.075),
|
||||
1px 2px 4px hsl(0deg 0% 0% / 0.075),
|
||||
1px 3px 8px hsl(0deg 0% 0% / 0.075),
|
||||
2px 4px 16px hsl(0deg 0% 0% / 0.075) !default;
|
||||
$swal2-toast-background: $swal2-white !default;
|
||||
$swal2-toast-close-button-width: 0.8em !default;
|
||||
$swal2-toast-close-button-height: 0.8em !default;
|
||||
$swal2-toast-close-button-margin: 0 !default;
|
||||
$swal2-toast-close-button-font-size: 2em !default;
|
||||
$swal2-toast-width: 360px !default;
|
||||
$swal2-toast-padding: 1em !default;
|
||||
$swal2-toast-title-margin: 0.5em 1em !default;
|
||||
$swal2-toast-title-padding: 0 !default;
|
||||
$swal2-toast-title-font-size: 1em !default;
|
||||
$swal2-toast-icon-font-size: 1.8em !default;
|
||||
$swal2-toast-html-container-margin: 0.5em 1em !default;
|
||||
$swal2-toast-html-container-padding: 0 !default;
|
||||
$swal2-toast-html-container-font-size: 1em !default;
|
||||
$swal2-toast-input-height: 2em !default;
|
||||
$swal2-toast-input-margin: 0.5em !default;
|
||||
$swal2-toast-input-font-size: 1em !default;
|
||||
$swal2-toast-validation-font-size: 1em !default;
|
||||
$swal2-toast-buttons-font-size: 1em !default;
|
||||
$swal2-toast-footer-margin: 0.5em 0 0 !default;
|
||||
$swal2-toast-footer-padding: 0.5em 0 0 !default;
|
||||
$swal2-toast-footer-font-size: 0.8em !default;
|
||||
1244
ZpcBulletinBoard/wwwroot/lib/sweetalert2/sweetalert2.d.ts
vendored
Normal file
1244
ZpcBulletinBoard/wwwroot/lib/sweetalert2/sweetalert2.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user