standard-ui/components/index.html
2021-07-14 22:51:44 +05:30

1254 lines
54 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="getRef('side_nav').open()">
<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>
<hamburger-menu 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>
</hamburger-menu>
<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>Encapsulated style and 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 <span class="highlight">&lt;/body&gt;</span> 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>
<p>These components use <strong>CSS variables</strong> to customize styling. they share some CSS variables that make global styling easier.</p>
<h4>Some common CSS variables and their use</h4>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Use</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="highlight">--accent-color</span></td>
<td>Color which will be used for denoting active state</td>
</tr>
<tr>
<td><span class="highlight">--text-color</span></td>
<td>
default text color for all components. <br>
( Use comma separated rgb values. e.g 17, 17, 17 )
</td>
</tr>
<tr>
<td><span class="highlight">--background-color</span></td>
<td>
default background color for all components. <br>
( Use comma separated rgb values. e.g 255, 255, 255 )
</td>
</tr>
<tr>
<td><span class="highlight">--danger-color</span></td>
<td>Used for error/invalid state</td>
</tr>
</tbody>
</table>
</section>
<section id="button_page" class="page hide-completely">
<h1 class="page__title">Buttons</h1>
<p><span class="highlight">sm-button</span> has 3 variants that define how the button looks.</p>
<table>
<thead>
<tr>
<th>Variant type</th>
<th>Example</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="highlight">primary</span></td>
<td>
<sm-button variant="primary">Primary</sm-button>
</td>
</tr>
<tr>
<td><span class="highlight">outlined</span></td>
<td>
<sm-button variant="outlined">Outlined</sm-button>
</td>
</tr>
<tr>
<td><span class="highlight">no--outline</span></td>
<td>
<sm-button variant="no-outline">No outline</sm-button>
</td>
</tr>
</tbody>
</table>
<h4>How to define variant</h4>
<pre>
<code class="prettyprint">
&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;
</code>
</pre>
<h2>States</h2>
<h4>Disabled</h4>
<p>To disable the button add <span class="highlight">disabled</span> attribute.</p>
<sm-button disabled>Disabled</sm-button>
<pre>
<code class="prettyprint">
&lt;sm-button disabled&gt;Disabled&lt;/sm-button&gt;
</code>
</pre>
<h2>Attributes</h2>
<p>All the native HTML checkbox attributes are valid</p>
<table>
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="highlight">disabled</span> (boolean)</td>
<td>
Button is disabled by default. all the interactions are disabled
</td>
</tr>
<tr>
<td><span class="highlight">type</span> (string)</td>
<td>
Has values <span class="highlight">submit</span> <span class="highlight">reset</span> <br>
Can only used withing <spna class="highlight">sm-form</spna> to submit or reset the form.
</td>
</tr>
</tbody>
</table>
<h2>Styling</h2>
<p>CSS variables used to style this component</p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="highlight">--background</span></td>
<td>
Define background of button. accepts all values of CSS background property
</td>
</tr>
<tr>
<td><span class="highlight">--border-radius</span></td>
<td>
Set curvature at button corners
</td>
</tr>
<tr>
<td><span class="highlight">--padding</span></td>
<td>
Specify padding of button
</td>
</tr>
</tbody>
</table>
</section>
<section id="carousel_page" class="page hide-completely">
<h1 class="page__title">Carousel</h1>
<p>
Carousel is a very common UI component primarily used to display images or slides.
This carousel switches user interactions based on type of input devices present. For hover capable devices slides can be scrolled with buttons and on
touch enabled devices swipe can be used.
</p>
<h2>Interactive demo</h2>
<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>
<h4>Markup for above carousel</h4>
<pre>
<code class="prettyprint">
&lt;sm-carousel align-items="start" indicator&gt; ...carousel items... &lt;/sm-carousel&gt;
</code>
</pre>
<h2>Custom attributes</h2>
<p>These attributes cane used to customize carousel behaviour and features</p>
<table>
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="highlight">align-items</span></td>
<td>
Has values <span class="highlight">start</span>
<span class="highlight">center</span> <span class="highlight">end</span>
Specifies how carousel items should align. default is <span class="highlight">center</span>.
</td>
</tr>
<tr>
<td><span class="highlight">indicator</span> (boolean)</td>
<td>
if added carousel shows dot indicators of carousel items.
</td>
</tr>
</tbody>
</table>
<h2>Styling</h2>
<p>CSS variables used to style this component</p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="highlight">--active-indicator-color</span></td>
<td>
Defines background color of active slide indicator
</td>
</tr>
<tr>
<td><span class="highlight">--nav-background-color</td>
<td>
Defines background color of carousel navigation buttons
</td>
</tr>
<tr>
<td><span class="highlight">--nav-box-shadow</td>
<td>
Defines box shadow of carousel navigation buttons
</td>
</tr>
<tr>
<td><span class="highlight">--nav-icon-fill</td>
<td>
Defines fill of arrow icon on carousel navigation buttons
</td>
</tr>
</tbody>
</table>
</section>
<section id="checkbox_page" class="page hide-completely">
<h1 class="page__title">Checkbox</h1>
<p><span class="highlight">sm-checkbox</span> supports all the attributes of native HTML5 checkbox</p>
<strong>
linking some HTML element with <span class="highlght">sm-checbox</span> using <span class="highlight">label</span> tag won't work. <br>
Add the element inside the opening and closing checkbox tag.
</strong>
<h2>Interactive demo</h2>
<sm-checkbox id="checkbox">
<div style="margin-left: 0.5rem;">
Check this box
</div>
</sm-checkbox>
<h2>States</h2>
<h4>Disabled</h4>
<p>To disable the checkbox add <span class="highlight">disabled</span> attribute.</p>
<sm-checkbox disabled>
<div style="margin-left: 0.5rem;">
Disabled checkbox
</div>
</sm-checkbox>
<pre>
<code class="prettyprint">
&lt;sm-checkbox disabled&gt;
&lt;div style="margin-left: 0.5rem;"&gt;Disabled checkbox&lt;/div&gt;
&lt;/sm-checkbox&gt;
</code>
</pre>
<h4>Checked</h4>
<p>To make checkbox checked by default add <span class="highlight">checked</span> attribute.</p>
<sm-checkbox checked>
<div style="margin-left: 0.5rem;">
Checked checkbox
</div>
</sm-checkbox>
<pre>
<code class="prettyprint">
&lt;sm-checkbox checked&gt;
&lt;div style="margin-left: 0.5rem;"&gt;Checked checkbox&lt;/div&gt;
&lt;/sm-checkbox&gt;
</code>
</pre>
<h2>Attributes</h2>
<p>All the native HTML checkbox attributes are valid</p>
<table>
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="highlight">checked</span> (boolean)</td>
<td>
Sets checked state as default if added
</td>
</tr>
<tr>
<td><span class="highlight">disabled</span> (boolean)</td>
<td>
Checkbox is disabled by default. all the interactions are disabled
</td>
</tr>
<tr>
<td><span class="highlight">value</span> (string)</td>
<td>
Sets value of checkbox which can be accessed by value property with JS
</td>
</tr>
</tbody>
</table>
<h2>Styling</h2>
<p>CSS variables used to style this component</p>
<table>
<thead>
<tr>
<th>Variable</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="highlight">--border-radius</span></td>
<td>
Defines border-radius of checkbox square
</td>
</tr>
<tr>
<td><span class="highlight">--height</td>
<td>
Defines height of checkbox
</td>
</tr>
<tr>
<td><span class="highlight">--width</td>
<td>
Defines width of checkbox
</td>
</tr>
</tbody>
</table>
</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="hamburger_menu_page" class="page hide-completely">
<h1 class="page__title">Hamburger menu</h1>
<hamburger-menu>
</hamburger-menu>
</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>
<span class="highlight">&lt;sm-select&gt;</span> 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>
<span class="highlight">&lt;sm-select&gt;</span> 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/hamburger-menu.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/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: 'Hamburger menu',
pageId: 'hamburger_menu_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 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>