| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- (function (global, factory) {
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
- typeof define === 'function' && define.amd ? define(factory) :
- (global.Layer = factory());
- }(this, (function () {
- 'use strict';
- const PREFIX = 'layer-';
-
- // Theme & Styles
- const css = `
- .${PREFIX}overlay {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background: rgba(0, 0, 0, 0.4);
- display: flex;
- justify-content: center;
- align-items: center;
- z-index: 1000;
- opacity: 0;
- transition: opacity 0.3s;
- }
- .${PREFIX}overlay.show {
- opacity: 1;
- }
- .${PREFIX}popup {
- background: #fff;
- border-radius: 8px;
- box-shadow: 0 4px 12px rgba(0,0,0,0.15);
- width: 32em;
- max-width: 90%;
- padding: 1.5em;
- display: flex;
- flex-direction: column;
- align-items: center;
- transform: scale(0.9);
- transition: transform 0.3s;
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
- }
- .${PREFIX}overlay.show .${PREFIX}popup {
- transform: scale(1);
- }
- .${PREFIX}title {
- font-size: 1.8em;
- font-weight: 600;
- color: #333;
- margin: 0 0 0.5em;
- text-align: center;
- }
- .${PREFIX}content {
- font-size: 1.125em;
- color: #545454;
- margin-bottom: 1.5em;
- text-align: center;
- line-height: 1.5;
- }
- .${PREFIX}actions {
- display: flex;
- justify-content: center;
- gap: 1em;
- width: 100%;
- }
- .${PREFIX}button {
- border: none;
- border-radius: 4px;
- padding: 0.6em 1.2em;
- font-size: 1em;
- cursor: pointer;
- transition: background-color 0.2s, box-shadow 0.2s;
- color: #fff;
- }
- .${PREFIX}confirm {
- background-color: #3085d6;
- }
- .${PREFIX}confirm:hover {
- background-color: #2b77c0;
- }
- .${PREFIX}cancel {
- background-color: #aaa;
- }
- .${PREFIX}cancel:hover {
- background-color: #999;
- }
- .${PREFIX}icon {
- width: 5em;
- height: 5em;
- border: 0.25em solid transparent;
- border-radius: 50%;
- margin: 1.5em auto 1.2em;
- box-sizing: content-box;
- position: relative;
- }
-
- /* Success Icon */
- .${PREFIX}icon.success {
- border-color: #a5dc86;
- color: #a5dc86;
- }
- .${PREFIX}icon.success::before, .${PREFIX}icon.success::after {
- content: '';
- position: absolute;
- background: #fff;
- border-radius: 50%;
- }
- .${PREFIX}success-line-tip {
- width: 1.5em;
- height: 0.3em;
- background-color: #a5dc86;
- display: block;
- position: absolute;
- top: 2.85em;
- left: 0.85em;
- transform: rotate(45deg);
- border-radius: 0.15em;
- }
- .${PREFIX}success-line-long {
- width: 2.9em;
- height: 0.3em;
- background-color: #a5dc86;
- display: block;
- position: absolute;
- top: 2.4em;
- right: 0.5em;
- transform: rotate(-45deg);
- border-radius: 0.15em;
- }
- /* Error Icon */
- .${PREFIX}icon.error {
- border-color: #f27474;
- color: #f27474;
- }
- .${PREFIX}error-x-mark {
- position: relative;
- display: block;
- }
- .${PREFIX}error-line {
- position: absolute;
- height: 0.3em;
- width: 3em;
- background-color: #f27474;
- display: block;
- top: 2.3em;
- left: 1em;
- border-radius: 0.15em;
- }
- .${PREFIX}error-line.left {
- transform: rotate(45deg);
- }
- .${PREFIX}error-line.right {
- transform: rotate(-45deg);
- }
-
- /* Warning Icon */
- .${PREFIX}icon.warning {
- border-color: #facea8;
- color: #f8bb86;
- }
- .${PREFIX}warning-body {
- position: absolute;
- width: 0.3em;
- height: 2.9em;
- background-color: #f8bb86;
- left: 50%;
- top: 0.6em;
- margin-left: -0.15em;
- border-radius: 0.15em;
- }
- .${PREFIX}warning-dot {
- position: absolute;
- width: 0.3em;
- height: 0.3em;
- background-color: #f8bb86;
- left: 50%;
- bottom: 0.6em;
- margin-left: -0.15em;
- border-radius: 50%;
- }
- `;
- // Inject Styles
- const injectStyles = () => {
- if (document.getElementById(`${PREFIX}styles`)) return;
- const styleSheet = document.createElement('style');
- styleSheet.id = `${PREFIX}styles`;
- styleSheet.textContent = css;
- document.head.appendChild(styleSheet);
- };
- class Layer {
- constructor() {
- injectStyles();
- this.params = {};
- this.dom = {};
- this.promise = null;
- this.resolve = null;
- this.reject = null;
- }
- // Static entry point
- static fire(options) {
- const instance = new Layer();
- return instance._fire(options);
- }
- _fire(options = {}) {
- if (typeof options === 'string') {
- options = { title: options };
- if (arguments[1]) options.text = arguments[1];
- if (arguments[2]) options.icon = arguments[2];
- }
- this.params = {
- title: '',
- text: '',
- icon: null,
- confirmButtonText: 'OK',
- cancelButtonText: 'Cancel',
- showCancelButton: false,
- confirmButtonColor: '#3085d6',
- cancelButtonColor: '#aaa',
- closeOnClickOutside: true,
- ...options
- };
- this.promise = new Promise((resolve, reject) => {
- this.resolve = resolve;
- this.reject = reject;
- });
- this._render();
- return this.promise;
- }
- _render() {
- // Remove existing if any
- const existing = document.querySelector(`.${PREFIX}overlay`);
- if (existing) existing.remove();
- // Create Overlay
- this.dom.overlay = document.createElement('div');
- this.dom.overlay.className = `${PREFIX}overlay`;
- // Create Popup
- this.dom.popup = document.createElement('div');
- this.dom.popup.className = `${PREFIX}popup`;
- this.dom.overlay.appendChild(this.dom.popup);
- // Icon
- if (this.params.icon) {
- this.dom.icon = this._createIcon(this.params.icon);
- this.dom.popup.appendChild(this.dom.icon);
- }
- // Title
- if (this.params.title) {
- this.dom.title = document.createElement('h2');
- this.dom.title.className = `${PREFIX}title`;
- this.dom.title.textContent = this.params.title;
- this.dom.popup.appendChild(this.dom.title);
- }
- // Text
- if (this.params.text) {
- this.dom.content = document.createElement('div');
- this.dom.content.className = `${PREFIX}content`;
- this.dom.content.textContent = this.params.text;
- this.dom.popup.appendChild(this.dom.content);
- }
- // Actions
- this.dom.actions = document.createElement('div');
- this.dom.actions.className = `${PREFIX}actions`;
-
- // Cancel Button
- if (this.params.showCancelButton) {
- this.dom.cancelBtn = document.createElement('button');
- this.dom.cancelBtn.className = `${PREFIX}button ${PREFIX}cancel`;
- this.dom.cancelBtn.textContent = this.params.cancelButtonText;
- this.dom.cancelBtn.style.backgroundColor = this.params.cancelButtonColor;
- this.dom.cancelBtn.onclick = () => this._close(false);
- this.dom.actions.appendChild(this.dom.cancelBtn);
- }
- // Confirm Button
- this.dom.confirmBtn = document.createElement('button');
- this.dom.confirmBtn.className = `${PREFIX}button ${PREFIX}confirm`;
- this.dom.confirmBtn.textContent = this.params.confirmButtonText;
- this.dom.confirmBtn.style.backgroundColor = this.params.confirmButtonColor;
- this.dom.confirmBtn.onclick = () => this._close(true);
- this.dom.actions.appendChild(this.dom.confirmBtn);
- this.dom.popup.appendChild(this.dom.actions);
- // Event Listeners
- if (this.params.closeOnClickOutside) {
- this.dom.overlay.addEventListener('click', (e) => {
- if (e.target === this.dom.overlay) {
- this._close(null); // Dismiss
- }
- });
- }
- document.body.appendChild(this.dom.overlay);
- // Animation
- requestAnimationFrame(() => {
- this.dom.overlay.classList.add('show');
- });
- }
- _createIcon(type) {
- const icon = document.createElement('div');
- icon.className = `${PREFIX}icon ${type}`;
-
- if (type === 'success') {
- const tip = document.createElement('div');
- tip.className = `${PREFIX}success-line-tip`;
- const long = document.createElement('div');
- long.className = `${PREFIX}success-line-long`;
- icon.appendChild(tip);
- icon.appendChild(long);
- } else if (type === 'error') {
- const xMark = document.createElement('span');
- xMark.className = `${PREFIX}error-x-mark`;
- const left = document.createElement('span');
- left.className = `${PREFIX}error-line left`;
- const right = document.createElement('span');
- right.className = `${PREFIX}error-line right`;
- xMark.appendChild(left);
- xMark.appendChild(right);
- icon.appendChild(xMark);
- } else if (type === 'warning') {
- const body = document.createElement('div');
- body.className = `${PREFIX}warning-body`;
- const dot = document.createElement('div');
- dot.className = `${PREFIX}warning-dot`;
- icon.appendChild(body);
- icon.appendChild(dot);
- }
-
- return icon;
- }
- _close(isConfirmed) {
- this.dom.overlay.classList.remove('show');
- setTimeout(() => {
- if (this.dom.overlay && this.dom.overlay.parentNode) {
- this.dom.overlay.parentNode.removeChild(this.dom.overlay);
- }
- }, 300);
- if (isConfirmed === true) {
- this.resolve({ isConfirmed: true, isDenied: false, isDismissed: false });
- } else if (isConfirmed === false) {
- this.resolve({ isConfirmed: false, isDenied: false, isDismissed: true, dismiss: 'cancel' });
- } else {
- this.resolve({ isConfirmed: false, isDenied: false, isDismissed: true, dismiss: 'backdrop' });
- }
- }
- }
- return Layer;
- })));
|