UNPKG

arlet-loadding

Version:

Un componente de indicador de carga con múltiples animaciones personalizables.

534 lines (408 loc) 17.3 kB
class ArletLoadding { constructor(container) { this.container = container; this.loadding = null; } show({ texto = 'Cargando...', tipo = 'zigzag-lines', }) { this.cerrar(); this.loadding = document.createElement('div'); this.loadding.classList.add('arlet-loaddign'); const normalizedTipo = typeof tipo === 'string' ? tipo.trim() : ''; const lowerTipo = normalizedTipo.toLowerCase(); const typeKey = lowerTipo.endsWith('-type') ? lowerTipo.slice(0, -5) : lowerTipo; const imageConfig = this._parseImageTipo(normalizedTipo); const spin = document.createElement('div'); spin.classList.add('spin'); const isImageTipo = Boolean(imageConfig); if (!isImageTipo && normalizedTipo) { const typeClass = normalizedTipo.endsWith('-type') ? normalizedTipo : `${normalizedTipo}-type`; this.loadding.classList.add(typeClass); } if (isImageTipo) { this._buildImageSpin({ spin, imageConfig, texto }); } else if (typeKey === 'ia') { this._buildIaSpin({ spin }); } else if (typeKey === 'robot') { this._buildRobotSpin({ spin }); } else if (typeKey === 'bike') { this._buildBikeSpin({ spin }); } else if (typeKey === 'motor-bike') { this._buildMotorBikeSpin({ spin }); } else if (typeKey === 'weaves') { this._buildWeavesSpin({ spin }); } else if (typeKey === 'glass-ring') { this._buildGlassRingSpin({ spin }); } else if (typeKey === 'gradient-bar') { this._buildGradientBarSpin({ spin }); } else if (typeKey === 'dual-pulse') { this._buildDualPulseSpin({ spin }); } else if (typeKey === 'line-wave') { this._buildLineWaveSpin({ spin }); } else { const spinCenter = document.createElement('div'); spinCenter.classList.add('spin-center'); for (let i = 0; i < 5; i += 1) { const circle = document.createElement('div'); circle.classList.add('spin-center__circle'); spinCenter.appendChild(circle); } spin.appendChild(spinCenter); } const textWrapper = document.createElement('p'); textWrapper.classList.add('text_arlet-loadding'); const textContent = document.createElement('span'); textContent.classList.add('text_arlet-loadding__text'); textContent.textContent = texto; textWrapper.appendChild(textContent); this.loadding.append(spin, textWrapper); this.container.appendChild(this.loadding); } cerrar() { if (this.loadding) { this.loadding.remove(); this.loadding = null; } } _parseImageTipo(tipo) { if (typeof tipo !== 'string') { return null; } const trimmedTipo = tipo.trim(); if (!trimmedTipo.toLowerCase().startsWith('img-')) { return null; } let remainder = trimmedTipo.slice(4).trim(); let rotate = false; let axis = null; let width; let height; const consume = (keyword) => { if (remainder.toLowerCase().startsWith(keyword)) { remainder = remainder.slice(keyword.length).trimStart(); return true; } return false; }; if (consume('rotate-')) { rotate = true; if (consume('vertical-')) { axis = 'vertical'; } else if (consume('horizontal-')) { axis = 'horizontal'; } } const sizeMatch = remainder.match(/\{([^}]*)\}\s*$/); if (sizeMatch) { const sizeContent = sizeMatch[1]; remainder = remainder.slice(0, sizeMatch.index).trimEnd(); const normalizeSize = (input) => { if (/^\d+(\.\d+)?$/.test(input)) { return `${input}px`; } return input; }; sizeContent.split(',').forEach((chunk) => { if (!chunk) { return; } const [rawKey, rawValue] = chunk.split(':'); if (!rawKey || !rawValue) { return; } const key = rawKey.trim().toLowerCase(); const value = rawValue.trim(); if (!value) { return; } if (key === 'w' || key === 'width') { width = normalizeSize(value); } else if (key === 'h' || key === 'height') { height = normalizeSize(value); } }); } const pathCandidate = remainder.trim(); if (!pathCandidate) { return null; } let path = pathCandidate; if (pathCandidate.startsWith('[')) { const closingIndex = pathCandidate.indexOf(']'); if (closingIndex === -1) { return null; } path = pathCandidate.slice(1, closingIndex).trim(); if (!path) { return null; } const leftover = pathCandidate.slice(closingIndex + 1).trim(); if (leftover) { return null; } } return { path, rotate, axis, width, height, }; } _buildImageSpin({ spin, imageConfig, texto }) { this.loadding.classList.add('image-type'); if (imageConfig.rotate) { if (imageConfig.axis === 'vertical') { this.loadding.classList.add('image-rotate-vertical'); } else if (imageConfig.axis === 'horizontal') { this.loadding.classList.add('image-rotate-horizontal'); } else { this.loadding.classList.add('image-rotate'); } } spin.classList.add('image-spin'); const wrapper = document.createElement('div'); wrapper.classList.add('image-wrapper'); if (imageConfig.width || imageConfig.height) { wrapper.classList.add('image-wrapper--custom-size'); } const image = document.createElement('img'); image.src = imageConfig.path; image.alt = texto || 'Cargando'; if (imageConfig.width) { const widthAttr = this._normalizeDimensionAttribute(imageConfig.width); if (widthAttr !== null) { image.setAttribute('width', widthAttr); } } if (imageConfig.height) { const heightAttr = this._normalizeDimensionAttribute(imageConfig.height); if (heightAttr !== null) { image.setAttribute('height', heightAttr); } } wrapper.appendChild(image); spin.appendChild(wrapper); } _buildIaSpin({ spin }) { const face = document.createElement('div'); face.classList.add('ia-face'); const antenna = document.createElement('div'); antenna.classList.add('ia-face__antenna'); face.appendChild(antenna); const eyes = document.createElement('div'); eyes.classList.add('ia-face__eyes'); for (let i = 0; i < 2; i += 1) { const eye = document.createElement('span'); eye.classList.add('ia-face__eye'); eye.style.setProperty('--eye-index', `${i}`); eyes.appendChild(eye); } const mouth = document.createElement('div'); mouth.classList.add('ia-face__mouth'); for (let i = 0; i < 3; i += 1) { const bar = document.createElement('span'); bar.classList.add('ia-face__mouth-bar'); bar.style.setProperty('--delay', `${i * 0.18}s`); mouth.appendChild(bar); } face.appendChild(eyes); face.appendChild(mouth); spin.appendChild(face); } _buildRobotSpin({ spin }) { const robot = document.createElement('div'); robot.classList.add('robot-loader'); const antenna = document.createElement('div'); antenna.classList.add('robot-loader__antenna'); robot.appendChild(antenna); const head = document.createElement('div'); head.classList.add('robot-loader__head'); const visor = document.createElement('div'); visor.classList.add('robot-loader__visor'); for (let i = 0; i < 2; i += 1) { const eye = document.createElement('span'); eye.classList.add('robot-loader__eye'); eye.style.setProperty('--eye-index', `${i}`); visor.appendChild(eye); } const scan = document.createElement('span'); scan.classList.add('robot-loader__scan'); visor.appendChild(scan); const mouth = document.createElement('div'); mouth.classList.add('robot-loader__mouth'); for (let i = 0; i < 3; i += 1) { const bar = document.createElement('span'); bar.classList.add('robot-loader__mouth-bar'); bar.style.setProperty('--delay', `${i * 0.18}s`); mouth.appendChild(bar); } head.appendChild(visor); head.appendChild(mouth); const body = document.createElement('div'); body.classList.add('robot-loader__body'); const core = document.createElement('div'); core.classList.add('robot-loader__core'); const panel = document.createElement('div'); panel.classList.add('robot-loader__panel'); for (let i = 0; i < 3; i += 1) { const led = document.createElement('span'); led.classList.add('robot-loader__panel-led'); led.style.setProperty('--delay', `${i * 0.22}s`); panel.appendChild(led); } body.append(core, panel); robot.append(head, body); spin.appendChild(robot); } _buildBikeSpin({ spin }) { const bike = document.createElement('div'); bike.classList.add('bike-loader'); const frame = document.createElement('div'); frame.classList.add('bike-loader__frame'); const topBar = document.createElement('span'); topBar.classList.add('bike-loader__bar', 'bike-loader__bar--top'); const seatBar = document.createElement('span'); seatBar.classList.add('bike-loader__bar', 'bike-loader__bar--seat'); const downBar = document.createElement('span'); downBar.classList.add('bike-loader__bar', 'bike-loader__bar--down'); const chainBar = document.createElement('span'); chainBar.classList.add('bike-loader__bar', 'bike-loader__bar--chain'); frame.append(topBar, seatBar, downBar, chainBar); bike.appendChild(frame); for (let i = 0; i < 2; i += 1) { const wheel = document.createElement('div'); wheel.classList.add('bike-loader__wheel'); wheel.classList.add(i === 0 ? 'bike-loader__wheel--back' : 'bike-loader__wheel--front'); wheel.style.setProperty('--index', `${i}`); const spokes = document.createElement('span'); spokes.classList.add('bike-loader__spokes'); wheel.appendChild(spokes); bike.appendChild(wheel); } const pedal = document.createElement('div'); pedal.classList.add('bike-loader__pedal'); for (let i = 0; i < 2; i += 1) { const arm = document.createElement('span'); arm.classList.add('bike-loader__pedal-arm'); if (i === 1) { arm.classList.add('bike-loader__pedal-arm--counter'); } pedal.appendChild(arm); } const seat = document.createElement('div'); seat.classList.add('bike-loader__seat'); const handle = document.createElement('div'); handle.classList.add('bike-loader__handle'); bike.append(pedal, seat, handle); spin.appendChild(bike); } _buildMotorBikeSpin({ spin }) { const moto = document.createElement('div'); moto.classList.add('motor-bike-loader'); const body = document.createElement('div'); body.classList.add('motor-bike-loader__body'); const tank = document.createElement('span'); tank.classList.add('motor-bike-loader__tank'); const seat = document.createElement('span'); seat.classList.add('motor-bike-loader__seat'); const light = document.createElement('span'); light.classList.add('motor-bike-loader__light'); body.append(tank, seat, light); moto.appendChild(body); for (let i = 0; i < 2; i += 1) { const wheel = document.createElement('div'); wheel.classList.add('motor-bike-loader__wheel'); wheel.classList.add(i === 0 ? 'motor-bike-loader__wheel--back' : 'motor-bike-loader__wheel--front'); wheel.style.setProperty('--index', `${i}`); const rim = document.createElement('span'); rim.classList.add('motor-bike-loader__rim'); wheel.appendChild(rim); moto.appendChild(wheel); } const smoke = document.createElement('div'); smoke.classList.add('motor-bike-loader__smoke'); for (let i = 0; i < 3; i += 1) { const puff = document.createElement('span'); puff.classList.add('motor-bike-loader__smoke-puff'); puff.style.setProperty('--delay', `${i * 0.3}s`); smoke.appendChild(puff); } moto.appendChild(smoke); spin.appendChild(moto); } _buildWeavesSpin({ spin }) { const weaves = document.createElement('div'); weaves.classList.add('weaves-loader'); for (let i = 0; i < 4; i += 1) { const strand = document.createElement('span'); strand.classList.add('weaves-loader__strand'); strand.style.setProperty('--index', `${i}`); weaves.appendChild(strand); } spin.appendChild(weaves); } _buildGlassRingSpin({ spin }) { const ring = document.createElement('div'); ring.classList.add('glass-ring-loader'); const inner = document.createElement('span'); inner.classList.add('glass-ring-loader__inner'); const runner = document.createElement('span'); runner.classList.add('glass-ring-loader__runner'); ring.append(inner, runner); spin.appendChild(ring); } _buildGradientBarSpin({ spin }) { const bar = document.createElement('div'); bar.classList.add('gradient-bar-loader'); const track = document.createElement('div'); track.classList.add('gradient-bar-loader__track'); const indicator = document.createElement('div'); indicator.classList.add('gradient-bar-loader__indicator'); const glow = document.createElement('div'); glow.classList.add('gradient-bar-loader__glow'); bar.append(track, indicator, glow); spin.appendChild(bar); } _buildDualPulseSpin({ spin }) { const pulse = document.createElement('div'); pulse.classList.add('dual-pulse-loader'); for (let i = 0; i < 2; i += 1) { const circle = document.createElement('span'); circle.classList.add('dual-pulse-loader__circle'); circle.style.setProperty('--index', `${i}`); pulse.appendChild(circle); } spin.appendChild(pulse); } _buildLineWaveSpin({ spin }) { const wave = document.createElement('div'); wave.classList.add('line-wave-loader'); for (let i = 0; i < 6; i += 1) { const segment = document.createElement('span'); segment.classList.add('line-wave-loader__segment'); segment.style.setProperty('--index', `${i}`); wave.appendChild(segment); } spin.appendChild(wave); } _normalizeDimensionAttribute(dimension) { if (typeof dimension !== 'string') { return null; } const trimmed = dimension.trim(); if (!trimmed) { return null; } const pxMatch = trimmed.match(/^(\d+(?:\.\d+)?)px$/i); if (pxMatch) { return pxMatch[1]; } if (/^\d+(?:\.\d+)?$/.test(trimmed)) { return trimmed; } return trimmed; } }