Merge pull request #273 from php-flasher/dev

fix flasher rtl support
This commit is contained in:
Younes ENNAJI
2025-03-23 14:57:02 +00:00
committed by GitHub
21 changed files with 114 additions and 32 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
{
"dist/main.css": "/dist/main.cfa0ed56.css",
"dist/main.js": "/dist/main.896f6a93.js",
"dist/main.css": "/dist/main.98f9c826.css",
"dist/main.js": "/dist/main.8b056786.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",
+18 -8
View File
@@ -146,6 +146,7 @@
<option value="10000">10 seconds</option>
<option value="5000">5 seconds</option>
<option value="3000">3 seconds</option>
<option value="false">Sticky</option>
</select>
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-slate-400">
<i class="fas fa-chevron-down text-xs"></i>
@@ -1038,7 +1039,7 @@ async function checkStatus() {
document.getElementById("title-input").value = state.title || "";
document.getElementById("message-input").value = state.message || "";
document.getElementById("position-select").value = state.position || "";
document.getElementById("timeout-select").value = state.timeout || "";
document.getElementById("timeout-select").value = state.timeout === false ? "false" : (state.timeout || "");
document.getElementById("theme-select").value = state.theme || "";
document.getElementById("direction-select").value = state.direction || "";
document.getElementById("rtl-check").checked = !!state.rtl;
@@ -1116,8 +1117,8 @@ async function checkStatus() {
if (state.position) {
options.position = state.position;
}
if (state.timeout) {
options.timeout = parseInt(state.timeout);
if (state.timeout !== undefined && state.timeout !== "") {
options.timeout = state.timeout;
}
if (state.theme) {
options.theme = state.theme;
@@ -1153,8 +1154,9 @@ async function checkStatus() {
if (state.position) {
lines.push(`${indent} ->option('position', '${state.position}')`);
}
if (state.timeout) {
lines.push(`${indent} ->option('timeout', ${state.timeout})`);
if (state.timeout !== undefined && state.timeout !== "") {
const timeoutValue = state.timeout === false ? 'false' : state.timeout;
lines.push(`${indent} ->option('timeout', ${timeoutValue})`);
}
if (state.direction) {
lines.push(`${indent} ->option('direction', '${state.direction}')`);
@@ -1311,8 +1313,8 @@ async function checkStatus() {
if (state.position) {
options.position = state.position;
}
if (state.timeout) {
options.timeout = parseInt(state.timeout);
if (state.timeout !== undefined && state.timeout !== "") {
options.timeout = state.timeout;
}
if (state.direction) {
options.direction = state.direction;
@@ -1324,6 +1326,8 @@ async function checkStatus() {
options.escapeHtml = state.escapeHtml;
}
console.log("Showing notification with options:", options);
try {
if (typeof flasher !== "undefined") {
if (state.theme) {
@@ -1380,7 +1384,13 @@ async function checkStatus() {
state.position = e.target.value;
});
document.getElementById("timeout-select").addEventListener("change", (e) => {
state.timeout = e.target.value ? parseInt(e.target.value) : "";
if (e.target.value === "false") {
state.timeout = false;
} else if (e.target.value) {
state.timeout = parseInt(e.target.value);
} else {
state.timeout = "";
}
});
document.getElementById("theme-select").addEventListener("change", (e) => {
state.theme = e.target.value;
+2 -2
View File
@@ -2,10 +2,10 @@
"entrypoints": {
"main": {
"css": [
"/dist/main.cfa0ed56.css"
"/dist/main.98f9c826.css"
],
"js": [
"/dist/main.896f6a93.js"
"/dist/main.8b056786.js"
]
}
}
File diff suppressed because one or more lines are too long
+1
View File
File diff suppressed because one or more lines are too long
-1
View File
File diff suppressed because one or more lines are too long
+38 -2
View File
@@ -60,6 +60,7 @@ export default class FlasherPlugin extends AbstractPlugin {
*/
private options: FlasherPluginOptions = {
// Default or type-specific timeout (milliseconds, null = use type-specific)
// Use false for sticky notifications, or any negative number
timeout: null,
// Type-specific timeout durations
@@ -132,7 +133,7 @@ export default class FlasherPlugin extends AbstractPlugin {
const mergedOptions = {
...this.options,
...envelope.options,
timeout: envelope.options.timeout ?? typeTimeout,
timeout: this.normalizeTimeout(envelope.options.timeout ?? typeTimeout),
escapeHtml: (envelope.options.escapeHtml ?? this.options.escapeHtml) as boolean,
}
@@ -271,12 +272,47 @@ export default class FlasherPlugin extends AbstractPlugin {
})
}
// Add timer if timeout is specified
// Add timer if timeout is greater than 0 (not sticky)
if (options.timeout > 0) {
this.addTimer(notification, options)
} else {
// For sticky notifications, we might want to add a class
notification.classList.add('fl-sticky')
// For sticky notifications with progress bar, set it to full width
const progressBarContainer = notification.querySelector('.fl-progress-bar')
if (progressBarContainer) {
// Create progress bar element that stays at 100%
const progressBar = document.createElement('span')
progressBar.classList.add('fl-progress', 'fl-sticky-progress')
progressBar.style.width = '100%'
progressBarContainer.append(progressBar)
}
}
}
/**
* Normalizes timeout value to handle different formats (number, boolean, null)
*
* @param timeout - The timeout value to normalize
* @returns A number representing milliseconds, or 0 for sticky notifications
* @private
*/
private normalizeTimeout(timeout: any): number {
// Handle false or negative numbers as sticky notifications (0)
if (timeout === false || (typeof timeout === 'number' && timeout < 0)) {
return 0
}
// Handle null or undefined
if (timeout == null) {
return 0
}
// Convert to number (handles string numbers too)
return Number(timeout) || 0
}
/**
* Adds a progress timer to the notification.
*
@@ -31,7 +31,6 @@
* For languages that read from right to left
*/
&.fl-rtl {
direction: rtl;
text-align: right;
}
}
@@ -78,8 +78,6 @@
*/
@mixin rtl-support {
&.fl-rtl {
direction: rtl;
.fl-content {
flex-direction: row-reverse;
}
+1 -1
View File
@@ -365,7 +365,7 @@ export type FlasherPluginOptions = {
* Default timeout in milliseconds (0 for no timeout).
* Set to null to use type-specific timeouts.
*/
timeout: number | null
timeout: number | boolean | null
/** Type-specific timeouts in milliseconds */
timeouts: Record<string, number>
+1
View File
@@ -9,6 +9,7 @@ export default class FlasherPlugin extends AbstractPlugin {
renderOptions(options: Options): void;
private createContainer;
private addToContainer;
private normalizeTimeout;
private addTimer;
private removeNotification;
private stringToHTML;
+20 -1
View File
@@ -153,7 +153,7 @@ class FlasherPlugin extends AbstractPlugin {
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 mergedOptions = Object.assign(Object.assign(Object.assign({}, this.options), envelope.options), { timeout: this.normalizeTimeout((_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,
@@ -225,6 +225,25 @@ class FlasherPlugin extends AbstractPlugin {
if (options.timeout > 0) {
this.addTimer(notification, options);
}
else {
notification.classList.add('fl-sticky');
const progressBarContainer = notification.querySelector('.fl-progress-bar');
if (progressBarContainer) {
const progressBar = document.createElement('span');
progressBar.classList.add('fl-progress', 'fl-sticky-progress');
progressBar.style.width = '100%';
progressBarContainer.append(progressBar);
}
}
}
normalizeTimeout(timeout) {
if (timeout === false || (typeof timeout === 'number' && timeout < 0)) {
return 0;
}
if (timeout == null) {
return 0;
}
return Number(timeout) || 0;
}
addTimer(notification, { timeout, fps }) {
if (timeout <= 0) {
+20 -1
View File
@@ -159,7 +159,7 @@
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 mergedOptions = Object.assign(Object.assign(Object.assign({}, this.options), envelope.options), { timeout: this.normalizeTimeout((_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,
@@ -231,6 +231,25 @@
if (options.timeout > 0) {
this.addTimer(notification, options);
}
else {
notification.classList.add('fl-sticky');
const progressBarContainer = notification.querySelector('.fl-progress-bar');
if (progressBarContainer) {
const progressBar = document.createElement('span');
progressBar.classList.add('fl-progress', 'fl-sticky-progress');
progressBar.style.width = '100%';
progressBarContainer.append(progressBar);
}
}
}
normalizeTimeout(timeout) {
if (timeout === false || (typeof timeout === 'number' && timeout < 0)) {
return 0;
}
if (timeout == null) {
return 0;
}
return Number(timeout) || 0;
}
addTimer(notification, { timeout, fps }) {
if (timeout <= 0) {
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -39,7 +39,7 @@ export type Asset = {
type: AssetType;
};
export type FlasherPluginOptions = {
timeout: number | null;
timeout: number | boolean | null;
timeouts: Record<string, number>;
fps: number;
position: string;
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long