# Conflicts:
#	codecs/cpp.Dockerfile
#	codecs/imagequant/example.html
#	codecs/webp/dec/webp_dec.d.ts
#	codecs/webp/dec/webp_dec.js
#	codecs/webp/dec/webp_dec.wasm
#	codecs/webp/enc/webp_enc.d.ts
#	codecs/webp/enc/webp_enc.js
#	codecs/webp/enc/webp_enc.wasm
#	package-lock.json
#	package.json
#	src/codecs/tiny.webp
#	src_old/codecs/encoders.ts
#	src_old/codecs/processor-worker/tiny.avif
#	src_old/codecs/processor-worker/tiny.webp
#	src_old/codecs/tiny.webp
#	src_old/components/compress/index.tsx
#	src_old/lib/util.ts
#	src_old/sw/util.ts
This commit is contained in:
Jake Archibald
2020-09-16 09:59:24 +01:00
parent dfee848a39
commit a6477b82fc
202 changed files with 10435 additions and 16953 deletions

View File

@@ -0,0 +1,95 @@
import * as style from './styles.css';
export interface SnackOptions {
timeout?: number;
actions?: string[];
}
function createSnack(
message: string,
options: SnackOptions,
): [Element, Promise<string>] {
const { timeout = 0, actions = ['dismiss'] } = options;
const el = document.createElement('div');
el.className = style.snackbar;
el.setAttribute('aria-live', 'assertive');
el.setAttribute('aria-atomic', 'true');
el.setAttribute('aria-hidden', 'false');
const text = document.createElement('div');
text.className = style.text;
text.textContent = message;
el.appendChild(text);
const result = new Promise<string>((resolve) => {
let timeoutId: number;
// Add action buttons
for (const action of actions) {
const button = document.createElement('button');
button.className = style.button;
button.textContent = action;
button.addEventListener('click', () => {
clearTimeout(timeoutId);
resolve(action);
});
el.appendChild(button);
}
// Add timeout
if (timeout) {
timeoutId = self.setTimeout(() => resolve(''), timeout);
}
});
return [el, result];
}
export default class SnackBarElement extends HTMLElement {
private _snackbars: [
string,
SnackOptions,
(action: Promise<string>) => void,
][] = [];
private _processingQueue = false;
/**
* Show a snackbar. Returns a promise for the name of the action clicked, or an empty string if no
* action is clicked.
*/
showSnackbar(message: string, options: SnackOptions = {}): Promise<string> {
return new Promise<string>((resolve) => {
this._snackbars.push([message, options, resolve]);
if (!this._processingQueue) this._processQueue();
});
}
private async _processQueue() {
this._processingQueue = true;
while (this._snackbars[0]) {
const [message, options, resolver] = this._snackbars[0];
const [el, result] = createSnack(message, options);
// Pass the result back to the original showSnackbar call.
resolver(result);
this.appendChild(el);
// Wait for the user to click an action, or for the snack to timeout.
await result;
// Transition the snack away.
el.setAttribute('aria-hidden', 'true');
await new Promise((resolve) => {
el.addEventListener('animationend', () => resolve());
});
el.remove();
this._snackbars.shift();
}
this._processingQueue = false;
}
}
customElements.define('snack-bar', SnackBarElement);

13
src_old/lib/SnackBar/missing-types.d.ts vendored Normal file
View File

@@ -0,0 +1,13 @@
import { SnackOptions, SnackShowResult } from '.';
declare global {
namespace JSX {
interface IntrinsicElements {
'snack-bar': SnackBarAttributes;
}
interface SnackBarAttributes extends HTMLAttributes {
showSnackbar?: (options: SnackOptions) => Promise<SnackShowResult>;
}
}
}

View File

@@ -0,0 +1,105 @@
snack-bar {
display: block;
position: fixed;
left: 0;
bottom: 0;
width: 100%;
height: 0;
overflow: visible;
}
.snackbar {
position: fixed;
display: flex;
box-sizing: border-box;
left: 50%;
bottom: 24px;
width: 344px;
margin-left: -172px;
background: #2a2a2a;
border-radius: 2px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
transform-origin: center;
color: #eee;
z-index: 100;
cursor: default;
will-change: transform;
animation: snackbar-show 300ms ease forwards 1;
}
.snackbar[aria-hidden='true'] {
animation: snackbar-hide 300ms ease forwards 1;
}
@keyframes snackbar-show {
from {
opacity: 0;
transform: scale(0.5);
}
}
@keyframes snackbar-hide {
to {
opacity: 0;
transform: translateY(100%);
}
}
@media (max-width: 400px) {
.snackbar {
width: 100%;
bottom: 0;
left: 0;
margin-left: 0;
border-radius: 0;
}
}
.text {
flex: 1 1 auto;
padding: 16px;
font-size: 100%;
}
.button {
position: relative;
flex: 0 1 auto;
padding: 8px;
height: 36px;
margin: auto 8px auto -8px;
min-width: 5em;
background: none;
border: none;
border-radius: 3px;
color: lightgreen;
font-weight: inherit;
letter-spacing: 0.05em;
font-size: 100%;
text-transform: uppercase;
text-align: center;
cursor: pointer;
overflow: hidden;
transition: background-color 200ms ease;
outline: none;
}
.button:hover {
background-color: rgba(0, 0, 0, 0.15);
}
.button:focus:before {
content: '';
position: absolute;
left: 50%;
top: 50%;
width: 120%;
height: 0;
padding: 0 0 120%;
margin: -60% 0 0 -60%;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
transform-origin: center;
will-change: transform;
animation: focus-ring 300ms ease-out forwards 1;
pointer-events: none;
}
@keyframes focus-ring {
from {
transform: scale(0.01);
}
}