@myusufazmi/ultimate-tools 1.0.0
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/LICENSE +15 -0
- package/README.md +52 -0
- package/package.json +35 -0
- package/src/dom.js +70 -0
- package/src/http.js +60 -0
- package/src/index.js +5 -0
- package/src/state.js +46 -0
- package/src/storage.js +58 -0
- package/src/utils.js +67 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, Your Name
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Ultimate JS Tools
|
|
2
|
+
|
|
3
|
+
A lightweight, high-performance, and modular JavaScript utility library designed for modern web applications. No external dependencies.
|
|
4
|
+
|
|
5
|
+
## Modules
|
|
6
|
+
|
|
7
|
+
### DOM Utilities (`dom.js`)
|
|
8
|
+
|
|
9
|
+
- `$(selector, context)`: Fast query selector.
|
|
10
|
+
- `$$(selector, context)`: Query selector all returning an array.
|
|
11
|
+
- `create(tag, options)`: Advanced element creation.
|
|
12
|
+
- `on(parent, event, selector, handler)`: Efficient event delegation.
|
|
13
|
+
|
|
14
|
+
### HTTP Utilities (`http.js`)
|
|
15
|
+
|
|
16
|
+
- `http.get(url, options)`
|
|
17
|
+
- `http.post(url, body, options)`
|
|
18
|
+
- `http.put(url, body, options)`
|
|
19
|
+
- `http.delete(url, options)`
|
|
20
|
+
- Supports JSON by default and interceptors.
|
|
21
|
+
|
|
22
|
+
### Storage Utilities (`storage.js`)
|
|
23
|
+
|
|
24
|
+
- `local.set(key, value)`, `local.get(key, fallback)`
|
|
25
|
+
- `session.set(key, value)`, `session.get(key, fallback)`
|
|
26
|
+
- Auto-serialization/deserialization for all data types.
|
|
27
|
+
|
|
28
|
+
### State Management (`state.js`)
|
|
29
|
+
|
|
30
|
+
- `createStore(initialValue)`: Reactive state management with `subscribe`, `update`, and `get`.
|
|
31
|
+
|
|
32
|
+
### General Utilities (`utils.js`)
|
|
33
|
+
|
|
34
|
+
- `debounce(fn, delay)`
|
|
35
|
+
- `throttle(fn, limit)`
|
|
36
|
+
- `deepClone(obj)`
|
|
37
|
+
- `uuid()`: Simple unique ID generator.
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
```javascript
|
|
42
|
+
import { $, on, createStore } from "./src/index.js";
|
|
43
|
+
|
|
44
|
+
const count = createStore(0);
|
|
45
|
+
count.subscribe((val) => console.log("Count:", val));
|
|
46
|
+
|
|
47
|
+
on(document, "click", "#btn", () => count.update((n) => n + 1));
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Demo
|
|
51
|
+
|
|
52
|
+
Open `examples/index.html` in your browser to see the tools in action.
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@myusufazmi/ultimate-tools",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Modern JS utility library for high-performance projects",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"module": "src/index.js",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"files": [
|
|
9
|
+
"src",
|
|
10
|
+
"README.md",
|
|
11
|
+
"LICENSE"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
15
|
+
"serve": "npx -y lite-server"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"javascript",
|
|
19
|
+
"utilities",
|
|
20
|
+
"dom",
|
|
21
|
+
"state",
|
|
22
|
+
"http",
|
|
23
|
+
"storage"
|
|
24
|
+
],
|
|
25
|
+
"author": "Your Name",
|
|
26
|
+
"license": "ISC",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/yourusername/ultimate-tools.git"
|
|
30
|
+
},
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/yourusername/ultimate-tools/issues"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/yourusername/ultimate-tools#readme"
|
|
35
|
+
}
|
package/src/dom.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM Utilities
|
|
3
|
+
* Premium query selectors and manipulation tools.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Higher performance querySelector wrapper
|
|
8
|
+
* @param {string} selector
|
|
9
|
+
* @param {HTMLElement|Document} context
|
|
10
|
+
* @returns {HTMLElement|null}
|
|
11
|
+
*/
|
|
12
|
+
export const $ = (selector, context = document) => {
|
|
13
|
+
return context.querySelector(selector);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* querySelectorAll wrapper that returns an array instead of a NodeList
|
|
18
|
+
* @param {string} selector
|
|
19
|
+
* @param {HTMLElement|Document} context
|
|
20
|
+
* @returns {HTMLElement[]}
|
|
21
|
+
*/
|
|
22
|
+
export const $$ = (selector, context = document) => {
|
|
23
|
+
return Array.from(context.querySelectorAll(selector));
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Create element with attributes and styles
|
|
28
|
+
* @param {string} tag
|
|
29
|
+
* @param {Object} options
|
|
30
|
+
* @returns {HTMLElement}
|
|
31
|
+
*/
|
|
32
|
+
export const create = (tag, options = {}) => {
|
|
33
|
+
const el = document.createElement(tag);
|
|
34
|
+
const {
|
|
35
|
+
attr = {},
|
|
36
|
+
style = {},
|
|
37
|
+
text = "",
|
|
38
|
+
html = "",
|
|
39
|
+
children = [],
|
|
40
|
+
} = options;
|
|
41
|
+
|
|
42
|
+
Object.entries(attr).forEach(([k, v]) => el.setAttribute(k, v));
|
|
43
|
+
Object.assign(el.style, style);
|
|
44
|
+
|
|
45
|
+
if (text) el.textContent = text;
|
|
46
|
+
if (html) el.innerHTML = html;
|
|
47
|
+
|
|
48
|
+
children.forEach((child) => {
|
|
49
|
+
if (child instanceof HTMLElement) el.appendChild(child);
|
|
50
|
+
else el.append(child);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
return el;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Event delegation helper
|
|
58
|
+
* @param {HTMLElement|Document} parent
|
|
59
|
+
* @param {string} event
|
|
60
|
+
* @param {string} selector
|
|
61
|
+
* @param {Function} handler
|
|
62
|
+
*/
|
|
63
|
+
export const on = (parent, event, selector, handler) => {
|
|
64
|
+
parent.addEventListener(event, (e) => {
|
|
65
|
+
const target = e.target.closest(selector);
|
|
66
|
+
if (target && parent.contains(target)) {
|
|
67
|
+
handler.call(target, e, target);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
};
|
package/src/http.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Utilities
|
|
3
|
+
* Clean Fetch API wrapper with easy JSON handling and interceptors.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const request = async (url, options = {}) => {
|
|
7
|
+
const {
|
|
8
|
+
method = "GET",
|
|
9
|
+
headers = {},
|
|
10
|
+
body = null,
|
|
11
|
+
interceptors = { request: [], response: [] },
|
|
12
|
+
} = options;
|
|
13
|
+
|
|
14
|
+
let config = {
|
|
15
|
+
method,
|
|
16
|
+
headers: {
|
|
17
|
+
"Content-Type": "application/json",
|
|
18
|
+
...headers,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
if (body && typeof body === "object") {
|
|
23
|
+
config.body = JSON.stringify(body);
|
|
24
|
+
} else if (body) {
|
|
25
|
+
config.body = body;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Request Interceptors
|
|
29
|
+
interceptors.request.forEach((fn) => {
|
|
30
|
+
config = fn(config) || config;
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
const response = await fetch(url, config);
|
|
35
|
+
let data = await response.json().catch(() => null);
|
|
36
|
+
|
|
37
|
+
// Response Interceptors
|
|
38
|
+
interceptors.response.forEach((fn) => {
|
|
39
|
+
data = fn(data, response) || data;
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
throw { status: response.status, data };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return data;
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.error("Fetch Error:", error);
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const http = {
|
|
54
|
+
get: (url, options) => request(url, { ...options, method: "GET" }),
|
|
55
|
+
post: (url, body, options) =>
|
|
56
|
+
request(url, { ...options, method: "POST", body }),
|
|
57
|
+
put: (url, body, options) =>
|
|
58
|
+
request(url, { ...options, method: "PUT", body }),
|
|
59
|
+
delete: (url, options) => request(url, { ...options, method: "DELETE" }),
|
|
60
|
+
};
|
package/src/index.js
ADDED
package/src/state.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State Management
|
|
3
|
+
* A tiny reactive store (inspired by Svelte stores).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Creates a reactive store
|
|
8
|
+
* @param {any} initialValue
|
|
9
|
+
* @returns {Object}
|
|
10
|
+
*/
|
|
11
|
+
export const createStore = (initialValue) => {
|
|
12
|
+
let value = initialValue;
|
|
13
|
+
const subscribers = new Set();
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Subscribe to changes
|
|
17
|
+
* @param {Function} fn
|
|
18
|
+
* @returns {Function} Unsubscribe function
|
|
19
|
+
*/
|
|
20
|
+
const subscribe = (fn) => {
|
|
21
|
+
subscribers.add(fn);
|
|
22
|
+
fn(value);
|
|
23
|
+
return () => subscribers.delete(fn);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Update value and notify subscribers
|
|
28
|
+
* @param {any|Function} newValue
|
|
29
|
+
*/
|
|
30
|
+
const update = (newValue) => {
|
|
31
|
+
if (typeof newValue === "function") {
|
|
32
|
+
value = newValue(value);
|
|
33
|
+
} else {
|
|
34
|
+
value = newValue;
|
|
35
|
+
}
|
|
36
|
+
subscribers.forEach((fn) => fn(value));
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get current value
|
|
41
|
+
* @returns {any}
|
|
42
|
+
*/
|
|
43
|
+
const get = () => value;
|
|
44
|
+
|
|
45
|
+
return { subscribe, update, get };
|
|
46
|
+
};
|
package/src/storage.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage Utilities
|
|
3
|
+
* Type-safe and auto-serialized local/session storage.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const createStorage = (type = "localStorage") => {
|
|
7
|
+
const storage = window[type];
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
/**
|
|
11
|
+
* Set item with auto-serialization
|
|
12
|
+
* @param {string} key
|
|
13
|
+
* @param {any} value
|
|
14
|
+
*/
|
|
15
|
+
set(key, value) {
|
|
16
|
+
try {
|
|
17
|
+
const serialized = JSON.stringify(value);
|
|
18
|
+
storage.setItem(key, serialized);
|
|
19
|
+
} catch (e) {
|
|
20
|
+
console.error(`Storage Error (set): ${key}`, e);
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get item with auto-deserialization
|
|
26
|
+
* @param {string} key
|
|
27
|
+
* @param {any} fallback
|
|
28
|
+
* @returns {any}
|
|
29
|
+
*/
|
|
30
|
+
get(key, fallback = null) {
|
|
31
|
+
try {
|
|
32
|
+
const item = storage.getItem(key);
|
|
33
|
+
return item ? JSON.parse(item) : fallback;
|
|
34
|
+
} catch (e) {
|
|
35
|
+
console.error(`Storage Error (get): ${key}`, e);
|
|
36
|
+
return fallback;
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Remove item
|
|
42
|
+
* @param {string} key
|
|
43
|
+
*/
|
|
44
|
+
remove(key) {
|
|
45
|
+
storage.removeItem(key);
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Clear all items
|
|
50
|
+
*/
|
|
51
|
+
clear() {
|
|
52
|
+
storage.clear();
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const local = createStorage("localStorage");
|
|
58
|
+
export const session = createStorage("sessionStorage");
|
package/src/utils.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* General Utilities
|
|
3
|
+
* Common helper functions.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Debounce function
|
|
8
|
+
* @param {Function} fn
|
|
9
|
+
* @param {number} delay
|
|
10
|
+
* @returns {Function}
|
|
11
|
+
*/
|
|
12
|
+
export const debounce = (fn, delay = 300) => {
|
|
13
|
+
let timeout;
|
|
14
|
+
return (...args) => {
|
|
15
|
+
clearTimeout(timeout);
|
|
16
|
+
timeout = setTimeout(() => fn.apply(this, args), delay);
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Throttle function
|
|
22
|
+
* @param {Function} fn
|
|
23
|
+
* @param {number} limit
|
|
24
|
+
* @returns {Function}
|
|
25
|
+
*/
|
|
26
|
+
export const throttle = (fn, limit = 300) => {
|
|
27
|
+
let lastFunc;
|
|
28
|
+
let lastRan;
|
|
29
|
+
return (...args) => {
|
|
30
|
+
if (!lastRan) {
|
|
31
|
+
fn.apply(this, args);
|
|
32
|
+
lastRan = Date.now();
|
|
33
|
+
} else {
|
|
34
|
+
clearTimeout(lastFunc);
|
|
35
|
+
lastFunc = setTimeout(
|
|
36
|
+
() => {
|
|
37
|
+
if (Date.now() - lastRan >= limit) {
|
|
38
|
+
fn.apply(this, args);
|
|
39
|
+
lastRan = Date.now();
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
limit - (Date.now() - lastRan),
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Deep clone an object
|
|
50
|
+
* @param {any} obj
|
|
51
|
+
* @returns {any}
|
|
52
|
+
*/
|
|
53
|
+
export const deepClone = (obj) => {
|
|
54
|
+
if (obj === null || typeof obj !== "object") return obj;
|
|
55
|
+
return JSON.parse(JSON.stringify(obj));
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Generates a simple UUID-like string
|
|
60
|
+
* @returns {string}
|
|
61
|
+
*/
|
|
62
|
+
export const uuid = () => {
|
|
63
|
+
return (
|
|
64
|
+
Math.random().toString(36).substring(2, 10) +
|
|
65
|
+
Date.now().toString(36).substring(2, 6)
|
|
66
|
+
);
|
|
67
|
+
};
|