Merge pull request #6 from ranchimall/main

UI
This commit is contained in:
Sai Raj 2022-03-09 20:46:07 +05:30 committed by GitHub
commit 136ba68b42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 325 additions and 355 deletions

3
.gitignore vendored
View File

@ -3,4 +3,5 @@
/args/config*.json
/args/param.json
/args/keys*.json
*test*
*test*
args/app-config.json

View File

@ -74,11 +74,13 @@ smButton.innerHTML = `
background-color: rgba(var(--text-color), 0.3);
}
@media (hover: hover){
:host(:not([disabled])) .button:hover{
:host(:not([disabled])) .button:hover,
:host(:focus-within:not([disabled])) .button{
-webkit-box-shadow: 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1), 0 0.2rem 0.8rem rgba(0, 0, 0, 0.12);
box-shadow: 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1), 0 0.2rem 0.8rem rgba(0, 0, 0, 0.12);
box-shadow: 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1), 0 0.2rem 0.8rem rgba(0, 0, 0, 0.12);
}
:host([variant='outlined']) .button:hover{
:host([variant='outlined']:not([disabled])) .button:hover,
:host(:focus-within[variant='outlined']:not([disabled])) .button:hover{
-webkit-box-shadow: 0 0 0 1px rgba(var(--text-color), 0.2) inset, 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1), 0 0.4rem 0.8rem rgba(0, 0, 0, 0.12);
box-shadow: 0 0 0 1px rgba(var(--text-color), 0.2) inset, 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1), 0 0.4rem 0.8rem rgba(0, 0, 0, 0.12);
}
@ -120,9 +122,12 @@ customElements.define('sm-button',
this.removeAttribute('disabled');
}
}
focusIn() {
this.focus();
}
handleKeyDown(e) {
if (!this.hasAttribute('disabled') && (e.key === 'Enter' || e.code === 'Space')) {
if (!this.hasAttribute('disabled') && (e.key === 'Enter' || e.key === ' ')) {
e.preventDefault();
this.click();
}
@ -986,6 +991,24 @@ customElements.define('sm-notifications', class extends HTMLElement {
});
}
});
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];
}
}
const popupStack = new Stack();
const smPopup = document.createElement('template');
smPopup.innerHTML = `
<style>
@ -1007,7 +1030,6 @@ smPopup.innerHTML = `
--height: auto;
--min-width: auto;
--min-height: auto;
--body-padding: 1.5rem;
--backdrop-background: rgba(0, 0, 0, 0.6);
--border-radius: 0.8rem 0.8rem 0 0;
}
@ -1020,10 +1042,6 @@ smPopup.innerHTML = `
left: 0;
right: 0;
place-items: center;
background: var(--backdrop-background);
-webkit-transition: opacity 0.3s;
-o-transition: opacity 0.3s;
transition: opacity 0.3s;
z-index: 10;
touch-action: none;
}
@ -1031,6 +1049,18 @@ smPopup.innerHTML = `
-webkit-transform: scale(0.9) translateY(-2rem) !important;
transform: scale(0.9) translateY(-2rem) !important;
}
.background{
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
pointer-events: none;
background: var(--backdrop-background);
-webkit-transition: opacity 0.3s;
-o-transition: opacity 0.3s;
transition: opacity 0.3s;
}
.popup{
display: -webkit-box;
display: -ms-flexbox;
@ -1050,17 +1080,9 @@ smPopup.innerHTML = `
min-height: var(--min-height);
max-height: 90vh;
border-radius: var(--border-radius);
-webkit-transform: scale(1) translateY(100%);
transform: scale(1) translateY(100%);
-webkit-transition: -webkit-transform 0.3s;
transition: -webkit-transform 0.3s;
-o-transition: transform 0.3s;
transition: transform 0.3s, -webkit-transform 0.3s;
transition: transform 0.3s;
background: rgba(var(--background-color), 1);
-webkit-box-shadow: 0 -1rem 2rem #00000020;
box-shadow: 0 -1rem 2rem #00000020;
content-visibility: auto;
}
.container-header{
display: -webkit-box;
@ -1087,17 +1109,15 @@ smPopup.innerHTML = `
-ms-flex: 1;
flex: 1;
width: 100%;
padding: var(--body-padding);
padding: var(--body-padding, 1.5rem);
overflow-y: auto;
}
.hide{
opacity: 0;
pointer-events: none;
visiblity: none;
display:none;
}
@media screen and (min-width: 640px){
:host{
--border-radius: 0.4rem;
--border-radius: 0.5rem;
}
.popup{
-ms-flex-item-align: center;
@ -1105,8 +1125,6 @@ smPopup.innerHTML = `
align-self: center;
border-radius: var(--border-radius);
height: var(--height);
-webkit-transform: scale(1) translateY(3rem);
transform: scale(1) translateY(3rem);
-webkit-box-shadow: 0 3rem 2rem -0.5rem #00000040;
box-shadow: 0 3rem 2rem -0.5rem #00000040;
}
@ -1141,7 +1159,8 @@ smPopup.innerHTML = `
}
}
</style>
<div part="background" class="popup-container hide" role="dialog">
<div class="popup-container hide" role="dialog">
<div part="background" class="background"></div>
<div part="popup" class="popup">
<div part="popup-header" class="popup-top">
<div class="handle"></div>
@ -1163,26 +1182,30 @@ customElements.define('sm-popup', class extends HTMLElement {
this.allowClosing = false;
this.isOpen = false;
this.pinned = false;
this.popupStack = undefined;
this.offset = 0;
this.touchStartY = 0;
this.touchEndY = 0;
this.touchStartTime = 0;
this.touchEndTime = 0;
this.touchEndAnimataion = undefined;
this.touchEndAnimation = undefined;
this.focusable
this.autoFocus
this.mutationObserver
this.popupContainer = this.shadowRoot.querySelector('.popup-container');
this.backdrop = this.shadowRoot.querySelector('.background');
this.popup = this.shadowRoot.querySelector('.popup');
this.popupBodySlot = this.shadowRoot.querySelector('.popup-body slot');
this.popupHeader = this.shadowRoot.querySelector('.popup-top');
this.resumeScrolling = this.resumeScrolling.bind(this);
this.setStateOpen = this.setStateOpen.bind(this);
this.show = this.show.bind(this);
this.hide = this.hide.bind(this);
this.handleTouchStart = this.handleTouchStart.bind(this);
this.handleTouchMove = this.handleTouchMove.bind(this);
this.handleTouchEnd = this.handleTouchEnd.bind(this);
this.movePopup = this.movePopup.bind(this);
this.detectFocus = this.detectFocus.bind(this);
}
static get observedAttributes() {
@ -1193,135 +1216,208 @@ customElements.define('sm-popup', class extends HTMLElement {
return this.isOpen;
}
animateTo(element, keyframes, options) {
const anime = element.animate(keyframes, { ...options, fill: 'both' })
anime.finished.then(() => {
anime.commitStyles()
anime.cancel()
})
return anime
}
resumeScrolling() {
const scrollY = document.body.style.top;
window.scrollTo(0, parseInt(scrollY || '0') * -1);
setTimeout(() => {
document.body.style.overflow = 'auto';
document.body.style.top = 'initial';
}, 300);
document.body.style.overflow = '';
document.body.style.top = 'initial';
}
setStateOpen() {
if (!this.isOpen || this.offset) {
const animOptions = {
duration: 300,
easing: 'ease'
}
const initialAnimation = (window.innerWidth > 640) ? 'scale(1.1)' : `translateY(${this.offset ? `${this.offset}px` : '100%'})`
this.animateTo(this.popup, [
{
opacity: this.offset ? 1 : 0,
transform: initialAnimation
},
{
opacity: 1,
transform: 'none'
},
], animOptions)
}
}
show(options = {}) {
const { pinned = false, popupStack } = options;
if (popupStack)
this.popupStack = popupStack;
if (this.popupStack && !this.hasAttribute('open')) {
this.popupStack.push({
const { pinned = false } = options;
if (!this.isOpen) {
const animOptions = {
duration: 300,
easing: 'ease'
}
popupStack.push({
popup: this,
permission: pinned
});
if (this.popupStack.items.length > 1) {
this.popupStack.items[this.popupStack.items.length - 2].popup.classList.add('stacked');
if (popupStack.items.length > 1) {
this.animateTo(popupStack.items[popupStack.items.length - 2].popup.shadowRoot.querySelector('.popup'), [
{ transform: 'none' },
{ transform: (window.innerWidth > 640) ? 'scale(0.95)' : 'translateY(-1.5rem)' },
], animOptions)
}
this.popupContainer.classList.remove('hide');
if (!this.offset)
this.backdrop.animate([
{ opacity: 0 },
{ opacity: 1 },
], animOptions)
this.setStateOpen()
this.dispatchEvent(
new CustomEvent("popupopened", {
bubbles: true,
detail: {
popup: this,
popupStack: this.popupStack
}
})
);
this.setAttribute('open', '');
this.pinned = pinned;
this.isOpen = true;
document.body.style.overflow = 'hidden';
document.body.style.top = `-${window.scrollY}px`;
const elementToFocus = this.autoFocus || this.focusable[0];
elementToFocus.tagName.includes('SM-') ? elementToFocus.focusIn() : elementToFocus.focus();
if (!this.hasAttribute('open'))
this.setAttribute('open', '');
}
this.popupContainer.classList.remove('hide');
this.popup.style.transform = 'none';
document.body.style.overflow = 'hidden';
document.body.style.top = `-${window.scrollY}px`;
return this.popupStack;
}
hide() {
if (window.innerWidth < 640)
this.popup.style.transform = 'translateY(100%)';
else
this.popup.style.transform = 'translateY(3rem)';
this.popupContainer.classList.add('hide');
this.removeAttribute('open');
if (typeof this.popupStack !== 'undefined') {
this.popupStack.pop();
if (this.popupStack.items.length) {
this.popupStack.items[this.popupStack.items.length - 1].popup.classList.remove('stacked');
} else {
this.resumeScrolling();
}
const animOptions = {
duration: 150,
easing: 'ease'
}
this.backdrop.animate([
{ opacity: 1 },
{ opacity: 0 }
], animOptions)
this.animateTo(this.popup, [
{
opacity: 1,
transform: (window.innerWidth > 640) ? 'none' : `translateY(${this.offset ? `${this.offset}px` : '0'})`
},
{
opacity: 0,
transform: (window.innerWidth > 640) ? 'scale(1.1)' : 'translateY(100%)'
},
], animOptions).finished
.finally(() => {
this.popupContainer.classList.add('hide');
this.popup.style = ''
this.removeAttribute('open');
if (this.forms.length) {
this.forms.forEach(form => form.reset());
}
this.dispatchEvent(
new CustomEvent("popupclosed", {
bubbles: true,
detail: {
popup: this,
}
})
);
this.isOpen = false;
})
popupStack.pop();
if (popupStack.items.length) {
this.animateTo(popupStack.items[popupStack.items.length - 1].popup.shadowRoot.querySelector('.popup'), [
{ transform: (window.innerWidth > 640) ? 'scale(0.95)' : 'translateY(-1.5rem)' },
{ transform: 'none' },
], animOptions)
} else {
this.resumeScrolling();
}
if (this.forms.length) {
setTimeout(() => {
this.forms.forEach(form => form.reset());
}, 300);
}
setTimeout(() => {
this.dispatchEvent(
new CustomEvent("popupclosed", {
bubbles: true,
detail: {
popup: this,
popupStack: this.popupStack
}
})
);
this.isOpen = false;
}, 300);
}
handleTouchStart(e) {
this.offset = 0
this.popupHeader.addEventListener('touchmove', this.handleTouchMove, { passive: true });
this.popupHeader.addEventListener('touchend', this.handleTouchEnd, { passive: true });
this.touchStartY = e.changedTouches[0].clientY;
this.popup.style.transition = 'transform 0.1s';
this.touchStartTime = e.timeStamp;
}
handleTouchMove(e) {
if (this.touchStartY < e.changedTouches[0].clientY) {
this.offset = e.changedTouches[0].clientY - this.touchStartY;
this.touchEndAnimataion = window.requestAnimationFrame(() => this.movePopup());
this.touchEndAnimation = window.requestAnimationFrame(() => {
this.popup.style.transform = `translateY(${this.offset}px)`;
});
}
}
handleTouchEnd(e) {
this.touchEndTime = e.timeStamp;
cancelAnimationFrame(this.touchEndAnimataion);
cancelAnimationFrame(this.touchEndAnimation);
this.touchEndY = e.changedTouches[0].clientY;
this.popup.style.transition = 'transform 0.3s';
this.threshold = this.popup.getBoundingClientRect().height * 0.3;
if (this.touchEndTime - this.touchStartTime > 200) {
if (this.touchEndY - this.touchStartY > this.threshold) {
if (this.pinned) {
this.show();
this.setStateOpen();
return;
} else
this.hide();
} else {
this.show();
this.setStateOpen();
}
} else {
if (this.touchEndY > this.touchStartY)
if (this.pinned) {
this.show();
this.setStateOpen();
return;
}
else
this.hide();
}
this.popupHeader.removeEventListener('touchmove', this.handleTouchMove, { passive: true });
this.popupHeader.removeEventListener('touchend', this.handleTouchEnd, { passive: true });
}
movePopup() {
this.popup.style.transform = `translateY(${this.offset}px)`;
detectFocus(e) {
if (e.key === 'Tab') {
const lastElement = this.focusable[this.focusable.length - 1];
const firstElement = this.focusable[0];
if (e.shiftKey && document.activeElement === firstElement) {
e.preventDefault();
lastElement.tagName.includes('SM-') ? lastElement.focusIn() : lastElement.focus();
} else if (!e.shiftKey && document.activeElement === lastElement) {
e.preventDefault();
firstElement.tagName.includes('SM-') ? firstElement.focusIn() : firstElement.focus();
}
}
}
updateFocusableList() {
this.focusable = this.querySelectorAll('sm-button:not([disabled]), button:not([disabled]), [href], sm-input, input, sm-select, select, sm-checkbox, sm-textarea, textarea, [tabindex]:not([tabindex="-1"])')
this.autoFocus = this.querySelector('[autofocus]')
}
connectedCallback() {
this.popupBodySlot.addEventListener('slotchange', () => {
this.forms = this.querySelectorAll('sm-form');
this.updateFocusableList()
});
this.popupContainer.addEventListener('mousedown', e => {
if (e.target === this.popupContainer && !this.pinned) {
if (this.pinned) {
this.show();
this.setStateOpen();
} else
this.hide();
}
@ -1340,16 +1436,19 @@ customElements.define('sm-popup', class extends HTMLElement {
});
resizeObserver.observe(this);
this.mutationObserver = new MutationObserver(entries => {
this.updateFocusableList()
})
this.mutationObserver.observe(this, { attributes: true, childList: true, subtree: true })
this.addEventListener('keydown', this.detectFocus);
this.popupHeader.addEventListener('touchstart', this.handleTouchStart, { passive: true });
this.popupHeader.addEventListener('touchmove', this.handleTouchMove, { passive: true });
this.popupHeader.addEventListener('touchend', this.handleTouchEnd, { passive: true });
}
disconnectedCallback() {
this.popupHeader.removeEventListener('touchstart', this.handleTouchStart, { passive: true });
this.popupHeader.removeEventListener('touchmove', this.handleTouchMove, { passive: true });
this.popupHeader.removeEventListener('touchend', this.handleTouchEnd, { passive: true });
this.removeEventListener('keydown', this.detectFocus);
resizeObserver.unobserve();
this.mutationObserver.disconnect()
this.popupHeader.removeEventListener('touchstart', this.handleTouchStart, { passive: true });
}
attributeChangedCallback(name) {
if (name === 'open') {
@ -2225,7 +2324,6 @@ smSelect.innerHTML = `
--accent-color: #4d2588;
--text-color: 17, 17, 17;
--background-color: 255, 255, 255;
--max-height: auto;
--min-width: 100%;
}
:host([disabled]) .select{
@ -2252,11 +2350,12 @@ smSelect.innerHTML = `
fill: rgba(var(--text-color), 0.7);
}
.selected-option-text{
font-size: 0.9rem;
font-size: inherit;
overflow: hidden;
-o-text-overflow: ellipsis;
text-overflow: ellipsis;
white-space: nowrap;
font-weight: 500;
}
.selection{
border-radius: 0.3rem;
@ -2265,13 +2364,13 @@ smSelect.innerHTML = `
-ms-grid-columns: 1fr auto;
grid-template-columns: 1fr auto;
grid-template-areas: 'heading heading' '. .';
padding: 0.4rem 0.8rem;
padding: var(--padding,0.6rem 0.8rem);
background: rgba(var(--text-color), 0.06);
border: solid 1px rgba(var(--text-color), 0.2);
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
outline: none;
z-index: 2;
}
.selection:focus{
-webkit-box-shadow: 0 0 0 0.1rem var(--accent-color);
@ -2285,6 +2384,7 @@ smSelect.innerHTML = `
}
.options{
top: 100%;
padding: var(--options-padding, 0.3rem);
margin-top: 0.2rem;
overflow: hidden auto;
position: absolute;
@ -2297,11 +2397,11 @@ smSelect.innerHTML = `
-ms-flex-direction: column;
flex-direction: column;
min-width: var(--min-width);
max-height: var(--max-height);
max-height: var(--max-height, auto);
background: rgba(var(--background-color), 1);
border: solid 1px rgba(var(--text-color), 0.2);
border-radius: 0.3rem;
z-index: 2;
border-radius: var(--border-radius, 0.5rem);
z-index: 1;
-webkit-box-shadow: 0.4rem 0.8rem 1.2rem #00000030;
box-shadow: 0.4rem 0.8rem 1.2rem #00000030;
}
@ -2328,7 +2428,7 @@ smSelect.innerHTML = `
}
}
</style>
<div class="select" >
<div class="select">
<div class="selection">
<div class="selected-option-text"></div>
<svg class="icon toggle" 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 13.172l4.95-4.95 1.414 1.414L12 16 5.636 9.636 7.05 8.222z"/></svg>
@ -2344,6 +2444,7 @@ customElements.define('sm-select', class extends HTMLElement {
mode: 'open'
}).append(smSelect.content.cloneNode(true))
this.focusIn = this.focusIn.bind(this)
this.reset = this.reset.bind(this)
this.open = this.open.bind(this)
this.collapse = this.collapse.bind(this)
@ -2356,6 +2457,7 @@ customElements.define('sm-select', class extends HTMLElement {
this.availableOptions
this.previousOption
this.isOpen = false;
this.label = ''
this.slideDown = [{
transform: `translateY(-0.5rem)`,
opacity: 0
@ -2386,13 +2488,24 @@ customElements.define('sm-select', class extends HTMLElement {
this.selectedOptionText = this.shadowRoot.querySelector('.selected-option-text')
}
static get observedAttributes() {
return ['value', 'disabled']
return ['disabled', 'label']
}
get value() {
return this.getAttribute('value')
}
set value(val) {
this.setAttribute('value', val)
const selectedOption = this.availableOptions.find(option => option.getAttribute('value') === val)
if (selectedOption) {
this.setAttribute('value', val)
this.selectedOptionText.textContent = `${this.label}${selectedOption.textContent}`;
if (this.previousOption) {
this.previousOption.classList.remove('check-selected')
}
selectedOption.classList.add('check-selected')
this.previousOption = selectedOption
} else {
console.warn(`There is no option with ${val} as value`)
}
}
reset(fire = true) {
@ -2403,7 +2516,7 @@ customElements.define('sm-select', class extends HTMLElement {
}
firstElement.classList.add('check-selected')
this.value = firstElement.getAttribute('value')
this.selectedOptionText.textContent = firstElement.textContent
this.selectedOptionText.textContent = `${this.label}${firstElement.textContent}`
this.previousOption = firstElement;
if (fire) {
this.fireEvent()
@ -2411,6 +2524,10 @@ customElements.define('sm-select', class extends HTMLElement {
}
}
focusIn() {
this.selection.focus()
}
open() {
this.optionList.classList.remove('hide')
this.optionList.animate(this.slideDown, this.animationOptions)
@ -2444,7 +2561,7 @@ customElements.define('sm-select', class extends HTMLElement {
}
handleOptionsNavigation(e) {
if (e.code === 'ArrowUp') {
if (e.key === 'ArrowUp') {
e.preventDefault()
if (document.activeElement.previousElementSibling) {
document.activeElement.previousElementSibling.focus()
@ -2452,7 +2569,7 @@ customElements.define('sm-select', class extends HTMLElement {
this.availableOptions[this.availableOptions.length - 1].focus()
}
}
else if (e.code === 'ArrowDown') {
else if (e.key === 'ArrowDown') {
e.preventDefault()
if (document.activeElement.nextElementSibling) {
document.activeElement.nextElementSibling.focus()
@ -2464,13 +2581,7 @@ customElements.define('sm-select', class extends HTMLElement {
handleOptionSelection(e) {
if (this.previousOption !== document.activeElement) {
this.value = document.activeElement.getAttribute('value')
this.selectedOptionText.textContent = document.activeElement.textContent;
this.fireEvent()
if (this.previousOption) {
this.previousOption.classList.remove('check-selected')
}
document.activeElement.classList.add('check-selected')
this.previousOption = document.activeElement
}
}
handleClick(e) {
@ -2484,12 +2595,12 @@ customElements.define('sm-select', class extends HTMLElement {
}
handleKeydown(e) {
if (e.target === this) {
if (this.isOpen && e.code === 'ArrowDown') {
if (this.isOpen && e.key === 'ArrowDown') {
e.preventDefault()
this.availableOptions[0].focus()
this.handleOptionSelection(e)
}
else if (e.code === 'Enter' || e.code === 'Space') {
else if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
this.toggle()
}
@ -2497,7 +2608,7 @@ customElements.define('sm-select', class extends HTMLElement {
else {
this.handleOptionsNavigation(e)
this.handleOptionSelection(e)
if (e.code === 'Enter' || e.code === 'Space') {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
this.collapse()
}
@ -2534,6 +2645,8 @@ customElements.define('sm-select', class extends HTMLElement {
} else {
this.selection.setAttribute('tabindex', '0')
}
} else if (name === 'label') {
this.label = this.hasAttribute('label') ? `${this.getAttribute('label')} ` : ''
}
}
})
@ -2562,11 +2675,12 @@ smOption.innerHTML = `
width: 100%;
gap: 0.5rem;
grid-template-columns: max-content minmax(0, 1fr);
padding: 0.8rem 1.2rem;
padding: var(--padding, 0.6rem 1rem);
cursor: pointer;
white-space: nowrap;
outline: none;
user-select: none;
border-radius: var(--border-radius, 0.3rem);
}
:host(:focus){
outline: none;

View File

@ -1,8 +1,7 @@
* {
padding: 0;
margin: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
box-sizing: border-box;
font-family: "Roboto", sans-serif;
}
@ -68,8 +67,7 @@ a:where([class]) {
text-decoration: none;
}
a:where([class]):focus-visible {
-webkit-box-shadow: 0 0 0 0.1rem rgba(var(--text-color), 1) inset;
box-shadow: 0 0 0 0.1rem rgba(var(--text-color), 1) inset;
box-shadow: 0 0 0 0.1rem rgba(var(--text-color), 1) inset;
}
a {
@ -83,24 +81,19 @@ button,
-ms-user-select: none;
user-select: none;
position: relative;
display: -webkit-inline-box;
display: -ms-inline-flexbox;
display: inline-flex;
border: none;
background-color: transparent;
overflow: hidden;
color: inherit;
cursor: pointer;
-webkit-transition: -webkit-transform 0.3s;
transition: -webkit-transform 0.3s;
transition: transform 0.3s;
transition: transform 0.3s, -webkit-transform 0.3s;
-webkit-tap-highlight-color: transparent;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
align-items: center;
font-size: 0.9rem;
font-weight: 500;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.02em;
}
.button {
@ -109,9 +102,7 @@ button,
border-radius: 0.3rem;
background-color: rgba(var(--text-color), 0.06);
color: rgba(var(--text-color), 0.8);
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
justify-content: center;
}
.button--primary {
background-color: var(--accent-color);
@ -141,6 +132,10 @@ sm-input {
}
sm-button {
text-transform: uppercase;
letter-spacing: 0.02em;
font-weight: 700;
font-size: 0.9rem;
--padding: 0.7rem 1rem;
}
sm-button[variant=primary] .icon {
@ -149,9 +144,6 @@ sm-button[variant=primary] .icon {
sm-button[disabled] .icon {
fill: rgba(var(--text-color), 0.6);
}
sm-button.uppercase {
letter-spacing: 0.05em;
}
sm-button.danger {
--background: var(--danger-color);
color: rgba(var(--background-color), 1);
@ -162,8 +154,6 @@ ul {
}
.flex {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
@ -230,8 +220,6 @@ ul {
}
.flex {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
@ -272,15 +260,11 @@ ul {
}
.align-start {
-webkit-box-align: start;
-ms-flex-align: start;
align-items: flex-start;
align-items: flex-start;
}
.align-center {
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
align-items: center;
}
.text-center {
@ -288,15 +272,11 @@ ul {
}
.justify-start {
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: start;
justify-content: start;
}
.justify-center {
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
justify-content: center;
}
.justify-right {
@ -304,8 +284,7 @@ ul {
}
.align-self-center {
-ms-flex-item-align: center;
align-self: center;
align-self: center;
}
.justify-self-center {
@ -321,16 +300,11 @@ ul {
}
.direction-column {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
flex-direction: column;
}
.space-between {
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
justify-content: space-between;
}
.w-100 {
@ -340,20 +314,16 @@ ul {
.interact {
position: relative;
cursor: pointer;
-webkit-transition: -webkit-transform 0.3s;
transition: -webkit-transform 0.3s;
transition: transform 0.3s;
transition: transform 0.3s, -webkit-transform 0.3s;
-webkit-tap-highlight-color: transparent;
}
.empty-state {
display: grid;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
justify-content: center;
text-align: center;
width: 100%;
max-width: none;
padding: 1.5rem;
}
@ -396,10 +366,7 @@ ul {
#confirmation_popup,
#prompt_popup {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
flex-direction: column;
}
#confirmation_popup h4,
#prompt_popup h4 {
@ -428,8 +395,7 @@ ul {
button:active,
.button:active,
.interact:active {
-webkit-transform: scale(0.96);
transform: scale(0.96);
transform: scale(0.96);
}
.popup__header {
@ -437,9 +403,7 @@ button:active,
gap: 0.5rem;
width: 100%;
padding: 0 1.5rem 0 0.5rem;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
align-items: center;
grid-template-columns: auto 1fr auto;
}
@ -452,15 +416,12 @@ button:active,
padding: 1.5rem;
}
#main_page > section:nth-of-type(1) {
-ms-flex-line-pack: start;
align-content: flex-start;
align-content: flex-start;
}
.logo {
display: grid;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
align-items: center;
width: 100%;
grid-template-columns: auto 1fr;
gap: 0 0.3rem;
@ -479,12 +440,8 @@ button:active,
}
details summary {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
justify-content: space-between;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
@ -495,8 +452,7 @@ details[open] > summary {
margin-bottom: 1rem;
}
details[open] > summary .icon {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
transform: rotate(180deg);
}
strip-select {
@ -557,17 +513,14 @@ sm-checkbox {
padding: 1.5rem 0;
}
#landing > .grid {
-ms-flex-line-pack: start;
align-content: flex-start;
align-content: flex-start;
text-align: center;
gap: 1rem;
}
#sign_up {
grid-template-rows: auto 1fr;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
align-items: center;
}
#sign_up section {
margin-top: -6rem;
@ -595,11 +548,8 @@ sm-checkbox {
#home {
height: 100%;
display: grid;
-webkit-box-align: start;
-ms-flex-align: start;
align-items: flex-start;
-ms-flex-line-pack: start;
align-content: flex-start;
align-items: flex-start;
align-content: flex-start;
grid-template-columns: minmax(0, 1fr);
}
@ -608,13 +558,11 @@ sm-checkbox {
}
#main_header {
margin-top: 2rem;
margin-top: 1.5rem;
margin-bottom: 1rem;
display: grid;
gap: 1rem;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
align-items: center;
grid-template-columns: 1fr auto auto;
grid-column: 1/-1;
}
@ -634,15 +582,12 @@ sm-checkbox {
#trade_form,
#login_form {
-ms-flex-item-align: start;
align-self: flex-start;
align-self: flex-start;
padding: 1rem 1.5rem 1.5rem 1.5rem;
}
.quantity-selector .button {
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
flex: 1;
padding: 0.5rem 0.6rem;
margin-left: 0.5rem;
}
@ -697,9 +642,7 @@ sm-checkbox {
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1.5rem 0.5rem 0.5rem;
grid-template-columns: -webkit-min-content repeat(3, 1fr) -webkit-min-content;
@ -737,9 +680,7 @@ sm-checkbox {
}
.cancel-order {
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
align-items: center;
padding: 0.4rem 0.6rem;
}
.cancel-order span {
@ -786,8 +727,7 @@ sm-checkbox {
#user_section {
gap: 1.5rem;
padding: 1.5rem;
-ms-flex-line-pack: start;
align-content: flex-start;
align-content: flex-start;
}
.wallet_actions__wrapper {
@ -796,9 +736,7 @@ sm-checkbox {
margin-top: 0.5rem;
}
.wallet_actions__wrapper .button {
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
flex: 1;
}
.label {
@ -809,9 +747,7 @@ sm-checkbox {
.balance-card {
display: grid;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
align-items: center;
gap: 0.3rem 1rem;
padding: 0.5rem 0;
border-radius: 0.5rem;
@ -824,14 +760,9 @@ sm-checkbox {
grid-template-columns: auto 1fr auto;
}
.balance-card__icon {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-line-pack: center;
align-content: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
align-content: center;
justify-content: center;
padding: 0.6rem;
border-radius: 0.8rem;
background-color: var(--accent-color--light);
@ -855,14 +786,10 @@ sm-checkbox {
}
#wallet_result {
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
justify-content: center;
text-align: center;
}
#wallet_result__icon {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
padding: 1rem;
border-radius: 50%;
@ -887,46 +814,35 @@ sm-checkbox {
@-webkit-keyframes pop-up {
from {
-webkit-transform: translateY(3rem) scale(0.5);
transform: translateY(3rem) scale(0.5);
transform: translateY(3rem) scale(0.5);
opacity: 0;
}
to {
-webkit-transform: translateY(0) scale(1);
transform: translateY(0) scale(1);
transform: translateY(0) scale(1);
opacity: 1;
}
}
@keyframes pop-up {
from {
-webkit-transform: translateY(3rem) scale(0.5);
transform: translateY(3rem) scale(0.5);
transform: translateY(3rem) scale(0.5);
opacity: 0;
}
to {
-webkit-transform: translateY(0) scale(1);
transform: translateY(0) scale(1);
transform: translateY(0) scale(1);
opacity: 1;
}
}
.stateful-button-wrapper {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
position: relative;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
justify-content: center;
align-items: center;
}
.stateful-button-wrapper sm-button,
.stateful-button-wrapper slide-button {
width: 100%;
z-index: 1;
-webkit-transition: -webkit-clip-path 0.3s;
transition: -webkit-clip-path 0.3s;
transition: clip-path 0.3s;
transition: clip-path 0.3s, -webkit-clip-path 0.3s;
@ -946,15 +862,9 @@ sm-checkbox {
.stateful-result {
overflow: hidden;
position: absolute;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
justify-content: center;
align-items: center;
height: 100%;
width: 100%;
left: 0;
@ -997,26 +907,22 @@ sm-checkbox {
@-webkit-keyframes pop {
from {
opacity: 0;
-webkit-transform: translateY(2rem);
transform: translateY(2rem);
transform: translateY(2rem);
}
to {
opacity: 1;
-webkit-transform: translateY(0);
transform: translateY(0);
transform: translateY(0);
}
}
@keyframes pop {
from {
opacity: 0;
-webkit-transform: translateY(2rem);
transform: translateY(2rem);
transform: translateY(2rem);
}
to {
opacity: 1;
-webkit-transform: translateY(0);
transform: translateY(0);
transform: translateY(0);
}
}
@-webkit-keyframes ripple-reveal {
@ -1057,24 +963,14 @@ sm-checkbox {
}
.bottom_nav__item {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
flex-direction: column;
align-items: center;
flex: 1;
padding: 0.5rem 0;
}
.bottom_nav__item .item__title,
.bottom_nav__item .icon {
-webkit-transition: 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
transition: 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.bottom_nav__item .item__title {
@ -1088,13 +984,11 @@ sm-checkbox {
}
.bottom_nav__item--active .item__title {
color: var(--accent-color);
-webkit-transform: translateY(100%);
transform: translateY(100%);
transform: translateY(100%);
opacity: 0;
}
.bottom_nav__item--active .icon {
-webkit-transform: translateY(50%) scale(1.2);
transform: translateY(50%) scale(1.2);
transform: translateY(50%) scale(1.2);
fill: var(--accent-color);
}
@ -1196,10 +1090,7 @@ sm-checkbox {
.interact,
button {
-webkit-transition: background-color 0.3s, -webkit-transform 0.3s;
transition: background-color 0.3s, -webkit-transform 0.3s;
transition: background-color 0.3s, transform 0.3s;
transition: background-color 0.3s, transform 0.3s, -webkit-transform 0.3s;
}
.interact:hover,
button:hover {
@ -1212,19 +1103,14 @@ button:hover {
}
.order-card .cancel-order .icon,
.order-card .cancel-order span {
-webkit-transition: opacity 0.3s, -webkit-transform 0.3s;
transition: opacity 0.3s, -webkit-transform 0.3s;
transition: opacity 0.3s, transform 0.3s;
transition: opacity 0.3s, transform 0.3s, -webkit-transform 0.3s;
}
.order-card .cancel-order .icon {
opacity: 0;
-webkit-transform: translateX(100%);
transform: translateX(100%);
transform: translateX(100%);
}
.order-card .cancel-order span {
-webkit-transform: translateX(100%);
transform: translateX(100%);
transform: translateX(100%);
opacity: 0;
}
.order-card:hover .cancel-order .icon, .order-card:focus-within .cancel-order .icon {
@ -1233,13 +1119,11 @@ button:hover {
.order-card .cancel-order:hover .icon,
.order-card .cancel-order:hover span {
opacity: 1;
-webkit-transform: translateX(0);
transform: translateX(0);
transform: translateX(0);
}
.transaction-card button {
opacity: 0;
-webkit-transition: opacity 0.3s;
transition: opacity 0.3s;
}
.transaction-card:hover button {

File diff suppressed because one or more lines are too long

View File

@ -92,7 +92,9 @@ button,
-webkit-tap-highlight-color: transparent;
align-items: center;
font-size: 0.9rem;
font-weight: 500;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.02em;
}
.button {
white-space: nowrap;
@ -114,13 +116,16 @@ button:disabled {
a:any-link:focus-visible {
outline: rgba(var(--text-color), 1) 0.1rem solid;
}
sm-input {
font-size: 0.9rem;
--border-radius: 0.3rem;
--background: var(--accent-color--light);
}
sm-button {
text-transform: uppercase;
letter-spacing: 0.02em;
font-weight: 700;
font-size: 0.9rem;
--padding: 0.7rem 1rem;
&[variant="primary"] {
.icon {
@ -133,9 +138,6 @@ sm-button {
fill: rgba(var(--text-color), 0.6);
}
}
&.uppercase {
letter-spacing: 0.05em;
}
&.danger {
--background: var(--danger-color);
color: rgba(var(--background-color), 1);
@ -315,6 +317,7 @@ ul {
justify-content: center;
text-align: center;
width: 100%;
max-width: none;
padding: 1.5rem;
}
@ -534,7 +537,7 @@ sm-checkbox {
}
#main_header {
margin-top: 2rem;
margin-top: 1.5rem;
margin-bottom: 1rem;
display: grid;
gap: 1rem;

View File

@ -57,7 +57,7 @@
</div>
</div>
<theme-toggle></theme-toggle>
<button onclick="showPopup('user_popup')">
<button id="user_popup_button" class="hide-completely" onclick="showPopup('user_popup')">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" height="24px" viewBox="0 0 24 24" width="24px"
fill="#000000">
<path d="M0 0h24v24H0V0z" fill="none" />
@ -66,7 +66,7 @@
</svg>
</button>
</header>
<section id="dashboard" class="card mobile-page hide-on-mobile">
<section id="dashboard" class="card mobile-page">
<sm-form id="login_form" class="hide-">
<div class="grid gap-0-5">
<h4>Login</h4>
@ -645,50 +645,16 @@
};
}
// Limits the rate of function execution
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);
}
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()
let zIndex = 10
// function required for popups or modals to appear
function showPopup(popupId, pinned) {
zIndex++
getRef(popupId).setAttribute('style', `z-index: ${zIndex}`)
popupStack = getRef(popupId).show({ pinned, popupStack })
getRef(popupId).show({ pinned })
return getRef(popupId);
}
// hides the popup or modal
// hides the popup or modal
function hidePopup() {
if (popupStack.peek() === undefined)
return;
@ -819,7 +785,7 @@
document.body.classList.remove('hide-completely')
document.querySelectorAll('sm-input[data-private-key]').forEach(input => input.customValidation = floCrypto.getPubKeyHex)
document.addEventListener('keyup', (e) => {
if (e.code === 'Escape') {
if (e.key === 'Escape') {
hidePopup()
}
})
@ -1070,6 +1036,7 @@
getRef('get_total').value = 0
setTimeout(() => {
hideProcess('trade_button_wrapper')
getRef('trade_button').disabled = true
setTimeout(() => {
getRef('trade_button_wrapper').querySelector('.stateful-result').remove()
}, 100);
@ -1435,7 +1402,7 @@
})
} else {
transactions.forEach(transaction => {
const {asset, quantity, unitValue, tx_time, buyer, seller } = transaction
const { asset, quantity, unitValue, tx_time, buyer, seller } = transaction
let type, other;
if (seller === proxy.userID) {
type = 'Sold';
@ -1570,20 +1537,20 @@
this.private = null;
this.public = null;
},
get sinkID(){
get sinkID() {
return getRef("sink_id").value;
},
set userID(id){
set userID(id) {
localStorage.setItem("exchange-user_ID", id);
this.user = id;
},
get userID(){
if(this.user)
get userID() {
if (this.user)
return this.user;
else{
else {
let id = localStorage.getItem('exchange-user_ID');
return id ? this.user = id : undefined;
}
}
},
set secret(key) {
localStorage.setItem("exchange-proxy_secret", key);
@ -1636,14 +1603,14 @@
function updateRate(init = false) {
getRates().then(rates => {
console.debug(rates);
if(init){
if (init) {
let assetList = getRef('get_asset');
let walletList = getRef('wallet_asset_selector');
let c = document.createElement('sm-option');
c.setAttribute('value', floGlobals.currency);
c.innerText = floGlobals.currency;
walletList.appendChild(c);
for(let asset in rates){
for (let asset in rates) {
let e = document.createElement('sm-option');
e.setAttribute('value', asset);
e.innerText = asset;
@ -1659,9 +1626,9 @@
}
function refresh(init = false) {
if (init){
if (init) {
console.info("init");
if(!proxy.userID){
if (!proxy.userID) {
getRef('home').classList.remove('signed-in');
getLoginCode().then(response => {
getRef("login_form").classList.remove('hide-completely');
@ -1675,7 +1642,7 @@
console.info("refresh");
updateRate(init);
renderMarketOrders();
if(proxy.userID)
if (proxy.userID)
account();
}
@ -1699,6 +1666,7 @@
getAccount(proxy.userID, await proxy.secret).then(acc => {
getRef("login_form").classList.add('hide-completely')
getRef('home').classList.add('signed-in')
getRef('user_popup_button').classList.remove('hide-completely')
accountDetails = acc
console.debug(acc);
//Element display
@ -1730,7 +1698,7 @@
const UI_evt = {
signup(privKey) {
let code = getRef('sign_in_code').value,
let code = getRef('sign_in_code').value,
hash = getRef('sign_in_hash').value;
if (!privKey)
privKey = getRef('get_registration_key').value.trim()
@ -1760,7 +1728,7 @@
login() {
showProcess('login_button_wrapper')
let privKey = getRef('login_form__priv_key').value;
let code = getRef('sign_in_code').value,
let code = getRef('sign_in_code').value,
hash = getRef('sign_in_hash').value;
let rememberMe = getRef('remember_me').checked;
let tmpKey = floCrypto.generateNewID();