minsky-kit
Version:
Kit of components for MINSKY web agency
89 lines (68 loc) • 3.08 kB
JavaScript
// imports
import { strToDom } from '../utils/dom';
import { svgIconString } from '../utils/svg';
import { strToCssClass } from '../utils/css';
// methods
export function generateAccordionHtmlString (args, name = 'accordion') {
args = args || {};
// set id
const id = args.id ? args.id : (Date.now() * Math.round(Math.random() * 1000)).toString(32);
// set default title wrapper tag
const titleTag = args.titleTag || 'div';
// set classes
const classes = [
strToCssClass(name),
...(args.classes || []).map((str) => strToCssClass(str)),
];
// set aria
args.aria = args.aria || {};
const aria = {
expanded: args.aria.expanded || false,
titleId: `accordion-title-${id}`,
contentId: `accordion-content-${id}`,
};
// return element string
return `
<div data-accordion-id="${id}" class="${classes.join(' ')}">
<div class="${strToCssClass(name, 'title-wrapper')}">
<${titleTag} class="${strToCssClass(name, 'title')}">
<button type="button" aria-expanded="${aria.expanded}" aria-controls="${aria.contentId}" class="${strToCssClass(name, 'trigger')}" id="${aria.titleId}">${args.title} <div class="${strToCssClass(name, 'icon')} ${strToCssClass(name, 'arrow')}">${svgIconString(args.arrowSvg || 'chevronDown', [strToCssClass(name, 'arrowSvg')])}</div></button>
</${titleTag}>
</div>
<div id="${aria.contentId}" class="${strToCssClass(name, 'content-wrapper')}" role="region" aria-labelledby="${aria.titleId}" ${aria.expanded ? 'hidden' : ''}>
<div class="${strToCssClass(name, 'content')}">${args.content || ''}</div>
</div>
</div>
`.trim();
}
export function generateAccordionElement (args, name = 'accordion') {
// clone into new object so we can edit the properties without interfering with parent stack logic (shallow!)
args = { ...args || {} };
// extract title & content in case these are elements
const title = args.title;
const content = args.content;
// clear title & content
args.title = '';
args.content = '';
// generate dom element
const $el = strToDom(generateAccordionHtmlString(args, name));
// add title & content in case they were given
if (title) $el.querySelector(`.${strToCssClass(name, 'trigger')}`).append(title);
if (content) $el.querySelector(`.${strToCssClass(name, 'content')}`).append(content);
// return el
return $el;
}
export function removeAccordionElement (el, name = 'accordion') {
// extract all content components
const content = [...el.querySelectorAll(`.${strToCssClass(name, 'content')} > *`)];
// append every content before the accordion
if (content.length) content.forEach((item) => { el.parentNode.insertBefore(item, el); });
// remove el
el.remove();
return content.length && content.length === 1 ? content[0] : content;
}
export default {
generateAccordionHtmlString,
generateAccordionElement,
removeAccordionElement,
};