@gohanfromgoku/ui-kit 0.0.2 → 0.0.4
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/dist/api/index.js +82 -1
- package/dist/components/Button/index.js +21 -1
- package/dist/components/Image/index.js +19 -1
- package/dist/components/Input/index.js +16 -1
- package/dist/components/Text/index.js +21 -1
- package/dist/components/Tooltip/index.js +53 -1
- package/dist/helpers/checkProps.js +5 -1
- package/dist/helpers/objectPath.js +21 -1
- package/dist/helpers/toast.js +45 -1
- package/dist/hooks/useHandleClickOutside.js +17 -1
- package/dist/hooks/useQueryParams.js +31 -1
- package/dist/hooks/useWindowSize.js +13 -1
- package/dist/prototypes/copyToClipboard.js +23 -1
- package/dist/prototypes/index.js +6 -1
- package/dist/prototypes/maskString.js +13 -1
- package/dist/storage/index.js +51 -1
- package/dist/translations/index.js +34 -1
- package/package.json +5 -6
- package/types/api/index.d.ts +3 -1
package/dist/api/index.js
CHANGED
|
@@ -1 +1,82 @@
|
|
|
1
|
-
export const METHODS
|
|
1
|
+
export const METHODS = {
|
|
2
|
+
GET: "GET",
|
|
3
|
+
POST: "POST",
|
|
4
|
+
PUT: "PUT",
|
|
5
|
+
DELETE: "DELETE"
|
|
6
|
+
};
|
|
7
|
+
const appendParams = (url, params) => {
|
|
8
|
+
if (!params)
|
|
9
|
+
return url;
|
|
10
|
+
const urlParams = new URLSearchParams({ ...params }).toString();
|
|
11
|
+
return urlParams ? `${url}?${urlParams}` : url;
|
|
12
|
+
};
|
|
13
|
+
const parseResponse = async (res) => {
|
|
14
|
+
const contentType = res.headers.get("content-type") || "";
|
|
15
|
+
if (contentType.includes("application/json")) {
|
|
16
|
+
return await res.json().catch(() => null);
|
|
17
|
+
}
|
|
18
|
+
if (contentType.includes("text/")) {
|
|
19
|
+
return await res.text();
|
|
20
|
+
}
|
|
21
|
+
return await res.blob().catch(() => null);
|
|
22
|
+
};
|
|
23
|
+
export class API {
|
|
24
|
+
baseURL;
|
|
25
|
+
defaultHeaders = {};
|
|
26
|
+
timeout = 0;
|
|
27
|
+
constructor(baseURL, headers = {}, timeout = 0) {
|
|
28
|
+
this.baseURL = baseURL.replace(/\/+$/, "");
|
|
29
|
+
this.defaultHeaders = { "Content-Type": "application/json", ...headers };
|
|
30
|
+
this.timeout = timeout;
|
|
31
|
+
}
|
|
32
|
+
createURL(endpoint) {
|
|
33
|
+
if (endpoint.startsWith("http"))
|
|
34
|
+
return endpoint;
|
|
35
|
+
if (endpoint === "/" || endpoint === "")
|
|
36
|
+
return this.baseURL;
|
|
37
|
+
if (endpoint.startsWith("/"))
|
|
38
|
+
return `${this.baseURL}${endpoint}`;
|
|
39
|
+
return `${this.baseURL}/${endpoint}`;
|
|
40
|
+
}
|
|
41
|
+
async request(method, endpoint, opts = {}) {
|
|
42
|
+
const { params, headers, body, signal } = opts;
|
|
43
|
+
const url = appendParams(this.createURL(endpoint), params);
|
|
44
|
+
const headersWithDefaults = body instanceof FormData || method === METHODS.GET ? { ...headers } : { ...this.defaultHeaders, ...headers };
|
|
45
|
+
const fetchBody = body ? body instanceof FormData || typeof body === "string" ? body : JSON.stringify(body) : undefined;
|
|
46
|
+
const fetchAbortController = new AbortController();
|
|
47
|
+
const onAbort = () => fetchAbortController.abort();
|
|
48
|
+
let timeoutId = null;
|
|
49
|
+
try {
|
|
50
|
+
if (this.timeout > 0) {
|
|
51
|
+
timeoutId = setTimeout(onAbort, this.timeout);
|
|
52
|
+
}
|
|
53
|
+
if (signal) {
|
|
54
|
+
signal.addEventListener("abort", onAbort);
|
|
55
|
+
}
|
|
56
|
+
const res = await fetch(url, {
|
|
57
|
+
method,
|
|
58
|
+
body: fetchBody,
|
|
59
|
+
headers: headersWithDefaults,
|
|
60
|
+
signal: fetchAbortController.signal,
|
|
61
|
+
});
|
|
62
|
+
const data = await parseResponse(res);
|
|
63
|
+
if (!res.ok)
|
|
64
|
+
throw data || new Error(res.statusText);
|
|
65
|
+
return data;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.error(`${method}: ${endpoint} :: `, error);
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
if (timeoutId)
|
|
73
|
+
clearTimeout(timeoutId);
|
|
74
|
+
if (signal)
|
|
75
|
+
signal.removeEventListener("abort", onAbort);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
GET = (endpoint, opts) => this.request(METHODS.GET, endpoint, opts);
|
|
79
|
+
POST = (endpoint, opts) => this.request(METHODS.POST, endpoint, opts);
|
|
80
|
+
PUT = (endpoint, opts) => this.request(METHODS.PUT, endpoint, opts);
|
|
81
|
+
DELETE = (endpoint, opts) => this.request(METHODS.DELETE, endpoint, opts);
|
|
82
|
+
}
|
|
@@ -1 +1,21 @@
|
|
|
1
|
-
import{jsx as _jsx}from"preact/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
2
|
+
import { memo, forwardRef } from "preact/compat";
|
|
3
|
+
import checkProps from "../../helpers/checkProps";
|
|
4
|
+
const defaultProps = {
|
|
5
|
+
onClick: () => { },
|
|
6
|
+
disabled: false,
|
|
7
|
+
className: "",
|
|
8
|
+
type: "button",
|
|
9
|
+
};
|
|
10
|
+
const Button = forwardRef((props, ref) => {
|
|
11
|
+
const { children, className, onClick, disabled, type, ...rest } = { ...defaultProps, ...props };
|
|
12
|
+
return (_jsx("button", { ref: ref, className: className, onClick: (event) => {
|
|
13
|
+
if (type === "button" || !type) {
|
|
14
|
+
event.preventDefault();
|
|
15
|
+
}
|
|
16
|
+
if (!disabled && onClick) {
|
|
17
|
+
onClick(event);
|
|
18
|
+
}
|
|
19
|
+
}, ...rest, children: children }));
|
|
20
|
+
});
|
|
21
|
+
export default memo(Button, checkProps);
|
|
@@ -1 +1,19 @@
|
|
|
1
|
-
import{jsx as _jsx}from"preact/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
2
|
+
import { forwardRef, memo } from "preact/compat";
|
|
3
|
+
import checkProps from "../../helpers/checkProps";
|
|
4
|
+
const defaultProps = {
|
|
5
|
+
altImage: null,
|
|
6
|
+
className: "",
|
|
7
|
+
alt: "",
|
|
8
|
+
priority: true,
|
|
9
|
+
onClick: () => { }
|
|
10
|
+
};
|
|
11
|
+
const Image = forwardRef((props, ref) => {
|
|
12
|
+
const { altImage, className, src, priority, onClick, alt, ...rest } = { ...defaultProps, ...props };
|
|
13
|
+
return (_jsx("img", { src: src, ref: ref, width: "100%", height: "100%", onClick: (event) => { event.preventDefault(); onClick(event); }, draggable: false, onError: async () => {
|
|
14
|
+
if (ref && 'current' in ref && ref.current) {
|
|
15
|
+
ref.current.src = altImage || "";
|
|
16
|
+
}
|
|
17
|
+
}, alt: alt, className: className, fetchPriority: priority ? "high" : "auto", loading: priority ? "eager" : "lazy", ...rest }));
|
|
18
|
+
});
|
|
19
|
+
export default memo(Image, checkProps);
|
|
@@ -1 +1,16 @@
|
|
|
1
|
-
import{jsx as _jsx}from"preact/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
2
|
+
import { memo } from "preact/compat";
|
|
3
|
+
import checkProps from "../../helpers/checkProps";
|
|
4
|
+
import { translate } from "../../translations/index";
|
|
5
|
+
const defaultProps = {
|
|
6
|
+
onChange: () => { },
|
|
7
|
+
className: "",
|
|
8
|
+
placeholder: "",
|
|
9
|
+
type: "text",
|
|
10
|
+
name: ""
|
|
11
|
+
};
|
|
12
|
+
const Input = (props) => {
|
|
13
|
+
const { onChange, className, placeholder, type, name, ...rest } = { ...defaultProps, ...props };
|
|
14
|
+
return _jsx("input", { className: className, placeholder: translate(placeholder), type: type, name: name, onChange: event => onChange(event.currentTarget.value, event), ...rest });
|
|
15
|
+
};
|
|
16
|
+
export default memo(Input, checkProps);
|
|
@@ -1 +1,21 @@
|
|
|
1
|
-
import{jsx as _jsx}from"preact/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
2
|
+
import checkProps from "../../helpers/checkProps";
|
|
3
|
+
import { translate } from "../../translations/index";
|
|
4
|
+
import { forwardRef, memo, useMemo } from "preact/compat";
|
|
5
|
+
const defaultProps = {
|
|
6
|
+
text: "",
|
|
7
|
+
data: {},
|
|
8
|
+
html: false,
|
|
9
|
+
className: "",
|
|
10
|
+
tag: "span",
|
|
11
|
+
onClick: () => { },
|
|
12
|
+
};
|
|
13
|
+
const Text = forwardRef((props, ref) => {
|
|
14
|
+
const { text, data, html, className, tag: Tag, onClick, ...rest } = { ...defaultProps, ...props };
|
|
15
|
+
const translated = useMemo(() => translate(text, data), [text, JSON.stringify(data)]);
|
|
16
|
+
if (html) {
|
|
17
|
+
return (_jsx(Tag, { ...rest, ref: ref, dangerouslySetInnerHTML: { __html: translated }, className: className, onClick: (event) => { event.preventDefault(); onClick(event); } }));
|
|
18
|
+
}
|
|
19
|
+
return (_jsx(Tag, { ...rest, ref: ref, className: className, onClick: (event) => { event.preventDefault(); onClick(event); }, children: translated }));
|
|
20
|
+
});
|
|
21
|
+
export default memo(Text, checkProps);
|
|
@@ -1 +1,53 @@
|
|
|
1
|
-
import{jsx as _jsx}from"preact/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef } from "preact/hooks";
|
|
3
|
+
import { memo } from "preact/compat";
|
|
4
|
+
import checkProps from "../../helpers/checkProps";
|
|
5
|
+
import toast from "../../helpers/toast";
|
|
6
|
+
import { translate } from "../../translations/index";
|
|
7
|
+
const isTouchDevice = () => typeof window !== "undefined" && "ontouchstart" in window;
|
|
8
|
+
const styles = {
|
|
9
|
+
width: "fit-content",
|
|
10
|
+
height: "fit-content"
|
|
11
|
+
};
|
|
12
|
+
const Tooltip = ({ message, children, className }) => {
|
|
13
|
+
const ref = useRef(null);
|
|
14
|
+
const toastRef = useRef(null);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
return () => {
|
|
17
|
+
toastRef.current?.();
|
|
18
|
+
toastRef.current = null;
|
|
19
|
+
};
|
|
20
|
+
}, []);
|
|
21
|
+
const showToast = () => {
|
|
22
|
+
if (ref.current) {
|
|
23
|
+
toastRef.current = toast(translate(message), ref.current, 0);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const hideToast = () => {
|
|
27
|
+
toastRef.current?.();
|
|
28
|
+
toastRef.current = null;
|
|
29
|
+
};
|
|
30
|
+
return (_jsx("section", { className: `${styles} ${className || ""}`, ref: ref, onMouseEnter: (e) => {
|
|
31
|
+
if (isTouchDevice())
|
|
32
|
+
return;
|
|
33
|
+
e.stopPropagation();
|
|
34
|
+
e.preventDefault();
|
|
35
|
+
showToast();
|
|
36
|
+
}, onMouseLeave: (e) => {
|
|
37
|
+
if (isTouchDevice())
|
|
38
|
+
return;
|
|
39
|
+
e.stopPropagation();
|
|
40
|
+
e.preventDefault();
|
|
41
|
+
hideToast();
|
|
42
|
+
}, onClick: (e) => {
|
|
43
|
+
e.stopPropagation();
|
|
44
|
+
e.preventDefault();
|
|
45
|
+
if (!isTouchDevice())
|
|
46
|
+
return;
|
|
47
|
+
if (toastRef.current)
|
|
48
|
+
hideToast();
|
|
49
|
+
else
|
|
50
|
+
toastRef.current = toast(translate(message), ref.current, 2000);
|
|
51
|
+
}, children: children }));
|
|
52
|
+
};
|
|
53
|
+
export default memo(Tooltip, checkProps);
|
|
@@ -1 +1,5 @@
|
|
|
1
|
-
const checkProps=(
|
|
1
|
+
const checkProps = (prevProps, nextProps) => {
|
|
2
|
+
const allKeys = Array.from(new Set([...Object.keys(prevProps), ...Object.keys(nextProps)]));
|
|
3
|
+
return allKeys.every(key => prevProps[key] === nextProps[key]);
|
|
4
|
+
};
|
|
5
|
+
export default checkProps;
|
|
@@ -1 +1,21 @@
|
|
|
1
|
-
const getPath=
|
|
1
|
+
const getPath = (object, path) => {
|
|
2
|
+
if (!object)
|
|
3
|
+
return undefined;
|
|
4
|
+
return path
|
|
5
|
+
.split('.')
|
|
6
|
+
.reduce((current, segment) => {
|
|
7
|
+
if (current == null || !(segment in current)) {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
return current[segment];
|
|
11
|
+
}, object);
|
|
12
|
+
};
|
|
13
|
+
const hasPath = (obj, path) => {
|
|
14
|
+
return getPath(obj, path) !== undefined;
|
|
15
|
+
};
|
|
16
|
+
const objectPath = (root) => ({
|
|
17
|
+
get: (p) => getPath(root, p),
|
|
18
|
+
has: (p) => hasPath(root, p),
|
|
19
|
+
print: () => root,
|
|
20
|
+
});
|
|
21
|
+
export default objectPath;
|
package/dist/helpers/toast.js
CHANGED
|
@@ -1 +1,45 @@
|
|
|
1
|
-
const toast=
|
|
1
|
+
const toast = (message, target, duration = 1500) => {
|
|
2
|
+
if (!target)
|
|
3
|
+
return;
|
|
4
|
+
const rect = target.getBoundingClientRect();
|
|
5
|
+
const el = document.createElement("div");
|
|
6
|
+
el.textContent = message;
|
|
7
|
+
el.className = "cursor-toast";
|
|
8
|
+
el.style.opacity = "0";
|
|
9
|
+
el.style.position = "fixed";
|
|
10
|
+
el.style.top = "0";
|
|
11
|
+
el.style.left = "0";
|
|
12
|
+
el.style.transform = "translateY(0)";
|
|
13
|
+
el.style.transition = "opacity 0.3s ease, transform 0.3s ease";
|
|
14
|
+
document.body.appendChild(el);
|
|
15
|
+
requestAnimationFrame(() => {
|
|
16
|
+
const toastRect = el.getBoundingClientRect();
|
|
17
|
+
let top = rect.top - toastRect.height - 8;
|
|
18
|
+
let left = rect.left + rect.width / 2 - toastRect.width / 2;
|
|
19
|
+
top = Math.max(8, Math.min(top, window.innerHeight - toastRect.height - 8));
|
|
20
|
+
left = Math.max(8, Math.min(left, window.innerWidth - toastRect.width - 8));
|
|
21
|
+
Object.assign(el.style, {
|
|
22
|
+
top: `${top}px`,
|
|
23
|
+
left: `${left}px`,
|
|
24
|
+
opacity: "1",
|
|
25
|
+
transform: "translateY(-4px)",
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
let hideTimeout = null;
|
|
29
|
+
const hide = () => {
|
|
30
|
+
if (!el.isConnected)
|
|
31
|
+
return;
|
|
32
|
+
el.style.opacity = "0";
|
|
33
|
+
el.style.transform = "translateY(0)";
|
|
34
|
+
setTimeout(() => el.remove(), 300);
|
|
35
|
+
};
|
|
36
|
+
if (duration > 0) {
|
|
37
|
+
hideTimeout = setTimeout(hide, duration);
|
|
38
|
+
}
|
|
39
|
+
return () => {
|
|
40
|
+
if (hideTimeout)
|
|
41
|
+
clearTimeout(hideTimeout);
|
|
42
|
+
hide();
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
export default toast;
|
|
@@ -1 +1,17 @@
|
|
|
1
|
-
import{useEffect}from"preact/compat";
|
|
1
|
+
import { useEffect } from "preact/compat";
|
|
2
|
+
const useHandleClickOutside = (ref, cb) => {
|
|
3
|
+
useEffect(() => {
|
|
4
|
+
const handlePointerDown = (event) => {
|
|
5
|
+
if (!ref.current)
|
|
6
|
+
return;
|
|
7
|
+
if (!ref.current.contains(event.target)) {
|
|
8
|
+
cb();
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
document.addEventListener("pointerdown", handlePointerDown, { passive: true });
|
|
12
|
+
return () => {
|
|
13
|
+
document.removeEventListener("pointerdown", handlePointerDown);
|
|
14
|
+
};
|
|
15
|
+
}, [ref, cb]);
|
|
16
|
+
};
|
|
17
|
+
export default useHandleClickOutside;
|
|
@@ -1 +1,31 @@
|
|
|
1
|
-
import{signal}from"@preact/signals";
|
|
1
|
+
import { signal } from "@preact/signals";
|
|
2
|
+
const queryParamsSignal = signal({});
|
|
3
|
+
const getParams = () => {
|
|
4
|
+
const search = window.location.search.slice(1);
|
|
5
|
+
const params = new URLSearchParams(search);
|
|
6
|
+
const obj = {};
|
|
7
|
+
for (const [key, value] of params.entries())
|
|
8
|
+
obj[key] = value;
|
|
9
|
+
return obj;
|
|
10
|
+
};
|
|
11
|
+
queryParamsSignal.value = getParams();
|
|
12
|
+
window.addEventListener("popstate", () => {
|
|
13
|
+
queryParamsSignal.value = getParams();
|
|
14
|
+
});
|
|
15
|
+
export const setQueryParams = (updates, { replace = false, pathname } = {}) => {
|
|
16
|
+
const params = new URLSearchParams();
|
|
17
|
+
Object.entries(updates).forEach(([key, value]) => {
|
|
18
|
+
if (value !== null && value !== undefined)
|
|
19
|
+
params.set(key, value);
|
|
20
|
+
});
|
|
21
|
+
const queryString = params.toString();
|
|
22
|
+
const currentPath = window.location.pathname;
|
|
23
|
+
const newPath = pathname ?? currentPath;
|
|
24
|
+
const newUrl = queryString ? `${newPath}?${queryString}` : newPath;
|
|
25
|
+
if (replace)
|
|
26
|
+
window.history.replaceState({}, "", newUrl);
|
|
27
|
+
else
|
|
28
|
+
window.history.pushState({}, "", newUrl);
|
|
29
|
+
queryParamsSignal.value = getParams();
|
|
30
|
+
};
|
|
31
|
+
export { queryParamsSignal as queryParams };
|
|
@@ -1 +1,13 @@
|
|
|
1
|
-
import{useLayoutEffect,useMemo,useState}from"preact/hooks";
|
|
1
|
+
import { useLayoutEffect, useMemo, useState } from "preact/hooks";
|
|
2
|
+
const useWindowSize = () => {
|
|
3
|
+
const [size, setSize] = useState({ height: window.innerHeight, width: window.innerWidth });
|
|
4
|
+
useLayoutEffect(() => {
|
|
5
|
+
const handleResize = () => {
|
|
6
|
+
setSize({ height: window.innerHeight, width: window.innerWidth });
|
|
7
|
+
};
|
|
8
|
+
window.addEventListener("resize", handleResize);
|
|
9
|
+
return () => { window.removeEventListener("resize", handleResize); };
|
|
10
|
+
}, []);
|
|
11
|
+
return useMemo(() => ({ height: size.height, width: size.width }), [size.height, size.width]);
|
|
12
|
+
};
|
|
13
|
+
export default useWindowSize;
|
|
@@ -1 +1,23 @@
|
|
|
1
|
-
import toast from"../helpers/toast";
|
|
1
|
+
import toast from "../helpers/toast";
|
|
2
|
+
const copyToClipboard = async (text = "", message = "Copied") => {
|
|
3
|
+
try {
|
|
4
|
+
if (navigator.clipboard && window.isSecureContext) {
|
|
5
|
+
await navigator.clipboard.writeText(text);
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
const textarea = document.createElement("textarea");
|
|
9
|
+
textarea.value = text;
|
|
10
|
+
textarea.style.position = "fixed";
|
|
11
|
+
textarea.style.opacity = "0";
|
|
12
|
+
document.body.appendChild(textarea);
|
|
13
|
+
textarea.focus();
|
|
14
|
+
textarea.select();
|
|
15
|
+
document.execCommand("copy");
|
|
16
|
+
document.body.removeChild(textarea);
|
|
17
|
+
toast(message, document.body, 1000);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
toast("Failed to copy", document.body, 1000);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
export default copyToClipboard;
|
package/dist/prototypes/index.js
CHANGED
|
@@ -1 +1,6 @@
|
|
|
1
|
-
import copyToClipboard from"./copyToClipboard";
|
|
1
|
+
import copyToClipboard from "./copyToClipboard";
|
|
2
|
+
import maskString from "./maskString";
|
|
3
|
+
if (!String.prototype.copy) {
|
|
4
|
+
String.prototype.copy = copyToClipboard;
|
|
5
|
+
String.prototype.mask = maskString;
|
|
6
|
+
}
|
|
@@ -1 +1,13 @@
|
|
|
1
|
-
const maskString=function(
|
|
1
|
+
const maskString = function (visibleCharacters = 6, maskWith = "...") {
|
|
2
|
+
if (this == null)
|
|
3
|
+
return "";
|
|
4
|
+
const str = String(this);
|
|
5
|
+
if (!str)
|
|
6
|
+
return "";
|
|
7
|
+
if (str.length <= visibleCharacters * 2)
|
|
8
|
+
return str;
|
|
9
|
+
const start = str.slice(0, visibleCharacters);
|
|
10
|
+
const end = str.slice(-visibleCharacters);
|
|
11
|
+
return `${start}${maskWith}${end}`;
|
|
12
|
+
};
|
|
13
|
+
export default maskString;
|
package/dist/storage/index.js
CHANGED
|
@@ -1 +1,51 @@
|
|
|
1
|
-
import{signal}from"@preact/signals";
|
|
1
|
+
import { signal } from "@preact/signals";
|
|
2
|
+
const createStore = (name, initialState, persist = []) => {
|
|
3
|
+
const state = signal({ ...initialState });
|
|
4
|
+
try {
|
|
5
|
+
const stored = localStorage.getItem(name);
|
|
6
|
+
if (stored) {
|
|
7
|
+
state.value = { ...state.value, ...JSON.parse(stored) };
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
// Catch any Errors
|
|
12
|
+
}
|
|
13
|
+
const setState = (values) => {
|
|
14
|
+
state.value = { ...state.value, ...values };
|
|
15
|
+
if (persist.length) {
|
|
16
|
+
const toStore = persist.reduce((acc, key) => {
|
|
17
|
+
acc[key] = state.value[key];
|
|
18
|
+
return acc;
|
|
19
|
+
}, {});
|
|
20
|
+
localStorage.setItem(name, JSON.stringify(toStore));
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const resetState = () => {
|
|
24
|
+
state.value = initialState;
|
|
25
|
+
localStorage.removeItem(name);
|
|
26
|
+
};
|
|
27
|
+
return Object.assign(new Proxy(initialState, {
|
|
28
|
+
get(_, prop) {
|
|
29
|
+
switch (prop) {
|
|
30
|
+
case "setState":
|
|
31
|
+
return setState;
|
|
32
|
+
case "resetState":
|
|
33
|
+
return resetState;
|
|
34
|
+
default:
|
|
35
|
+
return state.value[prop];
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
set(_, prop, value) {
|
|
39
|
+
state.value = { ...state.value, [prop]: value };
|
|
40
|
+
if (persist.includes(prop)) {
|
|
41
|
+
const toStore = persist.reduce((acc, key) => {
|
|
42
|
+
acc[key] = state.value[key];
|
|
43
|
+
return acc;
|
|
44
|
+
}, {});
|
|
45
|
+
localStorage.setItem(name, JSON.stringify(toStore));
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
},
|
|
49
|
+
}), { __signal: state });
|
|
50
|
+
};
|
|
51
|
+
export default createStore;
|
|
@@ -1 +1,34 @@
|
|
|
1
|
-
import{signal,computed}from"@preact/signals";
|
|
1
|
+
import { signal, computed } from "@preact/signals";
|
|
2
|
+
import objectPath from "../helpers/objectPath";
|
|
3
|
+
export const languages = signal({});
|
|
4
|
+
export const language = signal(window.localStorage.getItem("language") || "en");
|
|
5
|
+
const translations = computed(() => objectPath(languages.value[language.value]));
|
|
6
|
+
const interpolate = (str, data) => {
|
|
7
|
+
if (typeof str === "string") {
|
|
8
|
+
return str.replace(/{{\s*(\w+)\s*}}/g, (_, key) => key in data ? String(data[key]) : `{{${key}}}`);
|
|
9
|
+
}
|
|
10
|
+
;
|
|
11
|
+
return JSON.stringify(str);
|
|
12
|
+
};
|
|
13
|
+
export const initTranslations = async (langs) => {
|
|
14
|
+
try {
|
|
15
|
+
languages.value = langs;
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
console.error(e);
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
export const translate = (key, data = {}) => {
|
|
24
|
+
const dictionary = translations.value;
|
|
25
|
+
if (!dictionary.has(key))
|
|
26
|
+
return key;
|
|
27
|
+
const value = dictionary.get(key);
|
|
28
|
+
return Object.keys(data).length ? interpolate(value, data) : value;
|
|
29
|
+
};
|
|
30
|
+
export const changeLanguage = (lang) => {
|
|
31
|
+
language.value = lang;
|
|
32
|
+
window.localStorage.setItem("language", lang);
|
|
33
|
+
return true;
|
|
34
|
+
};
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gohanfromgoku/ui-kit",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "",
|
|
3
|
+
"version": "0.0.4",
|
|
4
|
+
"description": "ui-kit is a TypeScript based UI component library designed for building modern web applications with ease and efficiency.",
|
|
5
|
+
"sideEffects": false,
|
|
5
6
|
"scripts": {
|
|
6
|
-
"build": "tsc && tsc-alias
|
|
7
|
-
"minify": "find dist -name '*.js' -exec terser {} --compress --mangle --output {} \\;",
|
|
7
|
+
"build": "tsc && tsc-alias",
|
|
8
8
|
"watch": "tsc --watch"
|
|
9
9
|
},
|
|
10
10
|
"keywords": [
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
],
|
|
22
22
|
"repository": {
|
|
23
23
|
"type": "git",
|
|
24
|
-
"url": "https://github.com/iamgohanfromgoku/kit.git"
|
|
24
|
+
"url": "https://github.com/iamgohanfromgoku/ui-kit.git"
|
|
25
25
|
},
|
|
26
26
|
"author": "GohanfromGoku",
|
|
27
27
|
"license": "MIT",
|
|
@@ -30,7 +30,6 @@
|
|
|
30
30
|
"preact": "^10.28.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"terser": "^5.44.1",
|
|
34
33
|
"tsc-alias": "^1.8.16",
|
|
35
34
|
"typescript": "^5.9.3"
|
|
36
35
|
},
|
package/types/api/index.d.ts
CHANGED
|
@@ -13,7 +13,9 @@ export interface RequestOptions {
|
|
|
13
13
|
}
|
|
14
14
|
export declare class API {
|
|
15
15
|
private baseURL;
|
|
16
|
-
|
|
16
|
+
private defaultHeaders;
|
|
17
|
+
private timeout;
|
|
18
|
+
constructor(baseURL: string, headers?: Record<string, string>, timeout?: number);
|
|
17
19
|
private createURL;
|
|
18
20
|
private request;
|
|
19
21
|
GET: <T = any>(endpoint: string, opts?: RequestOptions) => Promise<T>;
|