frutjam 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +38 -34
- package/src/index.ts +3 -1
- package/src/plugins/notification/config.ts +14 -0
- package/src/plugins/notification/index.ts +89 -39
- package/src/plugins/notification/interfaces.ts +15 -1
- package/src/plugins/notification/styles.css +9 -0
- package/src/plugins/notification/types.ts +5 -1
- package/src/plugins/popover/index.ts +45 -0
- package/src/plugins/popover/styles.css +12 -0
- package/src/plugins/telephoneInput/data.ts +1131 -0
- package/src/plugins/telephoneInput/index.ts +117 -0
- package/src/plugins/telephoneInput/interfaces.ts +6 -0
- package/src/plugins/telephoneInput/types.ts +7 -0
- package/README.md +0 -1
package/package.json
CHANGED
|
@@ -1,34 +1,38 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "frutjam",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Frutjam includes prebuilt UI components and plugins that are completely open-source",
|
|
5
|
-
"main": "./dist/index.js",
|
|
6
|
-
"module": "./dist/index.mjs",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "github",
|
|
10
|
-
"url": "git+https://github.com/nezanuha/frutjam.git"
|
|
11
|
-
},
|
|
12
|
-
"scripts": {
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "frutjam",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Frutjam includes prebuilt UI components and plugins that are completely open-source",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "github",
|
|
10
|
+
"url": "git+https://github.com/nezanuha/frutjam.git"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"dev": "tsup --watch",
|
|
14
|
+
"build": "tsup",
|
|
15
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"frutjam",
|
|
19
|
+
"Nezanuha"
|
|
20
|
+
],
|
|
21
|
+
"author": "Nezanuha",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"homepage": "https://frutjam.com",
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/nezanuha/frutjam/issues"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"src/**/*"
|
|
29
|
+
],
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"autoprefixer": "^10.4.19",
|
|
32
|
+
"esbuild": "^0.20.2",
|
|
33
|
+
"postcss": "^8.4.38",
|
|
34
|
+
"tailwindcss": "^3.4.3",
|
|
35
|
+
"tsup": "^8.0.2",
|
|
36
|
+
"typescript": "^5.4.5"
|
|
37
|
+
}
|
|
38
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { NotificationConfig } from "./interfaces";
|
|
2
|
+
|
|
3
|
+
export const config: NotificationConfig = {
|
|
4
|
+
arriveFrom: {
|
|
5
|
+
right: 'translate-x-full',
|
|
6
|
+
left: '-translate-x-full',
|
|
7
|
+
bottom: 'translate-y-full',
|
|
8
|
+
top: '-translate-y-full',
|
|
9
|
+
},
|
|
10
|
+
effects: {
|
|
11
|
+
slide: 'duration-300',
|
|
12
|
+
fade: 'opacity-0 duration-300',
|
|
13
|
+
},
|
|
14
|
+
};
|
|
@@ -1,74 +1,124 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Notification
|
|
3
|
+
* @version: 0.0.2
|
|
4
|
+
* @author: Nezanuha
|
|
5
|
+
* @license: Licensed under MIT
|
|
6
|
+
* Copyright 2023 Nezanuha
|
|
7
|
+
*/
|
|
8
|
+
|
|
1
9
|
import { NotificationOptions } from './interfaces';
|
|
2
|
-
import { TimeoutId } from './types';
|
|
10
|
+
import type { ArriveFrom, TimeoutId } from './types';
|
|
11
|
+
import "./styles.css"
|
|
12
|
+
import { config } from './config';
|
|
3
13
|
|
|
4
14
|
export default class Notification {
|
|
5
15
|
effect: string;
|
|
6
16
|
escapeTime: number;
|
|
7
17
|
arriveTime: number;
|
|
8
18
|
autoClose: boolean;
|
|
19
|
+
arriveFrom: ArriveFrom;
|
|
9
20
|
element: HTMLElement | null;
|
|
10
21
|
timeoutId: TimeoutId;
|
|
11
22
|
|
|
12
|
-
constructor({ effect = 'fade', escapeTime = 3000, arriveTime = 200, autoClose = true, element = null }: NotificationOptions = {}) {
|
|
23
|
+
constructor({ effect = 'fade', escapeTime = 3000, arriveTime = 200, autoClose = true, arriveFrom = 'right', element = null }: NotificationOptions = {}) {
|
|
13
24
|
this.effect = effect;
|
|
14
25
|
this.arriveTime = arriveTime;
|
|
15
26
|
this.autoClose = autoClose;
|
|
27
|
+
this.arriveFrom = arriveFrom;
|
|
16
28
|
this.escapeTime = escapeTime;
|
|
17
29
|
this.element = element;
|
|
18
30
|
this.timeoutId = null; // Initialize timeout ID as null
|
|
19
31
|
this.render();
|
|
20
|
-
this.
|
|
32
|
+
this.init();
|
|
21
33
|
}
|
|
22
34
|
|
|
23
35
|
render() {
|
|
24
|
-
if (this.element) {
|
|
25
|
-
document.
|
|
36
|
+
if (typeof this.element === 'string') {
|
|
37
|
+
const tempDiv = document.createElement('div');
|
|
38
|
+
tempDiv.innerHTML = this.element;
|
|
39
|
+
this.element = tempDiv.firstChild as HTMLElement;
|
|
40
|
+
this.element.setAttribute("data-fj", "user-element");
|
|
26
41
|
}
|
|
27
|
-
|
|
42
|
+
|
|
43
|
+
// Inside the render method of the Notification class
|
|
44
|
+
if (this.element instanceof HTMLElement) {
|
|
45
|
+
let container = document.querySelector<HTMLElement>("[data-fj='notification']");
|
|
46
|
+
if (!container) {
|
|
47
|
+
container = document.createElement('div');
|
|
48
|
+
container.setAttribute('data-fj', 'notification');
|
|
49
|
+
document.querySelector("body")?.insertAdjacentElement('beforeend', container);
|
|
50
|
+
}
|
|
28
51
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const container = self.closest<HTMLElement>("[data-fj='notification']");
|
|
34
|
-
if (container) {
|
|
35
|
-
this.toggleNotification(container);
|
|
36
|
-
}
|
|
52
|
+
// Check if the element being appended is not the same as the container itself
|
|
53
|
+
if (this.element !== container) {
|
|
54
|
+
container.appendChild(this.element);
|
|
55
|
+
}
|
|
37
56
|
|
|
38
|
-
// Clear the timeout when the click event occurs
|
|
39
|
-
if (this.timeoutId !== null) {
|
|
40
|
-
clearTimeout(this.timeoutId);
|
|
41
|
-
this.timeoutId = null;
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
57
|
|
|
46
|
-
|
|
58
|
+
if (this.effect == 'slide') {
|
|
59
|
+
const arriveFromClass = config.arriveFrom[this.arriveFrom];
|
|
60
|
+
this.element.classList.add(arriveFromClass, 'duration-300');
|
|
61
|
+
} else {
|
|
62
|
+
this.element.classList.add('opacity-0', 'duration-300');
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
console.error("No element provided. Element must be either an HTMLElement or a string representing raw HTML.");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
47
69
|
this.timeoutId = setTimeout(() => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this.toggleNotification(container);
|
|
51
|
-
});
|
|
52
|
-
this.timeoutId = null; // Reset timeout ID after it's triggered
|
|
70
|
+
this.toggleNotification(this.element); // Pass the current element to toggleNotification
|
|
71
|
+
this.timeoutId = null;
|
|
53
72
|
}, this.arriveTime);
|
|
54
|
-
|
|
73
|
+
|
|
55
74
|
if (this.autoClose === true) {
|
|
56
75
|
this.timeoutId = setTimeout(() => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
this.toggleNotification(container);
|
|
60
|
-
});
|
|
61
|
-
this.timeoutId = null; // Reset timeout ID after it's triggered
|
|
76
|
+
this.toggleNotification(this.element, 'close'); // Pass the current element to toggleNotification
|
|
77
|
+
this.timeoutId = null;
|
|
62
78
|
}, this.escapeTime);
|
|
63
79
|
}
|
|
64
80
|
}
|
|
65
81
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
82
|
+
init() {
|
|
83
|
+
const handleClick = (e: MouseEvent) => {
|
|
84
|
+
const self = e.target as HTMLElement;
|
|
85
|
+
const userElement = self.closest<HTMLElement>("[data-fj='user-element']");
|
|
86
|
+
if (userElement) {
|
|
87
|
+
this.toggleNotification(userElement, 'close');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (this.timeoutId !== null) {
|
|
91
|
+
clearTimeout(this.timeoutId);
|
|
92
|
+
this.timeoutId = null;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// Add event listeners only once for all toggle buttons
|
|
97
|
+
const toggleButtons = document.querySelectorAll<HTMLElement>("[data-fj='toggle-btn']");
|
|
98
|
+
toggleButtons.forEach(button => {
|
|
99
|
+
// Check if the event listener is already added before adding it again
|
|
100
|
+
if (!button.dataset.clickEventAdded) {
|
|
101
|
+
button.dataset.clickEventAdded = "true"; // Set a flag to indicate that the event listener is added
|
|
102
|
+
button.addEventListener("click", handleClick);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
toggleNotification(container: HTMLElement | null, type?: string) {
|
|
108
|
+
if (container instanceof HTMLElement) {
|
|
109
|
+
if (this.effect == 'slide') {
|
|
110
|
+
const arriveFromClass = config.arriveFrom[this.arriveFrom];
|
|
111
|
+
container.classList.toggle(arriveFromClass, !container.classList.contains(arriveFromClass));
|
|
112
|
+
} else {
|
|
113
|
+
container.classList.toggle("opacity-0", !container.classList.contains("opacity-0"));
|
|
114
|
+
}
|
|
115
|
+
if (type === 'close') {
|
|
116
|
+
setTimeout(() => {
|
|
117
|
+
container.remove();
|
|
118
|
+
}, 300);
|
|
119
|
+
}
|
|
69
120
|
} else {
|
|
70
|
-
|
|
121
|
+
console.error("Container is null or not an HTMLElement.");
|
|
71
122
|
}
|
|
72
|
-
|
|
73
|
-
}
|
|
123
|
+
}
|
|
74
124
|
}
|
|
@@ -1,9 +1,23 @@
|
|
|
1
|
-
import { TimeoutId } from './types';
|
|
1
|
+
import type { ArriveFrom, TimeoutId } from './types';
|
|
2
2
|
|
|
3
3
|
export interface NotificationOptions {
|
|
4
4
|
effect?: string;
|
|
5
5
|
escapeTime?: number;
|
|
6
6
|
arriveTime?: number;
|
|
7
7
|
autoClose?: boolean;
|
|
8
|
+
arriveFrom?: ArriveFrom; // Use the ArriveFrom type here
|
|
8
9
|
element?: HTMLElement | null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Define your Config interface or type with index signature for effects
|
|
13
|
+
export interface NotificationConfig {
|
|
14
|
+
arriveFrom: {
|
|
15
|
+
right: string;
|
|
16
|
+
left: string;
|
|
17
|
+
bottom: string;
|
|
18
|
+
top: string;
|
|
19
|
+
};
|
|
20
|
+
effects: {
|
|
21
|
+
[key: string]: string; // Index signature for effects
|
|
22
|
+
};
|
|
9
23
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import "./styles.css"
|
|
2
|
+
export default class Popover {
|
|
3
|
+
autoPopup: boolean;
|
|
4
|
+
popupTime: number;
|
|
5
|
+
timeoutId: number | null;
|
|
6
|
+
|
|
7
|
+
constructor({ autoPopup = false, popupTime = 2000 }: { autoPopup?: boolean; popupTime?: number } = {}) {
|
|
8
|
+
this.autoPopup = autoPopup;
|
|
9
|
+
this.popupTime = popupTime;
|
|
10
|
+
this.timeoutId = null;
|
|
11
|
+
this.action();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
action(): void {
|
|
15
|
+
document.querySelectorAll<HTMLElement>(".fj-popover-toggle").forEach((event) => {
|
|
16
|
+
event.addEventListener("click", (e) => {
|
|
17
|
+
const self = e.target as HTMLElement;
|
|
18
|
+
const popoverContent = self.closest(".fj-popover")!.querySelector(".fj-popover-content") as HTMLElement | null;
|
|
19
|
+
if (popoverContent) {
|
|
20
|
+
this.togglePopover(popoverContent);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (this.timeoutId !== null) {
|
|
24
|
+
clearTimeout(this.timeoutId);
|
|
25
|
+
this.timeoutId = null;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
if (this.autoPopup === true) {
|
|
31
|
+
this.timeoutId = window.setTimeout(() => {
|
|
32
|
+
const popoverContents = document.querySelectorAll<HTMLElement>(".fj-popover .fj-popover-content");
|
|
33
|
+
popoverContents.forEach((popoverContent) => {
|
|
34
|
+
this.togglePopover(popoverContent);
|
|
35
|
+
});
|
|
36
|
+
this.timeoutId = null;
|
|
37
|
+
}, this.popupTime);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
togglePopover(popoverContent: HTMLElement): void {
|
|
42
|
+
popoverContent.classList.toggle("translate-y-0");
|
|
43
|
+
// Add other toggle logic here if needed
|
|
44
|
+
}
|
|
45
|
+
}
|