Skip to content

Commit

Permalink
feat: added minimal library functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexandrshy committed Jun 7, 2020
1 parent 29577d6 commit 6d06831
Show file tree
Hide file tree
Showing 6 changed files with 7,254 additions and 8 deletions.
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "keukenhof",
"version": "1.0.0",
"description": "GitHub template for starting new projects",
"description": "Lightweight modal library 🌷",
"main": "./dist/index.js",
"module": "./dist/index.es.js",
"types": "./dist/index.d.ts",
Expand All @@ -15,9 +15,10 @@
"author": "Alex Shualev <alexandrshy@gmail.com>",
"license": "MIT",
"keywords": [
"template",
"javascript",
"package"
"modal",
"dialog",
"popup"
],
"bugs": {
"url": "https://github.com/Alexandrshy/keukenhof/issues"
Expand Down Expand Up @@ -72,4 +73,4 @@
"semantic-release": "^17.0.7",
"typescript": "^3.9.3"
}
}
}
4 changes: 4 additions & 0 deletions src/consts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const ATTRIBUTES = {
OPEN: 'data-keukenhof-open',
CLOSE: 'data-keukenhof-close',
};
136 changes: 132 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,133 @@
export const log = (a: string): string => {
console.log('a:', a);
import {ConfigType, ModalType, KeukenhofType} from './types';
import {ATTRIBUTES} from './consts';

return a;
};
export const Keukenhof = ((): KeukenhofType => {
/**
* Modal window
*/
class Modal {
$modal: HTMLElement | null;
openAttribute: string;
closeAttribute: string;
openClass: string;

/**
* Modal constructor
*
* @param {ConfigType} param - config
*/
constructor({
selector = '',
triggers = [],
openAttribute = ATTRIBUTES.OPEN,
closeAttribute = ATTRIBUTES.CLOSE,
openClass = 'isOpen',
}: ConfigType) {
this.$modal = document.querySelector(selector);
this.openAttribute = openAttribute;
this.closeAttribute = closeAttribute;
this.openClass = openClass;

this.registerNodes(triggers);

this.onClick = this.onClick.bind(this);
}

/**
* Add handlers for clicking on elements to open related modal windows
*
* @param {Array} nodeList - list of elements for opening modal windows
*/
registerNodes(nodeList: HTMLElement[]) {
nodeList
.filter(Boolean)
.forEach((element) =>
element.addEventListener('click', (event) => this.open(event)),
);
}

/**
* Open moda window
*/
open() {
this.$modal?.classList.add(this.openClass);
this.addEventListeners();
}

/**
* Close modal window
*/
close() {
this.$modal?.classList.remove(this.openClass);
this.removeEventListeners();
}

/**
* Click handler
*
* @param {object} event - Event data
*/
onClick(event: Event) {
if ((event.target as Element).closest(`[${this.closeAttribute}]`)) this.close();
}

/**
* Add event listeners for an open modal
*/
addEventListeners() {
this.$modal?.addEventListener('touchstart', this.onClick);
this.$modal?.addEventListener('click', this.onClick);
}

/**
* Remove event listener for an open modal
*/
removeEventListeners() {
this.$modal?.removeEventListener('touchstart', this.onClick);
this.$modal?.removeEventListener('click', this.onClick);
}
}

let modal: ModalType;

/**
* Create a map for registering modal windows
*
* @param {Array} nodeList - list of items
* @param {string} attribute - selector for opening
* @returns {object} - nodes map
*/
const createRegisterMap = (nodeList: HTMLElement[], attribute: string) => {
return nodeList.reduce((acc: {[key: string]: HTMLElement[]}, element: HTMLElement): {
[key: string]: HTMLElement[];
} => {
const attributeValue = element.getAttribute(attribute);
if (!attributeValue) return acc;
if (!acc[attributeValue]) acc[attributeValue] = [];
acc[attributeValue].push(element);
return acc;
}, {});
};

/**
* Initialize modal windows according to markup
*
* @param {ConfigType} config - modal window configur
*/
const init = (config?: ConfigType) => {
const options = {openAttribute: ATTRIBUTES.OPEN, ...config};
const nodeList = document.querySelectorAll<HTMLElement>(`[${options.openAttribute}]`);
const registeredMap = createRegisterMap(Array.from(nodeList), options.openAttribute);

for (const selector in registeredMap) {
const value = registeredMap[selector];
options.selector = selector;
options.triggers = [...value];
modal = new Modal(options);
}
};

return {init};
})();

window.Keukenhof = Keukenhof;
16 changes: 16 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export type ConfigType = {
selector?: string;
triggers?: HTMLElement[];
openAttribute?: string;
closeAttribute?: string;
openClass?: string;
};

export type ModalType = {
open: (event: Event) => void;
close: (event: Event) => void;
};

export type KeukenhofType = {
init: (config?: ConfigType) => void;
};
5 changes: 5 additions & 0 deletions typeScript/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
interface Window {
Keukenhof: {
init: (config?: any) => void;
};
}
Loading

0 comments on commit 6d06831

Please sign in to comment.