Skip to content

Commit

Permalink
feat: rework esl-note
Browse files Browse the repository at this point in the history
  • Loading branch information
dshovchko committed Jun 16, 2021
1 parent a619d73 commit c709022
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 29 deletions.
4 changes: 4 additions & 0 deletions src/modules/esl-note/core/esl-note.less
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ esl-note {
&::after {
content: ']';
}

&[active] {
color: red;
}
}
129 changes: 100 additions & 29 deletions src/modules/esl-note/core/esl-note.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,43 @@
import {ExportNs} from '../../esl-utils/environment/export-ns';
import {attr, boolAttr, ESLBaseElement} from '../../esl-base-element/core';
import {bind} from '../../esl-utils/decorators/bind';
import {attr, boolAttr} from '../../esl-base-element/core';
import {ESLTrigger} from '../../esl-trigger/core';
import {ready} from '../../esl-utils/decorators/ready';
import {ESLTooltip} from '../../esl-tooltip/core';
import {ESLFootnotes} from '../../esl-footnotes/core/esl-footnotes';
import {EventUtils} from '../../esl-utils/dom/events';
import {ENTER, SPACE} from '../../esl-utils/dom/keys';
import {DeviceDetector} from '../../esl-utils/environment/device-detector';
import {ESLMediaQuery} from '../../esl-media-query/core';

import type {ToggleableActionParams} from '../../esl-toggleable/core/esl-toggleable';

@ExportNs('Note')
export class ESLNote extends ESLTrigger {
export class ESLNote extends ESLBaseElement {
static is = 'esl-note';
static eventNs = 'esl:note';

/** Linked state marker */
@boolAttr() public linked: boolean;

@attr({defaultValue: 'toggle'}) public mode: string;
/** @readonly Observed Toggleable active state marker */
@boolAttr({readonly: true}) public active: boolean;

/** Click event tracking media query. Default: `all` */
@attr({defaultValue: 'all'}) public trackClick: string;
/** Hover event tracking media query. Default: `all` */
@attr({defaultValue: 'all'}) public trackHover: string;

public target = 'body';

protected _$footnotes: ESLFootnotes | null;
protected _index: number;
protected _text: string;

constructor() {
super();
this._text = this.innerText;
/** Marker to allow track hover */
public get allowHover() {
return DeviceDetector.hasHover && ESLMediaQuery.for(this.trackHover).matches;
}
/** Marker to allow track clicks */
public get allowClick() {
return ESLMediaQuery.for(this.trackClick).matches;
}

get index(): number {
Expand All @@ -43,63 +52,125 @@ export class ESLNote extends ESLTrigger {
return this._text;
}

public static parseDelayValue2(delay: string): number | undefined {
return isNaN(+delay) ? undefined : +delay;
}

@ready
protected connectedCallback() {
this._text = this.innerText;

super.connectedCallback();

EventUtils.dispatch(this, `${ESLNote.eventNs}:ready`);
document.body.addEventListener(`${ESLFootnotes.eventNs}:ready`, this._handlerFootnotesReady);
this.bindEvents();
}

@ready
protected disconnectedCallback() {
super.disconnectedCallback();
this.unbindEvents();

if (this._$footnotes) {
this._$footnotes.unlinkNote(this);
}
}

link(footnotes: ESLFootnotes, index: number) {
protected bindEvents() {
this.addEventListener('click', this._onClick);
this.addEventListener('keydown', this._onKeydown);
this.addEventListener('mouseenter', this._onMouseEnter);
this.addEventListener('mouseleave', this._onMouseLeave);
}
protected unbindEvents() {
this.removeEventListener('click', this._onClick);
this.removeEventListener('keydown', this._onKeydown);
this.removeEventListener('mouseenter', this._onMouseEnter);
this.removeEventListener('mouseleave', this._onMouseLeave);
}

public link(footnotes: ESLFootnotes, index: number) {
this.linked = true;
this._$footnotes = footnotes;
this.index = index;
this.innerHTML = `${this.index}`;
this.tabIndex = 0;
}

unlink() {
public unlink() {
this.linked = false;
this._$footnotes = null;
this.innerText = this.text;
this.tabIndex = -1;
EventUtils.dispatch(this, `${ESLNote.eventNs}:ready`);
}

@bind
protected _handlerFootnotesReady(e: CustomEvent) {
if (!this.linked) {
EventUtils.dispatch(this, `${ESLNote.eventNs}:ready`);
}
/** Merge params to pass to the toggleable */
protected mergeToggleableParams(this: ESLNote, ...params: ToggleableActionParams[]) {
return Object.assign({
initiator: 'note',
activator: this
}, ...params);
}

/** Show target toggleable with passed params */
public showTarget(params: ToggleableActionParams = {}) {
/** Show tooltip with passed params */
public showTooltip(params: ToggleableActionParams = {}) {
const actionParams = this.mergeToggleableParams({
delay: ESLNote.parseDelayValue2(this.showDelay),
text: this.text,
behavior: 'none',
disableArrow: true,
// behavior: 'none',
// disableArrow: true,
}, params);
ESLTooltip.show(actionParams);
}

/** Hide target toggleable with passed params */
public hideTarget(params: ToggleableActionParams = {}) {
/** Hide tooltip with passed params */
public hideTooltip(params: ToggleableActionParams = {}) {
const actionParams = this.mergeToggleableParams({
delay: ESLNote.parseDelayValue2(this.hideDelay)
}, params);
ESLTooltip.hide(actionParams);
}
/** Toggles tooltip with passed params */
public toggleTooltip(params: ToggleableActionParams = {}, state: boolean = !this.active) {
state ? this.showTooltip(params) : this.hideTooltip(params);
}
/** Toggles note active state */
public updateState(newState: boolean) {
this.toggleAttribute('active', newState);
}

/** Handles `click` event */
@bind
protected _onClick(event: MouseEvent) {
if (!this.allowClick) return;
event.preventDefault();
return this.toggleTooltip({event});
}

/** Handles `keydown` event */
@bind
protected _onKeydown(event: KeyboardEvent) {
if (![ENTER, SPACE].includes(event.key)) return;
event.preventDefault();
return this.toggleTooltip({event});
}

/** Handles hover `mouseenter` event */
@bind
protected _onMouseEnter(event: MouseEvent) {
if (!this.allowHover) return;
this.showTooltip({event});
event.preventDefault();
}

/** Handles hover `mouseleave` event */
@bind
protected _onMouseLeave(event: MouseEvent) {
if (!this.allowHover) return;
this.hideTooltip({event, trackHover: true});
event.preventDefault();
}

@bind
protected _handlerFootnotesReady(e: CustomEvent) {
if (!this.linked) {
EventUtils.dispatch(this, `${ESLNote.eventNs}:ready`);
}
}

}

0 comments on commit c709022

Please sign in to comment.