shimmer 0.0.1 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/src/modal.ts ADDED
@@ -0,0 +1,100 @@
1
+ import { get } from "@rails/request.js";
2
+
3
+ export interface ModalOptions {
4
+ id?: string;
5
+ url: string;
6
+ size?: string;
7
+ close?: boolean;
8
+ }
9
+
10
+ const loaded: Promise<void> = new Promise((res) => {
11
+ document.addEventListener("DOMContentLoaded", () => {
12
+ res();
13
+ });
14
+ });
15
+
16
+ async function nextFrame(): Promise<void> {
17
+ return new Promise((res) => {
18
+ setTimeout(res, 10);
19
+ });
20
+ }
21
+
22
+ async function getHTML(url: string): Promise<string> {
23
+ const response = await get(url, { headers: { "X-Shimmer": "true" } });
24
+ if (response.ok) {
25
+ return await response.response.text();
26
+ }
27
+ return "";
28
+ }
29
+
30
+ function createElement(parent: HTMLElement, className: string): HTMLDivElement {
31
+ const element = document.createElement("div");
32
+ element.className = className;
33
+ parent.append(element);
34
+ return element;
35
+ }
36
+
37
+ export class ModalPresenter {
38
+ private modals: Record<string, Modal> = {};
39
+
40
+ constructor() {
41
+ loaded.then(this.prepareBlind);
42
+ }
43
+
44
+ async open(options: ModalOptions): Promise<void> {
45
+ const id = (options.id = options.id ?? "default-modal");
46
+ (this.modals[id] = new Modal({ presenter: this, id })).open(options);
47
+ this.updateBlindStatus();
48
+ }
49
+
50
+ async close({ id }: { id?: string } = {}): Promise<void> {
51
+ let promise: Promise<unknown> | null = null;
52
+ if (id) {
53
+ promise = this.modals[id]?.close();
54
+ delete this.modals[id];
55
+ } else {
56
+ promise = Promise.all(Object.values(this.modals).map((e) => e.close()));
57
+ this.modals = {};
58
+ }
59
+ this.updateBlindStatus();
60
+ await promise;
61
+ }
62
+
63
+ private updateBlindStatus(): void {
64
+ const open = Object.keys(this.modals).length > 0;
65
+ document.body.classList.toggle("modal-open", open);
66
+ }
67
+
68
+ private async prepareBlind(): Promise<void> {
69
+ createElement(document.body, "modal-blind");
70
+ }
71
+ }
72
+
73
+ export class Modal {
74
+ private readonly root: HTMLDivElement;
75
+ private readonly frame: HTMLDivElement;
76
+ private readonly closeButton: HTMLDivElement;
77
+
78
+ constructor({ presenter, id }: { presenter: ModalPresenter; id: string }) {
79
+ this.root = createElement(document.body, "modal");
80
+ const content = createElement(this.root, "modal__content");
81
+ this.closeButton = createElement(content, "modal__close");
82
+ this.closeButton.addEventListener("click", () => {
83
+ presenter.close({ id });
84
+ });
85
+ this.frame = createElement(content, "modal__frame");
86
+ }
87
+
88
+ async open({ size, url, close }: ModalOptions): Promise<void> {
89
+ await nextFrame();
90
+ this.closeButton.style.display = close ?? true ? "block" : "none";
91
+ this.root.classList.add("modal--open");
92
+ this.root.classList.add("modal--loading");
93
+ this.root.classList.toggle("modal--small", size === "small");
94
+ this.frame.innerHTML = await getHTML(url);
95
+ }
96
+
97
+ async close(): Promise<void> {
98
+ this.root.classList.remove("modal--open");
99
+ }
100
+ }
@@ -0,0 +1,7 @@
1
+ export async function registerServiceWorker(): Promise<void> {
2
+ if (navigator.serviceWorker) {
3
+ await navigator.serviceWorker.register("/serviceworker.js", {
4
+ scope: "./",
5
+ });
6
+ }
7
+ }
data/src/touch.ts ADDED
@@ -0,0 +1,20 @@
1
+ document.addEventListener("turbo:load", () => {
2
+ if (window.ontouchstart !== undefined) {
3
+ document.body.classList.add("touch");
4
+ } else {
5
+ document.body.classList.add("no-touch");
6
+ }
7
+ });
8
+
9
+ document.addEventListener("focusin", (event) => {
10
+ const input = event.target as HTMLElement;
11
+ if (input.tagName === "INPUT" || input.tagName === "TEXTAREA") {
12
+ document.body.classList.add("keyboard-visible");
13
+ }
14
+ });
15
+
16
+ document.addEventListener("focusout", () => {
17
+ document.body.classList.remove("keyboard-visible");
18
+ });
19
+
20
+ export {};
data/tsconfig.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "compilerOptions": {
3
+ "outDir": "dist",
4
+ "allowJs": true,
5
+ "esModuleInterop": true,
6
+ "experimentalDecorators": true,
7
+ "forceConsistentCasingInFileNames": true,
8
+ "lib": ["dom", "esnext"],
9
+ "module": "commonjs",
10
+ "moduleResolution": "node",
11
+ "noImplicitAny": false,
12
+ "noImplicitReturns": true,
13
+ "noImplicitThis": true,
14
+ "noUnusedLocals": true,
15
+ "noUnusedParameters": true,
16
+ "rootDir": "src",
17
+ "skipLibCheck": true,
18
+ "sourceMap": true,
19
+ "strict": false,
20
+ "strictNullChecks": true,
21
+ "suppressImplicitAnyIndexErrors": true,
22
+ "target": "es6",
23
+ "isolatedModules": true,
24
+ "declaration": true
25
+ },
26
+ "exclude": ["node_modules", "dist"],
27
+ "files": ["src/index.ts"]
28
+ }
data/typings.d.ts ADDED
@@ -0,0 +1 @@
1
+ declare module "@rails/request.js";