robert преди 1 ден
родител
ревизия
b511fa7e0e
променени са 3 файла, в които са добавени 5296 реда и са изтрити 26 реда
  1. 4824 0
      doc/sweetalert2.all.js
  2. 240 14
      layer.js
  3. 232 12
      xjs.js

Файловите разлики са ограничени, защото са твърде много
+ 4824 - 0
doc/sweetalert2.all.js


+ 240 - 14
layer.js

@@ -150,7 +150,159 @@
       transform-origin: center;
     }
 
-    .${PREFIX}icon.success { color: #a5dc86; }
+    /* =========================================
+       SweetAlert2-compatible SUCCESS icon (DOM)
+       (matches sweetalert2 v11.26.17)
+       ========================================= */
+    .${PREFIX}icon.success {
+      /* Override the generic SVG icon box */
+      display: block;
+      place-items: initial;
+      box-sizing: content-box;
+      width: 5em;
+      height: 5em;
+      margin: 2.5em auto 0.6em;
+      border: 0.25em solid rgba(0, 0, 0, 0);
+      border-radius: 50%;
+      border-color: #a5dc86;
+      color: #a5dc86;
+      font-family: inherit;
+      line-height: 5em;
+      cursor: default;
+      user-select: none;
+    }
+    .${PREFIX}icon.success .${PREFIX}success-ring {
+      position: absolute;
+      z-index: 2;
+      top: -0.25em;
+      left: -0.25em;
+      box-sizing: content-box;
+      width: 100%;
+      height: 100%;
+      border: 0.25em solid rgba(165, 220, 134, 0.3);
+      border-radius: 50%;
+    }
+    .${PREFIX}icon.success .${PREFIX}success-fix {
+      position: absolute;
+      z-index: 1;
+      top: 0.5em;
+      left: 1.625em;
+      width: 0.4375em;
+      height: 5.625em;
+      transform: rotate(-45deg);
+      background-color: #fff; /* adjusted at runtime to popup bg */
+    }
+    .${PREFIX}icon.success .${PREFIX}success-circular-line-left,
+    .${PREFIX}icon.success .${PREFIX}success-circular-line-right {
+      position: absolute;
+      width: 3.75em;
+      height: 7.5em;
+      border-radius: 50%;
+      background-color: #fff; /* adjusted at runtime to popup bg */
+    }
+    .${PREFIX}icon.success .${PREFIX}success-circular-line-left {
+      top: -0.4375em;
+      left: -2.0635em;
+      transform: rotate(-45deg);
+      transform-origin: 3.75em 3.75em;
+      border-radius: 7.5em 0 0 7.5em;
+    }
+    .${PREFIX}icon.success .${PREFIX}success-circular-line-right {
+      top: -0.6875em;
+      left: 1.875em;
+      transform: rotate(-45deg);
+      transform-origin: 0 3.75em;
+      border-radius: 0 7.5em 7.5em 0;
+    }
+    .${PREFIX}icon.success .${PREFIX}success-line-tip,
+    .${PREFIX}icon.success .${PREFIX}success-line-long {
+      display: block;
+      position: absolute;
+      z-index: 2;
+      height: 0.3125em;
+      border-radius: 0.125em;
+      background-color: #a5dc86;
+    }
+    .${PREFIX}icon.success .${PREFIX}success-line-tip {
+      top: 2.875em;
+      left: 0.8125em;
+      width: 1.5625em;
+      transform: rotate(45deg);
+    }
+    .${PREFIX}icon.success .${PREFIX}success-line-long {
+      top: 2.375em;
+      right: 0.5em;
+      width: 2.9375em;
+      transform: rotate(-45deg);
+    }
+
+    /* Triggered when icon has .${PREFIX}icon-show */
+    .${PREFIX}icon.success.${PREFIX}icon-show .${PREFIX}success-line-tip {
+      animation: ${PREFIX}animate-success-line-tip 0.75s;
+    }
+    .${PREFIX}icon.success.${PREFIX}icon-show .${PREFIX}success-line-long {
+      animation: ${PREFIX}animate-success-line-long 0.75s;
+    }
+    .${PREFIX}icon.success.${PREFIX}icon-show .${PREFIX}success-circular-line-right {
+      animation: ${PREFIX}rotate-success-circular-line 4.25s ease-in;
+    }
+
+    @keyframes ${PREFIX}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 ${PREFIX}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 ${PREFIX}rotate-success-circular-line {
+      0% { transform: rotate(-45deg); }
+      5% { transform: rotate(-45deg); }
+      12% { transform: rotate(-405deg); }
+      100% { transform: rotate(-405deg); }
+    }
+
     .${PREFIX}icon.error { color: #f27474; }
     .${PREFIX}icon.warning { color: #f8bb86; }
     .${PREFIX}icon.info { color: #3fc3ee; }
@@ -348,18 +500,66 @@
       const icon = document.createElement('div');
       icon.className = `${PREFIX}icon ${type}`;
 
-      // Allow per-popup icon sizing (overrides CSS default)
-      if (this.params && this.params.iconSize) {
+      const applyIconSize = (mode) => {
+        if (!(this.params && this.params.iconSize)) return;
         try {
-          const s = String(this.params.iconSize).trim();
-          if (s) {
-            icon.style.width = s;
-            icon.style.height = s;
+          const raw = this.params.iconSize;
+          const s = String(raw).trim();
+          if (!s) return;
+          // For SweetAlert2-style success icon, scale via font-size so all `em`-based
+          // parts remain proportional.
+          if (mode === 'font') {
+            const m = s.match(/^(-?\d*\.?\d+)\s*(px|em|rem)$/i);
+            if (m) {
+              const n = parseFloat(m[1]);
+              const unit = m[2];
+              if (Number.isFinite(n) && n > 0) {
+                icon.style.fontSize = (n / 5) + unit; // icon is 5em wide/tall
+                return;
+              }
+            }
           }
+          // Fallback: directly size the box (works great for SVG icons)
+          icon.style.width = s;
+          icon.style.height = s;
         } catch {}
-      }
+      };
       
       const svgNs = 'http://www.w3.org/2000/svg';
+      if (type === 'success') {
+        // SweetAlert2-compatible DOM structure (circle + tick) for exact style parity
+        //   <div class="...success-circular-line-left"></div>
+        //   <span class="...success-line-tip"></span>
+        //   <span class="...success-line-long"></span>
+        //   <div class="...success-ring"></div>
+        //   <div class="...success-fix"></div>
+        //   <div class="...success-circular-line-right"></div>
+        const left = document.createElement('div');
+        left.className = `${PREFIX}success-circular-line-left`;
+        const tip = document.createElement('span');
+        tip.className = `${PREFIX}success-line-tip`;
+        const long = document.createElement('span');
+        long.className = `${PREFIX}success-line-long`;
+        const ring = document.createElement('div');
+        ring.className = `${PREFIX}success-ring`;
+        const fix = document.createElement('div');
+        fix.className = `${PREFIX}success-fix`;
+        const right = document.createElement('div');
+        right.className = `${PREFIX}success-circular-line-right`;
+        icon.appendChild(left);
+        icon.appendChild(tip);
+        icon.appendChild(long);
+        icon.appendChild(ring);
+        icon.appendChild(fix);
+        icon.appendChild(right);
+
+        applyIconSize('font');
+        return icon;
+      }
+
+      // Default to SVG icons for other types
+      applyIconSize('box');
+
       const svg = document.createElementNS(svgNs, 'svg');
       svg.setAttribute('viewBox', '0 0 80 80');
       svg.setAttribute('aria-hidden', 'true');
@@ -383,9 +583,7 @@
         return p;
       };
 
-      if (type === 'success') {
-        addPath('M23 41 L34.5 53 L58 29', `${PREFIX}svg-success`);
-      } else if (type === 'error') {
+      if (type === 'error') {
         addPath('M28 28 L52 52', `${PREFIX}svg-error-left`);
         addPath('M52 28 L28 52', `${PREFIX}svg-error-right`);
       } else if (type === 'warning') {
@@ -417,7 +615,7 @@
         dot.setAttribute('fill', 'currentColor');
         svg.appendChild(dot);
       } else {
-        // Fallback to info-like ring only
+        // Fallback: ring only
       }
 
       icon.appendChild(svg);
@@ -425,6 +623,20 @@
       return icon;
     }
 
+    _adjustSuccessIconBackgroundColor() {
+      try {
+        const icon = this.dom && this.dom.icon;
+        const popup = this.dom && this.dom.popup;
+        if (!icon || !popup) return;
+        if (!(icon.classList && icon.classList.contains('success'))) return;
+        const bg = getComputedStyle(popup).backgroundColor;
+        const parts = icon.querySelectorAll(`.${PREFIX}success-circular-line-left, .${PREFIX}success-circular-line-right, .${PREFIX}success-fix`);
+        parts.forEach((el) => {
+          try { el.style.backgroundColor = bg; } catch {}
+        });
+      } catch {}
+    }
+
     _didOpen() {
       // Keyboard close (ESC)
       if (this.params.closeOnEsc) {
@@ -435,6 +647,9 @@
         document.addEventListener('keydown', this._onKeydown);
       }
 
+      // Keep SweetAlert2 success icon perfectly blended with popup bg
+      this._adjustSuccessIconBackgroundColor();
+
       // Popup animation (optional)
       if (this.params.popupAnimation) {
         const X = Layer._getXjs();
@@ -468,10 +683,21 @@
       const icon = this.dom.icon;
       if (!icon) return;
       const X = Layer._getXjs();
-      if (!X) return;
-
       const type = (this.params && this.params.icon) || '';
 
+      // SweetAlert2-style success icon uses pure CSS keyframes; keep the look identical.
+      if (type === 'success') {
+        this._adjustSuccessIconBackgroundColor();
+        // Force restart by removing/adding the class
+        try { icon.classList.remove(`${PREFIX}icon-show`); } catch {}
+        requestAnimationFrame(() => {
+          try { icon.classList.add(`${PREFIX}icon-show`); } catch {}
+        });
+        return;
+      }
+
+      if (!X) return;
+
       try {
         // Entrance varies slightly by type (SweetAlert-like feel)
         if (type === 'error') {

+ 232 - 12
xjs.js

@@ -166,7 +166,159 @@
       transform-origin: center;
     }
 
-    .${PREFIX}icon.success { color: #a5dc86; }
+    /* =========================================
+       SweetAlert2-compatible SUCCESS icon (DOM)
+       (matches sweetalert2 v11.26.17)
+       ========================================= */
+    .${PREFIX}icon.success {
+      /* Override the generic SVG icon box */
+      display: block;
+      place-items: initial;
+      box-sizing: content-box;
+      width: 5em;
+      height: 5em;
+      margin: 2.5em auto 0.6em;
+      border: 0.25em solid rgba(0, 0, 0, 0);
+      border-radius: 50%;
+      border-color: #a5dc86;
+      color: #a5dc86;
+      font-family: inherit;
+      line-height: 5em;
+      cursor: default;
+      user-select: none;
+    }
+    .${PREFIX}icon.success .${PREFIX}success-ring {
+      position: absolute;
+      z-index: 2;
+      top: -0.25em;
+      left: -0.25em;
+      box-sizing: content-box;
+      width: 100%;
+      height: 100%;
+      border: 0.25em solid rgba(165, 220, 134, 0.3);
+      border-radius: 50%;
+    }
+    .${PREFIX}icon.success .${PREFIX}success-fix {
+      position: absolute;
+      z-index: 1;
+      top: 0.5em;
+      left: 1.625em;
+      width: 0.4375em;
+      height: 5.625em;
+      transform: rotate(-45deg);
+      background-color: #fff; /* adjusted at runtime to popup bg */
+    }
+    .${PREFIX}icon.success .${PREFIX}success-circular-line-left,
+    .${PREFIX}icon.success .${PREFIX}success-circular-line-right {
+      position: absolute;
+      width: 3.75em;
+      height: 7.5em;
+      border-radius: 50%;
+      background-color: #fff; /* adjusted at runtime to popup bg */
+    }
+    .${PREFIX}icon.success .${PREFIX}success-circular-line-left {
+      top: -0.4375em;
+      left: -2.0635em;
+      transform: rotate(-45deg);
+      transform-origin: 3.75em 3.75em;
+      border-radius: 7.5em 0 0 7.5em;
+    }
+    .${PREFIX}icon.success .${PREFIX}success-circular-line-right {
+      top: -0.6875em;
+      left: 1.875em;
+      transform: rotate(-45deg);
+      transform-origin: 0 3.75em;
+      border-radius: 0 7.5em 7.5em 0;
+    }
+    .${PREFIX}icon.success .${PREFIX}success-line-tip,
+    .${PREFIX}icon.success .${PREFIX}success-line-long {
+      display: block;
+      position: absolute;
+      z-index: 2;
+      height: 0.3125em;
+      border-radius: 0.125em;
+      background-color: #a5dc86;
+    }
+    .${PREFIX}icon.success .${PREFIX}success-line-tip {
+      top: 2.875em;
+      left: 0.8125em;
+      width: 1.5625em;
+      transform: rotate(45deg);
+    }
+    .${PREFIX}icon.success .${PREFIX}success-line-long {
+      top: 2.375em;
+      right: 0.5em;
+      width: 2.9375em;
+      transform: rotate(-45deg);
+    }
+
+    /* Triggered when icon has .${PREFIX}icon-show */
+    .${PREFIX}icon.success.${PREFIX}icon-show .${PREFIX}success-line-tip {
+      animation: ${PREFIX}animate-success-line-tip 0.75s;
+    }
+    .${PREFIX}icon.success.${PREFIX}icon-show .${PREFIX}success-line-long {
+      animation: ${PREFIX}animate-success-line-long 0.75s;
+    }
+    .${PREFIX}icon.success.${PREFIX}icon-show .${PREFIX}success-circular-line-right {
+      animation: ${PREFIX}rotate-success-circular-line 4.25s ease-in;
+    }
+
+    @keyframes ${PREFIX}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 ${PREFIX}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 ${PREFIX}rotate-success-circular-line {
+      0% { transform: rotate(-45deg); }
+      5% { transform: rotate(-45deg); }
+      12% { transform: rotate(-405deg); }
+      100% { transform: rotate(-405deg); }
+    }
+
     .${PREFIX}icon.error { color: #f27474; }
     .${PREFIX}icon.warning { color: #f8bb86; }
     .${PREFIX}icon.info { color: #3fc3ee; }
@@ -364,18 +516,60 @@
       const icon = document.createElement('div');
       icon.className = `${PREFIX}icon ${type}`;
       
-      // Allow per-popup icon sizing (overrides CSS default)
-      if (this.params && this.params.iconSize) {
+      const applyIconSize = (mode) => {
+        if (!(this.params && this.params.iconSize)) return;
         try {
-          const s = String(this.params.iconSize).trim();
-          if (s) {
-            icon.style.width = s;
-            icon.style.height = s;
+          const raw = this.params.iconSize;
+          const s = String(raw).trim();
+          if (!s) return;
+          // For SweetAlert2-style success icon, scale via font-size so all `em`-based
+          // parts remain proportional.
+          if (mode === 'font') {
+            const m = s.match(/^(-?\d*\.?\d+)\s*(px|em|rem)$/i);
+            if (m) {
+              const n = parseFloat(m[1]);
+              const unit = m[2];
+              if (Number.isFinite(n) && n > 0) {
+                icon.style.fontSize = (n / 5) + unit; // icon is 5em wide/tall
+                return;
+              }
+            }
           }
+          // Fallback: directly size the box (works great for SVG icons)
+          icon.style.width = s;
+          icon.style.height = s;
         } catch {}
-      }
+      };
 
       const svgNs = 'http://www.w3.org/2000/svg';
+
+      if (type === 'success') {
+        // SweetAlert2-compatible DOM structure (circle + tick) for exact style parity
+        const left = document.createElement('div');
+        left.className = `${PREFIX}success-circular-line-left`;
+        const tip = document.createElement('span');
+        tip.className = `${PREFIX}success-line-tip`;
+        const long = document.createElement('span');
+        long.className = `${PREFIX}success-line-long`;
+        const ring = document.createElement('div');
+        ring.className = `${PREFIX}success-ring`;
+        const fix = document.createElement('div');
+        fix.className = `${PREFIX}success-fix`;
+        const right = document.createElement('div');
+        right.className = `${PREFIX}success-circular-line-right`;
+        icon.appendChild(left);
+        icon.appendChild(tip);
+        icon.appendChild(long);
+        icon.appendChild(ring);
+        icon.appendChild(fix);
+        icon.appendChild(right);
+
+        applyIconSize('font');
+        return icon;
+      }
+
+      applyIconSize('box');
+
       const svg = document.createElementNS(svgNs, 'svg');
       svg.setAttribute('viewBox', '0 0 80 80');
       svg.setAttribute('aria-hidden', 'true');
@@ -398,9 +592,7 @@
         return p;
       };
 
-      if (type === 'success') {
-        addPath('M23 41 L34.5 53 L58 29', `${PREFIX}svg-success`);
-      } else if (type === 'error') {
+      if (type === 'error') {
         addPath('M28 28 L52 52', `${PREFIX}svg-error-left`);
         addPath('M52 28 L28 52', `${PREFIX}svg-error-right`);
       } else if (type === 'warning') {
@@ -439,6 +631,20 @@
       return icon;
     }
 
+    _adjustSuccessIconBackgroundColor() {
+      try {
+        const icon = this.dom && this.dom.icon;
+        const popup = this.dom && this.dom.popup;
+        if (!icon || !popup) return;
+        if (!(icon.classList && icon.classList.contains('success'))) return;
+        const bg = getComputedStyle(popup).backgroundColor;
+        const parts = icon.querySelectorAll(`.${PREFIX}success-circular-line-left, .${PREFIX}success-circular-line-right, .${PREFIX}success-fix`);
+        parts.forEach((el) => {
+          try { el.style.backgroundColor = bg; } catch {}
+        });
+      } catch {}
+    }
+
     _didOpen() {
       // Keyboard close (ESC)
       if (this.params.closeOnEsc) {
@@ -449,6 +655,9 @@
         document.addEventListener('keydown', this._onKeydown);
       }
 
+      // Keep SweetAlert2 success icon perfectly blended with popup bg
+      this._adjustSuccessIconBackgroundColor();
+
       // Popup animation (optional)
       if (this.params.popupAnimation) {
         const X = Layer._getXjs();
@@ -479,10 +688,21 @@
       const icon = this.dom.icon;
       if (!icon) return;
       const X = Layer._getXjs();
-      if (!X) return;
 
       const type = (this.params && this.params.icon) || '';
 
+      // SweetAlert2-style success icon uses pure CSS keyframes; keep the look identical.
+      if (type === 'success') {
+        this._adjustSuccessIconBackgroundColor();
+        try { icon.classList.remove(`${PREFIX}icon-show`); } catch {}
+        requestAnimationFrame(() => {
+          try { icon.classList.add(`${PREFIX}icon-show`); } catch {}
+        });
+        return;
+      }
+
+      if (!X) return;
+
       try {
         if (type === 'error') {
           X(icon).animate({

Някои файлове не бяха показани, защото твърде много файлове са промени