activator-oce-exporter
Version:
Extract Activator binder and convert it to valid OCE mono pacakge
367 lines (330 loc) • 8.53 kB
JavaScript
import { html } from '@polymer/lit-element';
import { FusionBase } from '../../base';
import { FusionApi } from '../../api';
import { FusionLogger } from '../../services/fusion-logger';
import { applyMixins, SlideComponent } from '../../mixins';
class FusionAction extends applyMixins(FusionBase, [SlideComponent]) {
static get animationAttr() {
return 'data-anijs';
}
static get properties() {
return {
if: {
type: String,
fieldType: 'Select',
value: 'click',
selectOptions: [
'click',
'dblclick',
'enter',
'exit',
'focus',
'blur',
'scroll',
'animationstart',
'animationend',
'transitionstart',
'transitionend',
'dragstart',
'drag',
'dragend',
'loadNotification',
'$custom',
],
},
on: {
type: String,
fieldType: 'Select',
value: 'root',
selectOptions: [
'root',
'$element',
'notifier',
],
},
to: {
type: String,
fieldType: 'Select',
value: '',
selectOptions: [
'target',
'$element',
'$parent',
'$closest',
'$find',
'$children',
'$slide',
'$binder',
],
},
do: {
type: String,
fieldType: 'Select',
value: '',
selectOptions: [
'$navigate',
'$next',
'$previous',
'toggleActivation',
'activate',
'inactivate',
'$applyState',
'$removeState',
'$toggleState',
'$setStates',
'nextState',
'previousState',
// '$clone',
// '$remove',
'bounce',
'fadeIn',
'fadeOut',
'pulse',
'slideInLeft',
'slideInRight',
// '$addClass',
// '$removeClass',
// '$toggleClass',
],
},
binder: {
type: String,
fieldType: 'String',
value: '',
},
slide: {
type: String,
fieldType: 'String',
value: '',
},
state: {
type: String,
fieldType: 'String',
value: '',
},
width: {
type: String,
fieldType: 'Number',
value: '1px',
},
height: {
type: String,
fieldType: 'Number',
value: '1px',
},
};
}
static get options() {
return {
componentName: 'fusion-action',
componentUIName: 'Action',
componentScope: 'standard',
componentType: 'system',
componentCategory: 'other',
componentDescription: 'Adds interactions and animations to components and other elements',
componentDomain: 'slide',
isTextEdit: false,
isRootNested: false,
nestedTypes: [],
nestedComponents: [],
isAction: true,
defaultTemplate: '',
goToProps: {
binder: '',
slide: '',
},
stateProps: {
state: '',
},
};
}
static get SUPPORTED_METHODS() {
return {
enter: '_open',
exit: '_close',
toggleActivation: '_toggleActivation',
nextState: '_nextState',
previousState: '_previousState',
$applyState: '_applyState',
$removeState: '_removeState',
$toggleState: '_toggleState',
$setStates: '_setStates',
$navigate: '_navigate',
$next: '_next',
$previous: '_previous',
};
}
static get SUPPORTED_ANIMATIONS() {
return [
'bounce',
'fadeIn',
'fadeOut',
'pulse',
'slideInLeft',
'slideInRight',
];
}
async createBehavior() {
const todo = FusionAction.getAction(this.do);
const actionHandler = FusionAction.getActionHandler(todo[0]);
let target = this.getTarget();
// Translate into AniJS strings
// @todo simplify this logic
if (this.if === 'loadNotification') {
this.if = 'onRunFinished';
}
if (this.on === 'notifier') {
this.on = '$AniJSNotifier';
}
if (this.on === '$AniJSNotifier') {
target = true;
}
if (target && actionHandler) {
this.listenerHandler = this[actionHandler].bind(this);
if (this.if === 'onRunFinished') {
await this.untilPublished;
this.listenerHandler();
} else {
target.addEventListener(this.if, (e) => {
this.listenerHandler();
e.stopPropagation();
});
this.removeAnimation();
}
} else if (target) {
this.setAnimation();
} else {
FusionLogger.error(`Target not found: ${this.on}`, 'fusion-action');
}
}
getTargetFromRoot(root) {
if (this.isInnerShadowRootAction()) {
root = this.getRootNode();
}
return root.querySelector(this.on);
}
isRootTarget() {
return this.on === 'root';
}
isInnerShadowRootAction() {
const actionTarget = document.querySelector(this.on);
// NOTE: should be `getElementById` because `.contains` doesn't work on iPad
return !document.contains(actionTarget) && !document.getElementById(this.id);
}
getTarget() {
const root = FusionApi.getRootNode();
return this.isRootTarget() ? root : this.getTargetFromRoot(root);
}
static getAction(todo) {
return todo.split(' ');
}
static getActionHandler(todo) {
return FusionAction.SUPPORTED_METHODS[todo];
}
isAnimation() {
return window.AniJS && this.getAttribute(FusionAction.animationAttr);
}
async setAnimation() {
const attrValue = `if: ${this.if}, on: ${this.on}, do: ${this.do} animated, to: ${this.to}`;
if (attrValue !== this.getAttribute(FusionAction.animationAttr)) {
this.setAttribute(FusionAction.animationAttr, attrValue);
await this.untilPublished;
FusionApi.saveAttributes(`#${this.id}`, { [FusionAction.animationAttr]: attrValue });
}
}
removeAnimation() {
if (this.isAnimation()) {
this.removeAttribute(FusionAction.animationAttr);
FusionApi.saveAttributes(`#${this.id}`, { [FusionAction.animationAttr]: '' });
}
}
removeListener() {
if (this.listenerHandler) {
const target = this.getTarget();
target.removeEventListener(this.if, this.listenerHandler);
}
}
isActionChanged(changedProps) {
return this.do && changedProps.get('do');
}
isStateChanged(changedProps) {
return this.state && changedProps.get('state');
}
changeHandler(changedProps) {
const doValue = changedProps.get('do') || this.do;
const oldAction = FusionAction.getAction(doValue)[0];
if (FusionAction.getActionHandler(oldAction)) {
this.removeListener();
}
}
update(changedProps) {
super.update(changedProps);
if (this.isActionChanged(changedProps) || this.isStateChanged(changedProps)) {
this.changeHandler(changedProps);
}
this.createBehavior();
}
disconnectedCallback() {
super.disconnectedCallback();
this.removeListener();
}
_applyState() {
this.pushState(this.state, '', false);
}
_removeState() {
this.removeState(this.state, '', false);
}
_toggleState() {
FusionApi.toggleState(this.state, '');
}
_setStates() {
this.setStates(this.state, '', false);
}
_nextState() {
this.nextState();
}
_previousState() {
this.previousState();
}
_navigate() {
FusionApi.goTo(this.slide, this.binder);
}
_next() {
FusionApi.goTo(this.slide, this.binder, 'next');
}
_previous() {
FusionApi.goTo(this.slide, this.binder, 'previous');
}
// Activate a stateful element
_open() {
const el = document.querySelector(this.to);
if (el && el.activate) el.activate();
this.emitCustomEvent('activateStateful');
}
// Inactivate a stateful element
_close() {
const el = document.querySelector(this.to);
if (el && el.inactivate) el.inactivate();
}
// Toggle activation in stateful element
_toggleActivation() {
const el = document.querySelector(this.to);
if (el && el.inactivate && el.activate) {
if (el.active) {
this.emitCustomEvent('inactivateStateful');
el.inactivate();
} else {
this.emitCustomEvent('activateStateful');
el.activate();
}
}
}
_createRoot() {
return this;
}
render() {
super.render();
return html``;
}
}
export { FusionAction };