frutjam 0.0.6 → 0.0.8-alpha.1

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/README.md DELETED
@@ -1,78 +0,0 @@
1
- ## Frutjam Useful Prebuilt Plugins & UI Components for TailwindCSS
2
-
3
- Frutjam is a powerful library with an array of useful plugins and UI components created exclusively for use with Tailwind CSS. Whether you're creating a web app, a website, or a digital product, Frutjam offers a variety of tools to help you boost your development process and improve user experience. Furthermore, it provides numerous customization options within its plugins, allowing you to design your solutions precisely to your requirements.
4
-
5
- ## Table of Contents
6
-
7
- - [Installation](#installation)
8
- - [Usage](#usage)
9
- - [License](#license)
10
-
11
- ## Documentations
12
- For detail documentation, visit [frutjam.com](https://frutjam.com)
13
-
14
- ## Key Features:
15
-
16
- 1. **Tailwind CSS Integration:** Frutjam is designed to work easily with Tailwind CSS, a well-known utility-focused CSS framework. This integration allows you to use the full power of Tailwind's utility classes while also benefiting from Frutjam's additional features.
17
-
18
- 2. **Useful Plugins:** Frutjam is releasing a number of plugins that will enhance your projects' functionality. These plugins include features like notifications, modals, sliders, form elements, and more. Each plugin is intended to be simple to use, adaptable, and compatible with current web development methods.
19
-
20
- 3. **UI Components:** In addition to plugins, Frutjam provides an extensive collection of UI components that can be simply integrated into your projects. From navigation menus and cards to buttons and input fields, these components are designed to be accessible, responsive, and visually appealing.
21
-
22
- 4. **Framework & Libraries Support:** Written in TypeScript, Frutjam supports CommonJS (CJS) and ECMAScript Modules (ESM). It is being developed to support new web frameworks and libraries, such as React, Next.js, Vue, and others.
23
-
24
- 5. **MIT License:** Frutjam is released under the MIT License, allowing you the freedom to use, alter, and distribute the library as needed for both commercial and personal projects.
25
-
26
- Whether you're a beginner exploring web development or an experienced developer looking for efficient tools, Frutjam offers a versatile set of resources to streamline your projects and elevate the user experience.
27
-
28
- ## Getting started
29
-
30
- Whether you're a newbie exploring web development or an experienced developer seeking for efficient tools, Frutjam provides a diverse variety of resources to help you streamline your projects and improve the user experience.
31
-
32
- ## Installation
33
-
34
- You can install Frutjam via npm:
35
-
36
- ```bash
37
- npm install frutjam
38
- ```
39
-
40
- ## Usage
41
-
42
- Import the `Notification` class from Frutjam:
43
-
44
- ```typescript
45
- import { Notification } from "frutjam";
46
- ```
47
-
48
- Create a new notification instance with custom configurations:
49
-
50
- ```typescript
51
- new Notification({
52
- effect: "slide",
53
- escapeTime: 5000,
54
- autoClose: false,
55
- arriveFrom: "top",
56
- element: "<div class='your-customizable-design-class'><button type='button' data-fj='toggle-btn'>Close</button><!-- Add your other elements here --></div>"
57
- });
58
- ```
59
-
60
- ### Configuration Options
61
-
62
- - `effect`: Choose between "fade" or "slide" for the notification effect.
63
- - `escapeTime`: Time in milliseconds before the notification automatically closes.
64
- - `arriveTime`: specifies the time in milliseconds after which the notification's arrival animation completes.
65
- - `autoClose`: Boolean to enable or disable automatic closing of the notification.
66
- - `arriveFrom`: Direction from which the notification should arrive ("left", "right", "top", "bottom").
67
- - `element`: Customise your own HTML element to be displayed in the notification.
68
-
69
- `<button type='button' data-fj='toggle-btn'>Close</button>`
70
- To enable manual closing of the current element, set the `data-fj='toggle-btn'` attribute to button.
71
-
72
- ## License
73
-
74
- Frutjam is Open Source project licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.
75
-
76
- ## Support
77
-
78
- For any questions or issues, please [open an issue](https://github.com/nezanuha/frutjam/issues) on GitHub.
package/src/index.ts DELETED
@@ -1,4 +0,0 @@
1
- export { default as Notification } from './plugins/notification'
2
- export { default as TelephoneInput } from './plugins/telephoneInput'
3
- export { default as Popover } from './plugins/popover'
4
- export { default as Tabs } from './plugins/tabs'
@@ -1,14 +0,0 @@
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,124 +0,0 @@
1
- /*
2
- * Notification
3
- * @version: 0.0.2
4
- * @author: Nezanuha
5
- * @license: Licensed under MIT
6
- * Copyright 2024 Nezanuha
7
- */
8
-
9
- import { NotificationOptions } from './interfaces';
10
- import type { ArriveFrom, TimeoutId } from './types';
11
- import "./styles.css"
12
- import { config } from './config';
13
-
14
- export default class Notification {
15
- effect: string;
16
- escapeTime: number;
17
- arriveTime: number;
18
- autoClose: boolean;
19
- arriveFrom: ArriveFrom;
20
- element: HTMLElement | null;
21
- timeoutId: TimeoutId;
22
-
23
- constructor({ effect = 'fade', escapeTime = 3000, arriveTime = 200, autoClose = true, arriveFrom = 'right', element = null }: NotificationOptions = {}) {
24
- this.effect = effect;
25
- this.arriveTime = arriveTime;
26
- this.autoClose = autoClose;
27
- this.arriveFrom = arriveFrom;
28
- this.escapeTime = escapeTime;
29
- this.element = element;
30
- this.timeoutId = null; // Initialize timeout ID as null
31
- this.render();
32
- this.init();
33
- }
34
-
35
- render() {
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");
41
- }
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
- }
51
-
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
- }
56
-
57
-
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
-
69
- this.timeoutId = setTimeout(() => {
70
- this.toggleNotification(this.element); // Pass the current element to toggleNotification
71
- this.timeoutId = null;
72
- }, this.arriveTime);
73
-
74
- if (this.autoClose === true) {
75
- this.timeoutId = setTimeout(() => {
76
- this.toggleNotification(this.element, 'close'); // Pass the current element to toggleNotification
77
- this.timeoutId = null;
78
- }, this.escapeTime);
79
- }
80
- }
81
-
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
- }
120
- } else {
121
- console.error("Container is null or not an HTMLElement.");
122
- }
123
- }
124
- }
@@ -1,22 +0,0 @@
1
- import type { ArriveFrom, TimeoutId } from './types';
2
-
3
- export interface NotificationOptions {
4
- effect?: string;
5
- escapeTime?: number;
6
- arriveTime?: number;
7
- autoClose?: boolean;
8
- arriveFrom?: ArriveFrom;
9
- element?: HTMLElement | null;
10
- }
11
-
12
- export interface NotificationConfig {
13
- arriveFrom: {
14
- right: string;
15
- left: string;
16
- bottom: string;
17
- top: string;
18
- };
19
- effects: {
20
- [key: string]: string;
21
- };
22
- }
@@ -1,9 +0,0 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
4
-
5
- @layer utilities{
6
- [data-fj='notification'] {
7
- @apply overflow-hidden m-6 max-h-max
8
- }
9
- }
@@ -1,5 +0,0 @@
1
- type ArriveFrom = 'right' | 'left' | 'bottom' | 'top';
2
-
3
- type TimeoutId = ReturnType<typeof setTimeout> | null;
4
-
5
- export type { ArriveFrom, TimeoutId }
@@ -1,45 +0,0 @@
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
- }
@@ -1,12 +0,0 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
4
-
5
- @layer utilities{
6
- .fj-popover{
7
- @apply flex flex-col gap-3 justify-end items-end
8
- }
9
- .fj-popover-content{
10
- @apply max-w-lg w-full z-50 translate-y-[40rem] duration-300
11
- }
12
- }
@@ -1,112 +0,0 @@
1
-
2
- /*
3
- * Tabs
4
- * @version: 0.0.2
5
- * @author: Nezanuha
6
- * @license: Licensed under MIT
7
- * Copyright 2024 Nezanuha
8
- */
9
-
10
- import { TabOptions } from "./types";
11
-
12
- export default class Tabs {
13
- private tabs: HTMLElement[];
14
- private tabContents: HTMLElement[];
15
- private options: TabOptions;
16
-
17
- constructor(options?: TabOptions) {
18
- this.tabs = Array.from(document.querySelectorAll('.tab'));
19
- this.tabContents = Array.from(document.querySelectorAll('.tab-content'));
20
- this.options = options || {};
21
-
22
- this.init();
23
- this.handleInitialTabState();
24
- }
25
-
26
- private init() {
27
- this.tabs.forEach(tab => {
28
- tab.addEventListener('click', () => this.toggleTab(tab));
29
- });
30
- }
31
-
32
- private toggleTab(selectedTab: HTMLElement) {
33
- const tabId = selectedTab.dataset.tab;
34
-
35
- if (!tabId || selectedTab.classList.contains('disabled')) return;
36
-
37
- this.tabs.forEach(tab => {
38
- tab.classList.remove('active');
39
- });
40
- selectedTab.classList.add('active');
41
-
42
- this.tabContents.forEach(content => {
43
- if (content.id === tabId) {
44
- content.style.display = 'block';
45
- this.animateTab(content);
46
- if (this.options.onTabActive) {
47
- this.options.onTabActive(tabId);
48
- }
49
- } else {
50
- content.style.display = 'none';
51
- }
52
- });
53
- }
54
-
55
- private animateTab(content: HTMLElement) {
56
- // Implement your animation logic here
57
- content.style.opacity = '0';
58
- setTimeout(() => {
59
- content.style.opacity = '1';
60
- }, 300);
61
- }
62
-
63
- private handleInitialTabState() {
64
- if (this.options.disableTabs === 'all') {
65
- this.disableAllTabs();
66
- } else if (Array.isArray(this.options.disableTabs)) {
67
- this.disableTabs(this.options.disableTabs);
68
- } else if (this.options.enableTabs === 'all') {
69
- this.enableAllTabs();
70
- } else if (Array.isArray(this.options.enableTabs)) {
71
- this.enableTabs(this.options.enableTabs);
72
- }
73
- }
74
-
75
- private disableAllTabs() {
76
- this.tabs.forEach(tab => {
77
- tab.classList.add('disabled');
78
- });
79
- }
80
-
81
- private enableAllTabs() {
82
- this.tabs.forEach(tab => {
83
- tab.classList.remove('disabled');
84
- });
85
- }
86
-
87
- enableTabs(tabIds?: string[] | 'all') {
88
- if (tabIds === 'all') {
89
- this.enableAllTabs();
90
- } else if (Array.isArray(tabIds)) {
91
- tabIds.forEach(tabId => {
92
- const tab = this.tabs.find(tab => tab.dataset.tab === tabId);
93
- if (tab) {
94
- tab.classList.remove('disabled');
95
- }
96
- });
97
- }
98
- }
99
-
100
- disableTabs(tabIds?: string[] | 'all') {
101
- if (tabIds === 'all') {
102
- this.disableAllTabs();
103
- } else if (Array.isArray(tabIds)) {
104
- tabIds.forEach(tabId => {
105
- const tab = this.tabs.find(tab => tab.dataset.tab === tabId);
106
- if (tab) {
107
- tab.classList.add('disabled');
108
- }
109
- });
110
- }
111
- }
112
- }
@@ -1,7 +0,0 @@
1
- type TabOptions = {
2
- disableTabs?: string[] | 'all'; // Array of tab IDs to disable or 'all' to disable all tabs
3
- enableTabs?: string[] | 'all'; // Array of tab IDs to enable or 'all' to enable all tabs
4
- onTabActive?: (tabId: string) => void;
5
- };
6
-
7
- export type { TabOptions }