Source: public/src/hooks/modal.js

/** @module hooks/modal */

import { hooks } from '../util';
import wp from 'wp';
import $ from 'jquery';

/**
 * When there is a new attachments browser in modal view then
 * prepare the media view for the AppTree container.
 */
hooks.register('attachmentsBrowser/modal', function() {
    // Wait the menu, it will immmediatly created
    setTimeout(() => {
        const { parent } = this.views,
            { views } = parent,
            [ mediaMenu ] = views.get('.media-frame-menu');
        let container = mediaMenu.views.get().filter(v => v.className === 'rml-modal-container');
        container && container.length && (container = container[0]) || (container = undefined);
            
        if (!container) {
            // Add seperator
            mediaMenu.views.add(new wp.media.View({
                className: 'separator'
            }));
            
            // Add ReactJS container
            container = new wp.media.View({
                className: "rml-modal-container"
            });
            mediaMenu.views.add(container);
        }
        
        // Always enable the menu
        this.controller.state().set('menu', true, { silent: true });
        parent.$el.addClass('rml-media-modal').removeClass('hide-menu');
        
        /**
         * A modal attachments browser is created and the view for the
         * React element is ready.
         * 
         * @event module:util/hooks#attachmentsBrowser/modal/dom/ready
         * @param {object} container The backbone view
         * @this wp.media.view.AttachmentsBrowser
         */
        hooks.call('attachmentsBrowser/modal/dom/ready', [container], this);
        
        setTimeout(() => $(window).trigger('resize'), 0);
    }, 50);
});

/**
 * The sortable state gets refreshed so check if we have to destroy the
 * draggable instance.
 * 
 * @returns {boolean}
 */
function isAttachmentsBrowserSortable(element) {
    return !element.attachmentsBrowser.attachments.$el.sortable('option', 'disabled');
}

/**
 * When a tree gets initialized then check if it is a modal and
 * modify the state.
 */
hooks.register('tree/init', function(state, { isModal }) {
    if (isModal) {
        state.isResizable = false,
        state.isSticky = false;
        state.isStickyHeader = false;
        state.isFullWidth = true;
        
        // Update WP attachment sort mode and disable the draggable items
        state.isWPAttachmentsSortMode = isAttachmentsBrowserSortable(this);
        this.attachmentsBrowser.collection.props.on('change:orderby', () => this.setState({
            isWPAttachmentsSortMode: isAttachmentsBrowserSortable(this)
        }));
    }
});

/**
 * When the window gets resized check the flexible modal containers
 * for responsiveness.
 */
$(() => $(window).resize(function() {
    $('.rml-modal-container .aiot-pad > div:nth-child(2)').each(function() {
        const parent = $(this).parents('.rml-media-modal'),
            menu = parent.find('.media-frame-menu .media-menu'),
            menuHeight = menu.get(0).offsetHeight,
            oppositeHeight = menu.children(':not(.rml-modal-container)').get().map(c => c.offsetHeight).reduce((a,b) => a + b, 0);
        if (menuHeight - oppositeHeight > 300) {
            parent.removeClass('rml-mobile-modal');
        }else{
            parent.addClass('rml-mobile-modal');
        }
    });
}));