mirror of
https://github.com/php-flasher/php-flasher.git
synced 2026-03-31 15:07:47 +01:00
compile assets
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"dist/main.css": "/dist/main.801e5ea3.css",
|
||||
"dist/main.js": "/dist/main.36e31cce.js",
|
||||
"dist/main.css": "/dist/main.a90b8c42.css",
|
||||
"dist/main.js": "/dist/main.2cce2675.js",
|
||||
"dist/455.3a7b4474.css": "/dist/455.3a7b4474.css",
|
||||
"dist/455.095e6545.js": "/dist/455.095e6545.js",
|
||||
"dist/411.29cd993e.css": "/dist/411.29cd993e.css",
|
||||
|
||||
Vendored
+2
-2
@@ -2,10 +2,10 @@
|
||||
"entrypoints": {
|
||||
"main": {
|
||||
"css": [
|
||||
"/dist/main.801e5ea3.css"
|
||||
"/dist/main.a90b8c42.css"
|
||||
],
|
||||
"js": [
|
||||
"/dist/main.36e31cce.js"
|
||||
"/dist/main.2cce2675.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+2
File diff suppressed because one or more lines are too long
Vendored
-2
File diff suppressed because one or more lines are too long
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
+66
-22
@@ -15,48 +15,92 @@ class AbstractPlugin {
|
||||
this.flash('warning', message, title, options);
|
||||
}
|
||||
flash(type, message, title, options) {
|
||||
let normalizedType;
|
||||
let normalizedMessage;
|
||||
let normalizedTitle;
|
||||
let normalizedOptions = {};
|
||||
if (typeof type === 'object') {
|
||||
options = type;
|
||||
type = options.type;
|
||||
message = options.message;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, type);
|
||||
normalizedType = normalizedOptions.type;
|
||||
normalizedMessage = normalizedOptions.message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.type;
|
||||
delete normalizedOptions.message;
|
||||
delete normalizedOptions.title;
|
||||
} else if (typeof message === 'object') {
|
||||
options = message;
|
||||
message = options.message;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, message);
|
||||
normalizedType = type;
|
||||
normalizedMessage = normalizedOptions.message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.message;
|
||||
delete normalizedOptions.title;
|
||||
} else if (typeof title === 'object') {
|
||||
options = title;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, title);
|
||||
normalizedType = type;
|
||||
normalizedMessage = message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.title;
|
||||
} else {
|
||||
normalizedType = type;
|
||||
normalizedMessage = message;
|
||||
normalizedTitle = title;
|
||||
normalizedOptions = options || {};
|
||||
}
|
||||
if (undefined === message) {
|
||||
throw new Error('message option is required');
|
||||
if (!normalizedType) {
|
||||
throw new Error('Type is required for notifications');
|
||||
}
|
||||
if (normalizedMessage === undefined || normalizedMessage === null) {
|
||||
throw new Error('Message is required for notifications');
|
||||
}
|
||||
const envelope = {
|
||||
type,
|
||||
message,
|
||||
title: title || type,
|
||||
options: options || {},
|
||||
type: normalizedType,
|
||||
message: normalizedMessage,
|
||||
title: normalizedTitle || normalizedType,
|
||||
options: normalizedOptions,
|
||||
metadata: {
|
||||
plugin: ''
|
||||
}
|
||||
};
|
||||
this.renderOptions(options || {});
|
||||
this.renderOptions(normalizedOptions);
|
||||
this.renderEnvelopes([envelope]);
|
||||
}
|
||||
}
|
||||
|
||||
class NotyPlugin extends AbstractPlugin {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.defaultOptions = {
|
||||
timeout: 10000,
|
||||
};
|
||||
}
|
||||
renderEnvelopes(envelopes) {
|
||||
if (!(envelopes === null || envelopes === void 0 ? void 0 : envelopes.length)) {
|
||||
return;
|
||||
}
|
||||
envelopes.forEach((envelope) => {
|
||||
var _a;
|
||||
const options = Object.assign({ text: envelope.message, type: envelope.type }, envelope.options);
|
||||
const noty = new Noty(options);
|
||||
noty.show();
|
||||
(_a = noty.layoutDom) === null || _a === void 0 ? void 0 : _a.dataset.turboTemporary = '';
|
||||
try {
|
||||
const options = Object.assign({ text: envelope.message, type: envelope.type }, this.defaultOptions);
|
||||
if (envelope.options) {
|
||||
Object.assign(options, envelope.options);
|
||||
}
|
||||
const noty = new Noty(options);
|
||||
noty.show();
|
||||
const layoutDom = noty.layoutDom;
|
||||
if (layoutDom && typeof layoutDom.dataset === 'object') {
|
||||
layoutDom.dataset.turboTemporary = '';
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('PHPFlasher Noty: Error rendering notification', error, envelope);
|
||||
}
|
||||
});
|
||||
}
|
||||
renderOptions(options) {
|
||||
Noty.overrideDefaults(Object.assign({ timeout: options.timeout || 5000 }, options));
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
Object.assign(this.defaultOptions, options);
|
||||
Noty.overrideDefaults(this.defaultOptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+66
-22
@@ -18,48 +18,92 @@
|
||||
this.flash('warning', message, title, options);
|
||||
}
|
||||
flash(type, message, title, options) {
|
||||
let normalizedType;
|
||||
let normalizedMessage;
|
||||
let normalizedTitle;
|
||||
let normalizedOptions = {};
|
||||
if (typeof type === 'object') {
|
||||
options = type;
|
||||
type = options.type;
|
||||
message = options.message;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, type);
|
||||
normalizedType = normalizedOptions.type;
|
||||
normalizedMessage = normalizedOptions.message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.type;
|
||||
delete normalizedOptions.message;
|
||||
delete normalizedOptions.title;
|
||||
} else if (typeof message === 'object') {
|
||||
options = message;
|
||||
message = options.message;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, message);
|
||||
normalizedType = type;
|
||||
normalizedMessage = normalizedOptions.message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.message;
|
||||
delete normalizedOptions.title;
|
||||
} else if (typeof title === 'object') {
|
||||
options = title;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, title);
|
||||
normalizedType = type;
|
||||
normalizedMessage = message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.title;
|
||||
} else {
|
||||
normalizedType = type;
|
||||
normalizedMessage = message;
|
||||
normalizedTitle = title;
|
||||
normalizedOptions = options || {};
|
||||
}
|
||||
if (undefined === message) {
|
||||
throw new Error('message option is required');
|
||||
if (!normalizedType) {
|
||||
throw new Error('Type is required for notifications');
|
||||
}
|
||||
if (normalizedMessage === undefined || normalizedMessage === null) {
|
||||
throw new Error('Message is required for notifications');
|
||||
}
|
||||
const envelope = {
|
||||
type,
|
||||
message,
|
||||
title: title || type,
|
||||
options: options || {},
|
||||
type: normalizedType,
|
||||
message: normalizedMessage,
|
||||
title: normalizedTitle || normalizedType,
|
||||
options: normalizedOptions,
|
||||
metadata: {
|
||||
plugin: ''
|
||||
}
|
||||
};
|
||||
this.renderOptions(options || {});
|
||||
this.renderOptions(normalizedOptions);
|
||||
this.renderEnvelopes([envelope]);
|
||||
}
|
||||
}
|
||||
|
||||
class NotyPlugin extends AbstractPlugin {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.defaultOptions = {
|
||||
timeout: 10000,
|
||||
};
|
||||
}
|
||||
renderEnvelopes(envelopes) {
|
||||
if (!(envelopes === null || envelopes === void 0 ? void 0 : envelopes.length)) {
|
||||
return;
|
||||
}
|
||||
envelopes.forEach((envelope) => {
|
||||
var _a;
|
||||
const options = Object.assign({ text: envelope.message, type: envelope.type }, envelope.options);
|
||||
const noty = new Noty(options);
|
||||
noty.show();
|
||||
(_a = noty.layoutDom) === null || _a === void 0 ? void 0 : _a.dataset.turboTemporary = '';
|
||||
try {
|
||||
const options = Object.assign({ text: envelope.message, type: envelope.type }, this.defaultOptions);
|
||||
if (envelope.options) {
|
||||
Object.assign(options, envelope.options);
|
||||
}
|
||||
const noty = new Noty(options);
|
||||
noty.show();
|
||||
const layoutDom = noty.layoutDom;
|
||||
if (layoutDom && typeof layoutDom.dataset === 'object') {
|
||||
layoutDom.dataset.turboTemporary = '';
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('PHPFlasher Noty: Error rendering notification', error, envelope);
|
||||
}
|
||||
});
|
||||
}
|
||||
renderOptions(options) {
|
||||
Noty.overrideDefaults(Object.assign({ timeout: options.timeout || 5000 }, options));
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
Object.assign(this.defaultOptions, options);
|
||||
Noty.overrideDefaults(this.defaultOptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("@flasher/flasher"),require("noty")):"function"==typeof define&&define.amd?define(["@flasher/flasher","noty"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).Noty=t(e.flasher,e.Noty)}(this,(function(e,t){"use strict";class s{success(e,t,s){this.flash("success",e,t,s)}error(e,t,s){this.flash("error",e,t,s)}info(e,t,s){this.flash("info",e,t,s)}warning(e,t,s){this.flash("warning",e,t,s)}flash(e,t,s,o){if("object"==typeof e?(e=(o=e).type,t=o.message,s=o.title):"object"==typeof t?(t=(o=t).message,s=o.title):"object"==typeof s&&(s=(o=s).title),void 0===t)throw new Error("message option is required");const n={type:e,message:t,title:s||e,options:o||{},metadata:{plugin:""}};this.renderOptions(o||{}),this.renderEnvelopes([n])}}const o=new class extends s{renderEnvelopes(e){e.forEach((e=>{var s;const o=Object.assign({text:e.message,type:e.type},e.options),n=new t(o);n.show(),null===(s=n.layoutDom)||void 0===s||(s.dataset.turboTemporary="")}))}renderOptions(e){t.overrideDefaults(Object.assign({timeout:e.timeout||5e3},e))}};return e.addPlugin("noty",o),o}));
|
||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("@flasher/flasher"),require("noty")):"function"==typeof define&&define.amd?define(["@flasher/flasher","noty"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).Noty=t(e.flasher,e.Noty)}(this,(function(e,t){"use strict";class s{success(e,t,s){this.flash("success",e,t,s)}error(e,t,s){this.flash("error",e,t,s)}info(e,t,s){this.flash("info",e,t,s)}warning(e,t,s){this.flash("warning",e,t,s)}flash(e,t,s,o){let i,n,r,a={};if("object"==typeof e?(a=Object.assign({},e),i=a.type,n=a.message,r=a.title,delete a.type,delete a.message,delete a.title):"object"==typeof t?(a=Object.assign({},t),i=e,n=a.message,r=a.title,delete a.message,delete a.title):"object"==typeof s?(a=Object.assign({},s),i=e,n=t,r=a.title,delete a.title):(i=e,n=t,r=s,a=o||{}),!i)throw new Error("Type is required for notifications");if(null==n)throw new Error("Message is required for notifications");const l={type:i,message:n,title:r||i,options:a,metadata:{plugin:""}};this.renderOptions(a),this.renderEnvelopes([l])}}const o=new class extends s{constructor(){super(...arguments),this.defaultOptions={timeout:1e4}}renderEnvelopes(e){(null==e?void 0:e.length)&&e.forEach((e=>{try{const s=Object.assign({text:e.message,type:e.type},this.defaultOptions);e.options&&Object.assign(s,e.options);const o=new t(s);o.show();const i=o.layoutDom;i&&"object"==typeof i.dataset&&(i.dataset.turboTemporary="")}catch(t){console.error("PHPFlasher Noty: Error rendering notification",t,e)}}))}renderOptions(e){e&&(Object.assign(this.defaultOptions,e),t.overrideDefaults(this.defaultOptions))}};return e.addPlugin("noty",o),o}));
|
||||
|
||||
+1
@@ -1,6 +1,7 @@
|
||||
import { AbstractPlugin } from '@flasher/flasher/dist/plugin';
|
||||
import type { Envelope, Options } from '@flasher/flasher/dist/types';
|
||||
export default class NotyPlugin extends AbstractPlugin {
|
||||
private defaultOptions;
|
||||
renderEnvelopes(envelopes: Envelope[]): void;
|
||||
renderOptions(options: Options): void;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("@flasher/flasher"),require("noty")):"function"==typeof define&&define.amd?define(["@flasher/flasher","noty"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).Noty=t(e.flasher,e.Noty)}(this,(function(e,t){"use strict";class s{success(e,t,s){this.flash("success",e,t,s)}error(e,t,s){this.flash("error",e,t,s)}info(e,t,s){this.flash("info",e,t,s)}warning(e,t,s){this.flash("warning",e,t,s)}flash(e,t,s,o){if("object"==typeof e?(e=(o=e).type,t=o.message,s=o.title):"object"==typeof t?(t=(o=t).message,s=o.title):"object"==typeof s&&(s=(o=s).title),void 0===t)throw new Error("message option is required");const n={type:e,message:t,title:s||e,options:o||{},metadata:{plugin:""}};this.renderOptions(o||{}),this.renderEnvelopes([n])}}const o=new class extends s{renderEnvelopes(e){e.forEach((e=>{var s;const o=Object.assign({text:e.message,type:e.type},e.options),n=new t(o);n.show(),null===(s=n.layoutDom)||void 0===s||(s.dataset.turboTemporary="")}))}renderOptions(e){t.overrideDefaults(Object.assign({timeout:e.timeout||5e3},e))}};return e.addPlugin("noty",o),o}));
|
||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("@flasher/flasher"),require("noty")):"function"==typeof define&&define.amd?define(["@flasher/flasher","noty"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).Noty=t(e.flasher,e.Noty)}(this,(function(e,t){"use strict";class s{success(e,t,s){this.flash("success",e,t,s)}error(e,t,s){this.flash("error",e,t,s)}info(e,t,s){this.flash("info",e,t,s)}warning(e,t,s){this.flash("warning",e,t,s)}flash(e,t,s,o){let i,n,r,a={};if("object"==typeof e?(a=Object.assign({},e),i=a.type,n=a.message,r=a.title,delete a.type,delete a.message,delete a.title):"object"==typeof t?(a=Object.assign({},t),i=e,n=a.message,r=a.title,delete a.message,delete a.title):"object"==typeof s?(a=Object.assign({},s),i=e,n=t,r=a.title,delete a.title):(i=e,n=t,r=s,a=o||{}),!i)throw new Error("Type is required for notifications");if(null==n)throw new Error("Message is required for notifications");const l={type:i,message:n,title:r||i,options:a,metadata:{plugin:""}};this.renderOptions(a),this.renderEnvelopes([l])}}const o=new class extends s{constructor(){super(...arguments),this.defaultOptions={timeout:1e4}}renderEnvelopes(e){(null==e?void 0:e.length)&&e.forEach((e=>{try{const s=Object.assign({text:e.message,type:e.type},this.defaultOptions);e.options&&Object.assign(s,e.options);const o=new t(s);o.show();const i=o.layoutDom;i&&"object"==typeof i.dataset&&(i.dataset.turboTemporary="")}catch(t){console.error("PHPFlasher Noty: Error rendering notification",t,e)}}))}renderOptions(e){e&&(Object.assign(this.defaultOptions,e),t.overrideDefaults(this.defaultOptions))}};return e.addPlugin("noty",o),o}));
|
||||
|
||||
+85
-25
@@ -14,32 +14,53 @@ class AbstractPlugin {
|
||||
this.flash('warning', message, title, options);
|
||||
}
|
||||
flash(type, message, title, options) {
|
||||
let normalizedType;
|
||||
let normalizedMessage;
|
||||
let normalizedTitle;
|
||||
let normalizedOptions = {};
|
||||
if (typeof type === 'object') {
|
||||
options = type;
|
||||
type = options.type;
|
||||
message = options.message;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, type);
|
||||
normalizedType = normalizedOptions.type;
|
||||
normalizedMessage = normalizedOptions.message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.type;
|
||||
delete normalizedOptions.message;
|
||||
delete normalizedOptions.title;
|
||||
} else if (typeof message === 'object') {
|
||||
options = message;
|
||||
message = options.message;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, message);
|
||||
normalizedType = type;
|
||||
normalizedMessage = normalizedOptions.message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.message;
|
||||
delete normalizedOptions.title;
|
||||
} else if (typeof title === 'object') {
|
||||
options = title;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, title);
|
||||
normalizedType = type;
|
||||
normalizedMessage = message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.title;
|
||||
} else {
|
||||
normalizedType = type;
|
||||
normalizedMessage = message;
|
||||
normalizedTitle = title;
|
||||
normalizedOptions = options || {};
|
||||
}
|
||||
if (undefined === message) {
|
||||
throw new Error('message option is required');
|
||||
if (!normalizedType) {
|
||||
throw new Error('Type is required for notifications');
|
||||
}
|
||||
if (normalizedMessage === undefined || normalizedMessage === null) {
|
||||
throw new Error('Message is required for notifications');
|
||||
}
|
||||
const envelope = {
|
||||
type,
|
||||
message,
|
||||
title: title || type,
|
||||
options: options || {},
|
||||
type: normalizedType,
|
||||
message: normalizedMessage,
|
||||
title: normalizedTitle || normalizedType,
|
||||
options: normalizedOptions,
|
||||
metadata: {
|
||||
plugin: ''
|
||||
}
|
||||
};
|
||||
this.renderOptions(options || {});
|
||||
this.renderOptions(normalizedOptions);
|
||||
this.renderEnvelopes([envelope]);
|
||||
}
|
||||
}
|
||||
@@ -469,18 +490,42 @@ var Notyf = function () {
|
||||
|
||||
class NotyfPlugin extends AbstractPlugin {
|
||||
renderEnvelopes(envelopes) {
|
||||
if (!this.notyf) {
|
||||
this.initializeNotyf();
|
||||
}
|
||||
envelopes.forEach((envelope) => {
|
||||
var _a;
|
||||
const options = Object.assign(Object.assign({}, envelope), envelope.options);
|
||||
(_a = this.notyf) === null || _a === void 0 ? void 0 : _a.open(options);
|
||||
try {
|
||||
const options = Object.assign(Object.assign({}, envelope), envelope.options);
|
||||
(_a = this.notyf) === null || _a === void 0 ? void 0 : _a.open(options);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('PHPFlasher Notyf: Error rendering notification', error, envelope);
|
||||
}
|
||||
});
|
||||
this.notyf.view.container.dataset.turboTemporary = '';
|
||||
this.notyf.view.a11yContainer.dataset.turboTemporary = '';
|
||||
try {
|
||||
if (this.notyf) {
|
||||
const container = this.notyf.view.container;
|
||||
const a11yContainer = this.notyf.view.a11yContainer;
|
||||
if (container && container.dataset) {
|
||||
container.dataset.turboTemporary = '';
|
||||
}
|
||||
if (a11yContainer && a11yContainer.dataset) {
|
||||
a11yContainer.dataset.turboTemporary = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('PHPFlasher Notyf: Error setting Turbo compatibility', error);
|
||||
}
|
||||
}
|
||||
renderOptions(options) {
|
||||
const nOptions = Object.assign({ duration: options.duration || 5000 }, options);
|
||||
nOptions.types = nOptions.types || [];
|
||||
nOptions.types.push({
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
const notyfOptions = Object.assign({ duration: options.duration || 10000 }, options);
|
||||
notyfOptions.types = notyfOptions.types || [];
|
||||
this.addTypeIfNotExists(notyfOptions.types, {
|
||||
type: 'info',
|
||||
className: 'notyf__toast--info',
|
||||
background: '#5784E5',
|
||||
@@ -489,7 +534,7 @@ class NotyfPlugin extends AbstractPlugin {
|
||||
tagName: 'i',
|
||||
},
|
||||
});
|
||||
nOptions.types.push({
|
||||
this.addTypeIfNotExists(notyfOptions.types, {
|
||||
type: 'warning',
|
||||
className: 'notyf__toast--warning',
|
||||
background: '#E3A008',
|
||||
@@ -498,7 +543,22 @@ class NotyfPlugin extends AbstractPlugin {
|
||||
tagName: 'i',
|
||||
},
|
||||
});
|
||||
this.notyf = this.notyf || new Notyf(nOptions);
|
||||
this.notyf = this.notyf || new Notyf(notyfOptions);
|
||||
}
|
||||
initializeNotyf() {
|
||||
if (!this.notyf) {
|
||||
this.renderOptions({
|
||||
duration: 10000,
|
||||
position: { x: 'right', y: 'top' },
|
||||
dismissible: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
addTypeIfNotExists(types, newType) {
|
||||
const exists = types.some((type) => type.type === newType.type);
|
||||
if (!exists) {
|
||||
types.push(newType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+85
-25
@@ -18,32 +18,53 @@
|
||||
this.flash('warning', message, title, options);
|
||||
}
|
||||
flash(type, message, title, options) {
|
||||
let normalizedType;
|
||||
let normalizedMessage;
|
||||
let normalizedTitle;
|
||||
let normalizedOptions = {};
|
||||
if (typeof type === 'object') {
|
||||
options = type;
|
||||
type = options.type;
|
||||
message = options.message;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, type);
|
||||
normalizedType = normalizedOptions.type;
|
||||
normalizedMessage = normalizedOptions.message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.type;
|
||||
delete normalizedOptions.message;
|
||||
delete normalizedOptions.title;
|
||||
} else if (typeof message === 'object') {
|
||||
options = message;
|
||||
message = options.message;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, message);
|
||||
normalizedType = type;
|
||||
normalizedMessage = normalizedOptions.message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.message;
|
||||
delete normalizedOptions.title;
|
||||
} else if (typeof title === 'object') {
|
||||
options = title;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, title);
|
||||
normalizedType = type;
|
||||
normalizedMessage = message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.title;
|
||||
} else {
|
||||
normalizedType = type;
|
||||
normalizedMessage = message;
|
||||
normalizedTitle = title;
|
||||
normalizedOptions = options || {};
|
||||
}
|
||||
if (undefined === message) {
|
||||
throw new Error('message option is required');
|
||||
if (!normalizedType) {
|
||||
throw new Error('Type is required for notifications');
|
||||
}
|
||||
if (normalizedMessage === undefined || normalizedMessage === null) {
|
||||
throw new Error('Message is required for notifications');
|
||||
}
|
||||
const envelope = {
|
||||
type,
|
||||
message,
|
||||
title: title || type,
|
||||
options: options || {},
|
||||
type: normalizedType,
|
||||
message: normalizedMessage,
|
||||
title: normalizedTitle || normalizedType,
|
||||
options: normalizedOptions,
|
||||
metadata: {
|
||||
plugin: ''
|
||||
}
|
||||
};
|
||||
this.renderOptions(options || {});
|
||||
this.renderOptions(normalizedOptions);
|
||||
this.renderEnvelopes([envelope]);
|
||||
}
|
||||
}
|
||||
@@ -473,18 +494,42 @@
|
||||
|
||||
class NotyfPlugin extends AbstractPlugin {
|
||||
renderEnvelopes(envelopes) {
|
||||
if (!this.notyf) {
|
||||
this.initializeNotyf();
|
||||
}
|
||||
envelopes.forEach((envelope) => {
|
||||
var _a;
|
||||
const options = Object.assign(Object.assign({}, envelope), envelope.options);
|
||||
(_a = this.notyf) === null || _a === void 0 ? void 0 : _a.open(options);
|
||||
try {
|
||||
const options = Object.assign(Object.assign({}, envelope), envelope.options);
|
||||
(_a = this.notyf) === null || _a === void 0 ? void 0 : _a.open(options);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('PHPFlasher Notyf: Error rendering notification', error, envelope);
|
||||
}
|
||||
});
|
||||
this.notyf.view.container.dataset.turboTemporary = '';
|
||||
this.notyf.view.a11yContainer.dataset.turboTemporary = '';
|
||||
try {
|
||||
if (this.notyf) {
|
||||
const container = this.notyf.view.container;
|
||||
const a11yContainer = this.notyf.view.a11yContainer;
|
||||
if (container && container.dataset) {
|
||||
container.dataset.turboTemporary = '';
|
||||
}
|
||||
if (a11yContainer && a11yContainer.dataset) {
|
||||
a11yContainer.dataset.turboTemporary = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('PHPFlasher Notyf: Error setting Turbo compatibility', error);
|
||||
}
|
||||
}
|
||||
renderOptions(options) {
|
||||
const nOptions = Object.assign({ duration: options.duration || 5000 }, options);
|
||||
nOptions.types = nOptions.types || [];
|
||||
nOptions.types.push({
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
const notyfOptions = Object.assign({ duration: options.duration || 10000 }, options);
|
||||
notyfOptions.types = notyfOptions.types || [];
|
||||
this.addTypeIfNotExists(notyfOptions.types, {
|
||||
type: 'info',
|
||||
className: 'notyf__toast--info',
|
||||
background: '#5784E5',
|
||||
@@ -493,7 +538,7 @@
|
||||
tagName: 'i',
|
||||
},
|
||||
});
|
||||
nOptions.types.push({
|
||||
this.addTypeIfNotExists(notyfOptions.types, {
|
||||
type: 'warning',
|
||||
className: 'notyf__toast--warning',
|
||||
background: '#E3A008',
|
||||
@@ -502,7 +547,22 @@
|
||||
tagName: 'i',
|
||||
},
|
||||
});
|
||||
this.notyf = this.notyf || new Notyf(nOptions);
|
||||
this.notyf = this.notyf || new Notyf(notyfOptions);
|
||||
}
|
||||
initializeNotyf() {
|
||||
if (!this.notyf) {
|
||||
this.renderOptions({
|
||||
duration: 10000,
|
||||
position: { x: 'right', y: 'top' },
|
||||
dismissible: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
addTypeIfNotExists(types, newType) {
|
||||
const exists = types.some((type) => type.type === newType.type);
|
||||
if (!exists) {
|
||||
types.push(newType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+3
-2
@@ -1,9 +1,10 @@
|
||||
import { AbstractPlugin } from '@flasher/flasher/dist/plugin';
|
||||
import type { Envelope, Options } from '@flasher/flasher/dist/types';
|
||||
import { Notyf } from 'notyf';
|
||||
import 'notyf/notyf.min.css';
|
||||
export default class NotyfPlugin extends AbstractPlugin {
|
||||
notyf?: Notyf;
|
||||
private notyf?;
|
||||
renderEnvelopes(envelopes: Envelope[]): void;
|
||||
renderOptions(options: Options): void;
|
||||
private initializeNotyf;
|
||||
private addTypeIfNotExists;
|
||||
}
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+4
@@ -0,0 +1,4 @@
|
||||
export * from './types';
|
||||
export { AbstractPlugin } from './plugin';
|
||||
export { default as FlasherPlugin } from './flasher-plugin';
|
||||
export { default } from './index';
|
||||
+1
-4
@@ -9,10 +9,7 @@ export default class FlasherPlugin extends AbstractPlugin {
|
||||
renderOptions(options: Options): void;
|
||||
private createContainer;
|
||||
private addToContainer;
|
||||
addProgressBar(notification: HTMLElement, { timeout, fps }: {
|
||||
timeout: number;
|
||||
fps: number;
|
||||
}): void;
|
||||
private addTimer;
|
||||
private removeNotification;
|
||||
private stringToHTML;
|
||||
private escapeHtml;
|
||||
|
||||
+1
@@ -4,6 +4,7 @@ export default class Flasher extends AbstractPlugin {
|
||||
private defaultPlugin;
|
||||
private plugins;
|
||||
private themes;
|
||||
private loadedAssets;
|
||||
render(response: Partial<Response>): Promise<void>;
|
||||
renderEnvelopes(envelopes: Envelope[]): void;
|
||||
renderOptions(options: Options): void;
|
||||
|
||||
+263
-115
@@ -44,34 +44,56 @@ class AbstractPlugin {
|
||||
this.flash('warning', message, title, options);
|
||||
}
|
||||
flash(type, message, title, options) {
|
||||
let normalizedType;
|
||||
let normalizedMessage;
|
||||
let normalizedTitle;
|
||||
let normalizedOptions = {};
|
||||
if (typeof type === 'object') {
|
||||
options = type;
|
||||
type = options.type;
|
||||
message = options.message;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, type);
|
||||
normalizedType = normalizedOptions.type;
|
||||
normalizedMessage = normalizedOptions.message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.type;
|
||||
delete normalizedOptions.message;
|
||||
delete normalizedOptions.title;
|
||||
}
|
||||
else if (typeof message === 'object') {
|
||||
options = message;
|
||||
message = options.message;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, message);
|
||||
normalizedType = type;
|
||||
normalizedMessage = normalizedOptions.message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.message;
|
||||
delete normalizedOptions.title;
|
||||
}
|
||||
else if (typeof title === 'object') {
|
||||
options = title;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, title);
|
||||
normalizedType = type;
|
||||
normalizedMessage = message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.title;
|
||||
}
|
||||
if (undefined === message) {
|
||||
throw new Error('message option is required');
|
||||
else {
|
||||
normalizedType = type;
|
||||
normalizedMessage = message;
|
||||
normalizedTitle = title;
|
||||
normalizedOptions = options || {};
|
||||
}
|
||||
if (!normalizedType) {
|
||||
throw new Error('Type is required for notifications');
|
||||
}
|
||||
if (normalizedMessage === undefined || normalizedMessage === null) {
|
||||
throw new Error('Message is required for notifications');
|
||||
}
|
||||
const envelope = {
|
||||
type,
|
||||
message,
|
||||
title: title || type,
|
||||
options: options || {},
|
||||
type: normalizedType,
|
||||
message: normalizedMessage,
|
||||
title: normalizedTitle || normalizedType,
|
||||
options: normalizedOptions,
|
||||
metadata: {
|
||||
plugin: '',
|
||||
},
|
||||
};
|
||||
this.renderOptions(options || {});
|
||||
this.renderOptions(normalizedOptions);
|
||||
this.renderEnvelopes([envelope]);
|
||||
}
|
||||
}
|
||||
@@ -82,10 +104,10 @@ class FlasherPlugin extends AbstractPlugin {
|
||||
this.options = {
|
||||
timeout: null,
|
||||
timeouts: {
|
||||
success: 5000,
|
||||
info: 5000,
|
||||
error: 5000,
|
||||
warning: 5000,
|
||||
success: 10000,
|
||||
info: 10000,
|
||||
error: 10000,
|
||||
warning: 10000,
|
||||
},
|
||||
fps: 30,
|
||||
position: 'top-right',
|
||||
@@ -94,18 +116,50 @@ class FlasherPlugin extends AbstractPlugin {
|
||||
style: {},
|
||||
escapeHtml: false,
|
||||
};
|
||||
if (!theme) {
|
||||
throw new Error('Theme is required');
|
||||
}
|
||||
if (typeof theme.render !== 'function') {
|
||||
throw new TypeError('Theme must have a render function');
|
||||
}
|
||||
this.theme = theme;
|
||||
}
|
||||
renderEnvelopes(envelopes) {
|
||||
const render = () => envelopes.forEach((envelope) => {
|
||||
var _a, _b, _c, _d;
|
||||
const typeTimeout = (_b = (_a = this.options.timeout) !== null && _a !== void 0 ? _a : this.options.timeouts[envelope.type]) !== null && _b !== void 0 ? _b : 5000;
|
||||
const options = Object.assign(Object.assign(Object.assign({}, this.options), envelope.options), { timeout: (_c = envelope.options.timeout) !== null && _c !== void 0 ? _c : typeTimeout, escapeHtml: ((_d = envelope.options.escapeHtml) !== null && _d !== void 0 ? _d : this.options.escapeHtml) });
|
||||
this.addToContainer(this.createContainer(options), envelope, options);
|
||||
});
|
||||
document.readyState === 'loading' ? document.addEventListener('DOMContentLoaded', render) : render();
|
||||
if (!(envelopes === null || envelopes === void 0 ? void 0 : envelopes.length)) {
|
||||
return;
|
||||
}
|
||||
const render = () => {
|
||||
envelopes.forEach((envelope) => {
|
||||
var _a, _b, _c, _d;
|
||||
try {
|
||||
const typeTimeout = (_b = (_a = this.options.timeout) !== null && _a !== void 0 ? _a : this.options.timeouts[envelope.type]) !== null && _b !== void 0 ? _b : 10000;
|
||||
const mergedOptions = Object.assign(Object.assign(Object.assign({}, this.options), envelope.options), { timeout: (_c = envelope.options.timeout) !== null && _c !== void 0 ? _c : typeTimeout, escapeHtml: ((_d = envelope.options.escapeHtml) !== null && _d !== void 0 ? _d : this.options.escapeHtml) });
|
||||
const container = this.createContainer(mergedOptions);
|
||||
const containerOptions = {
|
||||
direction: mergedOptions.direction,
|
||||
timeout: Number(mergedOptions.timeout || 0),
|
||||
fps: mergedOptions.fps,
|
||||
rtl: mergedOptions.rtl,
|
||||
escapeHtml: mergedOptions.escapeHtml,
|
||||
};
|
||||
this.addToContainer(container, envelope, containerOptions);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('PHPFlasher: Error rendering envelope', error, envelope);
|
||||
}
|
||||
});
|
||||
};
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', render);
|
||||
}
|
||||
else {
|
||||
render();
|
||||
}
|
||||
}
|
||||
renderOptions(options) {
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
this.options = Object.assign(Object.assign({}, this.options), options);
|
||||
}
|
||||
createContainer(options) {
|
||||
@@ -114,60 +168,87 @@ class FlasherPlugin extends AbstractPlugin {
|
||||
container = document.createElement('div');
|
||||
container.className = 'fl-wrapper';
|
||||
container.dataset.position = options.position;
|
||||
Object.entries(options.style).forEach(([key, value]) => container.style.setProperty(key, value));
|
||||
Object.entries(options.style).forEach(([key, value]) => {
|
||||
if (value !== undefined && value !== null) {
|
||||
container.style.setProperty(key, String(value));
|
||||
}
|
||||
});
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
container.dataset.turboTemporary = '';
|
||||
return container;
|
||||
}
|
||||
addToContainer(container, envelope, options) {
|
||||
var _a;
|
||||
if (options.escapeHtml) {
|
||||
envelope.title = this.escapeHtml(envelope.title);
|
||||
envelope.message = this.escapeHtml(envelope.message);
|
||||
}
|
||||
const notification = this.stringToHTML(this.theme.render(envelope));
|
||||
notification.classList.add(...`fl-container${options.rtl ? ' fl-rtl' : ''}`.split(' '));
|
||||
options.direction === 'bottom' ? container.append(notification) : container.prepend(notification);
|
||||
notification.classList.add('fl-container');
|
||||
if (options.rtl) {
|
||||
notification.classList.add('fl-rtl');
|
||||
}
|
||||
if (options.direction === 'bottom') {
|
||||
container.append(notification);
|
||||
}
|
||||
else {
|
||||
container.prepend(notification);
|
||||
}
|
||||
requestAnimationFrame(() => notification.classList.add('fl-show'));
|
||||
(_a = notification.querySelector('.fl-close')) === null || _a === void 0 ? void 0 : _a.addEventListener('click', (event) => {
|
||||
event.stopPropagation();
|
||||
this.removeNotification(notification);
|
||||
});
|
||||
this.addProgressBar(notification, options);
|
||||
const closeButton = notification.querySelector('.fl-close');
|
||||
if (closeButton) {
|
||||
closeButton.addEventListener('click', (event) => {
|
||||
event.stopPropagation();
|
||||
this.removeNotification(notification);
|
||||
});
|
||||
}
|
||||
if (options.timeout > 0) {
|
||||
this.addTimer(notification, options);
|
||||
}
|
||||
}
|
||||
addProgressBar(notification, { timeout, fps }) {
|
||||
if (timeout <= 0 || fps <= 0) {
|
||||
addTimer(notification, { timeout, fps }) {
|
||||
if (timeout <= 0) {
|
||||
return;
|
||||
}
|
||||
const progressBarContainer = notification.querySelector('.fl-progress-bar');
|
||||
if (!progressBarContainer) {
|
||||
return;
|
||||
}
|
||||
const progressBar = document.createElement('span');
|
||||
progressBar.classList.add('fl-progress');
|
||||
progressBarContainer.append(progressBar);
|
||||
const lapse = 1000 / fps;
|
||||
let width = 0;
|
||||
const updateProgress = () => {
|
||||
width += 1;
|
||||
const percent = (1 - lapse * (width / timeout)) * 100;
|
||||
progressBar.style.width = `${percent}%`;
|
||||
if (percent <= 0) {
|
||||
let elapsed = 0;
|
||||
let intervalId;
|
||||
const updateTimer = () => {
|
||||
elapsed += lapse;
|
||||
const progressBarContainer = notification.querySelector('.fl-progress-bar');
|
||||
if (progressBarContainer) {
|
||||
let progressBar = progressBarContainer.querySelector('.fl-progress');
|
||||
if (!progressBar) {
|
||||
progressBar = document.createElement('span');
|
||||
progressBar.classList.add('fl-progress');
|
||||
progressBarContainer.append(progressBar);
|
||||
}
|
||||
const percent = (1 - elapsed / timeout) * 100;
|
||||
progressBar.style.width = `${Math.max(0, percent)}%`;
|
||||
}
|
||||
if (elapsed >= timeout) {
|
||||
clearInterval(intervalId);
|
||||
this.removeNotification(notification);
|
||||
}
|
||||
};
|
||||
let intervalId = window.setInterval(updateProgress, lapse);
|
||||
notification.addEventListener('mouseout', () => intervalId = window.setInterval(updateProgress, lapse));
|
||||
intervalId = window.setInterval(updateTimer, lapse);
|
||||
notification.addEventListener('mouseout', () => {
|
||||
clearInterval(intervalId);
|
||||
intervalId = window.setInterval(updateTimer, lapse);
|
||||
});
|
||||
notification.addEventListener('mouseover', () => clearInterval(intervalId));
|
||||
}
|
||||
removeNotification(notification) {
|
||||
if (!notification) {
|
||||
return;
|
||||
}
|
||||
notification.classList.remove('fl-show');
|
||||
notification.ontransitionend = () => {
|
||||
var _a, _b;
|
||||
!((_a = notification.parentElement) === null || _a === void 0 ? void 0 : _a.hasChildNodes()) && ((_b = notification.parentElement) === null || _b === void 0 ? void 0 : _b.remove());
|
||||
const parent = notification.parentElement;
|
||||
notification.remove();
|
||||
if (parent && !parent.hasChildNodes()) {
|
||||
parent.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
stringToHTML(str) {
|
||||
@@ -179,18 +260,17 @@ class FlasherPlugin extends AbstractPlugin {
|
||||
if (str == null) {
|
||||
return '';
|
||||
}
|
||||
return str.replace(/[&<>"'`=\/]/g, (char) => {
|
||||
return {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
'\'': ''',
|
||||
'`': '`',
|
||||
'=': '=',
|
||||
'/': '/',
|
||||
}[char];
|
||||
});
|
||||
const htmlEscapes = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
'\'': ''',
|
||||
'`': '`',
|
||||
'=': '=',
|
||||
'/': '/',
|
||||
};
|
||||
return str.replace(/[&<>"'`=/]/g, (char) => htmlEscapes[char] || char);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,54 +280,82 @@ class Flasher extends AbstractPlugin {
|
||||
this.defaultPlugin = 'flasher';
|
||||
this.plugins = new Map();
|
||||
this.themes = new Map();
|
||||
this.loadedAssets = new Set();
|
||||
}
|
||||
render(response) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const resolved = this.resolveResponse(response);
|
||||
yield this.addAssets([
|
||||
{
|
||||
urls: resolved.styles,
|
||||
nonce: resolved.context.csp_style_nonce,
|
||||
type: 'style',
|
||||
},
|
||||
{
|
||||
urls: resolved.scripts,
|
||||
nonce: resolved.context.csp_script_nonce,
|
||||
type: 'script',
|
||||
},
|
||||
]);
|
||||
this.renderOptions(resolved.options);
|
||||
this.renderEnvelopes(resolved.envelopes);
|
||||
try {
|
||||
yield this.addAssets([
|
||||
{
|
||||
urls: resolved.styles,
|
||||
nonce: resolved.context.csp_style_nonce,
|
||||
type: 'style',
|
||||
},
|
||||
{
|
||||
urls: resolved.scripts,
|
||||
nonce: resolved.context.csp_script_nonce,
|
||||
type: 'script',
|
||||
},
|
||||
]);
|
||||
this.renderOptions(resolved.options);
|
||||
this.renderEnvelopes(resolved.envelopes);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('PHPFlasher: Error rendering notifications', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
renderEnvelopes(envelopes) {
|
||||
const map = {};
|
||||
if (!(envelopes === null || envelopes === void 0 ? void 0 : envelopes.length)) {
|
||||
return;
|
||||
}
|
||||
const groupedByPlugin = {};
|
||||
envelopes.forEach((envelope) => {
|
||||
const plugin = this.resolvePluginAlias(envelope.metadata.plugin);
|
||||
map[plugin] = map[plugin] || [];
|
||||
map[plugin].push(envelope);
|
||||
groupedByPlugin[plugin] = groupedByPlugin[plugin] || [];
|
||||
groupedByPlugin[plugin].push(envelope);
|
||||
});
|
||||
Object.entries(map).forEach(([plugin, envelopes]) => {
|
||||
this.use(plugin).renderEnvelopes(envelopes);
|
||||
Object.entries(groupedByPlugin).forEach(([pluginName, pluginEnvelopes]) => {
|
||||
try {
|
||||
this.use(pluginName).renderEnvelopes(pluginEnvelopes);
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`PHPFlasher: Error rendering envelopes for plugin "${pluginName}"`, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
renderOptions(options) {
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
Object.entries(options).forEach(([plugin, option]) => {
|
||||
this.use(plugin).renderOptions(option);
|
||||
try {
|
||||
this.use(plugin).renderOptions(option);
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`PHPFlasher: Error applying options for plugin "${plugin}"`, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
addPlugin(name, plugin) {
|
||||
if (!name || !plugin) {
|
||||
throw new Error('Both plugin name and instance are required');
|
||||
}
|
||||
this.plugins.set(name, plugin);
|
||||
}
|
||||
addTheme(name, theme) {
|
||||
if (!name || !theme) {
|
||||
throw new Error('Both theme name and definition are required');
|
||||
}
|
||||
this.themes.set(name, theme);
|
||||
}
|
||||
use(name) {
|
||||
name = this.resolvePluginAlias(name);
|
||||
this.resolvePlugin(name);
|
||||
const plugin = this.plugins.get(name);
|
||||
const resolvedName = this.resolvePluginAlias(name);
|
||||
this.resolvePlugin(resolvedName);
|
||||
const plugin = this.plugins.get(resolvedName);
|
||||
if (!plugin) {
|
||||
throw new Error(`Unable to resolve "${name}" plugin, did you forget to register it?`);
|
||||
throw new Error(`Unable to resolve "${resolvedName}" plugin, did you forget to register it?`);
|
||||
}
|
||||
return plugin;
|
||||
}
|
||||
@@ -271,10 +379,14 @@ class Flasher extends AbstractPlugin {
|
||||
return resolved;
|
||||
}
|
||||
resolveOptions(options) {
|
||||
Object.entries(options).forEach(([key, value]) => {
|
||||
options[key] = this.resolveFunction(value);
|
||||
if (!options) {
|
||||
return {};
|
||||
}
|
||||
const resolved = Object.assign({}, options);
|
||||
Object.entries(resolved).forEach(([key, value]) => {
|
||||
resolved[key] = this.resolveFunction(value);
|
||||
});
|
||||
return options;
|
||||
return resolved;
|
||||
}
|
||||
resolveFunction(func) {
|
||||
var _a, _b;
|
||||
@@ -296,7 +408,7 @@ class Flasher extends AbstractPlugin {
|
||||
return new Function(...args, body);
|
||||
}
|
||||
catch (e) {
|
||||
console.error('Error converting string to function:', e);
|
||||
console.error('PHPFlasher: Error converting string to function:', e);
|
||||
return func;
|
||||
}
|
||||
}
|
||||
@@ -305,11 +417,12 @@ class Flasher extends AbstractPlugin {
|
||||
if (factory || !alias.includes('theme.')) {
|
||||
return;
|
||||
}
|
||||
const view = this.themes.get(alias.replace('theme.', ''));
|
||||
if (!view) {
|
||||
const themeName = alias.replace('theme.', '');
|
||||
const theme = this.themes.get(themeName);
|
||||
if (!theme) {
|
||||
return;
|
||||
}
|
||||
this.addPlugin(alias, new FlasherPlugin(view));
|
||||
this.addPlugin(alias, new FlasherPlugin(theme));
|
||||
}
|
||||
resolvePluginAlias(alias) {
|
||||
alias = alias || this.defaultPlugin;
|
||||
@@ -317,18 +430,46 @@ class Flasher extends AbstractPlugin {
|
||||
}
|
||||
addAssets(assets) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
for (const { urls, nonce, type } of assets) {
|
||||
for (const url of urls) {
|
||||
yield this.loadAsset(url, nonce, type);
|
||||
try {
|
||||
const styleAssets = assets.filter((asset) => asset.type === 'style');
|
||||
const stylePromises = [];
|
||||
for (const { urls, nonce, type } of styleAssets) {
|
||||
if (!(urls === null || urls === void 0 ? void 0 : urls.length)) {
|
||||
continue;
|
||||
}
|
||||
for (const url of urls) {
|
||||
if (!url || this.loadedAssets.has(url)) {
|
||||
continue;
|
||||
}
|
||||
stylePromises.push(this.loadAsset(url, nonce, type));
|
||||
this.loadedAssets.add(url);
|
||||
}
|
||||
}
|
||||
yield Promise.all(stylePromises);
|
||||
const scriptAssets = assets.filter((asset) => asset.type === 'script');
|
||||
for (const { urls, nonce, type } of scriptAssets) {
|
||||
if (!(urls === null || urls === void 0 ? void 0 : urls.length)) {
|
||||
continue;
|
||||
}
|
||||
for (const url of urls) {
|
||||
if (!url || this.loadedAssets.has(url)) {
|
||||
continue;
|
||||
}
|
||||
yield this.loadAsset(url, nonce, type);
|
||||
this.loadedAssets.add(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('PHPFlasher: Error loading assets', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
loadAsset(url, nonce, type) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (document.querySelector(`${type === 'style' ? 'link' : 'script'}[src="${url}"]`)) {
|
||||
return;
|
||||
}
|
||||
if (document.querySelector(`${type === 'style' ? 'link' : 'script'}[src="${url}"]`)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const element = document.createElement(type === 'style' ? 'link' : 'script');
|
||||
if (type === 'style') {
|
||||
element.rel = 'stylesheet';
|
||||
@@ -341,21 +482,22 @@ class Flasher extends AbstractPlugin {
|
||||
if (nonce) {
|
||||
element.setAttribute('nonce', nonce);
|
||||
}
|
||||
element.onload = () => resolve();
|
||||
element.onerror = () => reject(new Error(`Failed to load ${url}`));
|
||||
document.head.appendChild(element);
|
||||
return new Promise((resolve, reject) => {
|
||||
element.onload = () => resolve();
|
||||
element.onerror = () => reject(new Error(`Failed to load ${url}`));
|
||||
});
|
||||
});
|
||||
}
|
||||
addThemeStyles(response, plugin) {
|
||||
var _a;
|
||||
if (plugin !== 'flasher' && !plugin.includes('theme.')) {
|
||||
return;
|
||||
}
|
||||
plugin = plugin.replace('theme.', '');
|
||||
const styles = ((_a = this.themes.get(plugin)) === null || _a === void 0 ? void 0 : _a.styles) || [];
|
||||
response.styles = Array.from(new Set([...response.styles, ...styles]));
|
||||
const themeName = plugin.replace('theme.', '');
|
||||
const theme = this.themes.get(themeName);
|
||||
if (!(theme === null || theme === void 0 ? void 0 : theme.styles)) {
|
||||
return;
|
||||
}
|
||||
const themeStyles = Array.isArray(theme.styles) ? theme.styles : [theme.styles];
|
||||
response.styles = Array.from(new Set([...response.styles, ...themeStyles]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,22 +507,28 @@ const flasherTheme = {
|
||||
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);
|
||||
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>
|
||||
<strong class="fl-title">${title}</strong>
|
||||
<strong class="fl-title">${displayTitle}</strong>
|
||||
<span class="fl-message">${message}</span>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
</div>
|
||||
<span class="fl-progress-bar"></span>
|
||||
<span class="fl-progress-bar">
|
||||
<span class="fl-progress"></span>
|
||||
</span>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
const flasher = new Flasher();
|
||||
flasher.addTheme('flasher', flasherTheme);
|
||||
if (typeof window !== 'undefined') {
|
||||
window.flasher = flasher;
|
||||
}
|
||||
|
||||
export { flasher as default };
|
||||
|
||||
Vendored
+263
-115
@@ -50,34 +50,56 @@
|
||||
this.flash('warning', message, title, options);
|
||||
}
|
||||
flash(type, message, title, options) {
|
||||
let normalizedType;
|
||||
let normalizedMessage;
|
||||
let normalizedTitle;
|
||||
let normalizedOptions = {};
|
||||
if (typeof type === 'object') {
|
||||
options = type;
|
||||
type = options.type;
|
||||
message = options.message;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, type);
|
||||
normalizedType = normalizedOptions.type;
|
||||
normalizedMessage = normalizedOptions.message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.type;
|
||||
delete normalizedOptions.message;
|
||||
delete normalizedOptions.title;
|
||||
}
|
||||
else if (typeof message === 'object') {
|
||||
options = message;
|
||||
message = options.message;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, message);
|
||||
normalizedType = type;
|
||||
normalizedMessage = normalizedOptions.message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.message;
|
||||
delete normalizedOptions.title;
|
||||
}
|
||||
else if (typeof title === 'object') {
|
||||
options = title;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, title);
|
||||
normalizedType = type;
|
||||
normalizedMessage = message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.title;
|
||||
}
|
||||
if (undefined === message) {
|
||||
throw new Error('message option is required');
|
||||
else {
|
||||
normalizedType = type;
|
||||
normalizedMessage = message;
|
||||
normalizedTitle = title;
|
||||
normalizedOptions = options || {};
|
||||
}
|
||||
if (!normalizedType) {
|
||||
throw new Error('Type is required for notifications');
|
||||
}
|
||||
if (normalizedMessage === undefined || normalizedMessage === null) {
|
||||
throw new Error('Message is required for notifications');
|
||||
}
|
||||
const envelope = {
|
||||
type,
|
||||
message,
|
||||
title: title || type,
|
||||
options: options || {},
|
||||
type: normalizedType,
|
||||
message: normalizedMessage,
|
||||
title: normalizedTitle || normalizedType,
|
||||
options: normalizedOptions,
|
||||
metadata: {
|
||||
plugin: '',
|
||||
},
|
||||
};
|
||||
this.renderOptions(options || {});
|
||||
this.renderOptions(normalizedOptions);
|
||||
this.renderEnvelopes([envelope]);
|
||||
}
|
||||
}
|
||||
@@ -88,10 +110,10 @@
|
||||
this.options = {
|
||||
timeout: null,
|
||||
timeouts: {
|
||||
success: 5000,
|
||||
info: 5000,
|
||||
error: 5000,
|
||||
warning: 5000,
|
||||
success: 10000,
|
||||
info: 10000,
|
||||
error: 10000,
|
||||
warning: 10000,
|
||||
},
|
||||
fps: 30,
|
||||
position: 'top-right',
|
||||
@@ -100,18 +122,50 @@
|
||||
style: {},
|
||||
escapeHtml: false,
|
||||
};
|
||||
if (!theme) {
|
||||
throw new Error('Theme is required');
|
||||
}
|
||||
if (typeof theme.render !== 'function') {
|
||||
throw new TypeError('Theme must have a render function');
|
||||
}
|
||||
this.theme = theme;
|
||||
}
|
||||
renderEnvelopes(envelopes) {
|
||||
const render = () => envelopes.forEach((envelope) => {
|
||||
var _a, _b, _c, _d;
|
||||
const typeTimeout = (_b = (_a = this.options.timeout) !== null && _a !== void 0 ? _a : this.options.timeouts[envelope.type]) !== null && _b !== void 0 ? _b : 5000;
|
||||
const options = Object.assign(Object.assign(Object.assign({}, this.options), envelope.options), { timeout: (_c = envelope.options.timeout) !== null && _c !== void 0 ? _c : typeTimeout, escapeHtml: ((_d = envelope.options.escapeHtml) !== null && _d !== void 0 ? _d : this.options.escapeHtml) });
|
||||
this.addToContainer(this.createContainer(options), envelope, options);
|
||||
});
|
||||
document.readyState === 'loading' ? document.addEventListener('DOMContentLoaded', render) : render();
|
||||
if (!(envelopes === null || envelopes === void 0 ? void 0 : envelopes.length)) {
|
||||
return;
|
||||
}
|
||||
const render = () => {
|
||||
envelopes.forEach((envelope) => {
|
||||
var _a, _b, _c, _d;
|
||||
try {
|
||||
const typeTimeout = (_b = (_a = this.options.timeout) !== null && _a !== void 0 ? _a : this.options.timeouts[envelope.type]) !== null && _b !== void 0 ? _b : 10000;
|
||||
const mergedOptions = Object.assign(Object.assign(Object.assign({}, this.options), envelope.options), { timeout: (_c = envelope.options.timeout) !== null && _c !== void 0 ? _c : typeTimeout, escapeHtml: ((_d = envelope.options.escapeHtml) !== null && _d !== void 0 ? _d : this.options.escapeHtml) });
|
||||
const container = this.createContainer(mergedOptions);
|
||||
const containerOptions = {
|
||||
direction: mergedOptions.direction,
|
||||
timeout: Number(mergedOptions.timeout || 0),
|
||||
fps: mergedOptions.fps,
|
||||
rtl: mergedOptions.rtl,
|
||||
escapeHtml: mergedOptions.escapeHtml,
|
||||
};
|
||||
this.addToContainer(container, envelope, containerOptions);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('PHPFlasher: Error rendering envelope', error, envelope);
|
||||
}
|
||||
});
|
||||
};
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', render);
|
||||
}
|
||||
else {
|
||||
render();
|
||||
}
|
||||
}
|
||||
renderOptions(options) {
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
this.options = Object.assign(Object.assign({}, this.options), options);
|
||||
}
|
||||
createContainer(options) {
|
||||
@@ -120,60 +174,87 @@
|
||||
container = document.createElement('div');
|
||||
container.className = 'fl-wrapper';
|
||||
container.dataset.position = options.position;
|
||||
Object.entries(options.style).forEach(([key, value]) => container.style.setProperty(key, value));
|
||||
Object.entries(options.style).forEach(([key, value]) => {
|
||||
if (value !== undefined && value !== null) {
|
||||
container.style.setProperty(key, String(value));
|
||||
}
|
||||
});
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
container.dataset.turboTemporary = '';
|
||||
return container;
|
||||
}
|
||||
addToContainer(container, envelope, options) {
|
||||
var _a;
|
||||
if (options.escapeHtml) {
|
||||
envelope.title = this.escapeHtml(envelope.title);
|
||||
envelope.message = this.escapeHtml(envelope.message);
|
||||
}
|
||||
const notification = this.stringToHTML(this.theme.render(envelope));
|
||||
notification.classList.add(...`fl-container${options.rtl ? ' fl-rtl' : ''}`.split(' '));
|
||||
options.direction === 'bottom' ? container.append(notification) : container.prepend(notification);
|
||||
notification.classList.add('fl-container');
|
||||
if (options.rtl) {
|
||||
notification.classList.add('fl-rtl');
|
||||
}
|
||||
if (options.direction === 'bottom') {
|
||||
container.append(notification);
|
||||
}
|
||||
else {
|
||||
container.prepend(notification);
|
||||
}
|
||||
requestAnimationFrame(() => notification.classList.add('fl-show'));
|
||||
(_a = notification.querySelector('.fl-close')) === null || _a === void 0 ? void 0 : _a.addEventListener('click', (event) => {
|
||||
event.stopPropagation();
|
||||
this.removeNotification(notification);
|
||||
});
|
||||
this.addProgressBar(notification, options);
|
||||
const closeButton = notification.querySelector('.fl-close');
|
||||
if (closeButton) {
|
||||
closeButton.addEventListener('click', (event) => {
|
||||
event.stopPropagation();
|
||||
this.removeNotification(notification);
|
||||
});
|
||||
}
|
||||
if (options.timeout > 0) {
|
||||
this.addTimer(notification, options);
|
||||
}
|
||||
}
|
||||
addProgressBar(notification, { timeout, fps }) {
|
||||
if (timeout <= 0 || fps <= 0) {
|
||||
addTimer(notification, { timeout, fps }) {
|
||||
if (timeout <= 0) {
|
||||
return;
|
||||
}
|
||||
const progressBarContainer = notification.querySelector('.fl-progress-bar');
|
||||
if (!progressBarContainer) {
|
||||
return;
|
||||
}
|
||||
const progressBar = document.createElement('span');
|
||||
progressBar.classList.add('fl-progress');
|
||||
progressBarContainer.append(progressBar);
|
||||
const lapse = 1000 / fps;
|
||||
let width = 0;
|
||||
const updateProgress = () => {
|
||||
width += 1;
|
||||
const percent = (1 - lapse * (width / timeout)) * 100;
|
||||
progressBar.style.width = `${percent}%`;
|
||||
if (percent <= 0) {
|
||||
let elapsed = 0;
|
||||
let intervalId;
|
||||
const updateTimer = () => {
|
||||
elapsed += lapse;
|
||||
const progressBarContainer = notification.querySelector('.fl-progress-bar');
|
||||
if (progressBarContainer) {
|
||||
let progressBar = progressBarContainer.querySelector('.fl-progress');
|
||||
if (!progressBar) {
|
||||
progressBar = document.createElement('span');
|
||||
progressBar.classList.add('fl-progress');
|
||||
progressBarContainer.append(progressBar);
|
||||
}
|
||||
const percent = (1 - elapsed / timeout) * 100;
|
||||
progressBar.style.width = `${Math.max(0, percent)}%`;
|
||||
}
|
||||
if (elapsed >= timeout) {
|
||||
clearInterval(intervalId);
|
||||
this.removeNotification(notification);
|
||||
}
|
||||
};
|
||||
let intervalId = window.setInterval(updateProgress, lapse);
|
||||
notification.addEventListener('mouseout', () => intervalId = window.setInterval(updateProgress, lapse));
|
||||
intervalId = window.setInterval(updateTimer, lapse);
|
||||
notification.addEventListener('mouseout', () => {
|
||||
clearInterval(intervalId);
|
||||
intervalId = window.setInterval(updateTimer, lapse);
|
||||
});
|
||||
notification.addEventListener('mouseover', () => clearInterval(intervalId));
|
||||
}
|
||||
removeNotification(notification) {
|
||||
if (!notification) {
|
||||
return;
|
||||
}
|
||||
notification.classList.remove('fl-show');
|
||||
notification.ontransitionend = () => {
|
||||
var _a, _b;
|
||||
!((_a = notification.parentElement) === null || _a === void 0 ? void 0 : _a.hasChildNodes()) && ((_b = notification.parentElement) === null || _b === void 0 ? void 0 : _b.remove());
|
||||
const parent = notification.parentElement;
|
||||
notification.remove();
|
||||
if (parent && !parent.hasChildNodes()) {
|
||||
parent.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
stringToHTML(str) {
|
||||
@@ -185,18 +266,17 @@
|
||||
if (str == null) {
|
||||
return '';
|
||||
}
|
||||
return str.replace(/[&<>"'`=\/]/g, (char) => {
|
||||
return {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
'\'': ''',
|
||||
'`': '`',
|
||||
'=': '=',
|
||||
'/': '/',
|
||||
}[char];
|
||||
});
|
||||
const htmlEscapes = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
'\'': ''',
|
||||
'`': '`',
|
||||
'=': '=',
|
||||
'/': '/',
|
||||
};
|
||||
return str.replace(/[&<>"'`=/]/g, (char) => htmlEscapes[char] || char);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,54 +286,82 @@
|
||||
this.defaultPlugin = 'flasher';
|
||||
this.plugins = new Map();
|
||||
this.themes = new Map();
|
||||
this.loadedAssets = new Set();
|
||||
}
|
||||
render(response) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const resolved = this.resolveResponse(response);
|
||||
yield this.addAssets([
|
||||
{
|
||||
urls: resolved.styles,
|
||||
nonce: resolved.context.csp_style_nonce,
|
||||
type: 'style',
|
||||
},
|
||||
{
|
||||
urls: resolved.scripts,
|
||||
nonce: resolved.context.csp_script_nonce,
|
||||
type: 'script',
|
||||
},
|
||||
]);
|
||||
this.renderOptions(resolved.options);
|
||||
this.renderEnvelopes(resolved.envelopes);
|
||||
try {
|
||||
yield this.addAssets([
|
||||
{
|
||||
urls: resolved.styles,
|
||||
nonce: resolved.context.csp_style_nonce,
|
||||
type: 'style',
|
||||
},
|
||||
{
|
||||
urls: resolved.scripts,
|
||||
nonce: resolved.context.csp_script_nonce,
|
||||
type: 'script',
|
||||
},
|
||||
]);
|
||||
this.renderOptions(resolved.options);
|
||||
this.renderEnvelopes(resolved.envelopes);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('PHPFlasher: Error rendering notifications', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
renderEnvelopes(envelopes) {
|
||||
const map = {};
|
||||
if (!(envelopes === null || envelopes === void 0 ? void 0 : envelopes.length)) {
|
||||
return;
|
||||
}
|
||||
const groupedByPlugin = {};
|
||||
envelopes.forEach((envelope) => {
|
||||
const plugin = this.resolvePluginAlias(envelope.metadata.plugin);
|
||||
map[plugin] = map[plugin] || [];
|
||||
map[plugin].push(envelope);
|
||||
groupedByPlugin[plugin] = groupedByPlugin[plugin] || [];
|
||||
groupedByPlugin[plugin].push(envelope);
|
||||
});
|
||||
Object.entries(map).forEach(([plugin, envelopes]) => {
|
||||
this.use(plugin).renderEnvelopes(envelopes);
|
||||
Object.entries(groupedByPlugin).forEach(([pluginName, pluginEnvelopes]) => {
|
||||
try {
|
||||
this.use(pluginName).renderEnvelopes(pluginEnvelopes);
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`PHPFlasher: Error rendering envelopes for plugin "${pluginName}"`, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
renderOptions(options) {
|
||||
if (!options) {
|
||||
return;
|
||||
}
|
||||
Object.entries(options).forEach(([plugin, option]) => {
|
||||
this.use(plugin).renderOptions(option);
|
||||
try {
|
||||
this.use(plugin).renderOptions(option);
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`PHPFlasher: Error applying options for plugin "${plugin}"`, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
addPlugin(name, plugin) {
|
||||
if (!name || !plugin) {
|
||||
throw new Error('Both plugin name and instance are required');
|
||||
}
|
||||
this.plugins.set(name, plugin);
|
||||
}
|
||||
addTheme(name, theme) {
|
||||
if (!name || !theme) {
|
||||
throw new Error('Both theme name and definition are required');
|
||||
}
|
||||
this.themes.set(name, theme);
|
||||
}
|
||||
use(name) {
|
||||
name = this.resolvePluginAlias(name);
|
||||
this.resolvePlugin(name);
|
||||
const plugin = this.plugins.get(name);
|
||||
const resolvedName = this.resolvePluginAlias(name);
|
||||
this.resolvePlugin(resolvedName);
|
||||
const plugin = this.plugins.get(resolvedName);
|
||||
if (!plugin) {
|
||||
throw new Error(`Unable to resolve "${name}" plugin, did you forget to register it?`);
|
||||
throw new Error(`Unable to resolve "${resolvedName}" plugin, did you forget to register it?`);
|
||||
}
|
||||
return plugin;
|
||||
}
|
||||
@@ -277,10 +385,14 @@
|
||||
return resolved;
|
||||
}
|
||||
resolveOptions(options) {
|
||||
Object.entries(options).forEach(([key, value]) => {
|
||||
options[key] = this.resolveFunction(value);
|
||||
if (!options) {
|
||||
return {};
|
||||
}
|
||||
const resolved = Object.assign({}, options);
|
||||
Object.entries(resolved).forEach(([key, value]) => {
|
||||
resolved[key] = this.resolveFunction(value);
|
||||
});
|
||||
return options;
|
||||
return resolved;
|
||||
}
|
||||
resolveFunction(func) {
|
||||
var _a, _b;
|
||||
@@ -302,7 +414,7 @@
|
||||
return new Function(...args, body);
|
||||
}
|
||||
catch (e) {
|
||||
console.error('Error converting string to function:', e);
|
||||
console.error('PHPFlasher: Error converting string to function:', e);
|
||||
return func;
|
||||
}
|
||||
}
|
||||
@@ -311,11 +423,12 @@
|
||||
if (factory || !alias.includes('theme.')) {
|
||||
return;
|
||||
}
|
||||
const view = this.themes.get(alias.replace('theme.', ''));
|
||||
if (!view) {
|
||||
const themeName = alias.replace('theme.', '');
|
||||
const theme = this.themes.get(themeName);
|
||||
if (!theme) {
|
||||
return;
|
||||
}
|
||||
this.addPlugin(alias, new FlasherPlugin(view));
|
||||
this.addPlugin(alias, new FlasherPlugin(theme));
|
||||
}
|
||||
resolvePluginAlias(alias) {
|
||||
alias = alias || this.defaultPlugin;
|
||||
@@ -323,18 +436,46 @@
|
||||
}
|
||||
addAssets(assets) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
for (const { urls, nonce, type } of assets) {
|
||||
for (const url of urls) {
|
||||
yield this.loadAsset(url, nonce, type);
|
||||
try {
|
||||
const styleAssets = assets.filter((asset) => asset.type === 'style');
|
||||
const stylePromises = [];
|
||||
for (const { urls, nonce, type } of styleAssets) {
|
||||
if (!(urls === null || urls === void 0 ? void 0 : urls.length)) {
|
||||
continue;
|
||||
}
|
||||
for (const url of urls) {
|
||||
if (!url || this.loadedAssets.has(url)) {
|
||||
continue;
|
||||
}
|
||||
stylePromises.push(this.loadAsset(url, nonce, type));
|
||||
this.loadedAssets.add(url);
|
||||
}
|
||||
}
|
||||
yield Promise.all(stylePromises);
|
||||
const scriptAssets = assets.filter((asset) => asset.type === 'script');
|
||||
for (const { urls, nonce, type } of scriptAssets) {
|
||||
if (!(urls === null || urls === void 0 ? void 0 : urls.length)) {
|
||||
continue;
|
||||
}
|
||||
for (const url of urls) {
|
||||
if (!url || this.loadedAssets.has(url)) {
|
||||
continue;
|
||||
}
|
||||
yield this.loadAsset(url, nonce, type);
|
||||
this.loadedAssets.add(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('PHPFlasher: Error loading assets', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
loadAsset(url, nonce, type) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (document.querySelector(`${type === 'style' ? 'link' : 'script'}[src="${url}"]`)) {
|
||||
return;
|
||||
}
|
||||
if (document.querySelector(`${type === 'style' ? 'link' : 'script'}[src="${url}"]`)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const element = document.createElement(type === 'style' ? 'link' : 'script');
|
||||
if (type === 'style') {
|
||||
element.rel = 'stylesheet';
|
||||
@@ -347,21 +488,22 @@
|
||||
if (nonce) {
|
||||
element.setAttribute('nonce', nonce);
|
||||
}
|
||||
element.onload = () => resolve();
|
||||
element.onerror = () => reject(new Error(`Failed to load ${url}`));
|
||||
document.head.appendChild(element);
|
||||
return new Promise((resolve, reject) => {
|
||||
element.onload = () => resolve();
|
||||
element.onerror = () => reject(new Error(`Failed to load ${url}`));
|
||||
});
|
||||
});
|
||||
}
|
||||
addThemeStyles(response, plugin) {
|
||||
var _a;
|
||||
if (plugin !== 'flasher' && !plugin.includes('theme.')) {
|
||||
return;
|
||||
}
|
||||
plugin = plugin.replace('theme.', '');
|
||||
const styles = ((_a = this.themes.get(plugin)) === null || _a === void 0 ? void 0 : _a.styles) || [];
|
||||
response.styles = Array.from(new Set([...response.styles, ...styles]));
|
||||
const themeName = plugin.replace('theme.', '');
|
||||
const theme = this.themes.get(themeName);
|
||||
if (!(theme === null || theme === void 0 ? void 0 : theme.styles)) {
|
||||
return;
|
||||
}
|
||||
const themeStyles = Array.isArray(theme.styles) ? theme.styles : [theme.styles];
|
||||
response.styles = Array.from(new Set([...response.styles, ...themeStyles]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,23 +513,29 @@
|
||||
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);
|
||||
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>
|
||||
<strong class="fl-title">${title}</strong>
|
||||
<strong class="fl-title">${displayTitle}</strong>
|
||||
<span class="fl-message">${message}</span>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
</div>
|
||||
<span class="fl-progress-bar"></span>
|
||||
<span class="fl-progress-bar">
|
||||
<span class="fl-progress"></span>
|
||||
</span>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
const flasher = new Flasher();
|
||||
flasher.addTheme('flasher', flasherTheme);
|
||||
if (typeof window !== 'undefined') {
|
||||
window.flasher = flasher;
|
||||
}
|
||||
|
||||
return flasher;
|
||||
|
||||
|
||||
+18
-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
Vendored
+38
-16
@@ -12,34 +12,56 @@ class AbstractPlugin {
|
||||
this.flash('warning', message, title, options);
|
||||
}
|
||||
flash(type, message, title, options) {
|
||||
let normalizedType;
|
||||
let normalizedMessage;
|
||||
let normalizedTitle;
|
||||
let normalizedOptions = {};
|
||||
if (typeof type === 'object') {
|
||||
options = type;
|
||||
type = options.type;
|
||||
message = options.message;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, type);
|
||||
normalizedType = normalizedOptions.type;
|
||||
normalizedMessage = normalizedOptions.message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.type;
|
||||
delete normalizedOptions.message;
|
||||
delete normalizedOptions.title;
|
||||
}
|
||||
else if (typeof message === 'object') {
|
||||
options = message;
|
||||
message = options.message;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, message);
|
||||
normalizedType = type;
|
||||
normalizedMessage = normalizedOptions.message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.message;
|
||||
delete normalizedOptions.title;
|
||||
}
|
||||
else if (typeof title === 'object') {
|
||||
options = title;
|
||||
title = options.title;
|
||||
normalizedOptions = Object.assign({}, title);
|
||||
normalizedType = type;
|
||||
normalizedMessage = message;
|
||||
normalizedTitle = normalizedOptions.title;
|
||||
delete normalizedOptions.title;
|
||||
}
|
||||
if (undefined === message) {
|
||||
throw new Error('message option is required');
|
||||
else {
|
||||
normalizedType = type;
|
||||
normalizedMessage = message;
|
||||
normalizedTitle = title;
|
||||
normalizedOptions = options || {};
|
||||
}
|
||||
if (!normalizedType) {
|
||||
throw new Error('Type is required for notifications');
|
||||
}
|
||||
if (normalizedMessage === undefined || normalizedMessage === null) {
|
||||
throw new Error('Message is required for notifications');
|
||||
}
|
||||
const envelope = {
|
||||
type,
|
||||
message,
|
||||
title: title || type,
|
||||
options: options || {},
|
||||
type: normalizedType,
|
||||
message: normalizedMessage,
|
||||
title: normalizedTitle || normalizedType,
|
||||
options: normalizedOptions,
|
||||
metadata: {
|
||||
plugin: '',
|
||||
},
|
||||
};
|
||||
this.renderOptions(options || {});
|
||||
this.renderOptions(normalizedOptions);
|
||||
this.renderEnvelopes([envelope]);
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
-4
@@ -1,4 +0,0 @@
|
||||
import type { Envelope } from './types';
|
||||
export declare const theme: {
|
||||
render: (envelope: Envelope) => string;
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
import './amazon.scss';
|
||||
import type { Envelope } from '../../types';
|
||||
export declare const amazonTheme: {
|
||||
render: (envelope: Envelope) => string;
|
||||
};
|
||||
@@ -0,0 +1,63 @@
|
||||
import flasher from '../../index.ts';
|
||||
|
||||
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';
|
||||
}
|
||||
};
|
||||
return `
|
||||
<div class="fl-amazon fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-amazon-alert">
|
||||
<div class="fl-alert-content">
|
||||
<div class="fl-icon-container">
|
||||
${getAlertIcon()}
|
||||
</div>
|
||||
<div class="fl-text-content">
|
||||
<div class="fl-alert-title">${getAlertTitle()}</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>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('amazon', amazonTheme);
|
||||
@@ -0,0 +1,69 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../index.ts')) :
|
||||
typeof define === 'function' && define.amd ? define(['../../index.ts'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
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';
|
||||
}
|
||||
};
|
||||
return `
|
||||
<div class="fl-amazon fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-amazon-alert">
|
||||
<div class="fl-alert-content">
|
||||
<div class="fl-icon-container">
|
||||
${getAlertIcon()}
|
||||
</div>
|
||||
<div class="fl-text-content">
|
||||
<div class="fl-alert-title">${getAlertTitle()}</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>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('amazon', amazonTheme);
|
||||
|
||||
}));
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("../../index.ts")):"function"==typeof define&&define.amd?define(["../../index.ts"],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,i="error"===n||"warning"===n;return`\n <div class="fl-amazon fl-${n}" role="${i?"alert":"status"}" aria-live="${i?"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>`}})}));
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,5 @@
|
||||
import './amber.scss';
|
||||
import type { Envelope } from '../../types';
|
||||
export declare const amberTheme: {
|
||||
render: (envelope: Envelope) => string;
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
import flasher from '../../index.ts';
|
||||
|
||||
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>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('amber', amberTheme);
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../index.ts')) :
|
||||
typeof define === 'function' && define.amd ? define(['../../index.ts'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
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>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('amber', amberTheme);
|
||||
|
||||
}));
|
||||
@@ -0,0 +1 @@
|
||||
.fl-amber{--amber-bg-light:#fff;--amber-bg-dark:#1e293b;--amber-text-light:#4b5563;--amber-text-dark:#f1f5f9;--amber-shadow:0 5px 15px rgba(0,0,0,.08);--amber-shadow-dark:0 5px 15px rgba(0,0,0,.2);--amber-border-radius:0.4rem;--amber-success:#10b981;--amber-info:#3b82f6;--amber-warning:#f59e0b;--amber-error:#ef4444}@-webkit-keyframes amberIn{0%{opacity:0;-webkit-transform:translateY(-12px);transform:translateY(-12px)}to{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@-moz-keyframes amberIn{0%{opacity:0;-moz-transform:translateY(-12px);transform:translateY(-12px)}to{opacity:1;-moz-transform:translateY(0);transform:translateY(0)}}@keyframes amberIn{0%{opacity:0;-webkit-transform:translateY(-12px);-moz-transform:translateY(-12px);transform:translateY(-12px)}to{opacity:1;-webkit-transform:translateY(0);-moz-transform:translateY(0);transform:translateY(0)}}.fl-amber{-webkit-animation:amberIn .3s ease-out;-moz-animation:amberIn .3s ease-out;animation:amberIn .3s ease-out;background-color:var(--amber-bg-light);border-radius:var(--amber-border-radius);-webkit-box-shadow:var(--amber-shadow);box-shadow:var(--amber-shadow);color:var(--amber-text-light);font-family:var(--fl-font),serif;margin:.6rem 0;padding:.85rem 1rem;position:relative;will-change:transform,opacity}.fl-amber:last-child{margin-bottom:0}.fl-amber .fl-content{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:flex}.fl-amber .fl-icon{font-size:1.85em;margin-right:.8rem}.fl-amber .fl-text{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;flex:1}.fl-amber .fl-message{font-size:.875em;line-height:1.4}.fl-amber .fl-close{background:none;border:none;color:currentColor;cursor:pointer;-webkit-flex-shrink:0;flex-shrink:0;font-size:1.15rem;margin-left:1rem;opacity:.6;padding:.25rem;touch-action:manipulation;-webkit-transition:opacity .2s;-moz-transition:opacity .2s;transition:opacity .2s}.fl-amber .fl-close:focus,.fl-amber .fl-close:hover{opacity:1}.fl-amber .fl-progress-bar{bottom:0;height:3px;left:0;overflow:hidden;position:absolute;right:0}.fl-amber .fl-progress-bar .fl-progress{height:100%;width:100%}.fl-amber.fl-success .fl-close{color:var(--amber-success)}.fl-amber.fl-info .fl-close{color:var(--amber-info)}.fl-amber.fl-warning .fl-close{color:var(--amber-warning)}.fl-amber.fl-error .fl-close{color:var(--amber-error)}.fl-amber.fl-rtl{direction:rtl}.fl-amber.fl-rtl .fl-icon{margin-left:.8rem;margin-right:0}.fl-amber.fl-rtl .fl-close{margin-left:0;margin-right:1rem}.fl-amber.fl-rtl .fl-progress .fl-progress{-webkit-transform-origin:right center;-moz-transform-origin:right center;-ms-transform-origin:right center;transform-origin:right center}@media (prefers-reduced-motion:reduce){.fl-amber{-webkit-animation:none;-moz-animation:none;animation:none}}.fl-amber.fl-auto-dark,body.fl-dark .fl-amber,html.fl-dark .fl-amber{background-color:var(--amber-bg-dark);-webkit-box-shadow:var(--amber-shadow-dark);box-shadow:var(--amber-shadow-dark);color:var(--amber-text-dark)}
|
||||
@@ -0,0 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("../../index.ts")):"function"==typeof define&&define.amd?define(["../../index.ts"],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,n="error"===s||"warning"===s;return`\n <div class="fl-amber fl-${s}" role="${n?"alert":"status"}" aria-live="${n?"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>`}})}));
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,5 @@
|
||||
import './aurora.scss';
|
||||
import type { Envelope } from '../../types';
|
||||
export declare const auroraTheme: {
|
||||
render: (envelope: Envelope) => string;
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
import flasher from '../../index.ts';
|
||||
|
||||
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>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('aurora', auroraTheme);
|
||||
@@ -0,0 +1,28 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../index.ts')) :
|
||||
typeof define === 'function' && define.amd ? define(['../../index.ts'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
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>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('aurora', auroraTheme);
|
||||
|
||||
}));
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("../../index.ts")):"function"==typeof define&&define.amd?define(["../../index.ts"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("aurora",{render:e=>{const{type:s,message:i}=e,n="error"===s||"warning"===s;return`\n <div class="fl-aurora fl-${s}" role="${n?"alert":"status"}" aria-live="${n?"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>`}})}));
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,5 @@
|
||||
import './crystal.scss';
|
||||
import type { Envelope } from '../../types';
|
||||
export declare const crystalTheme: {
|
||||
render: (envelope: Envelope) => string;
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
import flasher from '../../index.ts';
|
||||
|
||||
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>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('crystal', crystalTheme);
|
||||
@@ -0,0 +1,30 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../index.ts')) :
|
||||
typeof define === 'function' && define.amd ? define(['../../index.ts'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
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>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('crystal', crystalTheme);
|
||||
|
||||
}));
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("../../index.ts")):"function"==typeof define&&define.amd?define(["../../index.ts"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("crystal",{render:e=>{const{type:s,message:n}=e,t="error"===s||"warning"===s;return`\n <div class="fl-crystal fl-${s}" role="${t?"alert":"status"}" aria-live="${t?"assertive":"polite"}" aria-atomic="true">\n <div class="fl-content">\n <div class="fl-text">\n <p class="fl-message">${n}</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>`}})}));
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,5 @@
|
||||
import './emerald.scss';
|
||||
import type { Envelope } from '../../types';
|
||||
export declare const emeraldTheme: {
|
||||
render: (envelope: Envelope) => string;
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
import flasher from '../../index.ts';
|
||||
|
||||
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>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('emerald', emeraldTheme);
|
||||
@@ -0,0 +1,25 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../index.ts')) :
|
||||
typeof define === 'function' && define.amd ? define(['../../index.ts'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
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>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('emerald', emeraldTheme);
|
||||
|
||||
}));
|
||||
@@ -0,0 +1 @@
|
||||
.fl-emerald{--emerald-bg-light:hsla(0,0%,100%,.9);--emerald-bg-dark:rgba(30,30,30,.9);--emerald-text-light:#333;--emerald-text-dark:hsla(0,0%,100%,.9);--emerald-shadow:rgba(0,0,0,.1);--emerald-blur:8px;--emerald-success:var(--success-color,#16a085);--emerald-error:var(--error-color,#e74c3c);--emerald-warning:var(--warning-color,#f39c12);--emerald-info:var(--info-color,#3498db)}@-webkit-keyframes emeraldIn{0%{opacity:0;-webkit-transform:scale(.5) translateY(20px);transform:scale(.5) translateY(20px)}60%{opacity:1;-webkit-transform:scale(1.1) translateY(-5px);transform:scale(1.1) translateY(-5px)}to{opacity:1;-webkit-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}}@-moz-keyframes emeraldIn{0%{opacity:0;-moz-transform:scale(.5) translateY(20px);transform:scale(.5) translateY(20px)}60%{opacity:1;-moz-transform:scale(1.1) translateY(-5px);transform:scale(1.1) translateY(-5px)}to{opacity:1;-moz-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}}@keyframes emeraldIn{0%{opacity:0;-webkit-transform:scale(.5) translateY(20px);-moz-transform:scale(.5) translateY(20px);transform:scale(.5) translateY(20px)}60%{opacity:1;-webkit-transform:scale(1.1) translateY(-5px);-moz-transform:scale(1.1) translateY(-5px);transform:scale(1.1) translateY(-5px)}to{opacity:1;-webkit-transform:scale(1) translateY(0);-moz-transform:scale(1) translateY(0);transform:scale(1) translateY(0)}}.fl-emerald{-webkit-animation:emeraldIn .5s cubic-bezier(.23,1,.32,1);-moz-animation:emeraldIn .5s cubic-bezier(.23,1,.32,1);animation:emeraldIn .5s cubic-bezier(.23,1,.32,1);backdrop-filter:blur(var(--emerald-blur));-webkit-backdrop-filter:blur(var(--emerald-blur));background:var(--emerald-bg-light);border-radius:10px;-webkit-box-shadow:0 10px 20px var(--emerald-shadow);box-shadow:0 10px 20px var(--emerald-shadow);color:var(--emerald-text-light);font-family:"Inter",var(--fl-font),serif;margin:0 0 .5rem;overflow:hidden;padding:1rem 1.5rem 1rem 1rem;position:relative}.fl-emerald .fl-content{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:flex}.fl-emerald .fl-message{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;flex:1;font-size:.9rem;font-weight:500;line-height:1.4}.fl-emerald .fl-close{background:transparent;border:none;color:currentColor;cursor:pointer;font-size:1.3rem;margin-left:auto;opacity:.7;-webkit-transition:opacity .2s ease;-moz-transition:opacity .2s ease;transition:opacity .2s ease}.fl-emerald .fl-close:focus,.fl-emerald .fl-close:hover{opacity:1}.fl-emerald.fl-success{color:var(--emerald-success)}.fl-emerald.fl-error{color:var(--emerald-error)}.fl-emerald.fl-warning{color:var(--emerald-warning)}.fl-emerald.fl-info{color:var(--emerald-info)}.fl-emerald.fl-rtl{direction:rtl;padding:1rem 1rem 1rem 1.5rem}.fl-emerald.fl-rtl .fl-content{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-moz-box-orient:horizontal;-moz-box-direction:reverse;flex-direction:row-reverse}.fl-emerald.fl-rtl .fl-close{margin-left:0;margin-right:auto}@media (prefers-reduced-motion:reduce){.fl-emerald{-webkit-animation:none;-moz-animation:none;animation:none}}.fl-emerald.fl-auto-dark,body.fl-dark .fl-emerald,html.fl-dark .fl-emerald{background:var(--emerald-bg-dark)}.fl-emerald.fl-auto-dark .fl-message,body.fl-dark .fl-emerald .fl-message,html.fl-dark .fl-emerald .fl-message{color:var(--emerald-text-dark)}
|
||||
@@ -0,0 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("../../index.ts")):"function"==typeof define&&define.amd?define(["../../index.ts"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("emerald",{render:e=>{const{type:s,message:n}=e,t="error"===s||"warning"===s;return`\n <div class="fl-emerald fl-${s}" role="${t?"alert":"status"}" aria-live="${t?"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>`}})}));
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,5 @@
|
||||
import './facebook.scss';
|
||||
import type { Envelope } from '../../types';
|
||||
export declare const facebookTheme: {
|
||||
render: (envelope: Envelope) => string;
|
||||
};
|
||||
@@ -0,0 +1,69 @@
|
||||
import flasher from '../../index.ts';
|
||||
|
||||
const facebookTheme = {
|
||||
render: (envelope) => {
|
||||
var _a;
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const timestamp = String(((_a = envelope.options) === null || _a === void 0 ? void 0 : _a.timestamp) || '2025-03-02 06:49:21');
|
||||
const formattedTime = timestamp.split(' ')[1].substring(0, 5);
|
||||
const getNotificationIcon = () => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return `<div class="fl-fb-icon fl-fb-icon-success">
|
||||
<svg viewBox="0 0 24 24" width="16" height="16">
|
||||
<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"/>
|
||||
</svg>
|
||||
</div>`;
|
||||
case 'error':
|
||||
return `<div class="fl-fb-icon fl-fb-icon-error">
|
||||
<svg viewBox="0 0 24 24" width="16" height="16">
|
||||
<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"/>
|
||||
</svg>
|
||||
</div>`;
|
||||
case 'warning':
|
||||
return `<div class="fl-fb-icon fl-fb-icon-warning">
|
||||
<svg viewBox="0 0 24 24" width="16" height="16">
|
||||
<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"/>
|
||||
</svg>
|
||||
</div>`;
|
||||
case 'info':
|
||||
return `<div class="fl-fb-icon fl-fb-icon-info">
|
||||
<svg viewBox="0 0 24 24" width="16" height="16">
|
||||
<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"/>
|
||||
</svg>
|
||||
</div>`;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
return `
|
||||
<div class="fl-facebook fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-fb-notification">
|
||||
<div class="fl-icon-container">
|
||||
${getNotificationIcon()}
|
||||
</div>
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">
|
||||
${message}
|
||||
</div>
|
||||
<div class="fl-meta">
|
||||
<span class="fl-time">${formattedTime}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-button fl-close" aria-label="Close ${type} message">
|
||||
<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 12 19 6.41z"/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('facebook', facebookTheme);
|
||||
@@ -0,0 +1,75 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../index.ts')) :
|
||||
typeof define === 'function' && define.amd ? define(['../../index.ts'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
const facebookTheme = {
|
||||
render: (envelope) => {
|
||||
var _a;
|
||||
const { type, message } = envelope;
|
||||
const isAlert = type === 'error' || type === 'warning';
|
||||
const role = isAlert ? 'alert' : 'status';
|
||||
const ariaLive = isAlert ? 'assertive' : 'polite';
|
||||
const timestamp = String(((_a = envelope.options) === null || _a === void 0 ? void 0 : _a.timestamp) || '2025-03-02 06:49:21');
|
||||
const formattedTime = timestamp.split(' ')[1].substring(0, 5);
|
||||
const getNotificationIcon = () => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return `<div class="fl-fb-icon fl-fb-icon-success">
|
||||
<svg viewBox="0 0 24 24" width="16" height="16">
|
||||
<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"/>
|
||||
</svg>
|
||||
</div>`;
|
||||
case 'error':
|
||||
return `<div class="fl-fb-icon fl-fb-icon-error">
|
||||
<svg viewBox="0 0 24 24" width="16" height="16">
|
||||
<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"/>
|
||||
</svg>
|
||||
</div>`;
|
||||
case 'warning':
|
||||
return `<div class="fl-fb-icon fl-fb-icon-warning">
|
||||
<svg viewBox="0 0 24 24" width="16" height="16">
|
||||
<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"/>
|
||||
</svg>
|
||||
</div>`;
|
||||
case 'info':
|
||||
return `<div class="fl-fb-icon fl-fb-icon-info">
|
||||
<svg viewBox="0 0 24 24" width="16" height="16">
|
||||
<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"/>
|
||||
</svg>
|
||||
</div>`;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
return `
|
||||
<div class="fl-facebook fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-fb-notification">
|
||||
<div class="fl-icon-container">
|
||||
${getNotificationIcon()}
|
||||
</div>
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">
|
||||
${message}
|
||||
</div>
|
||||
<div class="fl-meta">
|
||||
<span class="fl-time">${formattedTime}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-button fl-close" aria-label="Close ${type} message">
|
||||
<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 12 19 6.41z"/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('facebook', facebookTheme);
|
||||
|
||||
}));
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
!function(n,i){"object"==typeof exports&&"undefined"!=typeof module?i(require("../../index.ts")):"function"==typeof define&&define.amd?define(["../../index.ts"],i):i((n="undefined"!=typeof globalThis?globalThis:n||self).flasher)}(this,(function(n){"use strict";const i={render:n=>{var i;const{type:s,message:e}=n,t="error"===s||"warning"===s,l=t?"alert":"status",o=t?"assertive":"polite",c=String((null===(i=n.options)||void 0===i?void 0:i.timestamp)||"2025-03-02 06:49:21").split(" ")[1].substring(0,5);return`\n <div class="fl-facebook fl-${s}" role="${l}" aria-live="${o}" aria-atomic="true">\n <div class="fl-fb-notification">\n <div class="fl-icon-container">\n ${(()=>{switch(s){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">${c}</span>\n </div>\n </div>\n <div class="fl-actions">\n <button class="fl-button fl-close" aria-label="Close ${s} 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 12 19 6.41z"/>\n </svg>\n </div>\n </button>\n </div>\n </div>\n </div>`}};n.addTheme("facebook",i)}));
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,5 @@
|
||||
import './flasher.scss';
|
||||
import type { Envelope } from '../../types';
|
||||
export declare const flasherTheme: {
|
||||
render: (envelope: Envelope) => string;
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
import flasher from '../../index.ts';
|
||||
|
||||
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);
|
||||
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>
|
||||
<strong class="fl-title">${displayTitle}</strong>
|
||||
<span class="fl-message">${message}</span>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
</div>
|
||||
<span class="fl-progress-bar">
|
||||
<span class="fl-progress"></span>
|
||||
</span>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('flasher', flasherTheme);
|
||||
@@ -0,0 +1,33 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../index.ts')) :
|
||||
typeof define === 'function' && define.amd ? define(['../../index.ts'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
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);
|
||||
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>
|
||||
<strong class="fl-title">${displayTitle}</strong>
|
||||
<span class="fl-message">${message}</span>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">×</button>
|
||||
</div>
|
||||
<span class="fl-progress-bar">
|
||||
<span class="fl-progress"></span>
|
||||
</span>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('flasher', flasherTheme);
|
||||
|
||||
}));
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("../../index.ts")):"function"==typeof define&&define.amd?define(["../../index.ts"],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,t="error"===s||"warning"===s,l=t?"alert":"status",i=t?"assertive":"polite",r=n||s.charAt(0).toUpperCase()+s.slice(1);return`\n <div class="fl-flasher fl-${s}" role="${l}" aria-live="${i}" aria-atomic="true">\n <div class="fl-content">\n <div class="fl-icon"></div>\n <div>\n <strong class="fl-title">${r}</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>`}})}));
|
||||
+1
-5
@@ -1,5 +1 @@
|
||||
import './flasher.scss';
|
||||
import type { Envelope } from '../../types';
|
||||
export declare const flasherTheme: {
|
||||
render: (envelope: Envelope) => string;
|
||||
};
|
||||
export {};
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import './google.scss';
|
||||
import type { Envelope } from '../../types';
|
||||
export declare const googleTheme: {
|
||||
render: (envelope: Envelope) => string;
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
import flasher from '../../index.ts';
|
||||
|
||||
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>` : '';
|
||||
return `
|
||||
<div class="fl-google fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-md-card">
|
||||
<div class="fl-content">
|
||||
<div class="fl-icon-wrapper">
|
||||
${getIcon()}
|
||||
</div>
|
||||
<div class="fl-text-content">
|
||||
${titleSection}
|
||||
<div class="fl-message">${message}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-action-button fl-close" aria-label="Close ${type} message">
|
||||
${actionText}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('google', googleTheme);
|
||||
@@ -0,0 +1,63 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../index.ts')) :
|
||||
typeof define === 'function' && define.amd ? define(['../../index.ts'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
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>` : '';
|
||||
return `
|
||||
<div class="fl-google fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-md-card">
|
||||
<div class="fl-content">
|
||||
<div class="fl-icon-wrapper">
|
||||
${getIcon()}
|
||||
</div>
|
||||
<div class="fl-text-content">
|
||||
${titleSection}
|
||||
<div class="fl-message">${message}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-action-button fl-close" aria-label="Close ${type} message">
|
||||
${actionText}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('google', googleTheme);
|
||||
|
||||
}));
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
!function(s,e){"object"==typeof exports&&"undefined"!=typeof module?e(require("../../index.ts")):"function"==typeof define&&define.amd?define(["../../index.ts"],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:i}=s,l="error"===e||"warning"===e,t=i?`<div class="fl-title">${i}</div>`:"";return`\n <div class="fl-google fl-${e}" role="${l?"alert":"status"}" aria-live="${l?"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>`}})}));
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
export { amazonTheme } from './amazon/amazon';
|
||||
export { amberTheme } from './amber/amber';
|
||||
export { auroraTheme } from './aurora/aurora';
|
||||
export { crystalTheme } from './crystal/crystal';
|
||||
export { emeraldTheme } from './emerald/emerald';
|
||||
export { facebookTheme } from './facebook/facebook';
|
||||
export { flasherTheme } from './flasher/flasher';
|
||||
export { googleTheme } from './google/google';
|
||||
export { iosTheme } from './ios/ios';
|
||||
export { jadeTheme } from './jade/jade';
|
||||
export { materialTheme } from './material/material';
|
||||
export { minimalTheme } from './minimal/minimal';
|
||||
export { neonTheme } from './neon/neon';
|
||||
export { onyxTheme } from './onyx/onyx';
|
||||
export { rubyTheme } from './ruby/ruby';
|
||||
export { sapphireTheme } from './sapphire/sapphire';
|
||||
export { slackTheme } from './slack/slack';
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,5 @@
|
||||
import './ios.scss';
|
||||
import type { Envelope } from '../../types';
|
||||
export declare const iosTheme: {
|
||||
render: (envelope: Envelope) => string;
|
||||
};
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
import flasher from '../../index.ts';
|
||||
|
||||
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;
|
||||
return `
|
||||
<div class="fl-ios fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-ios-notification">
|
||||
<div class="fl-header">
|
||||
<div class="fl-app-icon">
|
||||
${getIcon()}
|
||||
</div>
|
||||
<div class="fl-app-info">
|
||||
<div class="fl-app-name">${displayTitle}</div>
|
||||
<div class="fl-time">${timeString}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('ios', iosTheme);
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../index.ts')) :
|
||||
typeof define === 'function' && define.amd ? define(['../../index.ts'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
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;
|
||||
return `
|
||||
<div class="fl-ios fl-${type}" role="${role}" aria-live="${ariaLive}" aria-atomic="true">
|
||||
<div class="fl-ios-notification">
|
||||
<div class="fl-header">
|
||||
<div class="fl-app-icon">
|
||||
${getIcon()}
|
||||
</div>
|
||||
<div class="fl-app-info">
|
||||
<div class="fl-app-name">${displayTitle}</div>
|
||||
<div class="fl-time">${timeString}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
</div>
|
||||
<button class="fl-close" aria-label="Close ${type} message">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('ios', iosTheme);
|
||||
|
||||
}));
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
!function(e,i){"object"==typeof exports&&"undefined"!=typeof module?i(require("../../index.ts")):"function"==typeof define&&define.amd?define(["../../index.ts"],i):i((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";const i={render:e=>{const{type:i,message:s,title:n}=e,t="error"===i||"warning"===i,l=t?"alert":"status",a=t?"assertive":"polite",r=(new Date).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"}),o=n||"PHPFlasher";return`\n <div class="fl-ios fl-${i}" role="${l}" 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(i){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">${s}</div>\n </div>\n <button class="fl-close" aria-label="Close ${i} message">\n <span aria-hidden="true">×</span>\n </button>\n </div>\n </div>`}};e.addTheme("ios",i)}));
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,5 @@
|
||||
import './jade.scss';
|
||||
import type { Envelope } from '../../types';
|
||||
export declare const jadeTheme: {
|
||||
render: (envelope: Envelope) => string;
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
import flasher from '../../index.ts';
|
||||
|
||||
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>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('jade', jadeTheme);
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../index.ts')) :
|
||||
typeof define === 'function' && define.amd ? define(['../../index.ts'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
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>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('jade', jadeTheme);
|
||||
|
||||
}));
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("../../index.ts")):"function"==typeof define&&define.amd?define(["../../index.ts"],s):s((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("jade",{render:e=>{const{type:s,message:i}=e,n="error"===s||"warning"===s;return`\n <div class="fl-jade fl-${s}" role="${n?"alert":"status"}" aria-live="${n?"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>`}})}));
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,5 @@
|
||||
import './material.scss';
|
||||
import type { Envelope } from '../../types';
|
||||
export declare const materialTheme: {
|
||||
render: (envelope: Envelope) => string;
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
import flasher from '../../index.ts';
|
||||
|
||||
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="fl-md-card">
|
||||
<div class="fl-content">
|
||||
<div class="fl-text-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-action-button fl-close" aria-label="Close ${type} message">
|
||||
${actionText}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('material', materialTheme);
|
||||
@@ -0,0 +1,37 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../index.ts')) :
|
||||
typeof define === 'function' && define.amd ? define(['../../index.ts'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
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="fl-md-card">
|
||||
<div class="fl-content">
|
||||
<div class="fl-text-content">
|
||||
<div class="fl-message">${message}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-actions">
|
||||
<button class="fl-action-button fl-close" aria-label="Close ${type} message">
|
||||
${actionText}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('material', materialTheme);
|
||||
|
||||
}));
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(require("../../index.ts")):"function"==typeof define&&define.amd?define(["../../index.ts"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).flasher)}(this,(function(e){"use strict";e.addTheme("material",{render:e=>{const{type:n,message:s}=e,i="error"===n||"warning"===n;return`\n <div class="fl-material fl-${n}" 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-text-content">\n <div class="fl-message">${s}</div>\n </div>\n </div>\n <div class="fl-actions">\n <button class="fl-action-button fl-close" aria-label="Close ${n} 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>`}})}));
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
@@ -0,0 +1,5 @@
|
||||
import './minimal.scss';
|
||||
import type { Envelope } from '../../types';
|
||||
export declare const minimalTheme: {
|
||||
render: (envelope: Envelope) => string;
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
import flasher from '../../index.ts';
|
||||
|
||||
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>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('minimal', minimalTheme);
|
||||
@@ -0,0 +1,28 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../index.ts')) :
|
||||
typeof define === 'function' && define.amd ? define(['../../index.ts'], factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.flasher));
|
||||
})(this, (function (flasher) { 'use strict';
|
||||
|
||||
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>
|
||||
<div class="fl-progress-bar">
|
||||
<div class="fl-progress"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
};
|
||||
|
||||
flasher.addTheme('minimal', minimalTheme);
|
||||
|
||||
}));
|
||||
@@ -0,0 +1 @@
|
||||
.fl-minimal{--minimal-bg-light:hsla(0,0%,100%,.8);--minimal-bg-dark:rgba(25,25,25,.8);--minimal-text-light:#333;--minimal-text-dark:#f5f5f5;--minimal-shadow:0 2px 8px rgba(0,0,0,.08);--minimal-shadow-dark:0 2px 8px rgba(0,0,0,.15);--minimal-border-radius:6px;--minimal-border-color:rgba(0,0,0,.05);--minimal-border-color-dark:hsla(0,0%,100%,.1);--minimal-success:rgba(34,197,94,.9);--minimal-info:rgba(14,165,233,.9);--minimal-warning:rgba(245,158,11,.9);--minimal-error:rgba(239,68,68,.9)}@-webkit-keyframes minimalIn{0%{opacity:0;-webkit-transform:translateY(-8px);transform:translateY(-8px)}to{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@-moz-keyframes minimalIn{0%{opacity:0;-moz-transform:translateY(-8px);transform:translateY(-8px)}to{opacity:1;-moz-transform:translateY(0);transform:translateY(0)}}@keyframes minimalIn{0%{opacity:0;-webkit-transform:translateY(-8px);-moz-transform:translateY(-8px);transform:translateY(-8px)}to{opacity:1;-webkit-transform:translateY(0);-moz-transform:translateY(0);transform:translateY(0)}}.fl-minimal{-webkit-animation:minimalIn .2s ease-out;-moz-animation:minimalIn .2s ease-out;animation:minimalIn .2s ease-out;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);background-color:var(--minimal-bg-light);border:1px solid var(--minimal-border-color);border-radius:var(--minimal-border-radius);-webkit-box-shadow:var(--minimal-shadow);box-shadow:var(--minimal-shadow);color:var(--minimal-text-light);font-family:-apple-system,BlinkMacSystemFont,var(--fl-font),sans-serif;margin:.5rem 0;max-width:320px;padding:.75rem 1rem;position:relative;will-change:transform,opacity}.fl-minimal:last-child{margin-bottom:0}.fl-minimal .fl-content{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:flex;gap:.75rem}.fl-minimal .fl-dot{border-radius:50%;-webkit-flex-shrink:0;flex-shrink:0;height:8px;width:8px}.fl-minimal .fl-message{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;flex:1;font-size:.875rem;font-weight:450;line-height:1.4;margin:0}.fl-minimal .fl-close{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;align-items:center;background:none;border:none;color:currentColor;cursor:pointer;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:flex;-webkit-flex-shrink:0;flex-shrink:0;font-size:1rem;height:1.5rem;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;justify-content:center;opacity:.5;padding:.25rem;-webkit-transition:opacity .15s;-moz-transition:opacity .15s;transition:opacity .15s;width:1.5rem}.fl-minimal .fl-close:focus,.fl-minimal .fl-close:hover{opacity:.8}.fl-minimal .fl-progress-bar{border-radius:0 0 var(--minimal-border-radius) var(--minimal-border-radius);bottom:0;height:2px;left:0;opacity:.7;overflow:hidden;position:absolute;right:0}.fl-minimal .fl-progress-bar .fl-progress{height:100%;width:100%}.fl-minimal.fl-success .fl-dot,.fl-minimal.fl-success .fl-progress-bar .fl-progress{background-color:var(--minimal-success)}.fl-minimal.fl-info .fl-dot,.fl-minimal.fl-info .fl-progress-bar .fl-progress{background-color:var(--minimal-info)}.fl-minimal.fl-warning .fl-dot,.fl-minimal.fl-warning .fl-progress-bar .fl-progress{background-color:var(--minimal-warning)}.fl-minimal.fl-error .fl-dot,.fl-minimal.fl-error .fl-progress-bar .fl-progress{background-color:var(--minimal-error)}.fl-minimal.fl-rtl{direction:rtl}.fl-minimal.fl-rtl .fl-progress .fl-progress{-webkit-transform-origin:right center;-moz-transform-origin:right center;-ms-transform-origin:right center;transform-origin:right center}@media (prefers-reduced-motion:reduce){.fl-minimal{-webkit-animation:none;-moz-animation:none;animation:none}}.fl-minimal.fl-auto-dark,body.fl-dark .fl-minimal,html.fl-dark .fl-minimal{background-color:var(--minimal-bg-dark);border-color:var(--minimal-border-color-dark);-webkit-box-shadow:var(--minimal-shadow-dark);box-shadow:var(--minimal-shadow-dark);color:var(--minimal-text-dark)}
|
||||
@@ -0,0 +1 @@
|
||||
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?s(require("../../index.ts")):"function"==typeof define&&define.amd?define(["../../index.ts"],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,n="error"===s||"warning"===s;return`\n <div class="fl-minimal fl-${s}" role="${n?"alert":"status"}" aria-live="${n?"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>`}})}));
|
||||
@@ -0,0 +1 @@
|
||||
export {};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user