Giter Club home page Giter Club logo

Comments (7)

ToshY avatar ToshY commented on September 26, 2024 1

I've found out the problem:

  1. Both @flasher/flasher and @flasher/flasher-sweetalert contain CSS imports in the JS files, causing it to add 2 additional styling elements to the DOM: one for .fl-main-container and one for .swal2-popup.swal2-toast.
  2. @flasher/flasher-sweetalert has import Swal from 'sweetalert2', which adds another additional style element to the DOM.
    • This is why I initially had a total of 3 additional .swal2-popup.swal2-toast style elements.
    • This should (for minified version) be import Swal from 'sweetalert2/src/sweetalert2.min' instead.

What "worked" in the meantime was extracting partial contents from flasher-sweetalert/dist/index.js to create the SweetAlertFactory, and pass that to flasher.

main.js
import flasher from "@flasher/flasher";
var __assign = function() {
    __assign = Object.assign || function __assign(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};

function __awaiter(thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
}

function __generator(thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (g && (g = 0, op[0] && (_ = 0)), _) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
}

var SweetAlertFactory = (function () {
    function SweetAlertFactory() {
        this.queue = [];
    }
    SweetAlertFactory.prototype.success = function (message, title, options) {
        this.flash('success', message, title, options);
    };
    SweetAlertFactory.prototype.info = function (message, title, options) {
        this.flash('info', message, title, options);
    };
    SweetAlertFactory.prototype.warning = function (message, title, options) {
        this.flash('warning', message, title, options);
    };
    SweetAlertFactory.prototype.error = function (message, title, options) {
        this.flash('error', message, title, options);
    };
    SweetAlertFactory.prototype.flash = function (type, message, title, options) {
        var notification = this.createNotification(type, message, title, options);
        this.renderOptions({});
        this.render({ notification: notification });
    };
    SweetAlertFactory.prototype.createNotification = function (type, message, title, options) {
        if (typeof type === 'object') {
            options = type;
            type = options.type;
        }
        if (typeof message === 'object') {
            options = message;
            message = options.message;
        }
        if (typeof title === 'object') {
            options = title;
            title = options.title;
        }
        if (undefined === message) {
            throw new Error('message option is required');
        }
        return {
            type: type || 'info',
            message: message,
            title: title,
            options: options
        };
    };
    SweetAlertFactory.prototype.render = function (envelope) {
        var _a;
        var notification = envelope.notification;
        var options = notification.options;
        notification.type = notification.type || 'info';
        options = __assign(__assign({}, options), { icon: ((options === null || options === void 0 ? void 0 : options.icon) || notification.type), text: ((options === null || options === void 0 ? void 0 : options.text) || notification.message) });
        return (_a = this.swalToastr) === null || _a === void 0 ? void 0 : _a.fire(options).then(function (promise) {
            window.dispatchEvent(new CustomEvent('flasher:sweetalert:promise', {
                detail: {
                    promise: promise,
                    envelope: envelope
                }
            }));
        });
    };
    SweetAlertFactory.prototype.renderOptions = function (options) {
        this.swalToastr = this.swalToastr || Swal.mixin(__assign({ timer: (options.timer || 5000), timerProgressBar: (options.timerProgressBar || true) }, options));
        document.addEventListener('turbo:before-cache', function () {
            var _a;
            if (Swal.isVisible()) {
                (_a = Swal.getPopup()) === null || _a === void 0 ? void 0 : _a.style.setProperty('animation-duration', '0ms');
                Swal.close();
            }
        });
    };
    SweetAlertFactory.prototype.addEnvelope = function (envelope) {
        var _a;
        (_a = this.queue) === null || _a === void 0 ? void 0 : _a.push(envelope);
    };
    SweetAlertFactory.prototype.resetQueue = function () {
        this.queue = [];
    };
    SweetAlertFactory.prototype.renderQueue = function () {
        return __awaiter(this, void 0, void 0, function () {
            var i;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        i = 0;
                        _a.label = 1;
                    case 1:
                        if (!(i < this.queue.length)) return [3, 4];
                        return [4, this.render(this.queue[i])];
                    case 2:
                        _a.sent();
                        _a.label = 3;
                    case 3:
                        i++;
                        return [3, 1];
                    case 4: return [2];
                }
            });
        });
    };
    return SweetAlertFactory;
}());

flasher.addFactory("sweetalert",  new SweetAlertFactory());
global.flasher = flasher;

Now if I add @sweetalert2/theme-dark and import it, it shows the correctly styled dark SweetAlert2 toast. The additional inline CSS is no longer there, but the flasher inline style tag (with .fl-main-container) is still in the DOM (as I could not easily figure out how to extract that part).


This is a really convoluted workaround for a problem which could be solved if the JS did not contain any CSS imports.

@yoeunes I propose to separate JS and CSS for all the packages (not just SweetAlert2).

from flasher-js.

yoeunes avatar yoeunes commented on September 26, 2024 1

Hey @ToshY 👋,

I wanted to reach out and let you know that I've just released v1.15.1 which I believe resolves the issue we've been discussing. Now, you'll find much more flexibility to adjust and override PHPFlasher styles in a way that aligns better with your specific needs.

You can find a demo here. I truly hope you'll find this update beneficial!

I apologize if this took a bit longer than anticipated. Balancing my regular commitments with open-source work sometimes stretches my time a bit thin, but your patience is genuinely appreciated.

Please don't hesitate to dive into the demo and the updated version. I'm eager to hear your thoughts and any feedback you might have to improve this solution.

from flasher-js.

ToshY avatar ToshY commented on September 26, 2024 1

Hello @yoeunes 👋

I've looked at the demo and it's easy to understand, and while it doesn't fully correspond to my use case, after updating flasher to v1.15.1 I no longer have additional styles in the DOM and the dark styling is now correctly applied.

Please don't hesitate to dive into the demo and the updated version. I'm eager to hear your thoughts and any feedback you might have to improve this solution.

My use case is slightly different as I already had SweetAlert2 in my application (I'm not sure if this was clear from the initial problem statement). Therefore I also initially had the scripts and basic styles imported (in assets/js/main.js and asssets/styles/global.scss resp.) for SweetAlert and were already getting bundled by webpack.

Maybe seeing some code makes more sense than the explanation above so I will post my simplified setup here for you (and possible future readers).

assets/js/main.js
// SweetAlert (which was already being used in the application)
import Swal from 'sweetalert2/dist/sweetalert2.min' //note: this contains only JS
global.Swal = Swal;

// Flasher
import flasher from "@flasher/flasher";
import sweetalert from '@flasher/flasher-sweetalert';
flasher.addFactory("sweetalert", sweetalert);
global.flasher = flasher
assets/styles/global.scss
@import "~sweetalert2/dist/sweetalert2.min.css";
@import "~@sweetalert2/theme-dark/dark";
webpack.config.js
const Encore = require('@symfony/webpack-encore');

if (!Encore.isRuntimeEnvironmentConfigured()) {
    Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}

Encore
    .setOutputPath('public/build/')
    .setPublicPath('/build')
    .addEntry('js/app', './assets/js/main.js')
    .addStyleEntry('css/app', './assets/styles/global.scss')
    .splitEntryChunks()
    .enableSingleRuntimeChunk()
    .cleanupOutputBeforeBuild()
    .enableBuildNotifications()
    .enableSourceMaps(!Encore.isProduction())
    .enableVersioning(Encore.isProduction())
    .configureBabel((config) => {})
    .configureBabelPresetEnv((config) => {
        config.useBuiltIns = 'usage';
        config.corejs = 3;
    })
    .enableIntegrityHashes(Encore.isProduction())
    .autoProvidejQuery()
;

module.exports = Encore.getWebpackConfig();

Note: In contrary to the demo, I now don't have to manually .copyFiles for the dark theme as it was already imported in assets/styles/global.scss.

config/packages/flasher.yaml
flasher:
  default: sweetalert
  use_cdn: false
  auto_translate: true
  auto_render: true
  flash_bag:
    enabled: true
    mapping:
      success: [ 'success' ]
      error: [ 'error', 'danger' ]
      warning: [ 'warning', 'alarm' ]
      info: [ 'info', 'notice', 'alert' ]
  filter_criteria:
    limit: 5

  presets:
    login:
      type: 'info'
      message: 'Welcome back'
      options:
        toast: true
        position: bottom-end
        showConfirmButton: false
        timer: 30000

    logout:
      type: 'info'
      message: 'Have a nice day'
      options:
        toast: true
        position: bottom-end
        showConfirmButton: false
        timer: 30000

flasher_sweetalert:
  scripts: ~
  styles: ~

Note: In contrary to the demo, I now also don't have to set the styles key in flasher_sweetalert, as no additional files were copied.

Result (disregard the symfony debug icon):

image

In conclusion: it works now 🙂


I apologize if this took a bit longer than anticipated. Balancing my regular commitments with open-source work sometimes stretches my time a bit thin, but your patience is genuinely appreciated.

The effort you've put into it is also much appreciated 🥇

from flasher-js.

ToshY avatar ToshY commented on September 26, 2024

@yoeunes Could you take a look at this issue and care to discuss the proposal?

from flasher-js.

yoeunes avatar yoeunes commented on September 26, 2024

Hello @ToshY,

Thank you for reporting this issue and investigate it.

I will examine it over the weekend and make the necessary improvements to ensure a cleaner version.

If you have the time and would like to contribute, please feel free to create a merge request with your proposed changes. I would be glad to review it and merge it into the codebase.

Thank you for your patience and for helping improve the package.

Best regards,
Younes

from flasher-js.

ToshY avatar ToshY commented on September 26, 2024

Hey @yoeunes 👋

Thank you for the response.

I would help if I could, but this is somewhat beyond my comfort zone as I have zero experience with typescript (or how to even compile it) at the moment of writing. That being said, I'm open to manually testing the final (compiled) results if that would be of any help. 🙂

To further elaborate on the proposed solution: I think the least intensive approach (to not cause any breaking changes for existing application) would be to keep the existing files that contain both the JS and CSS (as you have now), and create additional files separating both of them1. That way newer applications, using Webpack or other bundlers, can benefit from separately importing the JS and CSS, which solves the main issue described here. Think SweetAlert2 takes a similar approach,

I'll await your next response after examination. Keep up the good work! PHP Flasher is really nice and easy to use 👍

Footnotes

  1. SweetAlert2 takes a similar approach.

from flasher-js.

yoeunes avatar yoeunes commented on September 26, 2024

Thank you for your feedback, I'm glad that everything is working now!

from flasher-js.

Related Issues (3)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.