migrate to new git

This commit is contained in:
2025-08-29 01:27:25 +08:00
parent 946eb9961e
commit af2c152ef6
8623 changed files with 1000453 additions and 1 deletions

View File

@@ -0,0 +1,21 @@
import { getPopup } from '../getters.js'
import { renderActions } from './renderActions.js'
import { renderContainer } from './renderContainer.js'
import { renderContent } from './renderContent.js'
import { renderFooter } from './renderFooter.js'
import { renderHeader } from './renderHeader.js'
import { renderPopup } from './renderPopup.js'
export const render = (instance, params) => {
renderPopup(instance, params)
renderContainer(instance, params)
renderHeader(instance, params)
renderContent(instance, params)
renderActions(instance, params)
renderFooter(instance, params)
if (typeof params.onRender === 'function') {
params.onRender(getPopup())
}
}

View File

@@ -0,0 +1,62 @@
import { swalClasses } from '../../classes.js'
import * as dom from '../../dom/index.js'
import { capitalizeFirstLetter } from '../../utils.js'
export const renderActions = (instance, params) => {
const actions = dom.getActions()
const confirmButton = dom.getConfirmButton()
const cancelButton = dom.getCancelButton()
// Actions (buttons) wrapper
if (!params.showConfirmButton && !params.showCancelButton) {
dom.hide(actions)
}
// Custom class
dom.applyCustomClass(actions, params, 'actions')
// Render confirm button
renderButton(confirmButton, 'confirm', params)
// render Cancel Button
renderButton(cancelButton, 'cancel', params)
if (params.buttonsStyling) {
handleButtonsStyling(confirmButton, cancelButton, params)
} else {
dom.removeClass([confirmButton, cancelButton], swalClasses.styled)
confirmButton.style.backgroundColor = confirmButton.style.borderLeftColor = confirmButton.style.borderRightColor = ''
cancelButton.style.backgroundColor = cancelButton.style.borderLeftColor = cancelButton.style.borderRightColor = ''
}
if (params.reverseButtons) {
confirmButton.parentNode.insertBefore(cancelButton, confirmButton)
}
}
function handleButtonsStyling (confirmButton, cancelButton, params) {
dom.addClass([confirmButton, cancelButton], swalClasses.styled)
// Buttons background colors
if (params.confirmButtonColor) {
confirmButton.style.backgroundColor = params.confirmButtonColor
}
if (params.cancelButtonColor) {
cancelButton.style.backgroundColor = params.cancelButtonColor
}
// Loading state
const confirmButtonBackgroundColor = window.getComputedStyle(confirmButton).getPropertyValue('background-color')
confirmButton.style.borderLeftColor = confirmButtonBackgroundColor
confirmButton.style.borderRightColor = confirmButtonBackgroundColor
}
function renderButton (button, buttonType, params) {
dom.toggle(button, params[`show${capitalizeFirstLetter(buttonType)}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`)
dom.addClass(button, params[`${buttonType}ButtonClass`])
}

View File

@@ -0,0 +1,13 @@
import * as dom from '../../dom/index.js'
export const renderCloseButton = (instance, params) => {
const closeButton = dom.getCloseButton()
dom.setInnerHtml(closeButton, params.closeButtonHtml)
// Custom class
dom.applyCustomClass(closeButton, params, 'closeButton')
dom.toggle(closeButton, params.showCloseButton)
closeButton.setAttribute('aria-label', params.closeButtonAriaLabel)
}

View File

@@ -0,0 +1,56 @@
import { swalClasses } from '../../classes.js'
import { warn } from '../../utils.js'
import * as dom from '../../dom/index.js'
function handleBackdropParam (container, backdrop) {
if (typeof backdrop === 'string') {
container.style.background = backdrop
} else if (!backdrop) {
dom.addClass([document.documentElement, document.body], swalClasses['no-backdrop'])
}
}
function handlePositionParam (container, position) {
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)
}
}
function handleGrowParam (container, grow) {
if (grow && typeof grow === 'string') {
const growClass = `grow-${grow}`
if (growClass in swalClasses) {
dom.addClass(container, swalClasses[growClass])
}
}
}
export const renderContainer = (instance, params) => {
const container = dom.getContainer()
if (!container) {
return
}
handleBackdropParam(container, params.backdrop)
if (!params.backdrop && params.allowOutsideClick) {
warn('"allowOutsideClick" parameter requires `backdrop` parameter to be set to `true`')
}
handlePositionParam(container, params.position)
handleGrowParam(container, params.grow)
// Custom class
dom.applyCustomClass(container, params, 'container')
// Set queue step attribute for getQueueStep() method
const queueStep = document.body.getAttribute('data-swal2-queue-step')
if (queueStep) {
container.setAttribute('data-queue-step', queueStep)
document.body.removeAttribute('data-swal2-queue-step')
}
}

View File

@@ -0,0 +1,27 @@
import { swalClasses } from '../../classes.js'
import * as dom from '../../dom/index.js'
import { renderInput } from './renderInput.js'
export const renderContent = (instance, params) => {
const content = dom.getContent().querySelector(`#${swalClasses.content}`)
// Content as HTML
if (params.html) {
dom.parseHtmlToContainer(params.html, content)
dom.show(content, 'block')
// Content as plain text
} else if (params.text) {
content.textContent = params.text
dom.show(content, 'block')
// No content
} else {
dom.hide(content)
}
renderInput(instance, params)
// Custom class
dom.applyCustomClass(dom.getContent(), params, 'content')
}

View File

@@ -0,0 +1,14 @@
import * as dom from '../../dom/index.js'
export const renderFooter = (instance, params) => {
const footer = dom.getFooter()
dom.toggle(footer, params.footer)
if (params.footer) {
dom.parseHtmlToContainer(params.footer, footer)
}
// Custom class
dom.applyCustomClass(footer, params, 'footer')
}

View File

@@ -0,0 +1,28 @@
import * as dom from '../../dom/index.js'
import { renderCloseButton } from './renderCloseButton.js'
import { renderIcon } from './renderIcon.js'
import { renderImage } from './renderImage.js'
import { renderProgressSteps } from './renderProgressSteps.js'
import { renderTitle } from './renderTitle.js'
export const renderHeader = (instance, params) => {
const header = dom.getHeader()
// Custom class
dom.applyCustomClass(header, params, 'header')
// Progress steps
renderProgressSteps(instance, params)
// Icon
renderIcon(instance, params)
// Image
renderImage(instance, params)
// Title
renderTitle(instance, params)
// Close button
renderCloseButton(instance, params)
}

View File

@@ -0,0 +1,85 @@
import { swalClasses, iconTypes } from '../../classes.js'
import { error } from '../../utils.js'
import * as dom from '../../dom/index.js'
import privateProps from '../../../privateProps.js'
export const renderIcon = (instance, params) => {
const innerParams = privateProps.innerParams.get(instance)
// if the give icon already rendered, apply the custom class without re-rendering the icon
if (innerParams && params.icon === innerParams.icon && dom.getIcon()) {
dom.applyCustomClass(dom.getIcon(), params, 'icon')
return
}
hideAllIcons()
if (!params.icon) {
return
}
if (Object.keys(iconTypes).indexOf(params.icon) !== -1) {
const icon = dom.elementBySelector(`.${swalClasses.icon}.${iconTypes[params.icon]}`)
dom.show(icon)
// Custom or default content
setContent(icon, params)
adjustSuccessIconBackgoundColor()
// Custom class
dom.applyCustomClass(icon, params, 'icon')
// Animate icon
dom.addClass(icon, params.showClass.icon)
} else {
error(`Unknown icon! Expected "success", "error", "warning", "info" or "question", got "${params.icon}"`)
}
}
const hideAllIcons = () => {
const icons = dom.getIcons()
for (let i = 0; i < icons.length; i++) {
dom.hide(icons[i])
}
}
// Adjust success icon background color to match the popup background color
const adjustSuccessIconBackgoundColor = () => {
const popup = dom.getPopup()
const popupBackgroundColor = window.getComputedStyle(popup).getPropertyValue('background-color')
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 setContent = (icon, params) => {
icon.textContent = ''
if (params.iconHtml) {
dom.setInnerHtml(icon, iconContent(params.iconHtml))
} else if (params.icon === 'success') {
dom.setInnerHtml(icon, `
<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>
`)
} else if (params.icon === 'error') {
dom.setInnerHtml(icon, `
<span class="swal2-x-mark">
<span class="swal2-x-mark-line-left"></span>
<span class="swal2-x-mark-line-right"></span>
</span>
`)
} else {
const defaultIconHtml = {
question: '?',
warning: '!',
info: 'i'
}
dom.setInnerHtml(icon, iconContent(defaultIconHtml[params.icon]))
}
}
const iconContent = (content) => `<div class="${swalClasses['icon-content']}">${content}</div>`

View File

@@ -0,0 +1,24 @@
import { swalClasses } from '../../classes.js'
import * as dom from '../../dom/index.js'
export const renderImage = (instance, params) => {
const image = dom.getImage()
if (!params.imageUrl) {
return dom.hide(image)
}
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')
}

View File

@@ -0,0 +1,179 @@
import { swalClasses } from '../../classes.js'
import { warn, error, isPromise } from '../../utils.js'
import * as dom from '../../dom/index.js'
import privateProps from '../../../privateProps.js'
const inputTypes = ['input', 'file', 'range', 'select', 'radio', 'checkbox', 'textarea']
export const renderInput = (instance, params) => {
const content = dom.getContent()
const innerParams = privateProps.innerParams.get(instance)
const rerender = !innerParams || params.input !== innerParams.input
inputTypes.forEach((inputType) => {
const inputClass = swalClasses[inputType]
const inputContainer = dom.getChildByClass(content, inputClass)
// set attributes
setAttributes(inputType, params.inputAttributes)
// set class
inputContainer.className = inputClass
if (rerender) {
dom.hide(inputContainer)
}
})
if (params.input) {
if (rerender) {
showInput(params)
}
// set custom class
setCustomClass(params)
}
}
const showInput = (params) => {
if (!renderInputType[params.input]) {
return error(`Unexpected type of input! Expected "text", "email", "password", "number", "tel", "select", "radio", "checkbox", "textarea", "file" or "url", got "${params.input}"`)
}
const inputContainer = getInputContainer(params.input)
const input = renderInputType[params.input](inputContainer, params)
dom.show(input)
// input autofocus
setTimeout(() => {
dom.focusInput(input)
})
}
const removeAttributes = (input) => {
for (let i = 0; i < input.attributes.length; i++) {
const attrName = input.attributes[i].name
if (!['type', 'value', 'style'].includes(attrName)) {
input.removeAttribute(attrName)
}
}
}
const setAttributes = (inputType, inputAttributes) => {
const input = dom.getInput(dom.getContent(), inputType)
if (!input) {
return
}
removeAttributes(input)
for (const attr in inputAttributes) {
// Do not set a placeholder for <input type="range">
// it'll crash Edge, #1298
if (inputType === 'range' && attr === 'placeholder') {
continue
}
input.setAttribute(attr, inputAttributes[attr])
}
}
const setCustomClass = (params) => {
const inputContainer = getInputContainer(params.input)
if (params.customClass) {
dom.addClass(inputContainer, params.customClass.input)
}
}
const setInputPlaceholder = (input, params) => {
if (!input.placeholder || params.inputPlaceholder) {
input.placeholder = params.inputPlaceholder
}
}
const getInputContainer = (inputType) => {
const inputClass = swalClasses[inputType] ? swalClasses[inputType] : swalClasses.input
return dom.getChildByClass(dom.getContent(), inputClass)
}
const renderInputType = {}
renderInputType.text =
renderInputType.email =
renderInputType.password =
renderInputType.number =
renderInputType.tel =
renderInputType.url = (input, params) => {
if (typeof params.inputValue === 'string' || typeof params.inputValue === 'number') {
input.value = params.inputValue
} else if (!isPromise(params.inputValue)) {
warn(`Unexpected type of inputValue! Expected "string", "number" or "Promise", got "${typeof params.inputValue}"`)
}
setInputPlaceholder(input, params)
input.type = params.input
return input
}
renderInputType.file = (input, params) => {
setInputPlaceholder(input, params)
return input
}
renderInputType.range = (range, params) => {
const rangeInput = range.querySelector('input')
const rangeOutput = range.querySelector('output')
rangeInput.value = params.inputValue
rangeInput.type = params.input
rangeOutput.value = params.inputValue
return range
}
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)
}
return select
}
renderInputType.radio = (radio) => {
radio.textContent = ''
return radio
}
renderInputType.checkbox = (checkboxContainer, params) => {
const checkbox = dom.getInput(dom.getContent(), 'checkbox')
checkbox.value = 1
checkbox.id = swalClasses.checkbox
checkbox.checked = Boolean(params.inputValue)
const label = checkboxContainer.querySelector('span')
dom.setInnerHtml(label, params.inputPlaceholder)
return checkboxContainer
}
renderInputType.textarea = (textarea, params) => {
textarea.value = params.inputValue
setInputPlaceholder(textarea, params)
if ('MutationObserver' in window) { // #1699
const initialPopupWidth = parseInt(window.getComputedStyle(dom.getPopup()).width)
const popupPadding = parseInt(window.getComputedStyle(dom.getPopup()).paddingLeft) + parseInt(window.getComputedStyle(dom.getPopup()).paddingRight)
const outputsize = () => {
const contentWidth = textarea.offsetWidth + popupPadding
if (contentWidth > initialPopupWidth) {
dom.getPopup().style.width = `${contentWidth}px`
} else {
dom.getPopup().style.width = null
}
}
new MutationObserver(outputsize).observe(textarea, {
attributes: true, attributeFilter: ['style']
})
}
return textarea
}

View File

@@ -0,0 +1,43 @@
import { swalClasses } from '../../classes.js'
import * as dom from '../../dom/index.js'
export const renderPopup = (instance, params) => {
const popup = dom.getPopup()
// Width
dom.applyNumericalStyle(popup, 'width', params.width)
// Padding
dom.applyNumericalStyle(popup, 'padding', params.padding)
// Background
if (params.background) {
popup.style.background = params.background
}
// Classes
addClasses(popup, params)
}
const addClasses = (popup, params) => {
// Default Class + showClass when updating Swal.update({})
popup.className = `${swalClasses.popup} ${dom.isVisible(popup) ? params.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}`])
}
}

View File

@@ -0,0 +1,50 @@
import { swalClasses } from '../../classes.js'
import { warn } from '../../utils.js'
import * as dom from '../../dom/index.js'
import { getQueueStep } from '../../../staticMethods/queue.js'
const createStepElement = (step) => {
const stepEl = document.createElement('li')
dom.addClass(stepEl, swalClasses['progress-step'])
dom.setInnerHtml(stepEl, step)
return stepEl
}
const createLineElement = (params) => {
const lineEl = document.createElement('li')
dom.addClass(lineEl, swalClasses['progress-step-line'])
if (params.progressStepsDistance) {
lineEl.style.width = params.progressStepsDistance
}
return lineEl
}
export const renderProgressSteps = (instance, params) => {
const progressStepsContainer = dom.getProgressSteps()
if (!params.progressSteps || params.progressSteps.length === 0) {
return dom.hide(progressStepsContainer)
}
dom.show(progressStepsContainer)
progressStepsContainer.textContent = ''
const currentProgressStep = parseInt(params.currentProgressStep === undefined ? getQueueStep() : params.currentProgressStep)
if (currentProgressStep >= params.progressSteps.length) {
warn(
'Invalid currentProgressStep parameter, it should be less than progressSteps.length ' +
'(currentProgressStep like JS arrays starts from 0)'
)
}
params.progressSteps.forEach((step, index) => {
const stepEl = createStepElement(step)
progressStepsContainer.appendChild(stepEl)
if (index === currentProgressStep) {
dom.addClass(stepEl, swalClasses['active-progress-step'])
}
if (index !== params.progressSteps.length - 1) {
const lineEl = createLineElement(step)
progressStepsContainer.appendChild(lineEl)
}
})
}

View File

@@ -0,0 +1,18 @@
import * as dom from '../../dom/index.js'
export const renderTitle = (instance, params) => {
const title = dom.getTitle()
dom.toggle(title, params.title || params.titleText)
if (params.title) {
dom.parseHtmlToContainer(params.title, title)
}
if (params.titleText) {
title.innerText = params.titleText
}
// Custom class
dom.applyCustomClass(title, params, 'title')
}