import React from 'react';
/**
* @fileOverview Redux Layer Actions
* @namespace Actions/Layer
*/
/* !- React Elements */
import Modal from './modal';
import Preload from './preload';
import Menu from './menu';
/* !- Constants */
const extendPositions = ({ left, top, width, height }) =>
{
const positions = { width, height, center: {}, screen: {} };
positions.left = left + window.pageXOffset;
positions.top = top + window.pageYOffset;
positions.center.x = positions.left + (positions.width / 2);
positions.center.y = positions.top + (positions.height / 2);
positions.screen.x = (positions.left - window.pageXOffset) / window.innerWidth;
positions.screen.y = (positions.top - window.pageYOffset) / window.innerHeight;
return positions;
}
const getPositionsElement = (target) =>
{
if (!target)
{
return {};
}
const rect = target.getBoundingClientRect();
return extendPositions(rect)
};
const getDynamicPopoverStyle = (position) =>
{
const style = {};
const { screen, left, top, center, width, height } = position;
if (screen.x < 0.3)
{
style.left = left;
style.transform = '';
}
else if (screen.x > 0.7)
{
style.left = left + width;
style.transform = 'translateX(-100%)';
}
else
{
style.left = `${center.x}px`;
style.transform = 'translateX(-50%)';
}
if (screen.y > 0.6)
{
style.top = `${top - 6}px`;
style.transform += ' translateY(-100%)';
}
else
{
style.top = `${top + height + 6}px`;
}
return style;
};
/**
* Create and show dialog layer.
*
* @since 1.0.0
* @memberof Actions/Layer
* @param {ReactElement} element Layer (dialog) content
* @example
* dialog(
This is a dialog content
);
* @example
* //=> options
* {
* }
*/
export const dialog = (element: React.Element, options = {}) =>
({
type: 'SET_LAYER',
active: true,
method: 'dialog',
element,
options,
containerStyle: options.containerStyle,
});
/**
* Create and show fullscreen layer.
*
* @since 1.0.0
* @memberof Actions/Layer
* @param {ReactElement} element Layer (fullscreen) content
* @example
* fullscreen(This is a fullscreen content
);
*/
export const fullscreen = (element: React.Element, options = {}) =>
({
type: 'SET_LAYER',
active: true,
method: 'fullscreen',
element,
options,
containerStyle: options.containerStyle,
});
/**
* Create and show sidebar layer.
*
* @since 1.0.0
* @memberof Actions/Layer
* @param {ReactElement} element Layer (sidebar) content
* @example
* sidebar(This is a sidebar content
);
*/
export const sidebar = (element: React.Element, options = {}) =>
({
type: 'SET_LAYER',
active: true,
method: 'sidebar',
element,
containerStyle: options.containerStyle,
options: {
...options,
className: options.position || 'right',
},
});
/**
* Create and show popover layer.
*
* @since 1.0.0
* @memberof Actions/Layer
* @param {ReactElement} element Layer (popover) content
* @param {object} event
* @param {object} options { className, containerStyle, useMousePosition }
* @example
* popover(
* Hello,
* event,
* {
* className: 'no-close',
* containerStyle: { width: '400px' },
* useMousePosition: true,
* },
* );
*/
export const popover = (element: React.Element | string, event: {} = {}, options = {}) =>
{
let containerStyle = options.containerStyle || {};
const target = event.currentTarget;
if (target)
{
const position = options.useMousePosition ?
extendPositions({
left: event.clientX + window.pageXOffset,
top: event.clientY + window.pageYOffset,
width: 0,
height: 0,
})
: getPositionsElement(target);
containerStyle = { ...getDynamicPopoverStyle(position), ...containerStyle };
}
// console.log(target);
//
// if (!options.style)
// {
// options.style = {};
// }
//
// options.style.pointerEvents = 'none';
// containerStyle.pointerEvents = 'auto';
return ({
type: 'SET_LAYER',
active: true,
method: 'popover',
closeable: true,
containerStyle,
// if the element is a string then put in a wrapper
element: React.isValidElement(element) ?
element : {element}
,
options,
});
};
/**
* Create and show tooltip layer.
*
* @since 1.15.0
* @memberof Actions/Layer
* @param {ReactElement} element Layer (tooltip) content
* @param {object} event
*/
export const tooltip = (element: React.Element | string, event: {} = {}, options = {}) =>
{
return ({
...popover(element, event, options),
closeable: false,
options: {
...options,
className: 'tooltip',
}
});
};
/**
* Set the layer visible.
*
* @since 1.0.0
* @memberof Actions/Layer
* @example
* show();
* open();
*/
export const show = () =>
({
type: 'SET_LAYER_VISIBLE',
active: true,
});
/**
* Set the layer invisible.
*
* @since 1.0.0
* @memberof Actions/Layer
* @example
* hide();
*/
export const hide = () =>
({
type: 'SET_LAYER_VISIBLE',
active: false,
});
/**
* Toggle visibility of layer.
*
* @since 1.0.0
* @memberof Actions/Layer
* @example
* toggle();
*/
export const toggle = () =>
({
type: 'TOGGLE_LAYER',
});
/**
* Truncate layer state.
*
* @since 1.0.0
* @memberof Actions/Layer
* @example
* flush();
*/
export const flush = () =>
({
type: 'FLUSH_LAYER',
});
/* !- Predefined actions */
/**
* Modal is a predefined dialog layer. Do not use element, just Modal element props.
*
* @since 1.0.0
* @memberof Actions/Layer
* @param {Object} [props={}] icon, title, content, button, buttonSecondary, className,
* @example
* modal();
*/
export const modal = (props = {}, options = {}) =>
({
type: 'SET_LAYER',
active: true,
method: 'dialog',
element: ,
options,
containerStyle: options.containerStyle,
});
/**
* Preloader layer
* @since 1.0.0
* @memberof Actions/Layer
*
* @param {ReactElement} [element] change default element
* @example
* preload(Loading...
)
*/
export const preload = (element: React.Element, event: React.MouseEvent) =>
{
const target = event || React.isValidElement(element) ? null : element;
let containerStyle = {};
if (target)
{
const { center } = getPositionsElement(target.target);
containerStyle = {
top: `${center.y}px`,
left: `${center.x}px`,
};
}
return ({
type: 'SET_LAYER',
active: true,
method: 'preload',
closeable: false,
element: ,
// options: { className: 'preload' },
containerStyle,
});
};
/**
* Menu is a special popover
* @param {Object} [props={}] { id, title, handler, icon }
* @param {Event} event
*/
export const menu = (props = {}, event: React.MouseEvent | {} = {}, options = {}) =>
popover(, event, { ...options, className: 'no-padding no-close' });
export const contextMenu = (props = {}, event: React.MouseEvent | {} = {}, options = {}) =>
{
event.preventDefault();
return menu(props, event, options);
}
/* !- Alias actions */
export const open = show;
export const close = flush;