standard-ui/components/index.html
2021-07-12 02:05:01 +05:30

982 lines
41 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SM Components</title>
<link rel="stylesheet" href="css/main.min.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;700&family=Roboto+Mono&family=Roboto:wght@400;500;700&display=swap"
rel="stylesheet">
</head>
<body class="hide-completely">
<sm-notifications id="notification_drawer"></sm-notifications>
<audio id="notification_sound">
<source src="https://rmservices.duckdns.org/files/notification-sound.mp3" type="audio/mpeg">
<source src="https://rmservices.duckdns.org/files/notification-sound.ogg" type="audio/ogg">
</audio>
<main>
<header id="main_header" class="flex align-center space-between">
<button id="side_nav_button" class="interact" onclick="sideNav()">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path fill="none" d="M0 0h24v24H0z" />
<path d="M16 18v2H5v-2h11zm5-7v2H3v-2h18zm-2-7v2H8V4h11z" />
</svg>
</button>
<h4>SM Components</h4>
<label class="theme-switcher" title="Change theme">
<input id="theme_switcher" class="theme-switcher__checkbox" type="checkbox"
aria-label="Dark mode toggle">
<svg class="icon moon-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24"
height="24">
<path fill="none" d="M0 0h24v24H0z" />
<path
d="M10 6a8 8 0 0 0 11.955 6.956C21.474 18.03 17.2 22 12 22 6.477 22 2 17.523 2 12c0-5.2 3.97-9.474 9.044-9.955A7.963 7.963 0 0 0 10 6zm-6 6a8 8 0 0 0 8 8 8.006 8.006 0 0 0 6.957-4.045c-.316.03-.636.045-.957.045-5.523 0-10-4.477-10-10 0-.321.015-.64.045-.957A8.006 8.006 0 0 0 4 12zm14.164-9.709L19 2.5v1l-.836.209a2 2 0 0 0-1.455 1.455L16.5 6h-1l-.209-.836a2 2 0 0 0-1.455-1.455L13 3.5v-1l.836-.209A2 2 0 0 0 15.29.836L15.5 0h1l.209.836a2 2 0 0 0 1.455 1.455zm5 5L24 7.5v1l-.836.209a2 2 0 0 0-1.455 1.455L21.5 11h-1l-.209-.836a2 2 0 0 0-1.455-1.455L18 8.5v-1l.836-.209a2 2 0 0 0 1.455-1.455L20.5 5h1l.209.836a2 2 0 0 0 1.455 1.455z" />
</svg>
<svg class="icon sun-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24"
height="24">
<path fill="none" d="M0 0h24v24H0z" />
<path
d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z" />
</svg>
</label>
</header>
<nav id="side_nav">
<h4>Getting Started</h4>
<ul class="list">
<li>
<a href="#overview_page" class="list__item list__item--active interact">
Overview
</a>
</li>
<li>
<a href="#quick_start_page" class="list__item interact">
Quick start
</a>
</li>
</ul>
<h4>Components</h4>
<ul id="components_list" class="list"></ul>
</nav>
<section id="backdrop" class="hide-completely" onclick="sideNav(false)"></section>
<div class="right language-html">
<section id="overview_page" class="page">
<div>
<h5 class="color-0-8 weight-500">Total components</h5>
<h1 id="total_components_count" class="h1"></h1>
</div>
<div>
<h1 class="page__title">Overview</h1>
<p class="description">
These components are based on HTML5 custom elements API. This is an attempt to unify UI
development
patterns and
elements that are used multiple times throughout any general web app.It uses 'sm' namespace for
all
components. So every
component tag starts with <strong>'sm-'</strong>
</p>
<p>
They can replace some older UI elements like <code>&lt;select&gt;</code>
<code>&lt;input&gt;</code>
<code>&lt;checkbox&gt;</code> <code>&lt;button&gt;</code>
But also more modern additions like <strong>popups(modals), tabs and many more.</strong>
</p>
<p>
Some of the components have some cool tricks under their sleeves like <strong>custom events and
variantions</strong>.
They allow developers to access more information about component or simply react to whatever
state
change happen to them.
We will go more in-depth about all the variantions and customs events related to each event as
we go
further.
</p>
</div>
</section>
<section id="quick_start_page" class="page hide-completely">
<h1 class="page__title">Quick Start</h1>
<p class="description">
To start using SM Components, Select components you want to download.
</p>
<div class="grid grid-3 gap-0-5 align-center">
<sm-checkbox id="get_minified" checked>
<span class="comp-checkbox__title">
Get minified
</span>
</sm-checkbox>
<sm-button onclick="selectAll()">Select all</sm-button>
<sm-button onclick="clearAll()">Clear all</sm-button>
</div>
<div id="components_selection_list"></div>
<div class="flex align-center space-between">
<sm-button onclick="copySourceCode()">Copy source code</sm-button>
<sm-button variant="primary" onclick="downloadComponents()">Download JS file</sm-button>
</div>
</section>
<section id="button_page" class="page hide-completely">
<h1 class="page__title">Buttons</h1>
<p class="description">
Buttons are used in various basic UI interactions to perform an action.
</p>
<sm-button>default</sm-button>
<sm-button variant="primary">primary</sm-button>
<sm-button variant="outlined">outlined</sm-button>
<sm-button variant="no-outline">no-outline</sm-button>
<sm-button variant="primary" disabled>disabled</sm-button>
<pre>
<code class="prettyprint">
&lt;sm-button&gt;default&lt;/sm-button&gt;
&lt;sm-button variant="primary"&gt;primary&lt;/sm-button&gt;
&lt;sm-button variant="outlined"&gt;outlined&lt;/sm-button&gt;
&lt;sm-button variant="no-outline"&gt;no-outline&lt;/sm-button&gt;
&lt;sm-button variant="primary" disabled&gt;disabled&lt;/sm-button&gt;
</code>
</pre>
</section>
<section id="carousel_page" class="page hide-completely">
<h1 class="page__title">Carousel</h1>
<p class="description">
To start using SM Components
</p>
<sm-carousel align-items="start" indicator>
<div class="card">
<h3>Title</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Provident, optio.</p>
</div>
<div class="card">
<h3>Title</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Provident, optio.</p>
</div>
<div class="card">
<h3>Title</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Provident, optio.</p>
</div>
<div class="card">
<h3>Title</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Provident, optio.</p>
</div>
</sm-carousel>
</section>
<section id="checkbox_page" class="page hide-completely">
<h1 class="page__title">Checkbox</h1>
<p class="description">
To start using SM Components
</p>
<label>
<sm-checkbox id="checkbox">Default</sm-checkbox>
<sm-checkbox id="checkbox" checked>Checked</sm-checkbox>
<sm-checkbox id="checkbox" disabled>Disabled</sm-checkbox>
<sm-checkbox id="checkbox" checked disabled>Checked Disabled</sm-checkbox>
</label>
</section>
<section id="copy_page" class="page hide-completely">
<h1 class="page__title">Copy</h1>
<p class="description">
To start using SM Components
</p>
<sm-copy value="copy this message"></sm-copy>
</section>
<section id="file_input_page" class="page hide-completely">
<h1 class="page__title">File input</h1>
<p class="description">
To start using SM Components
</p>
<file-input></file-input>
<p id="insert_text"></p>
</section>
<section id="form_page" class="page hide-completely">
<h1 class="page__title">Form</h1>
<p class="description">
To start using SM Components
</p>
<sm-form>
<sm-input placeholder="Email" type="email" error-text="please enter correct email" required animate></sm-input>
<sm-input placeholder="Password" type="password" required animate></sm-input>
<sm-button variant="primary" disabled>Submit</sm-button>
</sm-form>
<p id="insert_text"></p>
</section>
<section id="input_page" class="page hide-completely">
<h1 class="page__title">Input</h1>
<p class="description">
To start using SM Components
</p>
<sm-input placeholder="something" type="email" error-text="please enter correct email"
animate></sm-input>
<p id="insert_text"></p>
</section>
<section id="menu_page" class="page hide-completely">
<h1 class="page__title">Menu</h1>
<p class="description">
To start using SM Components
</p>
<sm-menu id="my_menu">
<sm-menu-option>first option</sm-menu-option>
<sm-menu-option>second option</sm-menu-option>
<sm-menu-option>third option</sm-menu-option>
</sm-menu>
<p id="insert_text"></p>
</section>
<section id="notifications_page" class="page hide-completely">
<h1 class="page__title">Notifications</h1>
<p class="description">
To start using SM Components
</p>
<h4>Example</h4>
<sm-button
onclick="notify('Lorem ipsum dolor, consectetur adipisicing elit.', 'success')">
push success notification</sm-button>
<sm-button onclick="notify('Lorem ipsum dolor, sit amet.', 'error')">
push error notification</sm-button>
<sm-button
onclick="notify('Lorem ipsum dolor, sit amet consectetur adipisicing elit.', '', {pinned: true})">
push pinned notification</sm-button>
</section>
<section id="popup_page" class="page hide-completely">
<h1 class="page__title">Popup / dialog</h1>
<p class="description">
Popups are used to show addition UI elements that you may want to hide at first and reveal them when
needed.
</p>
<sm-popup id="popup" heading="something">
idhfioushdfiuh<br>
idhfioushdfiuh<br>
idhfioushdfiuh<br>
idhfioushdfiuh<br>
idhfioushdfiuh<br>
idhfioushdfiuh<br>
idhfioushdfiuh<br>
idhfioushdfiuh<br>
idhfioushdfiuh<br>
</sm-popup>
<sm-button variant="primary" onclick="getRef('popup').show()">show popup</sm-button>
</section>
<section id="radio_page" class="page hide-completely">
<h1 class="page__title">Radio</h1>
<p class="description">
Popups are used to show addition UI elements that you may want to hide at first and reveal them when
needed.
</p>
<div class="grid gap-0-5">
<sm-radio name="abc" value="on" checked>
<div class="flex">&nbsp;&nbsp;On</div>
</sm-radio>
<sm-radio name="abc" value="off">
<div class="flex">&nbsp;&nbsp;Off</div>
</sm-radio>
<sm-radio name="abc" value="🤷">
<div class="flex">&nbsp;&nbsp;🤷</div>
</sm-radio>
</div>
</section>
<section id="switch_page" class="page hide-completely">
<h1 class="page__title">Switch</h1>
<p class="description">
To start using SM Components
</p>
<sm-switch id="switch"></sm-switch>
<sm-switch id="switch" checked></sm-switch>
<sm-switch id="switch" disabled></sm-switch>
</section>
<section id="select_page" class="page hide-completely">
<h1 class="page__title">Select</h1>
<p>
<code>&lt;sm-select&gt;</code> is very similar to starndatd HTML5 select and it's markup stucture is
also identical.
</p>
<sm-select>
<sm-option value="1">option1</sm-option>
<sm-option value="2">option2 something</sm-option>
<sm-option value="3">option3</sm-option>
</sm-select>
</section>
<section id="spinner_page" class="page hide-completely">
<h1 class="page__title">Spinner</h1>
<p>
<code>&lt;sm-select&gt;</code> is very similar to starndatd HTML5 select and it's markup stucture is
also identical.
</p>
<sm-spinner></sm-spinner>
</section>
<section id="strip_select_page" class="page hide-completely">
<h1 class="page__title">Strip select</h1>
<p class="description">
To start using SM Components
</p>
<strip-select id="browse_category_selector" multiline>
<strip-option value="movie" selected>Movie</strip-option>
<strip-option value="tv series">TV series</strip-option>
<strip-option value="video">Video</strip-option>
<strip-option value="music">Music</strip-option>
</strip-select>
</section>
<section id="tabs_page" class="page hide-completely">
<h1 class="page__title">Tabs</h1>
<p class="description">
To start using SM Components
</p>
<sm-tab-header variant="tab" target="tab1">
<sm-tab>inbox</sm-tab>
<sm-tab>sent</sm-tab>
<sm-tab>draft</sm-tab>
<sm-tab>spam</sm-tab>
</sm-tab-header>
<sm-tab-panels id="tab1">
<sm-panel>
gjdhnsrfijbgn<br>bdfjnbj
</sm-panel>
<sm-panel>
jadifjoaijdiajdo
dosfighjoi<br>
flkmgklfmzkl<br>
hbdsfhb
</sm-panel>
<sm-panel>
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Facere neque incidunt aut laudantium,
quam
id,
molestiae vero blanditiis nisi alias in magnam autem quasi cumque eveniet qui cupiditate nam
corrupti?
</sm-panel>
<sm-panel>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Blanditiis fuga ipsam, explicabo, eius
accusamus
consectetur ex sunt soluta voluptatem iure totam nulla expedita suscipit minus molestiae
similique
odio optio
quibusdam.
</sm-panel>
</sm-tab-panels>
</section>
<section id="tags_input_page" class="page hide-completely">
<h1 class="page__title">Tags input</h1>
<p class="description">
To start using SM Components
</p>
<tags-input placeholder="Add tags..."></tags-input>
</section>
<section id="textarea_page" class="page hide-completely">
<h1 class="page__title">Textarea</h1>
<p class="description">
To start using SM Components
</p>
<sm-textarea placeholder="Add some text here..." rows="4"></sm-textarea>
</section>
<section id="text_field_page" class="page hide-completely">
<h1 class="page__title">Text field</h1>
<p class="description">
To start using SM Components
</p>
<text-field value="Double click me!"></text-field>
</section>
</div>
</main>
<template id="nav_item_template">
<li>
<a class="list__item interact"></a>
</li>
</template>
<template id="comp_checkbox_template">
<sm-checkbox>
<span class="comp-checkbox__title"></span>
</sm-checkbox>
</template>
<script src="dist/button.js"></script>
<script src="dist/carousel.js"></script>
<script src="dist/checkbox.js"></script>
<script src="dist/copy.js"></script>
<script src="dist/file-input.js"></script>
<script src="dist/form.js"></script>
<script src="dist/input.js"></script>
<script src="dist/menu.js"></script>
<script src="dist/notifications.js"></script>
<script src="dist/popup.js"></script>
<script src="dist/radio.js"></script>
<script src="dist/select.js"></script>
<script src="dist/sm-spinner.js"></script>
<script src="dist/strip-select.js"></script>
<script src="dist/switch.js"></script>
<script src="dist/tabs.js"></script>
<script src="dist/tags-input.js"></script>
<script src="dist/textarea.js"></script>
<script src="dist/text-field.js"></script>
<script id="default_ui_library">
const domRefs = {};
function getRef(elementId) {
if (!domRefs.hasOwnProperty(elementId)) {
domRefs[elementId] = {
count: 1,
ref: null,
};
return document.getElementById(elementId);
} else {
if (domRefs[elementId].count < 3) {
domRefs[elementId].count = domRefs[elementId].count + 1;
return document.getElementById(elementId);
} else {
if (!domRefs[elementId].ref)
domRefs[elementId].ref = document.getElementById(elementId);
return domRefs[elementId].ref;
}
}
}
function createElement(tagName, obj) {
const { className, textContent, innerHTML, attributes = {}} = obj
const elem = document.createElement(tagName)
for(let attribute in attributes){
elem.setAttribute(attribute, attributes[attribute])
}
if (className)
elem.className = className
elem.textContent = textContent
if (innerHTML)
elem.innerHTML = innerHTML
return elem
}
const debounce = (callback, wait) => {
let timeoutId = null;
return (...args) => {
window.clearTimeout(timeoutId);
timeoutId = window.setTimeout(() => {
callback.apply(null, args);
}, wait);
};
}
let timerId;
function throttle(func, delay) {
// If setTimeout is already scheduled, no need to do anything
if (timerId) {
return;
}
// Schedule a setTimeout after delay seconds
timerId = setTimeout(function () {
func();
// Once setTimeout function execution is finished, timerId = undefined so that in
// the next scroll event function execution can be scheduled by the setTimeout
timerId = undefined;
}, delay);
}
//Checks for internet connection status
if (!navigator.onLine)
notify(
"There seems to be a problem connecting to the internet, Please check you internet connection.",
"error",
{sound: true}
);
window.addEventListener("offline", () => {
notify(
"There seems to be a problem connecting to the internet, Please check you internet connection.",
"error",
{pinned: true, sound: true}
);
});
window.addEventListener("online", () => {
getRef("notification_drawer").clearAll();
notify("We are back online.", "success");
});
if (getRef("theme_switcher")) {
if (localStorage.theme === "dark") {
nightlight();
getRef("theme_switcher").checked = true;
} else if (localStorage.theme === "light") {
daylight();
getRef("theme_switcher").checked = false;
}
else {
if (window.matchMedia(`(prefers-color-scheme: dark)`).matches) {
nightlight();
getRef("theme_switcher").checked = true;
} else {
daylight();
getRef("theme_switcher").checked = false;
}
}
function daylight() {
document.body.setAttribute("data-theme", "light");
}
function nightlight() {
document.body.setAttribute("data-theme", "dark");
}
getRef("theme_switcher").addEventListener("change", function (e) {
if (this.checked) {
nightlight();
localStorage.setItem("theme", "dark");
} else {
daylight();
localStorage.setItem("theme", "light");
}
});
}
// function required for popups or modals to appear
class Stack {
constructor() {
this.items = [];
}
push(element) {
this.items.push(element);
}
pop() {
if (this.items.length == 0)
return "Underflow";
return this.items.pop();
}
peek() {
return this.items[this.items.length - 1];
}
}
let popupStack = new Stack(),
zIndex = 10;
async function showPopup(popup, pinned) {
zIndex++
getRef(popup).setAttribute('style', `z-index: ${zIndex}`)
popupStack = getRef(popup).show(pinned, popupStack)
return getRef(popup);
}
// hides the popup or modal
function hidePopup() {
if (popupStack.peek() === undefined)
return;
popupStack.peek().popup.hide()
}
// displays a popup for asking permission. Use this instead of JS confirm
let confirmation = (title, message, cancelText = 'Cancel', confirmText = 'OK') => {
return new Promise(resolve => {
showPopup('confirmation_popup', true)
getRef('confirm_title').textContent = title;
getRef('confirm_message').textContent = message;
let cancelButton = getRef('confirmation_popup').children[2].children[0],
submitButton = getRef('confirmation_popup').children[2].children[1]
submitButton.textContent = confirmText
cancelButton.textContent = cancelText
submitButton.onclick = () => {
hidePopup()
resolve(true);
}
cancelButton.onclick = () => {
hidePopup()
resolve(false);
}
})
}
// displays a popup for asking user input. Use this instead of JS prompt
async function getPromptInput(title, message = '', showText = true, trueBtn = "Ok", falseBtn = "Cancel") {
showPopup('prompt_popup', true)
getRef('prompt_title').textContent = title;
let input = getRef('prompt_input');
input.setAttribute("placeholder", message)
let buttons = getRef('prompt_popup').querySelectorAll("sm-button");
if (showText)
input.setAttribute("type", "text")
else
input.setAttribute("type", "password")
input.focusIn()
buttons[0].textContent = falseBtn;
buttons[1].textContent = trueBtn;
return new Promise((resolve, reject) => {
buttons[0].onclick = () => {
hidePopup()
return;
}
buttons[1].onclick = () => {
let value = input.value;
hidePopup()
resolve(value)
}
})
}
//Function for displaying toast notifications. pass in error for mode param if you want to show an error.
function notify(message, mode, options = {}) {
const {pinned = false, sound} = options
if (mode === "error") console.error(message);
let icon
switch(mode){
case 'success':
icon = `<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414z"/></svg>`
break;
case 'error':
icon = `<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-1-7v2h2v-2h-2zm0-8v6h2V7h-2z"/></svg>`
break;
}
getRef("notification_drawer").push(message, {pinned, icon});
if (navigator.onLine && sound) {
getRef("notification_sound").currentTime = 0;
getRef("notification_sound").play();
}
}
const currentYear = new Date().getFullYear();
function getFormatedTime(time, relative) {
try {
if (String(time).indexOf("_")) time = String(time).split("_")[0];
const intTime = parseInt(time);
if (String(intTime).length < 13) time *= 1000;
let timeFrag = new Date(intTime).toString().split(" "),
day = timeFrag[0],
month = timeFrag[1],
date = timeFrag[2],
year = timeFrag[3],
minutes = new Date(intTime).getMinutes(),
hours = new Date(intTime).getHours(),
currentTime = new Date().toString().split(" ");
minutes = minutes < 10 ? `0${minutes}` : minutes;
let finalHours = ``;
if (hours > 12) finalHours = `${hours - 12}:${minutes}`;
else if (hours === 0) finalHours = `12:${minutes}`;
else finalHours = `${hours}:${minutes}`;
finalHours = hours >= 12 ? `${finalHours} PM` : `${finalHours} AM`;
if (relative) {
return `${date} ${month} ${year}`;
} else return `${finalHours} ${month} ${date} ${year}`;
} catch (e) {
console.error(e);
return time;
}
}
window.addEventListener("load", () => {
// document.querySelectorAll('sm-input[data-flo-id]').forEach(input => input.customValidation = validateAddr)
document.addEventListener('keyup', (e) => {
if (e.code === 'Escape') {
hidePopup()
}
})
document.addEventListener("pointerdown", (e) => {
if (e.target.closest("button, sm-button:not([disabled]), .interact")) {
createRipple(e, e.target.closest("button, sm-button, .interact"));
}
});
document.addEventListener('copy', () => {
notify('copied', 'success')
})
});
function createRipple(event, target) {
const circle = document.createElement("span");
const diameter = Math.max(target.clientWidth, target.clientHeight);
const radius = diameter / 2;
const targetDimensions = target.getBoundingClientRect();
circle.style.width = circle.style.height = `${diameter}px`;
circle.style.left = `${event.clientX - (targetDimensions.left + radius)}px`;
circle.style.top = `${event.clientY - (targetDimensions.top + radius)}px`;
circle.classList.add("ripple");
const rippleAnimation = circle.animate(
[
{
transform: "scale(3)",
opacity: 0,
},
],
{
duration: 1000,
fill: "forwards",
easing: "ease-out",
}
);
target.append(circle);
rippleAnimation.onfinish = () => {
circle.remove();
};
}
</script>
<script>
const render = {
navListItem(obj) {
const { name, pageId } = obj
const item = getRef('nav_item_template').content.cloneNode(true).firstElementChild
const itemLink = item.firstElementChild
itemLink.textContent = name
itemLink.href = `#${pageId}`
return item
},
compCheckbox(obj){
const {name} = obj
const checkbox = getRef('comp_checkbox_template').content.cloneNode(true).firstElementChild
checkbox.setAttribute('value', name.toLowerCase().replaceAll(' ', '-'))
checkbox.firstElementChild.textContent = name
return checkbox
}
}
window.addEventListener('hashchange', e => showPage(window.location.hash, { hashChange: true }))
window.addEventListener('load', e => {
document.body.classList.remove('hide-completely')
renderComponentList()
showPage(window.location.hash, { firstLoad: true })
getRef('total_components_count').textContent = componentsList.length
PR.prettyPrint()
getComponents()
})
function showPage(targetPage, options = {}) {
const { firstLoad, hashChange } = options
let pageId
if (targetPage === '') {
pageId = 'overview_page'
}
else {
pageId = targetPage.includes('#') ? targetPage.split('#')[1] : targetPage
}
document.querySelector('.page:not(.hide-completely)').classList.add('hide-completely')
document.querySelector('.list__item--active').classList.remove('list__item--active')
getRef(pageId).classList.remove('hide-completely')
getRef(pageId).animate([
{
opacity: 0,
transform: 'translateX(-1rem)'
},
{
opacity: 1,
transform: 'none'
},
],
{
duration: 300,
easing: 'ease'
})
const targetListItem = document.querySelector(`.list__item[href="#${pageId}"]`)
targetListItem.classList.add('list__item--active')
if (firstLoad && window.innerWidth > 640 && targetListItem.getBoundingClientRect().top > getRef('side_nav').getBoundingClientRect().height){
getRef('side_nav').scrollTo({
top: (targetListItem.getBoundingClientRect().top - getRef('side_nav').getBoundingClientRect().top + getRef('side_nav').scrollTop),
behavior: 'smooth'
})
}
if (hashChange && window.innerWidth < 640) {
sideNav(false)
}
}
const componentsList = [
{
name: 'button',
pageId: 'button_page'
},
{
name: 'Carousel',
pageId: 'carousel_page'
},
{
name: 'Checkbox',
pageId: 'checkbox_page'
},
{
name: 'Copy',
pageId: 'copy_page'
},
{
name: 'File input',
pageId: 'file_input_page'
},
{
name: 'Form',
pageId: 'form_page'
},
{
name: 'Input',
pageId: 'input_page'
},
{
name: 'Menu',
pageId: 'menu_page'
},
{
name: 'Notifications',
pageId: 'notifications_page'
},
{
name: 'Popup',
pageId: 'popup_page'
},
{
name: 'Radio',
pageId: 'radio_page'
},
{
name: 'Switch',
pageId: 'switch_page'
},
{
name: 'Select',
pageId: 'select_page'
},
{
name: 'Spinner',
pageId: 'spinner_page'
},
{
name: 'Strip select',
pageId: 'strip_select_page'
},
{
name: 'Tabs',
pageId: 'tabs_page'
},
{
name: 'Tags input',
pageId: 'tags_input_page'
},
{
name: 'textarea',
pageId: 'textarea_page'
},
{
name: 'Text field',
pageId: 'text_field_page'
},
]
function sideNav(show = true) {
if (show) {
getRef('side_nav').classList.add('reveal')
getRef('backdrop').classList.remove('hide-completely')
getRef('backdrop').animate([
{
opacity: 0
},
{
opacity: 1
},
],
{
duration: 300,
easing: 'ease'
})
}
else {
getRef('side_nav').classList.remove('reveal')
getRef('backdrop').animate([
{
opacity: 1
},
{
opacity: 0
},
],
{
duration: 300,
easing: 'ease'
})
.onfinish = () => {
getRef('backdrop').classList.add('hide-completely')
}
}
}
function renderComponentList() {
const itemsFrag = document.createDocumentFragment()
const checkboxFrag = document.createDocumentFragment()
componentsList.forEach((component, index) => {
itemsFrag.append(render.navListItem(component))
checkboxFrag.append(render.compCheckbox({...component, index}))
})
getRef('components_list').innerHTML = ''
getRef('components_selection_list').innerHTML = ''
getRef('components_list').append(itemsFrag)
getRef('components_selection_list').append(checkboxFrag)
}
function selectAll() {
getRef('components_selection_list').querySelectorAll('sm-checkbox').forEach(elem => elem.checked = true)
}
function clearAll() {
getRef('components_selection_list').querySelectorAll('sm-checkbox').forEach(elem => elem.checked = false)
}
async function getSelectedComponents(){
const selectedComponents = [...getRef('components_selection_list').querySelectorAll('sm-checkbox[checked]')].map(v => v.value)
const extension = getRef('get_minified').checked ? '.min.js' : '.js'
const filesList = []
selectedComponents.forEach(async component => {
for (let compObj in allComponentsObj) {
const {name, download_url} = allComponentsObj[compObj]
if(name === `${component}${extension}`){
filesList.push(fetch(download_url).then(async res => await res.text()))
}
}
});
return await Promise.all(filesList)
}
async function downloadComponents() {
const selectedComponents = await getSelectedComponents()
if(selectedComponents.length){
downloadJs(selectedComponents, {minified: getRef('get_minified').checked})
}
else{
notify('Please select atleast one component', 'error')
}
}
async function copySourceCode(){
const selectedComponents = await getSelectedComponents()
if(selectedComponents.length){
const sourceCode = selectedComponents.join("\n")
window.navigator.clipboard.writeText(sourceCode).then(success => {
notify('Copied components source code')
}).catch(err => console.error(error))
}
else{
notify('Please select atleast one component', 'error')
}
}
let allComponentsObj = []
async function getComponents() {
const files = await fetch('https://api.github.com/repos/ranchimall/standard-visual-design-system/contents/components/dist')
allComponentsObj = await files.json()
}
function downloadJs(componentsArray, options = {minified: true}){
const {minified} = options
const extension = minified ? '.min.js': '.js'
const element = createElement('a', {
attributes: {
'href': 'data:application/javascript;charset=utf-8,' + encodeURIComponent(componentsArray.join("\n")),
'download': `components${extension}`,
'style': 'display:none'
}
});
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
</script>
<script src="prettify.js"></script>
</body>
</html>