mirror of
https://github.com/php-flasher/php-flasher.git
synced 2026-03-31 15:07:47 +01:00
refactor(themes): create shared utilities and design tokens
This refactoring improves code quality and reduces duplication: ## New Files - `themes/shared/icons.ts` - Centralized SVG icons (getIcon, getCloseIcon) - `themes/shared/accessibility.ts` - A11y helpers (getA11yString, getCloseButtonA11y) - `themes/shared/constants.ts` - Standard class names and default titles ## Design Tokens Added (index.scss) - Spacing scale: --fl-spacing-xs through --fl-spacing-2xl - Typography scale: --fl-font-size-xs through --fl-font-size-xl - Close button sizes: --fl-close-sm, --fl-close-md, --fl-close-lg - Border radius: --fl-radius-sm through --fl-radius-full - Shadow tokens: --fl-shadow-sm through --fl-shadow-lg - Animation: --fl-duration-*, --fl-easing-*, --fl-slide-* ## Mixins Updated - Added `close-button-sized($size)` with sm/md/lg support - Added `close-button-circular($size)` variant - Added `close-button-text` for text-style buttons - Updated existing mixins to use design tokens ## All 17 Themes Refactored Each theme now uses shared utilities instead of duplicating code: - Icon code: 20+ lines → 1 function call - Accessibility: 3 lines → 1 function call - Class names: via CLASS_NAMES constants Backwards compatible - no breaking changes.
This commit is contained in:
@@ -1,63 +1,37 @@
|
||||
import './amazon.scss'
|
||||
import type { Envelope } from '../../types'
|
||||
import { getTypeIcon, getCloseIcon } from '../shared/icons'
|
||||
import { getA11yString, getCloseButtonA11y } from '../shared/accessibility'
|
||||
import { CLASS_NAMES, DEFAULT_TITLES } from '../shared/constants'
|
||||
|
||||
const AMAZON_TITLES: Record<string, string> = {
|
||||
success: 'Success!',
|
||||
error: 'Problem',
|
||||
warning: 'Warning',
|
||||
info: 'Information',
|
||||
}
|
||||
|
||||
export const amazonTheme = {
|
||||
render: (envelope: Envelope): string => {
|
||||
const { type, message } = envelope
|
||||
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
const role = isAlert ? 'alert' : 'status'
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||
|
||||
const getAlertIcon = () => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return `<svg viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
|
||||
</svg>`
|
||||
case 'error':
|
||||
return `<svg viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
|
||||
</svg>`
|
||||
case 'warning':
|
||||
return `<svg viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/>
|
||||
</svg>`
|
||||
case 'info':
|
||||
return `<svg viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
|
||||
</svg>`
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
const getAlertTitle = () => {
|
||||
switch (type) {
|
||||
case 'success': return 'Success!'
|
||||
case 'error': return 'Problem'
|
||||
case 'warning': return 'Warning'
|
||||
case 'info': return 'Information'
|
||||
default: return 'Alert'
|
||||
}
|
||||
}
|
||||
const alertTitle = AMAZON_TITLES[type] || DEFAULT_TITLES[type] || 'Alert'
|
||||
|
||||
return `
|
||||
<div class="fl-amazon fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('amazon')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-amazon-alert">
|
||||
<div class="fl-alert-content">
|
||||
<div class="fl-icon-container">
|
||||
${getAlertIcon()}
|
||||
${getTypeIcon(type, { size: 'lg' })}
|
||||
</div>
|
||||
<div class="fl-text-content">
|
||||
<div class="fl-alert-title">${getAlertTitle()}</div>
|
||||
<div class="fl-alert-title">${alertTitle}</div>
|
||||
<div class="fl-alert-message">${message}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-alert-actions">
|
||||
<button class="fl-close" aria-label="Close notification">
|
||||
<svg viewBox="0 0 24 24" width="16" height="16">
|
||||
<path fill="currentColor" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
|
||||
</svg>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
${getCloseIcon()}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
import './amber.scss'
|
||||
import type { Envelope } from '../../types'
|
||||
import { getA11yString, getCloseButtonA11y } from '../shared/accessibility'
|
||||
import { CLASS_NAMES } from '../shared/constants'
|
||||
|
||||
export const amberTheme = {
|
||||
render: (envelope: Envelope): string => {
|
||||
const { type, message } = envelope
|
||||
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
const role = isAlert ? 'alert' : 'status'
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||
|
||||
return `
|
||||
<div class="fl-amber fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-icon"></div>
|
||||
<div class="fl-text">
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.theme('amber')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.icon}"></div>
|
||||
<div class="${CLASS_NAMES.text}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`
|
||||
},
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import './aurora.scss'
|
||||
import type { Envelope } from '../../types'
|
||||
import { getA11yString, getCloseButtonA11y } from '../shared/accessibility'
|
||||
import { CLASS_NAMES } from '../shared/constants'
|
||||
|
||||
export const auroraTheme = {
|
||||
render: (envelope: Envelope): string => {
|
||||
const { type, message } = envelope
|
||||
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
const role = isAlert ? 'alert' : 'status'
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||
|
||||
return `
|
||||
<div class="fl-aurora fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<div class="${CLASS_NAMES.theme('aurora')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`
|
||||
},
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
import './crystal.scss'
|
||||
import type { Envelope } from '../../types'
|
||||
import { getA11yString, getCloseButtonA11y } from '../shared/accessibility'
|
||||
import { CLASS_NAMES } from '../shared/constants'
|
||||
|
||||
export const crystalTheme = {
|
||||
render: (envelope: Envelope): string => {
|
||||
const { type, message } = envelope
|
||||
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
const role = isAlert ? 'alert' : 'status'
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||
|
||||
return `
|
||||
<div class="fl-crystal fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-text">
|
||||
<p class="fl-message">${message}</p>
|
||||
<div class="${CLASS_NAMES.theme('crystal')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.text}">
|
||||
<p class="${CLASS_NAMES.message}">${message}</p>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`
|
||||
},
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
import './emerald.scss'
|
||||
import type { Envelope } from '../../types'
|
||||
import { getA11yString, getCloseButtonA11y } from '../shared/accessibility'
|
||||
import { CLASS_NAMES } from '../shared/constants'
|
||||
|
||||
export const emeraldTheme = {
|
||||
render: (envelope: Envelope): string => {
|
||||
const { type, message } = envelope
|
||||
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
const role = isAlert ? 'alert' : 'status'
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||
|
||||
return `
|
||||
<div class="fl-emerald fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<div class="${CLASS_NAMES.theme('emerald')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
</div>`
|
||||
},
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import './facebook.scss'
|
||||
import type { Envelope } from '../../types'
|
||||
import { getCloseIcon } from '../shared/icons'
|
||||
import { getA11yString, getCloseButtonA11y } from '../shared/accessibility'
|
||||
import { CLASS_NAMES } from '../shared/constants'
|
||||
|
||||
function getTimeString(): string {
|
||||
const now = new Date()
|
||||
return now.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' })
|
||||
}
|
||||
|
||||
export const facebookTheme = {
|
||||
render: (envelope: Envelope): string => {
|
||||
const { type, message } = envelope
|
||||
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
const role = isAlert ? 'alert' : 'status'
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||
|
||||
const now = new Date()
|
||||
const timeString = now.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' })
|
||||
|
||||
const getNotificationIcon = () => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
@@ -43,25 +44,23 @@ export const facebookTheme = {
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="fl-facebook fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('facebook')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-fb-notification">
|
||||
<div class="fl-icon-container">
|
||||
${getNotificationIcon()}
|
||||
</div>
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">
|
||||
${message}
|
||||
</div>
|
||||
<div class="fl-meta">
|
||||
<span class="fl-time">${timeString}</span>
|
||||
<span class="fl-time">${getTimeString()}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-button fl-close" aria-label="Close ${type} message">
|
||||
<div class="${CLASS_NAMES.actions}">
|
||||
<button class="fl-button ${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
<div class="fl-button-icon">
|
||||
<svg viewBox="0 0 24 24" width="20" height="20">
|
||||
<path fill="currentColor" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
|
||||
</svg>
|
||||
${getCloseIcon({ size: 'md' })}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
import './flasher.scss'
|
||||
import type { Envelope } from '../../types'
|
||||
import { getA11yString, getCloseButtonA11y } from '../shared/accessibility'
|
||||
import { CLASS_NAMES, getTitle } from '../shared/constants'
|
||||
|
||||
export const flasherTheme = {
|
||||
render: (envelope: Envelope): string => {
|
||||
const { type, title, message } = envelope
|
||||
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
const role = isAlert ? 'alert' : 'status'
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||
|
||||
const displayTitle = title || type.charAt(0).toUpperCase() + type.slice(1)
|
||||
const displayTitle = getTitle(title, type)
|
||||
|
||||
return `
|
||||
<div class="fl-flasher fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-icon"></div>
|
||||
<div class="${CLASS_NAMES.theme('flasher')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.icon}"></div>
|
||||
<div>
|
||||
<strong class="fl-title">${displayTitle}</strong>
|
||||
<span class="fl-message">${message}</span>
|
||||
<strong class="${CLASS_NAMES.title}">${displayTitle}</strong>
|
||||
<span class="${CLASS_NAMES.message}">${message}</span>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<span class="fl-progress-bar">
|
||||
<span class="fl-progress"></span>
|
||||
<span class="${CLASS_NAMES.progressBar}">
|
||||
<span class="${CLASS_NAMES.progress}"></span>
|
||||
</span>
|
||||
</div>`
|
||||
},
|
||||
|
||||
@@ -1,60 +1,35 @@
|
||||
import './google.scss'
|
||||
import type { Envelope } from '../../types'
|
||||
import { getTypeIcon } from '../shared/icons'
|
||||
import { getA11yString, getCloseButtonA11y } from '../shared/accessibility'
|
||||
import { CLASS_NAMES, DEFAULT_TEXT } from '../shared/constants'
|
||||
|
||||
export const googleTheme = {
|
||||
render: (envelope: Envelope): string => {
|
||||
const { type, message, title } = envelope
|
||||
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
const role = isAlert ? 'alert' : 'status'
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||
|
||||
const actionText = 'DISMISS'
|
||||
|
||||
const getIcon = () => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
|
||||
</svg>`
|
||||
case 'error':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"/>
|
||||
</svg>`
|
||||
case 'warning':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z"/>
|
||||
</svg>`
|
||||
case 'info':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
|
||||
</svg>`
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
const titleSection = title ? `<div class="fl-title">${title}</div>` : ''
|
||||
const titleSection = title ? `<div class="${CLASS_NAMES.title}">${title}</div>` : ''
|
||||
|
||||
return `
|
||||
<div class="fl-google fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('google')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-md-card">
|
||||
<div class="fl-content">
|
||||
<div class="fl-icon-wrapper">
|
||||
${getIcon()}
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.iconWrapper}">
|
||||
${getTypeIcon(type, { size: 'lg', className: 'fl-icon-svg' })}
|
||||
</div>
|
||||
<div class="fl-text-content">
|
||||
${titleSection}
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-action-button fl-close" aria-label="Close ${type} message">
|
||||
${actionText}
|
||||
<div class="${CLASS_NAMES.actions}">
|
||||
<button class="fl-action-button ${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
${DEFAULT_TEXT.dismissButton}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
@use "sass:meta";
|
||||
|
||||
:root {
|
||||
// Colors
|
||||
--fl-success: #10b981;
|
||||
--fl-info: #3b82f6;
|
||||
--fl-warning: #f59e0b;
|
||||
@@ -19,12 +20,56 @@
|
||||
--fl-text-light: rgb(75, 85, 99);
|
||||
--fl-text-dark: var(--fl-white);
|
||||
|
||||
// Typography
|
||||
--fl-font: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
--fl-font-size-xs: 0.75rem;
|
||||
--fl-font-size-sm: 0.875rem;
|
||||
--fl-font-size-base: 1rem;
|
||||
--fl-font-size-lg: 1.125rem;
|
||||
--fl-font-size-xl: 1.25rem;
|
||||
|
||||
// Spacing scale (rem for consistency)
|
||||
--fl-spacing-xs: 0.25rem;
|
||||
--fl-spacing-sm: 0.5rem;
|
||||
--fl-spacing-md: 0.75rem;
|
||||
--fl-spacing-lg: 1rem;
|
||||
--fl-spacing-xl: 1.5rem;
|
||||
--fl-spacing-2xl: 2rem;
|
||||
|
||||
// Close button sizes
|
||||
--fl-close-sm: 1.125rem;
|
||||
--fl-close-md: 1.5rem;
|
||||
--fl-close-lg: 1.875rem;
|
||||
|
||||
// Border radius
|
||||
--fl-border-radius: 4px;
|
||||
--fl-radius-sm: 0.25rem;
|
||||
--fl-radius-md: 0.5rem;
|
||||
--fl-radius-lg: 0.75rem;
|
||||
--fl-radius-xl: 1rem;
|
||||
--fl-radius-full: 9999px;
|
||||
|
||||
// Shadows
|
||||
--fl-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
--fl-shadow-dark: 0 4px 12px rgba(0, 0, 0, 0.35);
|
||||
--fl-transition: 0.4s cubic-bezier(0.23, 1, 0.32, 1);
|
||||
--fl-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
||||
--fl-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
--fl-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
|
||||
// Animation
|
||||
--fl-transition: 0.4s cubic-bezier(0.23, 1, 0.32, 1);
|
||||
--fl-duration-fast: 0.15s;
|
||||
--fl-duration-base: 0.3s;
|
||||
--fl-duration-slow: 0.5s;
|
||||
--fl-easing-spring: cubic-bezier(0.23, 1, 0.32, 1);
|
||||
--fl-easing-material: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
// Animation distances
|
||||
--fl-slide-sm: 8px;
|
||||
--fl-slide-md: 12px;
|
||||
--fl-slide-lg: 20px;
|
||||
|
||||
// Legacy aliases (for backwards compatibility)
|
||||
--background-color: var(--fl-bg-light);
|
||||
--text-color: var(--fl-text-light);
|
||||
--dark-background-color: var(--fl-bg-dark);
|
||||
|
||||
@@ -1,59 +1,38 @@
|
||||
import './ios.scss'
|
||||
import type { Envelope } from '../../types'
|
||||
import { getTypeIcon } from '../shared/icons'
|
||||
import { getA11yString, getCloseButtonA11y } from '../shared/accessibility'
|
||||
import { CLASS_NAMES } from '../shared/constants'
|
||||
|
||||
const APP_NAME = 'PHPFlasher'
|
||||
|
||||
function getTimeString(): string {
|
||||
const now = new Date()
|
||||
return now.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' })
|
||||
}
|
||||
|
||||
export const iosTheme = {
|
||||
render: (envelope: Envelope): string => {
|
||||
const { type, message, title } = envelope
|
||||
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
const role = isAlert ? 'alert' : 'status'
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||
|
||||
const appName = 'PHPFlasher'
|
||||
|
||||
const now = new Date()
|
||||
const timeString = now.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' })
|
||||
|
||||
const getIcon = () => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
|
||||
</svg>`
|
||||
case 'error':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
|
||||
</svg>`
|
||||
case 'warning':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">
|
||||
<path fill="currentColor" d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/>
|
||||
</svg>`
|
||||
case 'info':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
|
||||
</svg>`
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
const displayTitle = title || appName
|
||||
const displayTitle = title || APP_NAME
|
||||
|
||||
return `
|
||||
<div class="fl-ios fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('ios')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-ios-notification">
|
||||
<div class="fl-header">
|
||||
<div class="fl-app-icon">
|
||||
${getIcon()}
|
||||
${getTypeIcon(type, { size: 'md', className: 'fl-icon-svg' })}
|
||||
</div>
|
||||
<div class="fl-app-info">
|
||||
<div class="fl-app-name">${displayTitle}</div>
|
||||
<div class="fl-time">${timeString}</div>
|
||||
<div class="fl-time">${getTimeString()}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import './jade.scss'
|
||||
import type { Envelope } from '../../types'
|
||||
import { getA11yString, getCloseButtonA11y } from '../shared/accessibility'
|
||||
import { CLASS_NAMES } from '../shared/constants'
|
||||
|
||||
export const jadeTheme = {
|
||||
render: (envelope: Envelope): string => {
|
||||
const { type, message } = envelope
|
||||
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
const role = isAlert ? 'alert' : 'status'
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||
|
||||
return `
|
||||
<div class="fl-jade fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<div class="${CLASS_NAMES.theme('jade')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`
|
||||
},
|
||||
|
||||
@@ -1,32 +1,28 @@
|
||||
import './material.scss'
|
||||
import type { Envelope } from '../../types'
|
||||
import { getA11yString, getCloseButtonA11y } from '../shared/accessibility'
|
||||
import { CLASS_NAMES, DEFAULT_TEXT } from '../shared/constants'
|
||||
|
||||
export const materialTheme = {
|
||||
render: (envelope: Envelope): string => {
|
||||
const { type, message } = envelope
|
||||
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
const role = isAlert ? 'alert' : 'status'
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||
|
||||
const actionText = 'DISMISS'
|
||||
|
||||
return `
|
||||
<div class="fl-material fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('material')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-md-card">
|
||||
<div class="fl-content">
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="fl-text-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-action-button fl-close" aria-label="Close ${type} message">
|
||||
${actionText}
|
||||
<div class="${CLASS_NAMES.actions}">
|
||||
<button class="fl-action-button ${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
${DEFAULT_TEXT.dismissButton}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`
|
||||
},
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import './minimal.scss'
|
||||
import type { Envelope } from '../../types'
|
||||
import { getA11yString, getCloseButtonA11y } from '../shared/accessibility'
|
||||
import { CLASS_NAMES } from '../shared/constants'
|
||||
|
||||
export const minimalTheme = {
|
||||
render: (envelope: Envelope): string => {
|
||||
const { type, message } = envelope
|
||||
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
const role = isAlert ? 'alert' : 'status'
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||
|
||||
return `
|
||||
<div class="fl-minimal fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<div class="${CLASS_NAMES.theme('minimal')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`
|
||||
},
|
||||
|
||||
@@ -8,26 +8,122 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy close button mixin (for backwards compatibility)
|
||||
@mixin close-button {
|
||||
.fl-close {
|
||||
position: absolute;
|
||||
right: 0.75rem;
|
||||
right: var(--fl-spacing-md, 0.75rem);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1.25rem;
|
||||
font-size: var(--fl-font-size-xl, 1.25rem);
|
||||
line-height: 1;
|
||||
padding: 0.25rem;
|
||||
padding: var(--fl-spacing-xs, 0.25rem);
|
||||
cursor: pointer;
|
||||
opacity: 0.5;
|
||||
transition: opacity 0.2s ease;
|
||||
transition: opacity var(--fl-duration-fast, 0.15s) ease;
|
||||
color: currentColor;
|
||||
touch-action: manipulation;
|
||||
|
||||
&:hover, &:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid currentColor;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parameterized close button with size variants
|
||||
@mixin close-button-sized($size: 'md', $position: 'absolute') {
|
||||
.fl-close {
|
||||
@if $position == 'absolute' {
|
||||
position: absolute;
|
||||
right: var(--fl-spacing-md, 0.75rem);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
} @else {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: currentColor;
|
||||
opacity: 0.5;
|
||||
transition: opacity var(--fl-duration-fast, 0.15s) ease,
|
||||
transform var(--fl-duration-fast, 0.15s) ease;
|
||||
touch-action: manipulation;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
|
||||
@if $size == 'sm' {
|
||||
width: var(--fl-close-sm, 1.125rem);
|
||||
height: var(--fl-close-sm, 1.125rem);
|
||||
font-size: var(--fl-font-size-base, 1rem);
|
||||
} @else if $size == 'lg' {
|
||||
width: var(--fl-close-lg, 1.875rem);
|
||||
height: var(--fl-close-lg, 1.875rem);
|
||||
font-size: var(--fl-font-size-xl, 1.25rem);
|
||||
} @else {
|
||||
width: var(--fl-close-md, 1.5rem);
|
||||
height: var(--fl-close-md, 1.5rem);
|
||||
font-size: var(--fl-font-size-lg, 1.125rem);
|
||||
}
|
||||
|
||||
&:hover, &:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid currentColor;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Circular close button variant
|
||||
@mixin close-button-circular($size: 'md') {
|
||||
@include close-button-sized($size, 'relative');
|
||||
|
||||
.fl-close {
|
||||
border-radius: var(--fl-radius-full, 9999px);
|
||||
|
||||
&:hover, &:focus {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Text-style close button (e.g., "DISMISS")
|
||||
@mixin close-button-text {
|
||||
.fl-close {
|
||||
background: transparent;
|
||||
border: none;
|
||||
font-family: inherit;
|
||||
font-weight: 500;
|
||||
font-size: var(--fl-font-size-sm, 0.875rem);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
padding: var(--fl-spacing-sm, 0.5rem) var(--fl-spacing-md, 0.75rem);
|
||||
cursor: pointer;
|
||||
color: currentColor;
|
||||
border-radius: var(--fl-radius-sm, 0.25rem);
|
||||
transition: background-color var(--fl-duration-fast, 0.15s) ease;
|
||||
|
||||
&:hover, &:focus {
|
||||
background-color: rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid currentColor;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +135,7 @@
|
||||
|
||||
.fl-close {
|
||||
right: auto;
|
||||
left: 0.75rem;
|
||||
left: var(--fl-spacing-md, 0.75rem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import './neon.scss'
|
||||
import type { Envelope } from '../../types'
|
||||
import { getA11yString, getCloseButtonA11y } from '../shared/accessibility'
|
||||
import { CLASS_NAMES } from '../shared/constants'
|
||||
|
||||
export const neonTheme = {
|
||||
render: (envelope: Envelope): string => {
|
||||
const { type, message } = envelope
|
||||
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
const role = isAlert ? 'alert' : 'status'
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||
|
||||
return `
|
||||
<div class="fl-neon fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<div class="${CLASS_NAMES.theme('neon')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`
|
||||
},
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
import './onyx.scss'
|
||||
import type { Envelope } from '../../types'
|
||||
import { getA11yString, getCloseButtonA11y } from '../shared/accessibility'
|
||||
import { CLASS_NAMES } from '../shared/constants'
|
||||
|
||||
export const onyxTheme = {
|
||||
render: (envelope: Envelope): string => {
|
||||
const { type, message } = envelope
|
||||
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
const role = isAlert ? 'alert' : 'status'
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||
|
||||
return `
|
||||
<div class="fl-onyx fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-text">
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.theme('onyx')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.text}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`
|
||||
},
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
import './ruby.scss'
|
||||
import type { Envelope } from '../../types'
|
||||
import { getA11yString, getCloseButtonA11y } from '../shared/accessibility'
|
||||
import { CLASS_NAMES } from '../shared/constants'
|
||||
|
||||
export const rubyTheme = {
|
||||
render: (envelope: Envelope): string => {
|
||||
const { type, message } = envelope
|
||||
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
const role = isAlert ? 'alert' : 'status'
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||
|
||||
return `
|
||||
<div class="fl-ruby fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('ruby')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-shine"></div>
|
||||
<div class="fl-content">
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="fl-icon-circle">
|
||||
<div class="fl-icon"></div>
|
||||
<div class="${CLASS_NAMES.icon}"></div>
|
||||
</div>
|
||||
<div class="fl-text">
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.text}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`
|
||||
},
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
import './sapphire.scss'
|
||||
import type { Envelope } from '../../types'
|
||||
import { getA11yString } from '../shared/accessibility'
|
||||
import { CLASS_NAMES } from '../shared/constants'
|
||||
|
||||
export const sapphireTheme = {
|
||||
render: (envelope: Envelope): string => {
|
||||
const { type, message } = envelope
|
||||
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
const role = isAlert ? 'alert' : 'status'
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||
|
||||
return `
|
||||
<div class="fl-sapphire fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<span class="fl-message">${message}</span>
|
||||
<div class="${CLASS_NAMES.theme('sapphire')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<span class="${CLASS_NAMES.message}">${message}</span>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`
|
||||
},
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
export type NotificationType = 'success' | 'info' | 'warning' | 'error'
|
||||
|
||||
export interface A11yAttributes {
|
||||
role: 'alert' | 'status'
|
||||
ariaLive: 'assertive' | 'polite'
|
||||
ariaAtomic: 'true'
|
||||
}
|
||||
|
||||
export function getA11yAttributes(type: NotificationType | string): A11yAttributes {
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
}
|
||||
}
|
||||
|
||||
export function getA11yString(type: NotificationType | string): string {
|
||||
const attrs = getA11yAttributes(type)
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`
|
||||
}
|
||||
|
||||
export function getCloseButtonA11y(type: NotificationType | string): string {
|
||||
return `aria-label="Close ${type} message"`
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
export const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
|
||||
type: (type: string) => `fl-${type}`,
|
||||
theme: (name: string) => `fl-${name}`,
|
||||
} as const
|
||||
|
||||
export const DEFAULT_TITLES: Record<string, string> = {
|
||||
success: 'Success',
|
||||
error: 'Error',
|
||||
warning: 'Warning',
|
||||
info: 'Information',
|
||||
}
|
||||
|
||||
export const DEFAULT_TEXT = {
|
||||
dismissButton: 'DISMISS',
|
||||
closeLabel: (type: string) => `Close ${type} message`,
|
||||
} as const
|
||||
|
||||
export function capitalizeType(type: string): string {
|
||||
return type.charAt(0).toUpperCase() + type.slice(1)
|
||||
}
|
||||
|
||||
export function getTitle(title: string | undefined, type: string): string {
|
||||
return title || DEFAULT_TITLES[type] || capitalizeType(type)
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
export type IconType = 'success' | 'info' | 'warning' | 'error' | 'close'
|
||||
export type IconSize = 'sm' | 'md' | 'lg' | number
|
||||
|
||||
export interface IconConfig {
|
||||
size?: IconSize
|
||||
className?: string
|
||||
}
|
||||
|
||||
const sizeMap: Record<string, number> = {
|
||||
sm: 16,
|
||||
md: 20,
|
||||
lg: 24,
|
||||
}
|
||||
|
||||
const iconPaths: Record<IconType, string> = {
|
||||
success:
|
||||
'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',
|
||||
error: 'M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z',
|
||||
warning:
|
||||
'M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z',
|
||||
info: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z',
|
||||
close: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',
|
||||
}
|
||||
|
||||
export function getIcon(type: IconType, config: IconConfig = {}): string {
|
||||
const { size = 'md', className = '' } = config
|
||||
const dimension = typeof size === 'number' ? size : sizeMap[size]
|
||||
const path = iconPaths[type]
|
||||
|
||||
if (!path) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const classAttr = className ? ` class="${className}"` : ''
|
||||
|
||||
return `<svg${classAttr} viewBox="0 0 24 24" width="${dimension}" height="${dimension}" aria-hidden="true"><path fill="currentColor" d="${path}"/></svg>`
|
||||
}
|
||||
|
||||
export function getCloseIcon(config: IconConfig = {}): string {
|
||||
return getIcon('close', { size: 'sm', ...config })
|
||||
}
|
||||
|
||||
export function getTypeIcon(
|
||||
type: string,
|
||||
config: IconConfig = {}
|
||||
): string {
|
||||
if (type === 'success' || type === 'error' || type === 'warning' || type === 'info') {
|
||||
return getIcon(type, config)
|
||||
}
|
||||
return ''
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
export { getIcon, getCloseIcon, getTypeIcon } from './icons'
|
||||
export type { IconType, IconSize, IconConfig } from './icons'
|
||||
|
||||
export { getA11yAttributes, getA11yString, getCloseButtonA11y } from './accessibility'
|
||||
export type { NotificationType, A11yAttributes } from './accessibility'
|
||||
|
||||
export {
|
||||
CLASS_NAMES,
|
||||
DEFAULT_TITLES,
|
||||
DEFAULT_TEXT,
|
||||
capitalizeType,
|
||||
getTitle,
|
||||
} from './constants'
|
||||
@@ -1,42 +1,34 @@
|
||||
import './slack.scss'
|
||||
import type { Envelope } from '../../types'
|
||||
import { getCloseIcon } from '../shared/icons'
|
||||
import { getA11yString, getCloseButtonA11y } from '../shared/accessibility'
|
||||
import { CLASS_NAMES } from '../shared/constants'
|
||||
|
||||
const TYPE_ICONS: Record<string, string> = {
|
||||
success: '✓',
|
||||
error: '✕',
|
||||
warning: '!',
|
||||
info: 'i',
|
||||
}
|
||||
|
||||
export const slackTheme = {
|
||||
render: (envelope: Envelope): string => {
|
||||
const { type, message } = envelope
|
||||
|
||||
const isAlert = type === 'error' || type === 'warning'
|
||||
const role = isAlert ? 'alert' : 'status'
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite'
|
||||
|
||||
const getTypeIcon = () => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return `<div class="fl-type-icon fl-success-icon">✓</div>`
|
||||
case 'error':
|
||||
return `<div class="fl-type-icon fl-error-icon">✕</div>`
|
||||
case 'warning':
|
||||
return `<div class="fl-type-icon fl-warning-icon">!</div>`
|
||||
case 'info':
|
||||
return `<div class="fl-type-icon fl-info-icon">i</div>`
|
||||
}
|
||||
return ''
|
||||
}
|
||||
const iconChar = TYPE_ICONS[type] || ''
|
||||
|
||||
return `
|
||||
<div class="fl-slack fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('slack')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-slack-message">
|
||||
<div class="fl-avatar">
|
||||
${getTypeIcon()}
|
||||
<div class="fl-type-icon fl-${type}-icon">${iconChar}</div>
|
||||
</div>
|
||||
<div class="fl-message-content">
|
||||
<div class="fl-message-text">${message}</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-close" aria-label="Close ${type} message">
|
||||
<svg viewBox="0 0 20 20" width="16" height="16">
|
||||
<path fill="currentColor" d="M10 8.586L6.707 5.293a1 1 0 00-1.414 1.414L8.586 10l-3.293 3.293a1 1 0 101.414 1.414L10 11.414l3.293 3.293a1 1 0 001.414-1.414L11.414 10l3.293-3.293a1 1 0 00-1.414-1.414L10 8.586z"/>
|
||||
</svg>
|
||||
<div class="${CLASS_NAMES.actions}">
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
${getCloseIcon()}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+57
-12
@@ -598,25 +598,70 @@ class Flasher extends AbstractPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
const DEFAULT_TITLES = {
|
||||
success: 'Success',
|
||||
error: 'Error',
|
||||
warning: 'Warning',
|
||||
info: 'Information',
|
||||
};
|
||||
function capitalizeType(type) {
|
||||
return type.charAt(0).toUpperCase() + type.slice(1);
|
||||
}
|
||||
function getTitle(title, type) {
|
||||
return title || DEFAULT_TITLES[type] || capitalizeType(type);
|
||||
}
|
||||
|
||||
const flasherTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, title, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const displayTitle = title || type.charAt(0).toUpperCase() + type.slice(1);
|
||||
const displayTitle = getTitle(title, type);
|
||||
return `
|
||||
<div class="fl-flasher fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-icon"></div>
|
||||
<div class="${CLASS_NAMES.theme('flasher')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.icon}"></div>
|
||||
<div>
|
||||
<strong class="fl-title">${displayTitle}</strong>
|
||||
<span class="fl-message">${message}</span>
|
||||
<strong class="${CLASS_NAMES.title}">${displayTitle}</strong>
|
||||
<span class="${CLASS_NAMES.message}">${message}</span>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<span class="fl-progress-bar">
|
||||
<span class="fl-progress"></span>
|
||||
<span class="${CLASS_NAMES.progressBar}">
|
||||
<span class="${CLASS_NAMES.progress}"></span>
|
||||
</span>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
Vendored
+57
-12
@@ -604,25 +604,70 @@
|
||||
}
|
||||
}
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
const DEFAULT_TITLES = {
|
||||
success: 'Success',
|
||||
error: 'Error',
|
||||
warning: 'Warning',
|
||||
info: 'Information',
|
||||
};
|
||||
function capitalizeType(type) {
|
||||
return type.charAt(0).toUpperCase() + type.slice(1);
|
||||
}
|
||||
function getTitle(title, type) {
|
||||
return title || DEFAULT_TITLES[type] || capitalizeType(type);
|
||||
}
|
||||
|
||||
const flasherTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, title, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const displayTitle = title || type.charAt(0).toUpperCase() + type.slice(1);
|
||||
const displayTitle = getTitle(title, type);
|
||||
return `
|
||||
<div class="fl-flasher fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-icon"></div>
|
||||
<div class="${CLASS_NAMES.theme('flasher')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.icon}"></div>
|
||||
<div>
|
||||
<strong class="fl-title">${displayTitle}</strong>
|
||||
<span class="fl-message">${message}</span>
|
||||
<strong class="${CLASS_NAMES.title}">${displayTitle}</strong>
|
||||
<span class="${CLASS_NAMES.message}">${message}</span>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<span class="fl-progress-bar">
|
||||
<span class="fl-progress"></span>
|
||||
<span class="${CLASS_NAMES.progressBar}">
|
||||
<span class="${CLASS_NAMES.progress}"></span>
|
||||
</span>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+2
-2
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+86
-40
@@ -5,59 +5,105 @@
|
||||
*/
|
||||
import flasher from '@flasher/flasher';
|
||||
|
||||
const sizeMap = {
|
||||
sm: 16,
|
||||
md: 20,
|
||||
lg: 24,
|
||||
};
|
||||
const iconPaths = {
|
||||
success: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',
|
||||
error: 'M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z',
|
||||
warning: 'M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z',
|
||||
info: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z',
|
||||
close: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',
|
||||
};
|
||||
function getIcon(type, config = {}) {
|
||||
const { size = 'md', className = '' } = config;
|
||||
const dimension = typeof size === 'number' ? size : sizeMap[size];
|
||||
const path = iconPaths[type];
|
||||
if (!path) {
|
||||
return '';
|
||||
}
|
||||
const classAttr = className ? ` class="${className}"` : '';
|
||||
return `<svg${classAttr} viewBox="0 0 24 24" width="${dimension}" height="${dimension}" aria-hidden="true"><path fill="currentColor" d="${path}"/></svg>`;
|
||||
}
|
||||
function getCloseIcon(config = {}) {
|
||||
return getIcon('close', Object.assign({ size: 'sm' }, config));
|
||||
}
|
||||
function getTypeIcon(type, config = {}) {
|
||||
if (type === 'success' || type === 'error' || type === 'warning' || type === 'info') {
|
||||
return getIcon(type, config);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
const DEFAULT_TITLES = {
|
||||
success: 'Success',
|
||||
error: 'Error',
|
||||
warning: 'Warning',
|
||||
info: 'Information',
|
||||
};
|
||||
|
||||
const AMAZON_TITLES = {
|
||||
success: 'Success!',
|
||||
error: 'Problem',
|
||||
warning: 'Warning',
|
||||
info: 'Information',
|
||||
};
|
||||
const amazonTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const getAlertIcon = () => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return `<svg viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
|
||||
</svg>`;
|
||||
case 'error':
|
||||
return `<svg viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
|
||||
</svg>`;
|
||||
case 'warning':
|
||||
return `<svg viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/>
|
||||
</svg>`;
|
||||
case 'info':
|
||||
return `<svg viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
|
||||
</svg>`;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
const getAlertTitle = () => {
|
||||
switch (type) {
|
||||
case 'success': return 'Success!';
|
||||
case 'error': return 'Problem';
|
||||
case 'warning': return 'Warning';
|
||||
case 'info': return 'Information';
|
||||
default: return 'Alert';
|
||||
}
|
||||
};
|
||||
const alertTitle = AMAZON_TITLES[type] || DEFAULT_TITLES[type] || 'Alert';
|
||||
return `
|
||||
<div class="fl-amazon fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('amazon')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-amazon-alert">
|
||||
<div class="fl-alert-content">
|
||||
<div class="fl-icon-container">
|
||||
${getAlertIcon()}
|
||||
${getTypeIcon(type, { size: 'lg' })}
|
||||
</div>
|
||||
<div class="fl-text-content">
|
||||
<div class="fl-alert-title">${getAlertTitle()}</div>
|
||||
<div class="fl-alert-title">${alertTitle}</div>
|
||||
<div class="fl-alert-message">${message}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-alert-actions">
|
||||
<button class="fl-close" aria-label="Close notification">
|
||||
<svg viewBox="0 0 24 24" width="16" height="16">
|
||||
<path fill="currentColor" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
|
||||
</svg>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
${getCloseIcon()}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+86
-40
@@ -9,59 +9,105 @@
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
const sizeMap = {
|
||||
sm: 16,
|
||||
md: 20,
|
||||
lg: 24,
|
||||
};
|
||||
const iconPaths = {
|
||||
success: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',
|
||||
error: 'M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z',
|
||||
warning: 'M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z',
|
||||
info: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z',
|
||||
close: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',
|
||||
};
|
||||
function getIcon(type, config = {}) {
|
||||
const { size = 'md', className = '' } = config;
|
||||
const dimension = typeof size === 'number' ? size : sizeMap[size];
|
||||
const path = iconPaths[type];
|
||||
if (!path) {
|
||||
return '';
|
||||
}
|
||||
const classAttr = className ? ` class="${className}"` : '';
|
||||
return `<svg${classAttr} viewBox="0 0 24 24" width="${dimension}" height="${dimension}" aria-hidden="true"><path fill="currentColor" d="${path}"/></svg>`;
|
||||
}
|
||||
function getCloseIcon(config = {}) {
|
||||
return getIcon('close', Object.assign({ size: 'sm' }, config));
|
||||
}
|
||||
function getTypeIcon(type, config = {}) {
|
||||
if (type === 'success' || type === 'error' || type === 'warning' || type === 'info') {
|
||||
return getIcon(type, config);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
const DEFAULT_TITLES = {
|
||||
success: 'Success',
|
||||
error: 'Error',
|
||||
warning: 'Warning',
|
||||
info: 'Information',
|
||||
};
|
||||
|
||||
const AMAZON_TITLES = {
|
||||
success: 'Success!',
|
||||
error: 'Problem',
|
||||
warning: 'Warning',
|
||||
info: 'Information',
|
||||
};
|
||||
const amazonTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const getAlertIcon = () => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return `<svg viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
|
||||
</svg>`;
|
||||
case 'error':
|
||||
return `<svg viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
|
||||
</svg>`;
|
||||
case 'warning':
|
||||
return `<svg viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/>
|
||||
</svg>`;
|
||||
case 'info':
|
||||
return `<svg viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
|
||||
</svg>`;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
const getAlertTitle = () => {
|
||||
switch (type) {
|
||||
case 'success': return 'Success!';
|
||||
case 'error': return 'Problem';
|
||||
case 'warning': return 'Warning';
|
||||
case 'info': return 'Information';
|
||||
default: return 'Alert';
|
||||
}
|
||||
};
|
||||
const alertTitle = AMAZON_TITLES[type] || DEFAULT_TITLES[type] || 'Alert';
|
||||
return `
|
||||
<div class="fl-amazon fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('amazon')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-amazon-alert">
|
||||
<div class="fl-alert-content">
|
||||
<div class="fl-icon-container">
|
||||
${getAlertIcon()}
|
||||
${getTypeIcon(type, { size: 'lg' })}
|
||||
</div>
|
||||
<div class="fl-text-content">
|
||||
<div class="fl-alert-title">${getAlertTitle()}</div>
|
||||
<div class="fl-alert-title">${alertTitle}</div>
|
||||
<div class="fl-alert-message">${message}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-alert-actions">
|
||||
<button class="fl-close" aria-label="Close notification">
|
||||
<svg viewBox="0 0 24 24" width="16" height="16">
|
||||
<path fill="currentColor" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
|
||||
</svg>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
${getCloseIcon()}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("amazon",{render:e=>{const{type:n,message:t}=e,r="error"===n||"warning"===n;return`\n <div class="fl-amazon fl-${n}" role="${r?"alert":"status"}" aria-live="${r?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-amazon-alert">\n <div class="fl-alert-content">\n <div class="fl-icon-container">\n ${(()=>{switch(n){case"success":return'<svg viewBox="0 0 24 24" width="24" height="24">\n <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>\n </svg>';case"error":return'<svg viewBox="0 0 24 24" width="24" height="24">\n <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>\n </svg>';case"warning":return'<svg viewBox="0 0 24 24" width="24" height="24">\n <path fill="currentColor" d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/>\n </svg>';case"info":return'<svg viewBox="0 0 24 24" width="24" height="24">\n <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>\n </svg>'}return""})()}\n </div>\n <div class="fl-text-content">\n <div class="fl-alert-title">${(()=>{switch(n){case"success":return"Success!";case"error":return"Problem";case"warning":return"Warning";case"info":return"Information";default:return"Alert"}})()}</div>\n <div class="fl-alert-message">${t}</div>\n </div>\n </div>\n <div class="fl-alert-actions">\n <button class="fl-close" aria-label="Close notification">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>\n </svg>\n </button>\n </div>\n </div>\n </div>`}})}));
|
||||
!function(n,e){"object"==typeof exports&&"undefined"!=typeof module?e(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],e):e((n="undefined"!=typeof globalThis?globalThis:n||self).flasher)}(this,(function(n){"use strict";const e={sm:16,md:20,lg:24},s={success:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z",error:"M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z",warning:"M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z",info:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z",close:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"};function r(n,r={}){const{size:i="md",className:t=""}=r,a="number"==typeof i?i:e[i],o=s[n];if(!o)return"";return`<svg${t?` class="${t}"`:""} viewBox="0 0 24 24" width="${a}" height="${a}" aria-hidden="true"><path fill="currentColor" d="${o}"/></svg>`}const i="fl-close",t=n=>`fl-${n}`,a=n=>`fl-${n}`,o={success:"Success",error:"Error",warning:"Warning",info:"Information"},l={success:"Success!",error:"Problem",warning:"Warning",info:"Information"},c={render:n=>{const{type:e,message:s}=n,c=l[e]||o[e]||"Alert";return`\n <div class="${a("amazon")} ${t(e)}" ${function(n){const e=function(n){const e="error"===n||"warning"===n;return{role:e?"alert":"status",ariaLive:e?"assertive":"polite",ariaAtomic:"true"}}(n);return`role="${e.role}" aria-live="${e.ariaLive}" aria-atomic="${e.ariaAtomic}"`}(e)}>\n <div class="fl-amazon-alert">\n <div class="fl-alert-content">\n <div class="fl-icon-container">\n ${function(n,e={}){return"success"===n||"error"===n||"warning"===n||"info"===n?r(n,e):""}(e,{size:"lg"})}\n </div>\n <div class="fl-text-content">\n <div class="fl-alert-title">${c}</div>\n <div class="fl-alert-message">${s}</div>\n </div>\n </div>\n <div class="fl-alert-actions">\n <button class="${i}" ${function(n){return`aria-label="Close ${n} message"`}(e)}>\n ${function(n={}){return r("close",Object.assign({size:"sm"},n))}()}\n </button>\n </div>\n </div>\n </div>`}};n.addTheme("amazon",c)}));
|
||||
|
||||
+44
-11
@@ -5,23 +5,56 @@
|
||||
*/
|
||||
import flasher from '@flasher/flasher';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const amberTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-amber fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-icon"></div>
|
||||
<div class="fl-text">
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.theme('amber')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.icon}"></div>
|
||||
<div class="${CLASS_NAMES.text}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+44
-11
@@ -9,23 +9,56 @@
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const amberTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-amber fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-icon"></div>
|
||||
<div class="fl-text">
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.theme('amber')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.icon}"></div>
|
||||
<div class="${CLASS_NAMES.text}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("amber",{render:e=>{const{type:s,message:i}=e,l="error"===s||"warning"===s;return`\n <div class="fl-amber fl-${s}" role="${l?"alert":"status"}" aria-live="${l?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-content">\n <div class="fl-icon"></div>\n <div class="fl-text">\n <div class="fl-message">${i}</div>\n </div>\n <button class="fl-close" aria-label="Close ${s} message">×</button>\n </div>\n <div class="fl-progress-bar">\n <div class="fl-progress"></div>\n </div>\n </div>`}})}));
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const s="fl-content",i="fl-message",n="fl-text",a="fl-icon",r="fl-close",t="fl-progress-bar",l="fl-progress",o=e=>`fl-${e}`,f=e=>`fl-${e}`,c={render:e=>{const{type:c,message:d}=e;return`\n <div class="${f("amber")} ${o(c)}" ${function(e){const s=function(e){const s="error"===e||"warning"===e;return{role:s?"alert":"status",ariaLive:s?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${s.role}" aria-live="${s.ariaLive}" aria-atomic="${s.ariaAtomic}"`}(c)}>\n <div class="${s}">\n <div class="${a}"></div>\n <div class="${n}">\n <div class="${i}">${d}</div>\n </div>\n <button class="${r}" ${function(e){return`aria-label="Close ${e} message"`}(c)}>×</button>\n </div>\n <div class="${t}">\n <div class="${l}"></div>\n </div>\n </div>`}};e.addTheme("amber",c)}));
|
||||
|
||||
+42
-9
@@ -5,20 +5,53 @@
|
||||
*/
|
||||
import flasher from '@flasher/flasher';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const auroraTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-aurora fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<div class="${CLASS_NAMES.theme('aurora')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+42
-9
@@ -9,20 +9,53 @@
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const auroraTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-aurora fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<div class="${CLASS_NAMES.theme('aurora')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("aurora",{render:e=>{const{type:s,message:a}=e,r="error"===s||"warning"===s;return`\n <div class="fl-aurora fl-${s}" role="${r?"alert":"status"}" aria-live="${r?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-content">\n <div class="fl-message">${a}</div>\n <button class="fl-close" aria-label="Close ${s} message">×</button>\n </div>\n <div class="fl-progress-bar">\n <div class="fl-progress"></div>\n </div>\n </div>`}})}));
|
||||
!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],r):r((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const r="fl-content",s="fl-message",a="fl-close",n="fl-progress-bar",i="fl-progress",t=e=>`fl-${e}`,o=e=>`fl-${e}`,l={render:e=>{const{type:l,message:f}=e;return`\n <div class="${o("aurora")} ${t(l)}" ${function(e){const r=function(e){const r="error"===e||"warning"===e;return{role:r?"alert":"status",ariaLive:r?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${r.role}" aria-live="${r.ariaLive}" aria-atomic="${r.ariaAtomic}"`}(l)}>\n <div class="${r}">\n <div class="${s}">${f}</div>\n <button class="${a}" ${function(e){return`aria-label="Close ${e} message"`}(l)}>×</button>\n </div>\n <div class="${n}">\n <div class="${i}"></div>\n </div>\n </div>`}};e.addTheme("aurora",l)}));
|
||||
|
||||
+43
-10
@@ -5,22 +5,55 @@
|
||||
*/
|
||||
import flasher from '@flasher/flasher';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const crystalTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-crystal fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-text">
|
||||
<p class="fl-message">${message}</p>
|
||||
<div class="${CLASS_NAMES.theme('crystal')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.text}">
|
||||
<p class="${CLASS_NAMES.message}">${message}</p>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+43
-10
@@ -9,22 +9,55 @@
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const crystalTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-crystal fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-text">
|
||||
<p class="fl-message">${message}</p>
|
||||
<div class="${CLASS_NAMES.theme('crystal')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.text}">
|
||||
<p class="${CLASS_NAMES.message}">${message}</p>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("crystal",{render:e=>{const{type:s,message:l}=e,a="error"===s||"warning"===s;return`\n <div class="fl-crystal fl-${s}" role="${a?"alert":"status"}" aria-live="${a?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-content">\n <div class="fl-text">\n <p class="fl-message">${l}</p>\n </div>\n <button class="fl-close" aria-label="Close ${s} message">×</button>\n </div>\n <div class="fl-progress-bar">\n <div class="fl-progress"></div>\n </div>\n </div>`}})}));
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const s="fl-content",n="fl-message",r="fl-text",t="fl-close",a="fl-progress-bar",i="fl-progress",l=e=>`fl-${e}`,o=e=>`fl-${e}`,f={render:e=>{const{type:f,message:c}=e;return`\n <div class="${o("crystal")} ${l(f)}" ${function(e){const s=function(e){const s="error"===e||"warning"===e;return{role:s?"alert":"status",ariaLive:s?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${s.role}" aria-live="${s.ariaLive}" aria-atomic="${s.ariaAtomic}"`}(f)}>\n <div class="${s}">\n <div class="${r}">\n <p class="${n}">${c}</p>\n </div>\n <button class="${t}" ${function(e){return`aria-label="Close ${e} message"`}(f)}>×</button>\n </div>\n <div class="${a}">\n <div class="${i}"></div>\n </div>\n </div>`}};e.addTheme("crystal",f)}));
|
||||
|
||||
+40
-7
@@ -5,17 +5,50 @@
|
||||
*/
|
||||
import flasher from '@flasher/flasher';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const emeraldTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-emerald fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<div class="${CLASS_NAMES.theme('emerald')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+40
-7
@@ -9,17 +9,50 @@
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const emeraldTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-emerald fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<div class="${CLASS_NAMES.theme('emerald')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("emerald",{render:e=>{const{type:s,message:a}=e,l="error"===s||"warning"===s;return`\n <div class="fl-emerald fl-${s}" role="${l?"alert":"status"}" aria-live="${l?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-content">\n <div class="fl-message">${a}</div>\n <button class="fl-close" aria-label="Close ${s} message">×</button>\n </div>\n </div>`}})}));
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const n="fl-content",t="fl-message",a="fl-close",i=e=>`fl-${e}`,r=e=>`fl-${e}`,s={render:e=>{const{type:s,message:l}=e;return`\n <div class="${r("emerald")} ${i(s)}" ${function(e){const n=function(e){const n="error"===e||"warning"===e;return{role:n?"alert":"status",ariaLive:n?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${n.role}" aria-live="${n.ariaLive}" aria-atomic="${n.ariaAtomic}"`}(s)}>\n <div class="${n}">\n <div class="${t}">${l}</div>\n <button class="${a}" ${function(e){return`aria-label="Close ${e} message"`}(s)}>×</button>\n </div>\n </div>`}};e.addTheme("emerald",s)}));
|
||||
|
||||
+70
-14
@@ -5,14 +5,72 @@
|
||||
*/
|
||||
import flasher from '@flasher/flasher';
|
||||
|
||||
const sizeMap = {
|
||||
sm: 16,
|
||||
md: 20,
|
||||
lg: 24,
|
||||
};
|
||||
const iconPaths = {
|
||||
success: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',
|
||||
error: 'M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z',
|
||||
warning: 'M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z',
|
||||
info: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z',
|
||||
close: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',
|
||||
};
|
||||
function getIcon(type, config = {}) {
|
||||
const { size = 'md', className = '' } = config;
|
||||
const dimension = typeof size === 'number' ? size : sizeMap[size];
|
||||
const path = iconPaths[type];
|
||||
const classAttr = className ? ` class="${className}"` : '';
|
||||
return `<svg${classAttr} viewBox="0 0 24 24" width="${dimension}" height="${dimension}" aria-hidden="true"><path fill="currentColor" d="${path}"/></svg>`;
|
||||
}
|
||||
function getCloseIcon(config = {}) {
|
||||
return getIcon('close', Object.assign({ size: 'sm' }, config));
|
||||
}
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
function getTimeString() {
|
||||
const now = new Date();
|
||||
return now.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });
|
||||
}
|
||||
const facebookTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const now = new Date();
|
||||
const timeString = now.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });
|
||||
const getNotificationIcon = () => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
@@ -43,25 +101,23 @@ const facebookTheme = {
|
||||
return '';
|
||||
};
|
||||
return `
|
||||
<div class="fl-facebook fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('facebook')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-fb-notification">
|
||||
<div class="fl-icon-container">
|
||||
${getNotificationIcon()}
|
||||
</div>
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">
|
||||
${message}
|
||||
</div>
|
||||
<div class="fl-meta">
|
||||
<span class="fl-time">${timeString}</span>
|
||||
<span class="fl-time">${getTimeString()}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-button fl-close" aria-label="Close ${type} message">
|
||||
<div class="${CLASS_NAMES.actions}">
|
||||
<button class="fl-button ${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
<div class="fl-button-icon">
|
||||
<svg viewBox="0 0 24 24" width="20" height="20">
|
||||
<path fill="currentColor" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
|
||||
</svg>
|
||||
${getCloseIcon({ size: 'md' })}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
+70
-14
@@ -9,14 +9,72 @@
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
const sizeMap = {
|
||||
sm: 16,
|
||||
md: 20,
|
||||
lg: 24,
|
||||
};
|
||||
const iconPaths = {
|
||||
success: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',
|
||||
error: 'M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z',
|
||||
warning: 'M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z',
|
||||
info: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z',
|
||||
close: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',
|
||||
};
|
||||
function getIcon(type, config = {}) {
|
||||
const { size = 'md', className = '' } = config;
|
||||
const dimension = typeof size === 'number' ? size : sizeMap[size];
|
||||
const path = iconPaths[type];
|
||||
const classAttr = className ? ` class="${className}"` : '';
|
||||
return `<svg${classAttr} viewBox="0 0 24 24" width="${dimension}" height="${dimension}" aria-hidden="true"><path fill="currentColor" d="${path}"/></svg>`;
|
||||
}
|
||||
function getCloseIcon(config = {}) {
|
||||
return getIcon('close', Object.assign({ size: 'sm' }, config));
|
||||
}
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
function getTimeString() {
|
||||
const now = new Date();
|
||||
return now.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });
|
||||
}
|
||||
const facebookTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const now = new Date();
|
||||
const timeString = now.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });
|
||||
const getNotificationIcon = () => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
@@ -47,25 +105,23 @@
|
||||
return '';
|
||||
};
|
||||
return `
|
||||
<div class="fl-facebook fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('facebook')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-fb-notification">
|
||||
<div class="fl-icon-container">
|
||||
${getNotificationIcon()}
|
||||
</div>
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">
|
||||
${message}
|
||||
</div>
|
||||
<div class="fl-meta">
|
||||
<span class="fl-time">${timeString}</span>
|
||||
<span class="fl-time">${getTimeString()}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-button fl-close" aria-label="Close ${type} message">
|
||||
<div class="${CLASS_NAMES.actions}">
|
||||
<button class="fl-button ${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
<div class="fl-button-icon">
|
||||
<svg viewBox="0 0 24 24" width="20" height="20">
|
||||
<path fill="currentColor" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
|
||||
</svg>
|
||||
${getCloseIcon({ size: 'md' })}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1 +1 @@
|
||||
!function(n,i){"object"==typeof exports&&"undefined"!=typeof module?i(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],i):i((n="undefined"!=typeof globalThis?globalThis:n||self).flasher)}(this,(function(n){"use strict";const i={render:n=>{const{type:i,message:e}=n,s="error"===i||"warning"===i,t=s?"alert":"status",l=s?"assertive":"polite",o=(new Date).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"});return`\n <div class="fl-facebook fl-${i}" role="${t}" aria-live="${l}" aria-atomic="true">\n <div class="fl-fb-notification">\n <div class="fl-icon-container">\n ${(()=>{switch(i){case"success":return'<div class="fl-fb-icon fl-fb-icon-success">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-1-11v6h2v-6h-2zm0-4v2h2V7h-2z"/>\n </svg>\n </div>';case"error":return'<div class="fl-fb-icon fl-fb-icon-error">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-11.5c-.69 0-1.25.56-1.25 1.25S11.31 13 12 13s1.25-.56 1.25-1.25S12.69 10.5 12 10.5zM12 9c.552 0 1-.448 1-1V7c0-.552-.448-1-1-1s-1 .448-1 1v1c0 .552.448 1 1 1z"/>\n </svg>\n </div>';case"warning":return'<div class="fl-fb-icon fl-fb-icon-warning">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M12.865 3.00017L22.3912 19.5002C22.6674 19.9785 22.5035 20.5901 22.0252 20.8662C21.8732 20.954 21.7008 21.0002 21.5252 21.0002H2.47266C1.92037 21.0002 1.47266 20.5525 1.47266 20.0002C1.47266 19.8246 1.51886 19.6522 1.60663 19.5002L11.1329 3.00017C11.409 2.52187 12.0206 2.358 12.4989 2.63414C12.651 2.72192 12.7772 2.84815 12.865 3.00017ZM11 16.0002V18.0002H13V16.0002H11ZM11 8.00017V14.0002H13V8.00017H11Z"/>\n </svg>\n </div>';case"info":return'<div class="fl-fb-icon fl-fb-icon-info">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 100-16 8 8 0 000 16zm-1-5h2v-2h-2v2zm0-4h2V7h-2v4z"/>\n </svg>\n </div>'}return""})()}\n </div>\n <div class="fl-content">\n <div class="fl-message">\n ${e}\n </div>\n <div class="fl-meta">\n <span class="fl-time">${o}</span>\n </div>\n </div>\n <div class="fl-actions">\n <button class="fl-button fl-close" aria-label="Close ${i} message">\n <div class="fl-button-icon">\n <svg viewBox="0 0 24 24" width="20" height="20">\n <path fill="currentColor" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>\n </svg>\n </div>\n </button>\n </div>\n </div>\n </div>`}};n.addTheme("facebook",i)}));
|
||||
!function(n,i){"object"==typeof exports&&"undefined"!=typeof module?i(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],i):i((n="undefined"!=typeof globalThis?globalThis:n||self).flasher)}(this,(function(n){"use strict";const i={sm:16,md:20,lg:24},e={success:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z",error:"M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z",warning:"M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z",info:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z",close:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"};function s(n={}){return function(n,s={}){const{size:t="md",className:o=""}=s,r="number"==typeof t?t:i[t];return`<svg${o?` class="${o}"`:""} viewBox="0 0 24 24" width="${r}" height="${r}" aria-hidden="true"><path fill="currentColor" d="${e[n]}"/></svg>`}("close",Object.assign({size:"sm"},n))}const t="fl-content",o="fl-message",r="fl-actions",l="fl-close",c=n=>`fl-${n}`,a=n=>`fl-${n}`;const f={render:n=>{const{type:i,message:e}=n;return`\n <div class="${a("facebook")} ${c(i)}" ${function(n){const i=function(n){const i="error"===n||"warning"===n;return{role:i?"alert":"status",ariaLive:i?"assertive":"polite",ariaAtomic:"true"}}(n);return`role="${i.role}" aria-live="${i.ariaLive}" aria-atomic="${i.ariaAtomic}"`}(i)}>\n <div class="fl-fb-notification">\n <div class="fl-icon-container">\n ${(()=>{switch(i){case"success":return'<div class="fl-fb-icon fl-fb-icon-success">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-1-11v6h2v-6h-2zm0-4v2h2V7h-2z"/>\n </svg>\n </div>';case"error":return'<div class="fl-fb-icon fl-fb-icon-error">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-11.5c-.69 0-1.25.56-1.25 1.25S11.31 13 12 13s1.25-.56 1.25-1.25S12.69 10.5 12 10.5zM12 9c.552 0 1-.448 1-1V7c0-.552-.448-1-1-1s-1 .448-1 1v1c0 .552.448 1 1 1z"/>\n </svg>\n </div>';case"warning":return'<div class="fl-fb-icon fl-fb-icon-warning">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M12.865 3.00017L22.3912 19.5002C22.6674 19.9785 22.5035 20.5901 22.0252 20.8662C21.8732 20.954 21.7008 21.0002 21.5252 21.0002H2.47266C1.92037 21.0002 1.47266 20.5525 1.47266 20.0002C1.47266 19.8246 1.51886 19.6522 1.60663 19.5002L11.1329 3.00017C11.409 2.52187 12.0206 2.358 12.4989 2.63414C12.651 2.72192 12.7772 2.84815 12.865 3.00017ZM11 16.0002V18.0002H13V16.0002H11ZM11 8.00017V14.0002H13V8.00017H11Z"/>\n </svg>\n </div>';case"info":return'<div class="fl-fb-icon fl-fb-icon-info">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 100-16 8 8 0 000 16zm-1-5h2v-2h-2v2zm0-4h2V7h-2v4z"/>\n </svg>\n </div>'}return""})()}\n </div>\n <div class="${t}">\n <div class="${o}">\n ${e}\n </div>\n <div class="fl-meta">\n <span class="fl-time">${(new Date).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"})}</span>\n </div>\n </div>\n <div class="${r}">\n <button class="fl-button ${l}" ${function(n){return`aria-label="Close ${n} message"`}(i)}>\n <div class="fl-button-icon">\n ${s({size:"md"})}\n </div>\n </button>\n </div>\n </div>\n </div>`}};n.addTheme("facebook",f)}));
|
||||
|
||||
+57
-12
@@ -5,25 +5,70 @@
|
||||
*/
|
||||
import flasher from '@flasher/flasher';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
const DEFAULT_TITLES = {
|
||||
success: 'Success',
|
||||
error: 'Error',
|
||||
warning: 'Warning',
|
||||
info: 'Information',
|
||||
};
|
||||
function capitalizeType(type) {
|
||||
return type.charAt(0).toUpperCase() + type.slice(1);
|
||||
}
|
||||
function getTitle(title, type) {
|
||||
return title || DEFAULT_TITLES[type] || capitalizeType(type);
|
||||
}
|
||||
|
||||
const flasherTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, title, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const displayTitle = title || type.charAt(0).toUpperCase() + type.slice(1);
|
||||
const displayTitle = getTitle(title, type);
|
||||
return `
|
||||
<div class="fl-flasher fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-icon"></div>
|
||||
<div class="${CLASS_NAMES.theme('flasher')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.icon}"></div>
|
||||
<div>
|
||||
<strong class="fl-title">${displayTitle}</strong>
|
||||
<span class="fl-message">${message}</span>
|
||||
<strong class="${CLASS_NAMES.title}">${displayTitle}</strong>
|
||||
<span class="${CLASS_NAMES.message}">${message}</span>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<span class="fl-progress-bar">
|
||||
<span class="fl-progress"></span>
|
||||
<span class="${CLASS_NAMES.progressBar}">
|
||||
<span class="${CLASS_NAMES.progress}"></span>
|
||||
</span>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+57
-12
@@ -9,25 +9,70 @@
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
const DEFAULT_TITLES = {
|
||||
success: 'Success',
|
||||
error: 'Error',
|
||||
warning: 'Warning',
|
||||
info: 'Information',
|
||||
};
|
||||
function capitalizeType(type) {
|
||||
return type.charAt(0).toUpperCase() + type.slice(1);
|
||||
}
|
||||
function getTitle(title, type) {
|
||||
return title || DEFAULT_TITLES[type] || capitalizeType(type);
|
||||
}
|
||||
|
||||
const flasherTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, title, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const displayTitle = title || type.charAt(0).toUpperCase() + type.slice(1);
|
||||
const displayTitle = getTitle(title, type);
|
||||
return `
|
||||
<div class="fl-flasher fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-icon"></div>
|
||||
<div class="${CLASS_NAMES.theme('flasher')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.icon}"></div>
|
||||
<div>
|
||||
<strong class="fl-title">${displayTitle}</strong>
|
||||
<span class="fl-message">${message}</span>
|
||||
<strong class="${CLASS_NAMES.title}">${displayTitle}</strong>
|
||||
<span class="${CLASS_NAMES.message}">${message}</span>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<span class="fl-progress-bar">
|
||||
<span class="fl-progress"></span>
|
||||
<span class="${CLASS_NAMES.progressBar}">
|
||||
<span class="${CLASS_NAMES.progress}"></span>
|
||||
</span>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("flasher",{render:e=>{const{type:s,title:n,message:a}=e,l="error"===s||"warning"===s,t=l?"alert":"status",r=l?"assertive":"polite",i=n||s.charAt(0).toUpperCase()+s.slice(1);return`\n <div class="fl-flasher fl-${s}" role="${t}" aria-live="${r}" aria-atomic="true">\n <div class="fl-content">\n <div class="fl-icon"></div>\n <div>\n <strong class="fl-title">${i}</strong>\n <span class="fl-message">${a}</span>\n </div>\n <button class="fl-close" aria-label="Close ${s} message">×</button>\n </div>\n <span class="fl-progress-bar">\n <span class="fl-progress"></span>\n </span>\n </div>`}})}));
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const n="fl-content",s="fl-message",r="fl-title",a="fl-icon",t="fl-close",i="fl-progress-bar",o="fl-progress",l=e=>`fl-${e}`,f=e=>`fl-${e}`,c={success:"Success",error:"Error",warning:"Warning",info:"Information"};const u={render:e=>{const{type:u,title:d,message:$}=e,p=function(e,n){return e||c[n]||function(e){return e.charAt(0).toUpperCase()+e.slice(1)}(n)}(d,u);return`\n <div class="${f("flasher")} ${l(u)}" ${function(e){const n=function(e){const n="error"===e||"warning"===e;return{role:n?"alert":"status",ariaLive:n?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${n.role}" aria-live="${n.ariaLive}" aria-atomic="${n.ariaAtomic}"`}(u)}>\n <div class="${n}">\n <div class="${a}"></div>\n <div>\n <strong class="${r}">${p}</strong>\n <span class="${s}">${$}</span>\n </div>\n <button class="${t}" ${function(e){return`aria-label="Close ${e} message"`}(u)}>×</button>\n </div>\n <span class="${i}">\n <span class="${o}"></span>\n </span>\n </div>`}};e.addTheme("flasher",u)}));
|
||||
|
||||
+78
-36
@@ -5,55 +5,97 @@
|
||||
*/
|
||||
import flasher from '@flasher/flasher';
|
||||
|
||||
const sizeMap = {
|
||||
sm: 16,
|
||||
md: 20,
|
||||
lg: 24,
|
||||
};
|
||||
const iconPaths = {
|
||||
success: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',
|
||||
error: 'M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z',
|
||||
warning: 'M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z',
|
||||
info: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z',
|
||||
close: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',
|
||||
};
|
||||
function getIcon(type, config = {}) {
|
||||
const { size = 'md', className = '' } = config;
|
||||
const dimension = typeof size === 'number' ? size : sizeMap[size];
|
||||
const path = iconPaths[type];
|
||||
if (!path) {
|
||||
return '';
|
||||
}
|
||||
const classAttr = className ? ` class="${className}"` : '';
|
||||
return `<svg${classAttr} viewBox="0 0 24 24" width="${dimension}" height="${dimension}" aria-hidden="true"><path fill="currentColor" d="${path}"/></svg>`;
|
||||
}
|
||||
function getTypeIcon(type, config = {}) {
|
||||
if (type === 'success' || type === 'error' || type === 'warning' || type === 'info') {
|
||||
return getIcon(type, config);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
const DEFAULT_TEXT = {
|
||||
dismissButton: 'DISMISS'};
|
||||
|
||||
const googleTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message, title } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const actionText = 'DISMISS';
|
||||
const getIcon = () => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
|
||||
</svg>`;
|
||||
case 'error':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"/>
|
||||
</svg>`;
|
||||
case 'warning':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z"/>
|
||||
</svg>`;
|
||||
case 'info':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
|
||||
</svg>`;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
const titleSection = title ? `<div class="fl-title">${title}</div>` : '';
|
||||
const titleSection = title ? `<div class="${CLASS_NAMES.title}">${title}</div>` : '';
|
||||
return `
|
||||
<div class="fl-google fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('google')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-md-card">
|
||||
<div class="fl-content">
|
||||
<div class="fl-icon-wrapper">
|
||||
${getIcon()}
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.iconWrapper}">
|
||||
${getTypeIcon(type, { size: 'lg', className: 'fl-icon-svg' })}
|
||||
</div>
|
||||
<div class="fl-text-content">
|
||||
${titleSection}
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-action-button fl-close" aria-label="Close ${type} message">
|
||||
${actionText}
|
||||
<div class="${CLASS_NAMES.actions}">
|
||||
<button class="fl-action-button ${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
${DEFAULT_TEXT.dismissButton}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+78
-36
@@ -9,55 +9,97 @@
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
const sizeMap = {
|
||||
sm: 16,
|
||||
md: 20,
|
||||
lg: 24,
|
||||
};
|
||||
const iconPaths = {
|
||||
success: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',
|
||||
error: 'M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z',
|
||||
warning: 'M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z',
|
||||
info: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z',
|
||||
close: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',
|
||||
};
|
||||
function getIcon(type, config = {}) {
|
||||
const { size = 'md', className = '' } = config;
|
||||
const dimension = typeof size === 'number' ? size : sizeMap[size];
|
||||
const path = iconPaths[type];
|
||||
if (!path) {
|
||||
return '';
|
||||
}
|
||||
const classAttr = className ? ` class="${className}"` : '';
|
||||
return `<svg${classAttr} viewBox="0 0 24 24" width="${dimension}" height="${dimension}" aria-hidden="true"><path fill="currentColor" d="${path}"/></svg>`;
|
||||
}
|
||||
function getTypeIcon(type, config = {}) {
|
||||
if (type === 'success' || type === 'error' || type === 'warning' || type === 'info') {
|
||||
return getIcon(type, config);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
const DEFAULT_TEXT = {
|
||||
dismissButton: 'DISMISS'};
|
||||
|
||||
const googleTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message, title } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const actionText = 'DISMISS';
|
||||
const getIcon = () => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
|
||||
</svg>`;
|
||||
case 'error':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"/>
|
||||
</svg>`;
|
||||
case 'warning':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z"/>
|
||||
</svg>`;
|
||||
case 'info':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
|
||||
</svg>`;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
const titleSection = title ? `<div class="fl-title">${title}</div>` : '';
|
||||
const titleSection = title ? `<div class="${CLASS_NAMES.title}">${title}</div>` : '';
|
||||
return `
|
||||
<div class="fl-google fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('google')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-md-card">
|
||||
<div class="fl-content">
|
||||
<div class="fl-icon-wrapper">
|
||||
${getIcon()}
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.iconWrapper}">
|
||||
${getTypeIcon(type, { size: 'lg', className: 'fl-icon-svg' })}
|
||||
</div>
|
||||
<div class="fl-text-content">
|
||||
${titleSection}
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-action-button fl-close" aria-label="Close ${type} message">
|
||||
${actionText}
|
||||
<div class="${CLASS_NAMES.actions}">
|
||||
<button class="fl-action-button ${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
${DEFAULT_TEXT.dismissButton}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(s,e){"object"==typeof exports&&"undefined"!=typeof module?e(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],e):e((s="undefined"!=typeof globalThis?globalThis:s||self).flasher)}(this,(function(s){"use strict";s.addTheme("google",{render:s=>{const{type:e,message:n,title:l}=s,i="error"===e||"warning"===e,t=l?`<div class="fl-title">${l}</div>`:"";return`\n <div class="fl-google fl-${e}" role="${i?"alert":"status"}" aria-live="${i?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-md-card">\n <div class="fl-content">\n <div class="fl-icon-wrapper">\n ${(()=>{switch(e){case"success":return'<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">\n <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>\n </svg>';case"error":return'<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">\n <path fill="currentColor" d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"/>\n </svg>';case"warning":return'<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">\n <path fill="currentColor" d="M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z"/>\n </svg>';case"info":return'<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">\n <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>\n </svg>'}return""})()}\n </div>\n <div class="fl-text-content">\n ${t}\n <div class="fl-message">${n}</div>\n </div>\n </div>\n <div class="fl-actions">\n <button class="fl-action-button fl-close" aria-label="Close ${e} message">\n DISMISS\n </button>\n </div>\n </div>\n <div class="fl-progress-bar">\n <div class="fl-progress"></div>\n </div>\n </div>`}})}));
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const n={sm:16,md:20,lg:24},s={success:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z",error:"M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z",warning:"M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z",info:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z",close:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"};function i(e,i={}){return"success"===e||"error"===e||"warning"===e||"info"===e?function(e,i={}){const{size:t="md",className:l=""}=i,r="number"==typeof t?t:n[t],a=s[e];return a?`<svg${l?` class="${l}"`:""} viewBox="0 0 24 24" width="${r}" height="${r}" aria-hidden="true"><path fill="currentColor" d="${a}"/></svg>`:""}(e,i):""}const t="fl-content",l="fl-message",r="fl-title",a="fl-icon-wrapper",o="fl-actions",c="fl-close",f="fl-progress-bar",d="fl-progress",v=e=>`fl-${e}`,u=e=>`fl-${e}`,$="DISMISS",h={render:e=>{const{type:n,message:s,title:h}=e,m=h?`<div class="${r}">${h}</div>`:"";return`\n <div class="${u("google")} ${v(n)}" ${function(e){const n=function(e){const n="error"===e||"warning"===e;return{role:n?"alert":"status",ariaLive:n?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${n.role}" aria-live="${n.ariaLive}" aria-atomic="${n.ariaAtomic}"`}(n)}>\n <div class="fl-md-card">\n <div class="${t}">\n <div class="${a}">\n ${i(n,{size:"lg",className:"fl-icon-svg"})}\n </div>\n <div class="fl-text-content">\n ${m}\n <div class="${l}">${s}</div>\n </div>\n </div>\n <div class="${o}">\n <button class="fl-action-button ${c}" ${function(e){return`aria-label="Close ${e} message"`}(n)}>\n ${$}\n </button>\n </div>\n </div>\n <div class="${f}">\n <div class="${d}"></div>\n </div>\n </div>`}};e.addTheme("google",h)}));
|
||||
|
||||
+77
-34
@@ -5,53 +5,96 @@
|
||||
*/
|
||||
import flasher from '@flasher/flasher';
|
||||
|
||||
const sizeMap = {
|
||||
sm: 16,
|
||||
md: 20,
|
||||
lg: 24,
|
||||
};
|
||||
const iconPaths = {
|
||||
success: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',
|
||||
error: 'M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z',
|
||||
warning: 'M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z',
|
||||
info: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z',
|
||||
close: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',
|
||||
};
|
||||
function getIcon(type, config = {}) {
|
||||
const { size = 'md', className = '' } = config;
|
||||
const dimension = typeof size === 'number' ? size : sizeMap[size];
|
||||
const path = iconPaths[type];
|
||||
if (!path) {
|
||||
return '';
|
||||
}
|
||||
const classAttr = className ? ` class="${className}"` : '';
|
||||
return `<svg${classAttr} viewBox="0 0 24 24" width="${dimension}" height="${dimension}" aria-hidden="true"><path fill="currentColor" d="${path}"/></svg>`;
|
||||
}
|
||||
function getTypeIcon(type, config = {}) {
|
||||
if (type === 'success' || type === 'error' || type === 'warning' || type === 'info') {
|
||||
return getIcon(type, config);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const APP_NAME = 'PHPFlasher';
|
||||
function getTimeString() {
|
||||
const now = new Date();
|
||||
return now.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });
|
||||
}
|
||||
const iosTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message, title } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const appName = 'PHPFlasher';
|
||||
const now = new Date();
|
||||
const timeString = now.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });
|
||||
const getIcon = () => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
|
||||
</svg>`;
|
||||
case 'error':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
|
||||
</svg>`;
|
||||
case 'warning':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">
|
||||
<path fill="currentColor" d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/>
|
||||
</svg>`;
|
||||
case 'info':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
|
||||
</svg>`;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
const displayTitle = title || appName;
|
||||
const displayTitle = title || APP_NAME;
|
||||
return `
|
||||
<div class="fl-ios fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('ios')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-ios-notification">
|
||||
<div class="fl-header">
|
||||
<div class="fl-app-icon">
|
||||
${getIcon()}
|
||||
${getTypeIcon(type, { size: 'md', className: 'fl-icon-svg' })}
|
||||
</div>
|
||||
<div class="fl-app-info">
|
||||
<div class="fl-app-name">${displayTitle}</div>
|
||||
<div class="fl-time">${timeString}</div>
|
||||
<div class="fl-time">${getTimeString()}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
+77
-34
@@ -9,53 +9,96 @@
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
const sizeMap = {
|
||||
sm: 16,
|
||||
md: 20,
|
||||
lg: 24,
|
||||
};
|
||||
const iconPaths = {
|
||||
success: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',
|
||||
error: 'M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z',
|
||||
warning: 'M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z',
|
||||
info: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z',
|
||||
close: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',
|
||||
};
|
||||
function getIcon(type, config = {}) {
|
||||
const { size = 'md', className = '' } = config;
|
||||
const dimension = typeof size === 'number' ? size : sizeMap[size];
|
||||
const path = iconPaths[type];
|
||||
if (!path) {
|
||||
return '';
|
||||
}
|
||||
const classAttr = className ? ` class="${className}"` : '';
|
||||
return `<svg${classAttr} viewBox="0 0 24 24" width="${dimension}" height="${dimension}" aria-hidden="true"><path fill="currentColor" d="${path}"/></svg>`;
|
||||
}
|
||||
function getTypeIcon(type, config = {}) {
|
||||
if (type === 'success' || type === 'error' || type === 'warning' || type === 'info') {
|
||||
return getIcon(type, config);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const APP_NAME = 'PHPFlasher';
|
||||
function getTimeString() {
|
||||
const now = new Date();
|
||||
return now.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });
|
||||
}
|
||||
const iosTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message, title } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const appName = 'PHPFlasher';
|
||||
const now = new Date();
|
||||
const timeString = now.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });
|
||||
const getIcon = () => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
|
||||
</svg>`;
|
||||
case 'error':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
|
||||
</svg>`;
|
||||
case 'warning':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">
|
||||
<path fill="currentColor" d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/>
|
||||
</svg>`;
|
||||
case 'info':
|
||||
return `<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
|
||||
</svg>`;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
const displayTitle = title || appName;
|
||||
const displayTitle = title || APP_NAME;
|
||||
return `
|
||||
<div class="fl-ios fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('ios')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-ios-notification">
|
||||
<div class="fl-header">
|
||||
<div class="fl-app-icon">
|
||||
${getIcon()}
|
||||
${getTypeIcon(type, { size: 'md', className: 'fl-icon-svg' })}
|
||||
</div>
|
||||
<div class="fl-app-info">
|
||||
<div class="fl-app-name">${displayTitle}</div>
|
||||
<div class="fl-time">${timeString}</div>
|
||||
<div class="fl-time">${getTimeString()}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const s={render:e=>{const{type:s,message:i,title:n}=e,l="error"===s||"warning"===s,t=l?"alert":"status",a=l?"assertive":"polite",r=(new Date).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"}),o=n||"PHPFlasher";return`\n <div class="fl-ios fl-${s}" role="${t}" aria-live="${a}" aria-atomic="true">\n <div class="fl-ios-notification">\n <div class="fl-header">\n <div class="fl-app-icon">\n ${(()=>{switch(s){case"success":return'<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">\n <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>\n </svg>';case"error":return'<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">\n <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>\n </svg>';case"warning":return'<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">\n <path fill="currentColor" d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/>\n </svg>';case"info":return'<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">\n <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>\n </svg>'}return""})()}\n </div>\n <div class="fl-app-info">\n <div class="fl-app-name">${o}</div>\n <div class="fl-time">${r}</div>\n </div>\n </div>\n <div class="fl-content">\n <div class="fl-message">${i}</div>\n </div>\n <button class="fl-close" aria-label="Close ${s} message">\n <span aria-hidden="true">×</span>\n </button>\n </div>\n </div>`}};e.addTheme("ios",s)}));
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const n={sm:16,md:20,lg:24},i={success:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z",error:"M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z",warning:"M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z",info:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z",close:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"};function s(e,s={}){return"success"===e||"error"===e||"warning"===e||"info"===e?function(e,s={}){const{size:a="md",className:t=""}=s,r="number"==typeof a?a:n[a],l=i[e];return l?`<svg${t?` class="${t}"`:""} viewBox="0 0 24 24" width="${r}" height="${r}" aria-hidden="true"><path fill="currentColor" d="${l}"/></svg>`:""}(e,s):""}const a="fl-content",t="fl-message",r="fl-close",l=e=>`fl-${e}`,o=e=>`fl-${e}`;const c={render:e=>{const{type:n,message:i,title:c}=e,d=c||"PHPFlasher";return`\n <div class="${o("ios")} ${l(n)}" ${function(e){const n=function(e){const n="error"===e||"warning"===e;return{role:n?"alert":"status",ariaLive:n?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${n.role}" aria-live="${n.ariaLive}" aria-atomic="${n.ariaAtomic}"`}(n)}>\n <div class="fl-ios-notification">\n <div class="fl-header">\n <div class="fl-app-icon">\n ${s(n,{size:"md",className:"fl-icon-svg"})}\n </div>\n <div class="fl-app-info">\n <div class="fl-app-name">${d}</div>\n <div class="fl-time">${(new Date).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"})}</div>\n </div>\n </div>\n <div class="${a}">\n <div class="${t}">${i}</div>\n </div>\n <button class="${r}" ${function(e){return`aria-label="Close ${e} message"`}(n)}>\n <span aria-hidden="true">×</span>\n </button>\n </div>\n </div>`}};e.addTheme("ios",c)}));
|
||||
|
||||
+42
-9
@@ -5,20 +5,53 @@
|
||||
*/
|
||||
import flasher from '@flasher/flasher';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const jadeTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-jade fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<div class="${CLASS_NAMES.theme('jade')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+42
-9
@@ -9,20 +9,53 @@
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const jadeTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-jade fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<div class="${CLASS_NAMES.theme('jade')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("jade",{render:e=>{const{type:s,message:a}=e,l="error"===s||"warning"===s;return`\n <div class="fl-jade fl-${s}" role="${l?"alert":"status"}" aria-live="${l?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-content">\n <div class="fl-message">${a}</div>\n <button class="fl-close" aria-label="Close ${s} message">×</button>\n </div>\n <div class="fl-progress-bar">\n <div class="fl-progress"></div>\n </div>\n </div>`}})}));
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const s="fl-content",n="fl-message",i="fl-close",a="fl-progress-bar",r="fl-progress",t=e=>`fl-${e}`,l=e=>`fl-${e}`,o={render:e=>{const{type:o,message:f}=e;return`\n <div class="${l("jade")} ${t(o)}" ${function(e){const s=function(e){const s="error"===e||"warning"===e;return{role:s?"alert":"status",ariaLive:s?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${s.role}" aria-live="${s.ariaLive}" aria-atomic="${s.ariaAtomic}"`}(o)}>\n <div class="${s}">\n <div class="${n}">${f}</div>\n <button class="${i}" ${function(e){return`aria-label="Close ${e} message"`}(o)}>×</button>\n </div>\n <div class="${a}">\n <div class="${r}"></div>\n </div>\n </div>`}};e.addTheme("jade",o)}));
|
||||
|
||||
+46
-12
@@ -5,29 +5,63 @@
|
||||
*/
|
||||
import flasher from '@flasher/flasher';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
const DEFAULT_TEXT = {
|
||||
dismissButton: 'DISMISS'};
|
||||
|
||||
const materialTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const actionText = 'DISMISS';
|
||||
return `
|
||||
<div class="fl-material fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('material')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-md-card">
|
||||
<div class="fl-content">
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="fl-text-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-action-button fl-close" aria-label="Close ${type} message">
|
||||
${actionText}
|
||||
<div class="${CLASS_NAMES.actions}">
|
||||
<button class="fl-action-button ${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
${DEFAULT_TEXT.dismissButton}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+46
-12
@@ -9,29 +9,63 @@
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
const DEFAULT_TEXT = {
|
||||
dismissButton: 'DISMISS'};
|
||||
|
||||
const materialTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const actionText = 'DISMISS';
|
||||
return `
|
||||
<div class="fl-material fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('material')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-md-card">
|
||||
<div class="fl-content">
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="fl-text-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-action-button fl-close" aria-label="Close ${type} message">
|
||||
${actionText}
|
||||
<div class="${CLASS_NAMES.actions}">
|
||||
<button class="fl-action-button ${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
${DEFAULT_TEXT.dismissButton}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("material",{render:e=>{const{type:s,message:n}=e,a="error"===s||"warning"===s;return`\n <div class="fl-material fl-${s}" role="${a?"alert":"status"}" aria-live="${a?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-md-card">\n <div class="fl-content">\n <div class="fl-text-content">\n <div class="fl-message">${n}</div>\n </div>\n </div>\n <div class="fl-actions">\n <button class="fl-action-button fl-close" aria-label="Close ${s} message">\n DISMISS\n </button>\n </div>\n </div>\n <div class="fl-progress-bar">\n <div class="fl-progress"></div>\n </div>\n </div>`}})}));
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const n="fl-content",i="fl-message",s="fl-actions",a="fl-close",t="fl-progress-bar",r="fl-progress",l=e=>`fl-${e}`,o=e=>`fl-${e}`,f="DISMISS",c={render:e=>{const{type:c,message:d}=e;return`\n <div class="${o("material")} ${l(c)}" ${function(e){const n=function(e){const n="error"===e||"warning"===e;return{role:n?"alert":"status",ariaLive:n?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${n.role}" aria-live="${n.ariaLive}" aria-atomic="${n.ariaAtomic}"`}(c)}>\n <div class="fl-md-card">\n <div class="${n}">\n <div class="fl-text-content">\n <div class="${i}">${d}</div>\n </div>\n </div>\n <div class="${s}">\n <button class="fl-action-button ${a}" ${function(e){return`aria-label="Close ${e} message"`}(c)}>\n ${f}\n </button>\n </div>\n </div>\n <div class="${t}">\n <div class="${r}"></div>\n </div>\n </div>`}};e.addTheme("material",c)}));
|
||||
|
||||
+42
-9
@@ -5,20 +5,53 @@
|
||||
*/
|
||||
import flasher from '@flasher/flasher';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const minimalTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-minimal fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<div class="${CLASS_NAMES.theme('minimal')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+42
-9
@@ -9,20 +9,53 @@
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const minimalTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-minimal fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<div class="${CLASS_NAMES.theme('minimal')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("minimal",{render:e=>{const{type:s,message:i}=e,l="error"===s||"warning"===s;return`\n <div class="fl-minimal fl-${s}" role="${l?"alert":"status"}" aria-live="${l?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-content">\n <div class="fl-message">${i}</div>\n <button class="fl-close" aria-label="Close ${s} message">×</button>\n </div>\n <div class="fl-progress-bar">\n <div class="fl-progress"></div>\n </div>\n </div>`}})}));
|
||||
!function(e,i){"object"==typeof exports&&"undefined"!=typeof module?i(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],i):i((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const i="fl-content",n="fl-message",s="fl-close",a="fl-progress-bar",r="fl-progress",t=e=>`fl-${e}`,l=e=>`fl-${e}`,o={render:e=>{const{type:o,message:f}=e;return`\n <div class="${l("minimal")} ${t(o)}" ${function(e){const i=function(e){const i="error"===e||"warning"===e;return{role:i?"alert":"status",ariaLive:i?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${i.role}" aria-live="${i.ariaLive}" aria-atomic="${i.ariaAtomic}"`}(o)}>\n <div class="${i}">\n <div class="${n}">${f}</div>\n <button class="${s}" ${function(e){return`aria-label="Close ${e} message"`}(o)}>×</button>\n </div>\n <div class="${a}">\n <div class="${r}"></div>\n </div>\n </div>`}};e.addTheme("minimal",o)}));
|
||||
|
||||
+42
-9
@@ -5,20 +5,53 @@
|
||||
*/
|
||||
import flasher from '@flasher/flasher';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const neonTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-neon fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<div class="${CLASS_NAMES.theme('neon')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+42
-9
@@ -9,20 +9,53 @@
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const neonTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-neon fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<div class="${CLASS_NAMES.theme('neon')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("neon",{render:e=>{const{type:s,message:n}=e,l="error"===s||"warning"===s;return`\n <div class="fl-neon fl-${s}" role="${l?"alert":"status"}" aria-live="${l?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-content">\n <div class="fl-message">${n}</div>\n <button class="fl-close" aria-label="Close ${s} message">×</button>\n </div>\n <div class="fl-progress-bar">\n <div class="fl-progress"></div>\n </div>\n </div>`}})}));
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const n="fl-content",s="fl-message",i="fl-close",r="fl-progress-bar",a="fl-progress",t=e=>`fl-${e}`,o=e=>`fl-${e}`,l={render:e=>{const{type:l,message:f}=e;return`\n <div class="${o("neon")} ${t(l)}" ${function(e){const n=function(e){const n="error"===e||"warning"===e;return{role:n?"alert":"status",ariaLive:n?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${n.role}" aria-live="${n.ariaLive}" aria-atomic="${n.ariaAtomic}"`}(l)}>\n <div class="${n}">\n <div class="${s}">${f}</div>\n <button class="${i}" ${function(e){return`aria-label="Close ${e} message"`}(l)}>×</button>\n </div>\n <div class="${r}">\n <div class="${a}"></div>\n </div>\n </div>`}};e.addTheme("neon",l)}));
|
||||
|
||||
+43
-10
@@ -5,22 +5,55 @@
|
||||
*/
|
||||
import flasher from '@flasher/flasher';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const onyxTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-onyx fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-text">
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.theme('onyx')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.text}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+43
-10
@@ -9,22 +9,55 @@
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const onyxTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-onyx fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<div class="fl-text">
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.theme('onyx')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="${CLASS_NAMES.text}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("onyx",{render:e=>{const{type:s,message:n}=e,l="error"===s||"warning"===s;return`\n <div class="fl-onyx fl-${s}" role="${l?"alert":"status"}" aria-live="${l?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-content">\n <div class="fl-text">\n <div class="fl-message">${n}</div>\n </div>\n <button class="fl-close" aria-label="Close ${s} message">×</button>\n </div>\n <div class="fl-progress-bar">\n <div class="fl-progress"></div>\n </div>\n </div>`}})}));
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const n="fl-content",s="fl-message",i="fl-text",r="fl-close",t="fl-progress-bar",a="fl-progress",l=e=>`fl-${e}`,o=e=>`fl-${e}`,f={render:e=>{const{type:f,message:c}=e;return`\n <div class="${o("onyx")} ${l(f)}" ${function(e){const n=function(e){const n="error"===e||"warning"===e;return{role:n?"alert":"status",ariaLive:n?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${n.role}" aria-live="${n.ariaLive}" aria-atomic="${n.ariaAtomic}"`}(f)}>\n <div class="${n}">\n <div class="${i}">\n <div class="${s}">${c}</div>\n </div>\n <button class="${r}" ${function(e){return`aria-label="Close ${e} message"`}(f)}>×</button>\n </div>\n <div class="${t}">\n <div class="${a}"></div>\n </div>\n </div>`}};e.addTheme("onyx",f)}));
|
||||
|
||||
+44
-11
@@ -5,26 +5,59 @@
|
||||
*/
|
||||
import flasher from '@flasher/flasher';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const rubyTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-ruby fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('ruby')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-shine"></div>
|
||||
<div class="fl-content">
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="fl-icon-circle">
|
||||
<div class="fl-icon"></div>
|
||||
<div class="${CLASS_NAMES.icon}"></div>
|
||||
</div>
|
||||
<div class="fl-text">
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.text}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+44
-11
@@ -9,26 +9,59 @@
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const rubyTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-ruby fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('ruby')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-shine"></div>
|
||||
<div class="fl-content">
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<div class="fl-icon-circle">
|
||||
<div class="fl-icon"></div>
|
||||
<div class="${CLASS_NAMES.icon}"></div>
|
||||
</div>
|
||||
<div class="fl-text">
|
||||
<div class="fl-message">${message}</div>
|
||||
<div class="${CLASS_NAMES.text}">
|
||||
<div class="${CLASS_NAMES.message}">${message}</div>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("ruby",{render:e=>{const{type:s,message:i}=e,l="error"===s||"warning"===s;return`\n <div class="fl-ruby fl-${s}" role="${l?"alert":"status"}" aria-live="${l?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-shine"></div>\n <div class="fl-content">\n <div class="fl-icon-circle">\n <div class="fl-icon"></div>\n </div>\n <div class="fl-text">\n <div class="fl-message">${i}</div>\n </div>\n <button class="fl-close" aria-label="Close ${s} message">×</button>\n </div>\n <div class="fl-progress-bar">\n <div class="fl-progress"></div>\n </div>\n </div>`}})}));
|
||||
!function(e,i){"object"==typeof exports&&"undefined"!=typeof module?i(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],i):i((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const i="fl-content",s="fl-message",n="fl-text",r="fl-icon",a="fl-close",l="fl-progress-bar",t="fl-progress",o=e=>`fl-${e}`,f=e=>`fl-${e}`,c={render:e=>{const{type:c,message:d}=e;return`\n <div class="${f("ruby")} ${o(c)}" ${function(e){const i=function(e){const i="error"===e||"warning"===e;return{role:i?"alert":"status",ariaLive:i?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${i.role}" aria-live="${i.ariaLive}" aria-atomic="${i.ariaAtomic}"`}(c)}>\n <div class="fl-shine"></div>\n <div class="${i}">\n <div class="fl-icon-circle">\n <div class="${r}"></div>\n </div>\n <div class="${n}">\n <div class="${s}">${d}</div>\n </div>\n <button class="${a}" ${function(e){return`aria-label="Close ${e} message"`}(c)}>×</button>\n </div>\n <div class="${l}">\n <div class="${t}"></div>\n </div>\n </div>`}};e.addTheme("ruby",c)}));
|
||||
|
||||
+38
-8
@@ -5,19 +5,49 @@
|
||||
*/
|
||||
import flasher from '@flasher/flasher';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const sapphireTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-sapphire fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<span class="fl-message">${message}</span>
|
||||
<div class="${CLASS_NAMES.theme('sapphire')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<span class="${CLASS_NAMES.message}">${message}</span>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
+38
-8
@@ -9,19 +9,49 @@
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const sapphireTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
return `
|
||||
<div class="fl-sapphire fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-content">
|
||||
<span class="fl-message">${message}</span>
|
||||
<div class="${CLASS_NAMES.theme('sapphire')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="${CLASS_NAMES.content}">
|
||||
<span class="${CLASS_NAMES.message}">${message}</span>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
<div class="${CLASS_NAMES.progressBar}">
|
||||
<div class="${CLASS_NAMES.progress}"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("sapphire",{render:e=>{const{type:s,message:a}=e,i="error"===s||"warning"===s;return`\n <div class="fl-sapphire fl-${s}" role="${i?"alert":"status"}" aria-live="${i?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-content">\n <span class="fl-message">${a}</span>\n </div>\n <div class="fl-progress-bar">\n <div class="fl-progress"></div>\n </div>\n </div>`}})}));
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const s="fl-content",i="fl-message",r="fl-progress-bar",n="fl-progress",a=e=>`fl-${e}`,t=e=>`fl-${e}`,o={render:e=>{const{type:o,message:l}=e;return`\n <div class="${t("sapphire")} ${a(o)}" ${function(e){const s=function(e){const s="error"===e||"warning"===e;return{role:s?"alert":"status",ariaLive:s?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${s.role}" aria-live="${s.ariaLive}" aria-atomic="${s.ariaAtomic}"`}(o)}>\n <div class="${s}">\n <span class="${i}">${l}</span>\n </div>\n <div class="${r}">\n <div class="${n}"></div>\n </div>\n </div>`}};e.addTheme("sapphire",o)}));
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
export type NotificationType = 'success' | 'info' | 'warning' | 'error';
|
||||
export interface A11yAttributes {
|
||||
role: 'alert' | 'status';
|
||||
ariaLive: 'assertive' | 'polite';
|
||||
ariaAtomic: 'true';
|
||||
}
|
||||
export declare function getA11yAttributes(type: NotificationType | string): A11yAttributes;
|
||||
export declare function getA11yString(type: NotificationType | string): string;
|
||||
export declare function getCloseButtonA11y(type: NotificationType | string): string;
|
||||
@@ -0,0 +1,26 @@
|
||||
export declare const CLASS_NAMES: {
|
||||
readonly container: "fl-container";
|
||||
readonly wrapper: "fl-wrapper";
|
||||
readonly content: "fl-content";
|
||||
readonly message: "fl-message";
|
||||
readonly title: "fl-title";
|
||||
readonly text: "fl-text";
|
||||
readonly icon: "fl-icon";
|
||||
readonly iconWrapper: "fl-icon-wrapper";
|
||||
readonly actions: "fl-actions";
|
||||
readonly close: "fl-close";
|
||||
readonly progressBar: "fl-progress-bar";
|
||||
readonly progress: "fl-progress";
|
||||
readonly show: "fl-show";
|
||||
readonly sticky: "fl-sticky";
|
||||
readonly rtl: "fl-rtl";
|
||||
readonly type: (type: string) => string;
|
||||
readonly theme: (name: string) => string;
|
||||
};
|
||||
export declare const DEFAULT_TITLES: Record<string, string>;
|
||||
export declare const DEFAULT_TEXT: {
|
||||
readonly dismissButton: "DISMISS";
|
||||
readonly closeLabel: (type: string) => string;
|
||||
};
|
||||
export declare function capitalizeType(type: string): string;
|
||||
export declare function getTitle(title: string | undefined, type: string): string;
|
||||
@@ -0,0 +1,9 @@
|
||||
export type IconType = 'success' | 'info' | 'warning' | 'error' | 'close';
|
||||
export type IconSize = 'sm' | 'md' | 'lg' | number;
|
||||
export interface IconConfig {
|
||||
size?: IconSize;
|
||||
className?: string;
|
||||
}
|
||||
export declare function getIcon(type: IconType, config?: IconConfig): string;
|
||||
export declare function getCloseIcon(config?: IconConfig): string;
|
||||
export declare function getTypeIcon(type: string, config?: IconConfig): string;
|
||||
@@ -0,0 +1,5 @@
|
||||
export { getIcon, getCloseIcon, getTypeIcon } from './icons';
|
||||
export type { IconType, IconSize, IconConfig } from './icons';
|
||||
export { getA11yAttributes, getA11yString, getCloseButtonA11y } from './accessibility';
|
||||
export type { NotificationType, A11yAttributes } from './accessibility';
|
||||
export { CLASS_NAMES, DEFAULT_TITLES, DEFAULT_TEXT, capitalizeType, getTitle, } from './constants';
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* @package PHPFlasher
|
||||
* @author Younes ENNAJI
|
||||
* @license MIT
|
||||
*/
|
||||
const sizeMap = {
|
||||
sm: 16,
|
||||
md: 20,
|
||||
lg: 24,
|
||||
};
|
||||
const iconPaths = {
|
||||
success: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',
|
||||
error: 'M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z',
|
||||
warning: 'M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z',
|
||||
info: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z',
|
||||
close: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',
|
||||
};
|
||||
function getIcon(type, config = {}) {
|
||||
const { size = 'md', className = '' } = config;
|
||||
const dimension = typeof size === 'number' ? size : sizeMap[size];
|
||||
const path = iconPaths[type];
|
||||
if (!path) {
|
||||
return '';
|
||||
}
|
||||
const classAttr = className ? ` class="${className}"` : '';
|
||||
return `<svg${classAttr} viewBox="0 0 24 24" width="${dimension}" height="${dimension}" aria-hidden="true"><path fill="currentColor" d="${path}"/></svg>`;
|
||||
}
|
||||
function getCloseIcon(config = {}) {
|
||||
return getIcon('close', Object.assign({ size: 'sm' }, config));
|
||||
}
|
||||
function getTypeIcon(type, config = {}) {
|
||||
if (type === 'success' || type === 'error' || type === 'warning' || type === 'info') {
|
||||
return getIcon(type, config);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
const DEFAULT_TITLES = {
|
||||
success: 'Success',
|
||||
error: 'Error',
|
||||
warning: 'Warning',
|
||||
info: 'Information',
|
||||
};
|
||||
const DEFAULT_TEXT = {
|
||||
dismissButton: 'DISMISS',
|
||||
closeLabel: (type) => `Close ${type} message`,
|
||||
};
|
||||
function capitalizeType(type) {
|
||||
return type.charAt(0).toUpperCase() + type.slice(1);
|
||||
}
|
||||
function getTitle(title, type) {
|
||||
return title || DEFAULT_TITLES[type] || capitalizeType(type);
|
||||
}
|
||||
|
||||
export { CLASS_NAMES, DEFAULT_TEXT, DEFAULT_TITLES, capitalizeType, getA11yAttributes, getA11yString, getCloseButtonA11y, getCloseIcon, getIcon, getTitle, getTypeIcon };
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* @package PHPFlasher
|
||||
* @author Younes ENNAJI
|
||||
* @license MIT
|
||||
*/
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
||||
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.theme = global.theme || {}, global.theme.shared = {})));
|
||||
})(this, (function (exports) { 'use strict';
|
||||
|
||||
const sizeMap = {
|
||||
sm: 16,
|
||||
md: 20,
|
||||
lg: 24,
|
||||
};
|
||||
const iconPaths = {
|
||||
success: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',
|
||||
error: 'M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z',
|
||||
warning: 'M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z',
|
||||
info: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z',
|
||||
close: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',
|
||||
};
|
||||
function getIcon(type, config = {}) {
|
||||
const { size = 'md', className = '' } = config;
|
||||
const dimension = typeof size === 'number' ? size : sizeMap[size];
|
||||
const path = iconPaths[type];
|
||||
if (!path) {
|
||||
return '';
|
||||
}
|
||||
const classAttr = className ? ` class="${className}"` : '';
|
||||
return `<svg${classAttr} viewBox="0 0 24 24" width="${dimension}" height="${dimension}" aria-hidden="true"><path fill="currentColor" d="${path}"/></svg>`;
|
||||
}
|
||||
function getCloseIcon(config = {}) {
|
||||
return getIcon('close', Object.assign({ size: 'sm' }, config));
|
||||
}
|
||||
function getTypeIcon(type, config = {}) {
|
||||
if (type === 'success' || type === 'error' || type === 'warning' || type === 'info') {
|
||||
return getIcon(type, config);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
const DEFAULT_TITLES = {
|
||||
success: 'Success',
|
||||
error: 'Error',
|
||||
warning: 'Warning',
|
||||
info: 'Information',
|
||||
};
|
||||
const DEFAULT_TEXT = {
|
||||
dismissButton: 'DISMISS',
|
||||
closeLabel: (type) => `Close ${type} message`,
|
||||
};
|
||||
function capitalizeType(type) {
|
||||
return type.charAt(0).toUpperCase() + type.slice(1);
|
||||
}
|
||||
function getTitle(title, type) {
|
||||
return title || DEFAULT_TITLES[type] || capitalizeType(type);
|
||||
}
|
||||
|
||||
exports.CLASS_NAMES = CLASS_NAMES;
|
||||
exports.DEFAULT_TEXT = DEFAULT_TEXT;
|
||||
exports.DEFAULT_TITLES = DEFAULT_TITLES;
|
||||
exports.capitalizeType = capitalizeType;
|
||||
exports.getA11yAttributes = getA11yAttributes;
|
||||
exports.getA11yString = getA11yString;
|
||||
exports.getCloseButtonA11y = getCloseButtonA11y;
|
||||
exports.getCloseIcon = getCloseIcon;
|
||||
exports.getIcon = getIcon;
|
||||
exports.getTitle = getTitle;
|
||||
exports.getTypeIcon = getTypeIcon;
|
||||
|
||||
}));
|
||||
@@ -0,0 +1 @@
|
||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(((e="undefined"!=typeof globalThis?globalThis:e||self).theme=e.theme||{},e.theme.shared={}))}(this,(function(e){"use strict";const t={sm:16,md:20,lg:24},r={success:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z",error:"M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z",warning:"M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z",info:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z",close:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"};function n(e,n={}){const{size:s="md",className:o=""}=n,i="number"==typeof s?s:t[s],l=r[e];if(!l)return"";return`<svg${o?` class="${o}"`:""} viewBox="0 0 24 24" width="${i}" height="${i}" aria-hidden="true"><path fill="currentColor" d="${l}"/></svg>`}function s(e){const t="error"===e||"warning"===e;return{role:t?"alert":"status",ariaLive:t?"assertive":"polite",ariaAtomic:"true"}}const o={success:"Success",error:"Error",warning:"Warning",info:"Information"};function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}e.CLASS_NAMES={container:"fl-container",wrapper:"fl-wrapper",content:"fl-content",message:"fl-message",title:"fl-title",text:"fl-text",icon:"fl-icon",iconWrapper:"fl-icon-wrapper",actions:"fl-actions",close:"fl-close",progressBar:"fl-progress-bar",progress:"fl-progress",show:"fl-show",sticky:"fl-sticky",rtl:"fl-rtl",type:e=>`fl-${e}`,theme:e=>`fl-${e}`},e.DEFAULT_TEXT={dismissButton:"DISMISS",closeLabel:e=>`Close ${e} message`},e.DEFAULT_TITLES=o,e.capitalizeType=i,e.getA11yAttributes=s,e.getA11yString=function(e){const t=s(e);return`role="${t.role}" aria-live="${t.ariaLive}" aria-atomic="${t.ariaAtomic}"`},e.getCloseButtonA11y=function(e){return`aria-label="Close ${e} message"`},e.getCloseIcon=function(e={}){return n("close",Object.assign({size:"sm"},e))},e.getIcon=n,e.getTitle=function(e,t){return e||o[t]||i(t)},e.getTypeIcon=function(e,t={}){return"success"===e||"error"===e||"warning"===e||"info"===e?n(e,t):""}}));
|
||||
+71
-23
@@ -5,39 +5,87 @@
|
||||
*/
|
||||
import flasher from '@flasher/flasher';
|
||||
|
||||
const sizeMap = {
|
||||
sm: 16,
|
||||
md: 20,
|
||||
lg: 24,
|
||||
};
|
||||
const iconPaths = {
|
||||
success: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',
|
||||
error: 'M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z',
|
||||
warning: 'M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z',
|
||||
info: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z',
|
||||
close: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',
|
||||
};
|
||||
function getIcon(type, config = {}) {
|
||||
const { size = 'md', className = '' } = config;
|
||||
const dimension = typeof size === 'number' ? size : sizeMap[size];
|
||||
const path = iconPaths[type];
|
||||
const classAttr = className ? ` class="${className}"` : '';
|
||||
return `<svg${classAttr} viewBox="0 0 24 24" width="${dimension}" height="${dimension}" aria-hidden="true"><path fill="currentColor" d="${path}"/></svg>`;
|
||||
}
|
||||
function getCloseIcon(config = {}) {
|
||||
return getIcon('close', Object.assign({ size: 'sm' }, config));
|
||||
}
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const TYPE_ICONS = {
|
||||
success: '✓',
|
||||
error: '✕',
|
||||
warning: '!',
|
||||
info: 'i',
|
||||
};
|
||||
const slackTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const getTypeIcon = () => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return `<div class="fl-type-icon fl-success-icon">✓</div>`;
|
||||
case 'error':
|
||||
return `<div class="fl-type-icon fl-error-icon">✕</div>`;
|
||||
case 'warning':
|
||||
return `<div class="fl-type-icon fl-warning-icon">!</div>`;
|
||||
case 'info':
|
||||
return `<div class="fl-type-icon fl-info-icon">i</div>`;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
const iconChar = TYPE_ICONS[type] || '';
|
||||
return `
|
||||
<div class="fl-slack fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('slack')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-slack-message">
|
||||
<div class="fl-avatar">
|
||||
${getTypeIcon()}
|
||||
<div class="fl-type-icon fl-${type}-icon">${iconChar}</div>
|
||||
</div>
|
||||
<div class="fl-message-content">
|
||||
<div class="fl-message-text">${message}</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-close" aria-label="Close ${type} message">
|
||||
<svg viewBox="0 0 20 20" width="16" height="16">
|
||||
<path fill="currentColor" d="M10 8.586L6.707 5.293a1 1 0 00-1.414 1.414L8.586 10l-3.293 3.293a1 1 0 101.414 1.414L10 11.414l3.293 3.293a1 1 0 001.414-1.414L11.414 10l3.293-3.293a1 1 0 00-1.414-1.414L10 8.586z"/>
|
||||
</svg>
|
||||
<div class="${CLASS_NAMES.actions}">
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
${getCloseIcon()}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+71
-23
@@ -9,39 +9,87 @@
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
const sizeMap = {
|
||||
sm: 16,
|
||||
md: 20,
|
||||
lg: 24,
|
||||
};
|
||||
const iconPaths = {
|
||||
success: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',
|
||||
error: 'M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z',
|
||||
warning: 'M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z',
|
||||
info: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z',
|
||||
close: 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z',
|
||||
};
|
||||
function getIcon(type, config = {}) {
|
||||
const { size = 'md', className = '' } = config;
|
||||
const dimension = typeof size === 'number' ? size : sizeMap[size];
|
||||
const path = iconPaths[type];
|
||||
const classAttr = className ? ` class="${className}"` : '';
|
||||
return `<svg${classAttr} viewBox="0 0 24 24" width="${dimension}" height="${dimension}" aria-hidden="true"><path fill="currentColor" d="${path}"/></svg>`;
|
||||
}
|
||||
function getCloseIcon(config = {}) {
|
||||
return getIcon('close', Object.assign({ size: 'sm' }, config));
|
||||
}
|
||||
|
||||
function getA11yAttributes(type) {
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
return {
|
||||
role: isAlert ? 'alert' : 'status',
|
||||
ariaLive: isAlert ? 'assertive' : 'polite',
|
||||
ariaAtomic: 'true',
|
||||
};
|
||||
}
|
||||
function getA11yString(type) {
|
||||
const attrs = getA11yAttributes(type);
|
||||
return `role="${attrs.role}" aria-live="${attrs.ariaLive}" aria-atomic="${attrs.ariaAtomic}"`;
|
||||
}
|
||||
function getCloseButtonA11y(type) {
|
||||
return `aria-label="Close ${type} message"`;
|
||||
}
|
||||
|
||||
const CLASS_NAMES = {
|
||||
container: 'fl-container',
|
||||
wrapper: 'fl-wrapper',
|
||||
content: 'fl-content',
|
||||
message: 'fl-message',
|
||||
title: 'fl-title',
|
||||
text: 'fl-text',
|
||||
icon: 'fl-icon',
|
||||
iconWrapper: 'fl-icon-wrapper',
|
||||
actions: 'fl-actions',
|
||||
close: 'fl-close',
|
||||
progressBar: 'fl-progress-bar',
|
||||
progress: 'fl-progress',
|
||||
show: 'fl-show',
|
||||
sticky: 'fl-sticky',
|
||||
rtl: 'fl-rtl',
|
||||
type: (type) => `fl-${type}`,
|
||||
theme: (name) => `fl-${name}`,
|
||||
};
|
||||
|
||||
const TYPE_ICONS = {
|
||||
success: '✓',
|
||||
error: '✕',
|
||||
warning: '!',
|
||||
info: 'i',
|
||||
};
|
||||
const slackTheme = {
|
||||
render: (envelope) => {
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const getTypeIcon = () => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return `<div class="fl-type-icon fl-success-icon">✓</div>`;
|
||||
case 'error':
|
||||
return `<div class="fl-type-icon fl-error-icon">✕</div>`;
|
||||
case 'warning':
|
||||
return `<div class="fl-type-icon fl-warning-icon">!</div>`;
|
||||
case 'info':
|
||||
return `<div class="fl-type-icon fl-info-icon">i</div>`;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
const iconChar = TYPE_ICONS[type] || '';
|
||||
return `
|
||||
<div class="fl-slack fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="${CLASS_NAMES.theme('slack')} ${CLASS_NAMES.type(type)}" ${getA11yString(type)}>
|
||||
<div class="fl-slack-message">
|
||||
<div class="fl-avatar">
|
||||
${getTypeIcon()}
|
||||
<div class="fl-type-icon fl-${type}-icon">${iconChar}</div>
|
||||
</div>
|
||||
<div class="fl-message-content">
|
||||
<div class="fl-message-text">${message}</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-close" aria-label="Close ${type} message">
|
||||
<svg viewBox="0 0 20 20" width="16" height="16">
|
||||
<path fill="currentColor" d="M10 8.586L6.707 5.293a1 1 0 00-1.414 1.414L8.586 10l-3.293 3.293a1 1 0 101.414 1.414L10 11.414l3.293 3.293a1 1 0 001.414-1.414L11.414 10l3.293-3.293a1 1 0 00-1.414-1.414L10 8.586z"/>
|
||||
</svg>
|
||||
<div class="${CLASS_NAMES.actions}">
|
||||
<button class="${CLASS_NAMES.close}" ${getCloseButtonA11y(type)}>
|
||||
${getCloseIcon()}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("slack",{render:e=>{const{type:s,message:i}=e,n="error"===s||"warning"===s;return`\n <div class="fl-slack fl-${s}" role="${n?"alert":"status"}" aria-live="${n?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-slack-message">\n <div class="fl-avatar">\n ${(()=>{switch(s){case"success":return'<div class="fl-type-icon fl-success-icon">✓</div>';case"error":return'<div class="fl-type-icon fl-error-icon">✕</div>';case"warning":return'<div class="fl-type-icon fl-warning-icon">!</div>';case"info":return'<div class="fl-type-icon fl-info-icon">i</div>'}return""})()}\n </div>\n <div class="fl-message-content">\n <div class="fl-message-text">${i}</div>\n </div>\n <div class="fl-actions">\n <button class="fl-close" aria-label="Close ${s} message">\n <svg viewBox="0 0 20 20" width="16" height="16">\n <path fill="currentColor" d="M10 8.586L6.707 5.293a1 1 0 00-1.414 1.414L8.586 10l-3.293 3.293a1 1 0 101.414 1.414L10 11.414l3.293 3.293a1 1 0 001.414-1.414L11.414 10l3.293-3.293a1 1 0 00-1.414-1.414L10 8.586z"/>\n </svg>\n </button>\n </div>\n </div>\n </div>`}})}));
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const s={sm:16,md:20,lg:24},n={success:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z",error:"M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z",warning:"M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z",info:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z",close:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"};function i(e={}){return function(e,i={}){const{size:a="md",className:t=""}=i,r="number"==typeof a?a:s[a];return`<svg${t?` class="${t}"`:""} viewBox="0 0 24 24" width="${r}" height="${r}" aria-hidden="true"><path fill="currentColor" d="${n[e]}"/></svg>`}("close",Object.assign({size:"sm"},e))}const a="fl-actions",t="fl-close",r=e=>`fl-${e}`,l=e=>`fl-${e}`,o={success:"✓",error:"✕",warning:"!",info:"i"},c={render:e=>{const{type:s,message:n}=e,c=o[s]||"";return`\n <div class="${l("slack")} ${r(s)}" ${function(e){const s=function(e){const s="error"===e||"warning"===e;return{role:s?"alert":"status",ariaLive:s?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${s.role}" aria-live="${s.ariaLive}" aria-atomic="${s.ariaAtomic}"`}(s)}>\n <div class="fl-slack-message">\n <div class="fl-avatar">\n <div class="fl-type-icon fl-${s}-icon">${c}</div>\n </div>\n <div class="fl-message-content">\n <div class="fl-message-text">${n}</div>\n </div>\n <div class="${a}">\n <button class="${t}" ${function(e){return`aria-label="Close ${e} message"`}(s)}>\n ${i()}\n </button>\n </div>\n </div>\n </div>`}};e.addTheme("slack",c)}));
|
||||
|
||||
+2
-2
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("amazon",{render:e=>{const{type:n,message:t}=e,r="error"===n||"warning"===n;return`\n <div class="fl-amazon fl-${n}" role="${r?"alert":"status"}" aria-live="${r?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-amazon-alert">\n <div class="fl-alert-content">\n <div class="fl-icon-container">\n ${(()=>{switch(n){case"success":return'<svg viewBox="0 0 24 24" width="24" height="24">\n <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>\n </svg>';case"error":return'<svg viewBox="0 0 24 24" width="24" height="24">\n <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>\n </svg>';case"warning":return'<svg viewBox="0 0 24 24" width="24" height="24">\n <path fill="currentColor" d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/>\n </svg>';case"info":return'<svg viewBox="0 0 24 24" width="24" height="24">\n <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>\n </svg>'}return""})()}\n </div>\n <div class="fl-text-content">\n <div class="fl-alert-title">${(()=>{switch(n){case"success":return"Success!";case"error":return"Problem";case"warning":return"Warning";case"info":return"Information";default:return"Alert"}})()}</div>\n <div class="fl-alert-message">${t}</div>\n </div>\n </div>\n <div class="fl-alert-actions">\n <button class="fl-close" aria-label="Close notification">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>\n </svg>\n </button>\n </div>\n </div>\n </div>`}})}));
|
||||
!function(n,e){"object"==typeof exports&&"undefined"!=typeof module?e(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],e):e((n="undefined"!=typeof globalThis?globalThis:n||self).flasher)}(this,(function(n){"use strict";const e={sm:16,md:20,lg:24},s={success:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z",error:"M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z",warning:"M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z",info:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z",close:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"};function r(n,r={}){const{size:i="md",className:t=""}=r,a="number"==typeof i?i:e[i],o=s[n];if(!o)return"";return`<svg${t?` class="${t}"`:""} viewBox="0 0 24 24" width="${a}" height="${a}" aria-hidden="true"><path fill="currentColor" d="${o}"/></svg>`}const i="fl-close",t=n=>`fl-${n}`,a=n=>`fl-${n}`,o={success:"Success",error:"Error",warning:"Warning",info:"Information"},l={success:"Success!",error:"Problem",warning:"Warning",info:"Information"},c={render:n=>{const{type:e,message:s}=n,c=l[e]||o[e]||"Alert";return`\n <div class="${a("amazon")} ${t(e)}" ${function(n){const e=function(n){const e="error"===n||"warning"===n;return{role:e?"alert":"status",ariaLive:e?"assertive":"polite",ariaAtomic:"true"}}(n);return`role="${e.role}" aria-live="${e.ariaLive}" aria-atomic="${e.ariaAtomic}"`}(e)}>\n <div class="fl-amazon-alert">\n <div class="fl-alert-content">\n <div class="fl-icon-container">\n ${function(n,e={}){return"success"===n||"error"===n||"warning"===n||"info"===n?r(n,e):""}(e,{size:"lg"})}\n </div>\n <div class="fl-text-content">\n <div class="fl-alert-title">${c}</div>\n <div class="fl-alert-message">${s}</div>\n </div>\n </div>\n <div class="fl-alert-actions">\n <button class="${i}" ${function(n){return`aria-label="Close ${n} message"`}(e)}>\n ${function(n={}){return r("close",Object.assign({size:"sm"},n))}()}\n </button>\n </div>\n </div>\n </div>`}};n.addTheme("amazon",c)}));
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("amber",{render:e=>{const{type:s,message:i}=e,l="error"===s||"warning"===s;return`\n <div class="fl-amber fl-${s}" role="${l?"alert":"status"}" aria-live="${l?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-content">\n <div class="fl-icon"></div>\n <div class="fl-text">\n <div class="fl-message">${i}</div>\n </div>\n <button class="fl-close" aria-label="Close ${s} message">×</button>\n </div>\n <div class="fl-progress-bar">\n <div class="fl-progress"></div>\n </div>\n </div>`}})}));
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const s="fl-content",i="fl-message",n="fl-text",a="fl-icon",r="fl-close",t="fl-progress-bar",l="fl-progress",o=e=>`fl-${e}`,f=e=>`fl-${e}`,c={render:e=>{const{type:c,message:d}=e;return`\n <div class="${f("amber")} ${o(c)}" ${function(e){const s=function(e){const s="error"===e||"warning"===e;return{role:s?"alert":"status",ariaLive:s?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${s.role}" aria-live="${s.ariaLive}" aria-atomic="${s.ariaAtomic}"`}(c)}>\n <div class="${s}">\n <div class="${a}"></div>\n <div class="${n}">\n <div class="${i}">${d}</div>\n </div>\n <button class="${r}" ${function(e){return`aria-label="Close ${e} message"`}(c)}>×</button>\n </div>\n <div class="${t}">\n <div class="${l}"></div>\n </div>\n </div>`}};e.addTheme("amber",c)}));
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("aurora",{render:e=>{const{type:s,message:a}=e,r="error"===s||"warning"===s;return`\n <div class="fl-aurora fl-${s}" role="${r?"alert":"status"}" aria-live="${r?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-content">\n <div class="fl-message">${a}</div>\n <button class="fl-close" aria-label="Close ${s} message">×</button>\n </div>\n <div class="fl-progress-bar">\n <div class="fl-progress"></div>\n </div>\n </div>`}})}));
|
||||
!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],r):r((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const r="fl-content",s="fl-message",a="fl-close",n="fl-progress-bar",i="fl-progress",t=e=>`fl-${e}`,o=e=>`fl-${e}`,l={render:e=>{const{type:l,message:f}=e;return`\n <div class="${o("aurora")} ${t(l)}" ${function(e){const r=function(e){const r="error"===e||"warning"===e;return{role:r?"alert":"status",ariaLive:r?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${r.role}" aria-live="${r.ariaLive}" aria-atomic="${r.ariaAtomic}"`}(l)}>\n <div class="${r}">\n <div class="${s}">${f}</div>\n <button class="${a}" ${function(e){return`aria-label="Close ${e} message"`}(l)}>×</button>\n </div>\n <div class="${n}">\n <div class="${i}"></div>\n </div>\n </div>`}};e.addTheme("aurora",l)}));
|
||||
|
||||
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("crystal",{render:e=>{const{type:s,message:l}=e,a="error"===s||"warning"===s;return`\n <div class="fl-crystal fl-${s}" role="${a?"alert":"status"}" aria-live="${a?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-content">\n <div class="fl-text">\n <p class="fl-message">${l}</p>\n </div>\n <button class="fl-close" aria-label="Close ${s} message">×</button>\n </div>\n <div class="fl-progress-bar">\n <div class="fl-progress"></div>\n </div>\n </div>`}})}));
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const s="fl-content",n="fl-message",r="fl-text",t="fl-close",a="fl-progress-bar",i="fl-progress",l=e=>`fl-${e}`,o=e=>`fl-${e}`,f={render:e=>{const{type:f,message:c}=e;return`\n <div class="${o("crystal")} ${l(f)}" ${function(e){const s=function(e){const s="error"===e||"warning"===e;return{role:s?"alert":"status",ariaLive:s?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${s.role}" aria-live="${s.ariaLive}" aria-atomic="${s.ariaAtomic}"`}(f)}>\n <div class="${s}">\n <div class="${r}">\n <p class="${n}">${c}</p>\n </div>\n <button class="${t}" ${function(e){return`aria-label="Close ${e} message"`}(f)}>×</button>\n </div>\n <div class="${a}">\n <div class="${i}"></div>\n </div>\n </div>`}};e.addTheme("crystal",f)}));
|
||||
|
||||
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("emerald",{render:e=>{const{type:s,message:a}=e,l="error"===s||"warning"===s;return`\n <div class="fl-emerald fl-${s}" role="${l?"alert":"status"}" aria-live="${l?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-content">\n <div class="fl-message">${a}</div>\n <button class="fl-close" aria-label="Close ${s} message">×</button>\n </div>\n </div>`}})}));
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const n="fl-content",t="fl-message",a="fl-close",i=e=>`fl-${e}`,r=e=>`fl-${e}`,s={render:e=>{const{type:s,message:l}=e;return`\n <div class="${r("emerald")} ${i(s)}" ${function(e){const n=function(e){const n="error"===e||"warning"===e;return{role:n?"alert":"status",ariaLive:n?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${n.role}" aria-live="${n.ariaLive}" aria-atomic="${n.ariaAtomic}"`}(s)}>\n <div class="${n}">\n <div class="${t}">${l}</div>\n <button class="${a}" ${function(e){return`aria-label="Close ${e} message"`}(s)}>×</button>\n </div>\n </div>`}};e.addTheme("emerald",s)}));
|
||||
|
||||
@@ -1 +1 @@
|
||||
!function(n,i){"object"==typeof exports&&"undefined"!=typeof module?i(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],i):i((n="undefined"!=typeof globalThis?globalThis:n||self).flasher)}(this,(function(n){"use strict";const i={render:n=>{const{type:i,message:e}=n,s="error"===i||"warning"===i,t=s?"alert":"status",l=s?"assertive":"polite",o=(new Date).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"});return`\n <div class="fl-facebook fl-${i}" role="${t}" aria-live="${l}" aria-atomic="true">\n <div class="fl-fb-notification">\n <div class="fl-icon-container">\n ${(()=>{switch(i){case"success":return'<div class="fl-fb-icon fl-fb-icon-success">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-1-11v6h2v-6h-2zm0-4v2h2V7h-2z"/>\n </svg>\n </div>';case"error":return'<div class="fl-fb-icon fl-fb-icon-error">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-11.5c-.69 0-1.25.56-1.25 1.25S11.31 13 12 13s1.25-.56 1.25-1.25S12.69 10.5 12 10.5zM12 9c.552 0 1-.448 1-1V7c0-.552-.448-1-1-1s-1 .448-1 1v1c0 .552.448 1 1 1z"/>\n </svg>\n </div>';case"warning":return'<div class="fl-fb-icon fl-fb-icon-warning">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M12.865 3.00017L22.3912 19.5002C22.6674 19.9785 22.5035 20.5901 22.0252 20.8662C21.8732 20.954 21.7008 21.0002 21.5252 21.0002H2.47266C1.92037 21.0002 1.47266 20.5525 1.47266 20.0002C1.47266 19.8246 1.51886 19.6522 1.60663 19.5002L11.1329 3.00017C11.409 2.52187 12.0206 2.358 12.4989 2.63414C12.651 2.72192 12.7772 2.84815 12.865 3.00017ZM11 16.0002V18.0002H13V16.0002H11ZM11 8.00017V14.0002H13V8.00017H11Z"/>\n </svg>\n </div>';case"info":return'<div class="fl-fb-icon fl-fb-icon-info">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 100-16 8 8 0 000 16zm-1-5h2v-2h-2v2zm0-4h2V7h-2v4z"/>\n </svg>\n </div>'}return""})()}\n </div>\n <div class="fl-content">\n <div class="fl-message">\n ${e}\n </div>\n <div class="fl-meta">\n <span class="fl-time">${o}</span>\n </div>\n </div>\n <div class="fl-actions">\n <button class="fl-button fl-close" aria-label="Close ${i} message">\n <div class="fl-button-icon">\n <svg viewBox="0 0 24 24" width="20" height="20">\n <path fill="currentColor" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>\n </svg>\n </div>\n </button>\n </div>\n </div>\n </div>`}};n.addTheme("facebook",i)}));
|
||||
!function(n,i){"object"==typeof exports&&"undefined"!=typeof module?i(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],i):i((n="undefined"!=typeof globalThis?globalThis:n||self).flasher)}(this,(function(n){"use strict";const i={sm:16,md:20,lg:24},e={success:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z",error:"M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z",warning:"M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z",info:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z",close:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"};function s(n={}){return function(n,s={}){const{size:t="md",className:o=""}=s,r="number"==typeof t?t:i[t];return`<svg${o?` class="${o}"`:""} viewBox="0 0 24 24" width="${r}" height="${r}" aria-hidden="true"><path fill="currentColor" d="${e[n]}"/></svg>`}("close",Object.assign({size:"sm"},n))}const t="fl-content",o="fl-message",r="fl-actions",l="fl-close",c=n=>`fl-${n}`,a=n=>`fl-${n}`;const f={render:n=>{const{type:i,message:e}=n;return`\n <div class="${a("facebook")} ${c(i)}" ${function(n){const i=function(n){const i="error"===n||"warning"===n;return{role:i?"alert":"status",ariaLive:i?"assertive":"polite",ariaAtomic:"true"}}(n);return`role="${i.role}" aria-live="${i.ariaLive}" aria-atomic="${i.ariaAtomic}"`}(i)}>\n <div class="fl-fb-notification">\n <div class="fl-icon-container">\n ${(()=>{switch(i){case"success":return'<div class="fl-fb-icon fl-fb-icon-success">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-1-11v6h2v-6h-2zm0-4v2h2V7h-2z"/>\n </svg>\n </div>';case"error":return'<div class="fl-fb-icon fl-fb-icon-error">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-11.5c-.69 0-1.25.56-1.25 1.25S11.31 13 12 13s1.25-.56 1.25-1.25S12.69 10.5 12 10.5zM12 9c.552 0 1-.448 1-1V7c0-.552-.448-1-1-1s-1 .448-1 1v1c0 .552.448 1 1 1z"/>\n </svg>\n </div>';case"warning":return'<div class="fl-fb-icon fl-fb-icon-warning">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M12.865 3.00017L22.3912 19.5002C22.6674 19.9785 22.5035 20.5901 22.0252 20.8662C21.8732 20.954 21.7008 21.0002 21.5252 21.0002H2.47266C1.92037 21.0002 1.47266 20.5525 1.47266 20.0002C1.47266 19.8246 1.51886 19.6522 1.60663 19.5002L11.1329 3.00017C11.409 2.52187 12.0206 2.358 12.4989 2.63414C12.651 2.72192 12.7772 2.84815 12.865 3.00017ZM11 16.0002V18.0002H13V16.0002H11ZM11 8.00017V14.0002H13V8.00017H11Z"/>\n </svg>\n </div>';case"info":return'<div class="fl-fb-icon fl-fb-icon-info">\n <svg viewBox="0 0 24 24" width="16" height="16">\n <path fill="currentColor" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 100-16 8 8 0 000 16zm-1-5h2v-2h-2v2zm0-4h2V7h-2v4z"/>\n </svg>\n </div>'}return""})()}\n </div>\n <div class="${t}">\n <div class="${o}">\n ${e}\n </div>\n <div class="fl-meta">\n <span class="fl-time">${(new Date).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"})}</span>\n </div>\n </div>\n <div class="${r}">\n <button class="fl-button ${l}" ${function(n){return`aria-label="Close ${n} message"`}(i)}>\n <div class="fl-button-icon">\n ${s({size:"md"})}\n </div>\n </button>\n </div>\n </div>\n </div>`}};n.addTheme("facebook",f)}));
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("flasher",{render:e=>{const{type:s,title:n,message:a}=e,l="error"===s||"warning"===s,t=l?"alert":"status",r=l?"assertive":"polite",i=n||s.charAt(0).toUpperCase()+s.slice(1);return`\n <div class="fl-flasher fl-${s}" role="${t}" aria-live="${r}" aria-atomic="true">\n <div class="fl-content">\n <div class="fl-icon"></div>\n <div>\n <strong class="fl-title">${i}</strong>\n <span class="fl-message">${a}</span>\n </div>\n <button class="fl-close" aria-label="Close ${s} message">×</button>\n </div>\n <span class="fl-progress-bar">\n <span class="fl-progress"></span>\n </span>\n </div>`}})}));
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const n="fl-content",s="fl-message",r="fl-title",a="fl-icon",t="fl-close",i="fl-progress-bar",o="fl-progress",l=e=>`fl-${e}`,f=e=>`fl-${e}`,c={success:"Success",error:"Error",warning:"Warning",info:"Information"};const u={render:e=>{const{type:u,title:d,message:$}=e,p=function(e,n){return e||c[n]||function(e){return e.charAt(0).toUpperCase()+e.slice(1)}(n)}(d,u);return`\n <div class="${f("flasher")} ${l(u)}" ${function(e){const n=function(e){const n="error"===e||"warning"===e;return{role:n?"alert":"status",ariaLive:n?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${n.role}" aria-live="${n.ariaLive}" aria-atomic="${n.ariaAtomic}"`}(u)}>\n <div class="${n}">\n <div class="${a}"></div>\n <div>\n <strong class="${r}">${p}</strong>\n <span class="${s}">${$}</span>\n </div>\n <button class="${t}" ${function(e){return`aria-label="Close ${e} message"`}(u)}>×</button>\n </div>\n <span class="${i}">\n <span class="${o}"></span>\n </span>\n </div>`}};e.addTheme("flasher",u)}));
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(s,e){"object"==typeof exports&&"undefined"!=typeof module?e(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],e):e((s="undefined"!=typeof globalThis?globalThis:s||self).flasher)}(this,(function(s){"use strict";s.addTheme("google",{render:s=>{const{type:e,message:n,title:l}=s,i="error"===e||"warning"===e,t=l?`<div class="fl-title">${l}</div>`:"";return`\n <div class="fl-google fl-${e}" role="${i?"alert":"status"}" aria-live="${i?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-md-card">\n <div class="fl-content">\n <div class="fl-icon-wrapper">\n ${(()=>{switch(e){case"success":return'<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">\n <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>\n </svg>';case"error":return'<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">\n <path fill="currentColor" d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"/>\n </svg>';case"warning":return'<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">\n <path fill="currentColor" d="M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z"/>\n </svg>';case"info":return'<svg class="fl-icon-svg" viewBox="0 0 24 24" width="24" height="24">\n <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>\n </svg>'}return""})()}\n </div>\n <div class="fl-text-content">\n ${t}\n <div class="fl-message">${n}</div>\n </div>\n </div>\n <div class="fl-actions">\n <button class="fl-action-button fl-close" aria-label="Close ${e} message">\n DISMISS\n </button>\n </div>\n </div>\n <div class="fl-progress-bar">\n <div class="fl-progress"></div>\n </div>\n </div>`}})}));
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const n={sm:16,md:20,lg:24},s={success:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z",error:"M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z",warning:"M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z",info:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z",close:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"};function i(e,i={}){return"success"===e||"error"===e||"warning"===e||"info"===e?function(e,i={}){const{size:t="md",className:l=""}=i,r="number"==typeof t?t:n[t],a=s[e];return a?`<svg${l?` class="${l}"`:""} viewBox="0 0 24 24" width="${r}" height="${r}" aria-hidden="true"><path fill="currentColor" d="${a}"/></svg>`:""}(e,i):""}const t="fl-content",l="fl-message",r="fl-title",a="fl-icon-wrapper",o="fl-actions",c="fl-close",f="fl-progress-bar",d="fl-progress",v=e=>`fl-${e}`,u=e=>`fl-${e}`,$="DISMISS",h={render:e=>{const{type:n,message:s,title:h}=e,m=h?`<div class="${r}">${h}</div>`:"";return`\n <div class="${u("google")} ${v(n)}" ${function(e){const n=function(e){const n="error"===e||"warning"===e;return{role:n?"alert":"status",ariaLive:n?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${n.role}" aria-live="${n.ariaLive}" aria-atomic="${n.ariaAtomic}"`}(n)}>\n <div class="fl-md-card">\n <div class="${t}">\n <div class="${a}">\n ${i(n,{size:"lg",className:"fl-icon-svg"})}\n </div>\n <div class="fl-text-content">\n ${m}\n <div class="${l}">${s}</div>\n </div>\n </div>\n <div class="${o}">\n <button class="fl-action-button ${c}" ${function(e){return`aria-label="Close ${e} message"`}(n)}>\n ${$}\n </button>\n </div>\n </div>\n <div class="${f}">\n <div class="${d}"></div>\n </div>\n </div>`}};e.addTheme("google",h)}));
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const s={render:e=>{const{type:s,message:i,title:n}=e,l="error"===s||"warning"===s,t=l?"alert":"status",a=l?"assertive":"polite",r=(new Date).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"}),o=n||"PHPFlasher";return`\n <div class="fl-ios fl-${s}" role="${t}" aria-live="${a}" aria-atomic="true">\n <div class="fl-ios-notification">\n <div class="fl-header">\n <div class="fl-app-icon">\n ${(()=>{switch(s){case"success":return'<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">\n <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>\n </svg>';case"error":return'<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">\n <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>\n </svg>';case"warning":return'<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">\n <path fill="currentColor" d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/>\n </svg>';case"info":return'<svg class="fl-icon-svg" viewBox="0 0 24 24" width="20" height="20">\n <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>\n </svg>'}return""})()}\n </div>\n <div class="fl-app-info">\n <div class="fl-app-name">${o}</div>\n <div class="fl-time">${r}</div>\n </div>\n </div>\n <div class="fl-content">\n <div class="fl-message">${i}</div>\n </div>\n <button class="fl-close" aria-label="Close ${s} message">\n <span aria-hidden="true">×</span>\n </button>\n </div>\n </div>`}};e.addTheme("ios",s)}));
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const n={sm:16,md:20,lg:24},i={success:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z",error:"M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z",warning:"M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z",info:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z",close:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"};function s(e,s={}){return"success"===e||"error"===e||"warning"===e||"info"===e?function(e,s={}){const{size:a="md",className:t=""}=s,r="number"==typeof a?a:n[a],l=i[e];return l?`<svg${t?` class="${t}"`:""} viewBox="0 0 24 24" width="${r}" height="${r}" aria-hidden="true"><path fill="currentColor" d="${l}"/></svg>`:""}(e,s):""}const a="fl-content",t="fl-message",r="fl-close",l=e=>`fl-${e}`,o=e=>`fl-${e}`;const c={render:e=>{const{type:n,message:i,title:c}=e,d=c||"PHPFlasher";return`\n <div class="${o("ios")} ${l(n)}" ${function(e){const n=function(e){const n="error"===e||"warning"===e;return{role:n?"alert":"status",ariaLive:n?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${n.role}" aria-live="${n.ariaLive}" aria-atomic="${n.ariaAtomic}"`}(n)}>\n <div class="fl-ios-notification">\n <div class="fl-header">\n <div class="fl-app-icon">\n ${s(n,{size:"md",className:"fl-icon-svg"})}\n </div>\n <div class="fl-app-info">\n <div class="fl-app-name">${d}</div>\n <div class="fl-time">${(new Date).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"})}</div>\n </div>\n </div>\n <div class="${a}">\n <div class="${t}">${i}</div>\n </div>\n <button class="${r}" ${function(e){return`aria-label="Close ${e} message"`}(n)}>\n <span aria-hidden="true">×</span>\n </button>\n </div>\n </div>`}};e.addTheme("ios",c)}));
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("jade",{render:e=>{const{type:s,message:a}=e,l="error"===s||"warning"===s;return`\n <div class="fl-jade fl-${s}" role="${l?"alert":"status"}" aria-live="${l?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-content">\n <div class="fl-message">${a}</div>\n <button class="fl-close" aria-label="Close ${s} message">×</button>\n </div>\n <div class="fl-progress-bar">\n <div class="fl-progress"></div>\n </div>\n </div>`}})}));
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const s="fl-content",n="fl-message",i="fl-close",a="fl-progress-bar",r="fl-progress",t=e=>`fl-${e}`,l=e=>`fl-${e}`,o={render:e=>{const{type:o,message:f}=e;return`\n <div class="${l("jade")} ${t(o)}" ${function(e){const s=function(e){const s="error"===e||"warning"===e;return{role:s?"alert":"status",ariaLive:s?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${s.role}" aria-live="${s.ariaLive}" aria-atomic="${s.ariaAtomic}"`}(o)}>\n <div class="${s}">\n <div class="${n}">${f}</div>\n <button class="${i}" ${function(e){return`aria-label="Close ${e} message"`}(o)}>×</button>\n </div>\n <div class="${a}">\n <div class="${r}"></div>\n </div>\n </div>`}};e.addTheme("jade",o)}));
|
||||
|
||||
@@ -1 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("material",{render:e=>{const{type:s,message:n}=e,a="error"===s||"warning"===s;return`\n <div class="fl-material fl-${s}" role="${a?"alert":"status"}" aria-live="${a?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-md-card">\n <div class="fl-content">\n <div class="fl-text-content">\n <div class="fl-message">${n}</div>\n </div>\n </div>\n <div class="fl-actions">\n <button class="fl-action-button fl-close" aria-label="Close ${s} message">\n DISMISS\n </button>\n </div>\n </div>\n <div class="fl-progress-bar">\n <div class="fl-progress"></div>\n </div>\n </div>`}})}));
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("@flasher/flasher")):"function"==typeof define&&define.amd?define(["@flasher/flasher"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const n="fl-content",i="fl-message",s="fl-actions",a="fl-close",t="fl-progress-bar",r="fl-progress",l=e=>`fl-${e}`,o=e=>`fl-${e}`,f="DISMISS",c={render:e=>{const{type:c,message:d}=e;return`\n <div class="${o("material")} ${l(c)}" ${function(e){const n=function(e){const n="error"===e||"warning"===e;return{role:n?"alert":"status",ariaLive:n?"assertive":"polite",ariaAtomic:"true"}}(e);return`role="${n.role}" aria-live="${n.ariaLive}" aria-atomic="${n.ariaAtomic}"`}(c)}>\n <div class="fl-md-card">\n <div class="${n}">\n <div class="fl-text-content">\n <div class="${i}">${d}</div>\n </div>\n </div>\n <div class="${s}">\n <button class="fl-action-button ${a}" ${function(e){return`aria-label="Close ${e} message"`}(c)}>\n ${f}\n </button>\n </div>\n </div>\n <div class="${t}">\n <div class="${r}"></div>\n </div>\n </div>`}};e.addTheme("material",c)}));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user