zextra
Version:
zikojs extra components
192 lines (187 loc) • 6 kB
JavaScript
import { UIElement } from 'ziko/dom'
// import { add_vendor_prefix } from 'ziko/dom/utils/index.js'
// import { register_click_away_event } from 'ziko/events/custom-events/click-away.js'
// import { register_swipe_event } from 'ziko/events/custom-events/swipe.js'
import {
add_class,
remove_class
} from './utils/index.js'
import {
setup_positions
} from './setup/index.js'
class UIMeny extends UIElement {
constructor(menu, contents, {
width= 300,
height= 300,
position= UIMeny.POSITION_L,
threshold= 40,
angle= 30,
overlap= 6,
transitionDuration= '0.5s',
transitionEasing= 'ease',
gradient= 'rgba(0,0,0,0.20) 0%, rgba(0,0,0,0.65) 100%)',
}= {}
){
super({element : 'div', name : 'meny'})
this.menu = menu.style({
opacity : 0
});
add_class(this.menu.element, 'zextra-meny')
this.contents = contents
this.cover = null
this.dom = {
menu : menu.element,
contents : contents.element,
wrapper : this.element
}
// register_click_away_event(this.dom.menu)
this.dom.menu.addEventListener('clickaway', ()=> this.close())
// register_swipe_event(this.dom.wrapper)
this.dom.wrapper.addEventListener('swiperight', ()=> {
console.log(this.isOpen())
setTimeout(()=>this.open(), 0)
console.log('Open ...')
})
this.dom.wrapper.addEventListener('dblclick', ()=> this.toggle())
this.dom.wrapper.style.border = '2px red solid'
this.style({
userSelect: 'none',
touchAction: 'none'
})
this.append(menu, contents)
Object.assign(this.cache, {
config : {
width,
height,
position,
threshold,
angle,
overlap,
transitionDuration,
transitionEasing,
gradient,
},
state : {
is_open : false,
},
transform : {
menu_origin : '',
menu_closed : '',
menu_opened : '',
contents_origin : '',
contents_closed : '',
contents_opend : ''
}})
this.originalStyles = {};
this.init();
}
init() {
setup_positions.call(this)
this.setupWrapper();
this.setupCover();
this.setupMenu();
this.setupContents();
}
setupWrapper() {
add_class(this.dom.wrapper, `zextra-meny-${this.cache.config.position}`);
this.originalStyles.wrapper = this.dom.wrapper.style.cssText;
// this.dom.wrapper.style[add_vendor_prefix('perspective')] = '800px';
// this.dom.wrapper.style[add_vendor_prefix('perspectiveOrigin')] = this.cache.transform.contents_origin;
}
setupCover() {
if(this.dom.cover) this.dom.cover.parentNode.removeChild(this.dom.cover);
this.dom.cover = document.createElement('div');
Object.assign(this.dom.cover.style, {
position: 'absolute',
display: 'block',
width: '100%',
height: '100%',
left: '0',
top: '0',
zIndex: '1000',
visibility: 'hidden',
opacity: '0',
[add_vendor_prefix('transition')] : `all ${this.cache.config.transitionDuration} ${this.cache.config.transitionEasing}`
});
this.dom.contents.appendChild(this.dom.cover);
}
setupMenu() {
switch(this.cache.config.position) {
case 'top': Object.assign(this.dom.menu.style, {
width : '100%',
height : `${this.cache.config.height}px`
}); break;
case 'right': Object.assign(this.dom.menu.style, {
right : '0',
width : `${this.cache.config.width}px`,
height : '100%'
}); break;
case 'bottom': Object.assign(this.dom.menu.style, {
bottom : '0',
width : '100%',
height : `${this.cache.config.height}px`
}); break;
case 'left': Object.assign(this.dom.menu.style,{
width : `${this.cache.config.width}px`,
height : '100%'
}); break;
}
this.originalStyles.menu = this.dom.menu.style.cssText;
Object.assign(this.dom.menu.style, {
position: 'fixed',
display: 'block',
zIndex: '1'
});
this.dom.menu.style[add_vendor_prefix('transform')] = this.cache.transform.menu_closed;
this.dom.menu.style[add_vendor_prefix('transformOrigin')] = this.cache.transform.menu_origin;
this.dom.menu.style[add_vendor_prefix('transition')] = `all ${this.cache.config.transitionDuration} ${this.cache.config.transitionEasing}`;
}
setupContents() {
const style = this.dom.contents.style;
this.originalStyles.contents = style.cssText;
Object.assign(this.dom.contents.style,{
[add_vendor_prefix('transform')] : this.cache.transform.contents_closed,
[add_vendor_prefix('transformOrigin')] : this.cache.transform.contents_origin,
[add_vendor_prefix('transition')] : `all ${this.cache.config.transitionDuration} ${this.cache.config.transitionEasing}`
})
}
open() {
if(!this.isOpen()) {
this.cache.state.is_open = true;
add_class(this.dom.wrapper, 'zextra-meny-active');
this.dom.cover.style.height = `${this.dom.contents.scrollHeight}px`;
this.dom.cover.style.visibility = 'visible';
this.dom.cover.style.opacity = '1';
this.dom.contents.style[add_vendor_prefix('transform')] = this.cache.transform.contents_opened;
this.dom.menu.style[add_vendor_prefix('transform')] = this.cache.transform.menu_opened;
this.menu.style({
opacity : 1
})
}
}
close() {
if(this.isOpen()) {
this.cache.state.is_open = false;
remove_class(this.dom.wrapper, 'zextra-meny-active');
this.dom.cover.style.visibility = 'hidden';
this.dom.cover.style.opacity = '0';
this.dom.contents.style[add_vendor_prefix('transform')] = this.cache.transform.contents_closed;
this.dom.menu.style[add_vendor_prefix('transform')] = this.cache.transform.menu_closed;
this.menu.style({
opacity : 0
})
}
}
toggle(){
this.isOpen() ? this.close() : this.open();
return this;
}
isOpen() {
return this.cache.state.is_open;
}
}
const Meny = (menu, contents, options) => new UIMeny(menu, contents, options)
export{
UIMeny,
Meny
}