standard-ui/components/index.html
2021-07-12 16:51:19 +05:30

994 lines
42 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>
<li>
<a href="#global_styling_page" class="list__item interact">
Global styling
</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>
Component-based design is the cornerstone of the modern UI development process. With rise of more UI frameworks every day, the web platform has a serious issue of fragmentation and portability.
</p>
<p>
Web components to the rescue! This is the collection of web components (WC here forward) that we use at RanchiMall.especially since we are a framework-less development environment so this was a logical choice.
</p>
<p>
Just download the components you like, link them with a script tag and drop it in HTML done!.
</p>
<h3>Features</h3>
<ul class="grid gap-1">
<li>Native and Cross framework support</li>
<li>Standalone functionality</li>
<li>Easy styling</li>
<li>Adaptive scaling </li>
</ul>
</div>
</section>
<section id="quick_start_page" class="page hide-completely">
<h1 class="page__title">Quick Start</h1>
<ol>
<li>
To start using these components, Select the ones you want to add to your project. You can un-check 'get minified' to get the readable code.
</li>
<li>
Now you can download or copy the source code for selected components.
<strong class="important">
You might get a warning while downloading like this file is not safe,
please allow the download as this is caused when downloading files with '.js' extension. These components are 100% safe to use.
</strong>
</li>
<li>
Link the downloaded js with <code>&lt;script src=".../components.js"&gt;&lt;/script&gt;</code> at bottom of your HTML file just before <code>&lt;/body&gt;</code> tag.
</li>
</ol>
<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="global_styling_page" class="page hide-completely">
<h1 class="page__title">Global styling</h1>
</section>
<section id="button_page" class="page hide-completely">
<h1 class="page__title">Buttons</h1>
<p>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>