@gohanfromgoku/ui-kit 0.1.1 → 0.1.3

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.
Files changed (28) hide show
  1. package/dist/navigation/createBrowserRouter.js +57 -0
  2. package/dist/navigation/createMemoryRouter.js +55 -0
  3. package/dist/navigation/index.js +2 -4
  4. package/dist/navigation/{extractParamsFromURL.js → support/params.support.js} +1 -2
  5. package/dist/navigation/support/query-params.support.js +43 -0
  6. package/dist/navigation/support/url.support.js +20 -0
  7. package/package.json +1 -1
  8. package/types/navigation/createBrowserRouter.d.ts +33 -0
  9. package/types/navigation/createMemoryRouter.d.ts +32 -0
  10. package/types/navigation/index.d.ts +2 -4
  11. package/types/navigation/{extractQueryParamsFromURL.d.ts → support/query-params.support.d.ts} +1 -0
  12. package/types/navigation/support/url.support.d.ts +2 -0
  13. package/dist/navigation/Outlet.js +0 -26
  14. package/dist/navigation/Page404.js +0 -2
  15. package/dist/navigation/createRoutes.js +0 -6
  16. package/dist/navigation/extractQueryParamsFromURL.js +0 -24
  17. package/dist/navigation/isRouteMatching.js +0 -15
  18. package/dist/navigation/navigate.js +0 -41
  19. package/dist/navigation/navigation.store.js +0 -4
  20. package/dist/navigation/useLocationDetails.js +0 -10
  21. package/types/navigation/Outlet.d.ts +0 -7
  22. package/types/navigation/Page404.d.ts +0 -1
  23. package/types/navigation/createRoutes.d.ts +0 -8
  24. package/types/navigation/isRouteMatching.d.ts +0 -5
  25. package/types/navigation/navigate.d.ts +0 -6
  26. package/types/navigation/navigation.store.d.ts +0 -46
  27. package/types/navigation/useLocationDetails.d.ts +0 -5
  28. /package/types/navigation/{extractParamsFromURL.d.ts → support/params.support.d.ts} +0 -0
@@ -0,0 +1,57 @@
1
+ import { Fragment as _Fragment, jsx as _jsx } from "preact/jsx-runtime";
2
+ import { useEffect } from "preact/compat";
3
+ import createStore from "../storage/index";
4
+ import { generateURLToNavigate, isRouteMatching } from "./support/url.support";
5
+ import { extractParamsFromURL } from "./support/params.support";
6
+ import { extractQueryParamsFromURL } from "./support/query-params.support";
7
+ import { computed } from "@preact/signals";
8
+ const locationDetails = createStore("location-details", { value: { params: {}, queryParams: {}, ...window.location } });
9
+ const activeRoute = createStore("active-route", { value: {} });
10
+ const createBrowserRouter = (routes, { page404 } = { page404: () => _jsx(_Fragment, { children: "Page Not Found" }) }) => {
11
+ const navigate = (to, { queryParams, replace } = {}) => {
12
+ if (typeof to === "number") {
13
+ window.history.go(to);
14
+ return;
15
+ }
16
+ const url = generateURLToNavigate(to, queryParams || {});
17
+ if (window.location.href === url) {
18
+ return;
19
+ }
20
+ if (replace) {
21
+ window.history.replaceState({}, "", url);
22
+ }
23
+ else {
24
+ window.history.pushState({}, "", url);
25
+ }
26
+ window.dispatchEvent(new Event("popstate"));
27
+ };
28
+ const useLocationDetails = () => {
29
+ if (routes.length === 0) {
30
+ throw "useLocationDetails cannot be used without initializing routes, use createRoutes initialize routes";
31
+ }
32
+ ;
33
+ const values = computed(() => locationDetails.value);
34
+ return values.value;
35
+ };
36
+ const Outlet = () => {
37
+ const component = computed(() => activeRoute.value?.component ?? page404);
38
+ useEffect(() => {
39
+ const updateLocation = () => {
40
+ const active = routes.find(r => isRouteMatching(r.pathname)) || { pathname: window.location.href, component: page404 };
41
+ activeRoute.setState({ value: active });
42
+ const params = extractParamsFromURL(window.location.pathname, active.pathname);
43
+ const queryParams = extractQueryParamsFromURL(window.location.href);
44
+ locationDetails.setState({ value: { params, queryParams, ...window.location } });
45
+ };
46
+ window.addEventListener("popstate", updateLocation);
47
+ return () => window.removeEventListener("popstate", updateLocation);
48
+ }, []);
49
+ return _jsx(component.value, {});
50
+ };
51
+ return {
52
+ navigate,
53
+ useLocationDetails,
54
+ Outlet
55
+ };
56
+ };
57
+ export default createBrowserRouter;
@@ -0,0 +1,55 @@
1
+ import { Fragment as _Fragment, jsx as _jsx } from "preact/jsx-runtime";
2
+ import {} from "preact/compat";
3
+ import createStore from "../storage/index";
4
+ import { generateURLToNavigate, isRouteMatching } from "./support/url.support";
5
+ import { extractParamsFromURL } from "./support/params.support";
6
+ import { extractQueryParamsFromURL } from "./support/query-params.support";
7
+ const createMemoryRouter = (routes, { page404 } = { page404: () => _jsx(_Fragment, { children: "Page Not Found" }) }) => {
8
+ if (routes.length === 0) {
9
+ throw "Atleast one route should present";
10
+ }
11
+ ;
12
+ const activeRoute = createStore("active-route", { value: routes.find(() => isRouteMatching("/")) || { pathname: "/", component: page404 } });
13
+ const locationDetails = createStore("location-details", { value: { params: {}, queryParams: {}, ...window.location, pathname: activeRoute.value.pathname } });
14
+ const entries = createStore("entries", { value: ["/"] });
15
+ const currentIndex = createStore("current-index", { value: 0 });
16
+ const navigate = (to, { queryParams } = {}) => {
17
+ if (typeof to === "number") {
18
+ const targetIndex = currentIndex.value + to;
19
+ if (targetIndex < 0 || targetIndex >= entries.value.length)
20
+ return;
21
+ const raw = entries.value[targetIndex];
22
+ const url = raw.startsWith("http") ? new URL(raw).pathname + new URL(raw).search : raw;
23
+ currentIndex.setState({ value: targetIndex });
24
+ const active = routes.find(r => isRouteMatching(r.pathname, url)) || { pathname: url, component: page404 };
25
+ activeRoute.setState({ value: active });
26
+ const params = extractParamsFromURL(url, active.pathname);
27
+ const allQueryParams = extractQueryParamsFromURL(url);
28
+ locationDetails.setState({ value: { params, queryParams: allQueryParams, ...window.location, pathname: active.pathname } });
29
+ return;
30
+ }
31
+ const url = generateURLToNavigate(to, queryParams || {});
32
+ if (activeRoute.value.pathname === url)
33
+ return;
34
+ entries.setState({ value: [...entries.value, url] });
35
+ const active = routes.find(r => isRouteMatching(r.pathname, to)) || { pathname: to, component: page404 };
36
+ activeRoute.setState({ value: active });
37
+ const params = extractParamsFromURL(to, activeRoute.value.pathname);
38
+ const allQueryParams = extractQueryParamsFromURL(url);
39
+ locationDetails.setState({ value: { params, queryParams: allQueryParams, ...window.location, pathname: active.pathname } });
40
+ currentIndex.setState({ value: currentIndex.value + 1 });
41
+ };
42
+ const useLocationDetails = () => {
43
+ return locationDetails.value;
44
+ };
45
+ const Outlet = () => {
46
+ const Component = activeRoute.value.component;
47
+ return _jsx(Component, {});
48
+ };
49
+ return {
50
+ navigate,
51
+ useLocationDetails,
52
+ Outlet
53
+ };
54
+ };
55
+ export default createMemoryRouter;
@@ -1,4 +1,2 @@
1
- export { default as Outlet } from "./Outlet";
2
- export { default as createRoutes } from "./createRoutes";
3
- export { default as navigate } from "./navigate";
4
- export { default as useLocationDetails } from "./useLocationDetails";
1
+ export { default as createBrowserRouter } from "./createBrowserRouter";
2
+ export { default as createMemoryRouter } from "./createMemoryRouter";
@@ -3,8 +3,7 @@
3
3
  */
4
4
  export const extractParamsFromURL = (url, compareWith) => {
5
5
  const params = {};
6
- const href = url.startsWith(window.location.origin) ? url.split(window.location.origin)[1] : url;
7
- const parts = href.split("?");
6
+ const parts = url.split("?");
8
7
  if (parts.length > 2) {
9
8
  throw "Invalid URL";
10
9
  }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @internal
3
+ */
4
+ export const createQueryParamsSearchString = (queryParams) => {
5
+ const keys = Object.keys(queryParams);
6
+ if (keys.length > 0) {
7
+ let search = "?";
8
+ for (let index = 0; index < keys.length; index++) {
9
+ const key = keys[index];
10
+ search = `${search}${key}=${queryParams[key]}`;
11
+ if (index !== keys.length - 1) {
12
+ search = search + "&";
13
+ }
14
+ }
15
+ return search;
16
+ }
17
+ return "";
18
+ };
19
+ export const extractQueryParamsFromURL = (url) => {
20
+ const queryObj = {};
21
+ const parts = url.split("?");
22
+ if (parts.length > 2) {
23
+ throw "Invalid URL";
24
+ }
25
+ ;
26
+ if (parts.length === 1) {
27
+ return queryObj;
28
+ }
29
+ ;
30
+ const search = parts[1];
31
+ if (search && search.length > 0) {
32
+ const queries = search.split("&");
33
+ for (const query of queries) {
34
+ const queryParts = query.split("=");
35
+ if (queryParts.length > 2) {
36
+ throw "Invalid URL";
37
+ }
38
+ const [key, value] = queryParts;
39
+ queryObj[decodeURIComponent(key)] = decodeURIComponent(value ?? "");
40
+ }
41
+ }
42
+ return queryObj;
43
+ };
@@ -0,0 +1,20 @@
1
+ import { createQueryParamsSearchString, extractQueryParamsFromURL } from "./query-params.support";
2
+ export const generateURLToNavigate = (pathname, queryParams) => {
3
+ const queryParamsFromPathname = extractQueryParamsFromURL(pathname);
4
+ const allQueryParams = createQueryParamsSearchString({ ...queryParamsFromPathname, ...queryParams });
5
+ const url = pathname.startsWith("/") ? `${window.location.origin}${pathname.split("?")[0]}` : `${window.location.origin}/${pathname.split("?")[0]}`;
6
+ const path = `${url}${allQueryParams}`;
7
+ return path;
8
+ };
9
+ export const isRouteMatching = (routePath, comparePath) => {
10
+ const current = comparePath ?? window.location.pathname;
11
+ if (routePath === "/" || routePath === "") {
12
+ const isRoot = current === "/" || current === "/index.html" || current === "";
13
+ return isRoot;
14
+ }
15
+ const routeParts = routePath.split("/").filter(Boolean);
16
+ const currentParts = current.split("/").filter(Boolean);
17
+ if (routeParts.length !== currentParts.length)
18
+ return false;
19
+ return routeParts.every((part, i) => part.startsWith(":") || part === currentParts[i]);
20
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gohanfromgoku/ui-kit",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "ui-kit is a TypeScript based UI component library designed for building modern web applications with ease and efficiency.",
5
5
  "sideEffects": false,
6
6
  "scripts": {
@@ -0,0 +1,33 @@
1
+ import { type ComponentType } from "preact/compat";
2
+ interface Route {
3
+ pathname: string;
4
+ component: ComponentType;
5
+ }
6
+ declare const createBrowserRouter: (routes: Route[], { page404 }?: {
7
+ page404?: ComponentType;
8
+ }) => {
9
+ navigate: (to: string | number, { queryParams, replace }?: {
10
+ queryParams?: Record<string, any>;
11
+ replace?: boolean;
12
+ }) => void;
13
+ useLocationDetails: () => {
14
+ ancestorOrigins: DOMStringList;
15
+ hash: string;
16
+ host: string;
17
+ hostname: string;
18
+ href: string;
19
+ toString(): string;
20
+ origin: string;
21
+ pathname: string;
22
+ port: string;
23
+ protocol: string;
24
+ search: string;
25
+ assign(url: string | URL): void;
26
+ reload(): void;
27
+ replace(url: string | URL): void;
28
+ params: {};
29
+ queryParams: {};
30
+ };
31
+ Outlet: () => import("preact").JSX.Element;
32
+ };
33
+ export default createBrowserRouter;
@@ -0,0 +1,32 @@
1
+ import { type ComponentType } from "preact/compat";
2
+ interface Route {
3
+ pathname: string;
4
+ component: ComponentType;
5
+ }
6
+ declare const createMemoryRouter: (routes: Route[], { page404 }?: {
7
+ page404?: ComponentType;
8
+ }) => {
9
+ navigate: (to: string | number, { queryParams }?: {
10
+ queryParams?: Record<string, any>;
11
+ }) => void;
12
+ useLocationDetails: () => {
13
+ pathname: string;
14
+ ancestorOrigins: DOMStringList;
15
+ hash: string;
16
+ host: string;
17
+ hostname: string;
18
+ href: string;
19
+ toString(): string;
20
+ origin: string;
21
+ port: string;
22
+ protocol: string;
23
+ search: string;
24
+ assign(url: string | URL): void;
25
+ reload(): void;
26
+ replace(url: string | URL): void;
27
+ params: {};
28
+ queryParams: {};
29
+ };
30
+ Outlet: () => import("preact").JSX.Element;
31
+ };
32
+ export default createMemoryRouter;
@@ -1,4 +1,2 @@
1
- export { default as Outlet } from "./Outlet";
2
- export { default as createRoutes } from "./createRoutes";
3
- export { default as navigate } from "./navigate";
4
- export { default as useLocationDetails } from "./useLocationDetails";
1
+ export { default as createBrowserRouter } from "./createBrowserRouter";
2
+ export { default as createMemoryRouter } from "./createMemoryRouter";
@@ -1,4 +1,5 @@
1
1
  /**
2
2
  * @internal
3
3
  */
4
+ export declare const createQueryParamsSearchString: (queryParams: Record<string, unknown>) => string;
4
5
  export declare const extractQueryParamsFromURL: (url: string) => Record<string, any>;
@@ -0,0 +1,2 @@
1
+ export declare const generateURLToNavigate: (pathname: string, queryParams: Record<string, any>) => string;
2
+ export declare const isRouteMatching: (routePath: string, comparePath?: string) => boolean;
@@ -1,26 +0,0 @@
1
- import { jsx as _jsx } from "preact/jsx-runtime";
2
- import { activeRoute, location } from "./navigation.store";
3
- import { Page404 } from "./Page404";
4
- import { useEffect } from "preact/compat";
5
- import isRouteMatching from "./isRouteMatching";
6
- import { computed } from "@preact/signals";
7
- import { extractParamsFromURL } from "./extractParamsFromURL";
8
- import { extractQueryParamsFromURL } from "./extractQueryParamsFromURL";
9
- const Outlet = ({ routes, page404: Page404Page = Page404 }) => {
10
- const component = computed(() => activeRoute.value?.component ?? Page404Page);
11
- useEffect(() => {
12
- const updateLocation = () => {
13
- const active = routes.find(r => isRouteMatching(r.pathname)) || { pathname: window.location.href, component: Page404Page };
14
- const { pathname: currentpath, href } = window.location;
15
- const params = extractParamsFromURL(currentpath, active.pathname);
16
- const queryParams = extractQueryParamsFromURL(href);
17
- activeRoute.setState({ value: active });
18
- location.setState({ value: { params, queryParams } });
19
- };
20
- updateLocation();
21
- window.addEventListener("popstate", updateLocation);
22
- return () => window.removeEventListener("popstate", updateLocation);
23
- }, [routes]);
24
- return _jsx(component.value, {});
25
- };
26
- export default Outlet;
@@ -1,2 +0,0 @@
1
- import { Fragment as _Fragment, jsx as _jsx } from "preact/jsx-runtime";
2
- export const Page404 = () => _jsx(_Fragment, { children: "Page Not Found" });
@@ -1,6 +0,0 @@
1
- import { globalRoutes } from "./navigation.store";
2
- const createRoutes = (routes) => {
3
- globalRoutes.setState({ value: routes });
4
- return routes;
5
- };
6
- export default createRoutes;
@@ -1,24 +0,0 @@
1
- /**
2
- * @internal
3
- */
4
- export const extractQueryParamsFromURL = (url) => {
5
- const query = {};
6
- const href = url.startsWith(window.location.origin) ? url.split(window.location.origin)[1] : url;
7
- const parts = href.split("?");
8
- if (parts.length > 2) {
9
- throw "Invalid URL";
10
- }
11
- const search = parts[1];
12
- if (search && search.length > 0) {
13
- const searchSegments = search.split("&");
14
- for (const ss of searchSegments) {
15
- const ssparts = ss.split("=");
16
- if (ssparts.length > 2) {
17
- throw "Invalid URL";
18
- }
19
- const [key, value] = ssparts;
20
- query[decodeURIComponent(key)] = decodeURIComponent(value ?? "");
21
- }
22
- }
23
- return query;
24
- };
@@ -1,15 +0,0 @@
1
- /**
2
- * @internal
3
- */
4
- const isRouteMatching = (routePath) => {
5
- const current = window.location.pathname;
6
- if (routePath === "/") {
7
- return current === "/";
8
- }
9
- const routeParts = routePath.split("/").filter(Boolean);
10
- const currentParts = current.split("/").filter(Boolean);
11
- if (routeParts.length !== currentParts.length)
12
- return false;
13
- return routeParts.every((part, i) => part.startsWith(":") || part === currentParts[i]);
14
- };
15
- export default isRouteMatching;
@@ -1,41 +0,0 @@
1
- import { extractQueryParamsFromURL } from "./extractQueryParamsFromURL";
2
- const createSearch = (queryParams) => {
3
- const keys = Object.keys(queryParams);
4
- if (keys.length > 0) {
5
- let search = "?";
6
- for (let index = 0; index < keys.length; index++) {
7
- const key = keys[index];
8
- search = `${search}${key}=${queryParams[key]}`;
9
- if (index !== keys.length - 1) {
10
- search = search + "&";
11
- }
12
- }
13
- return search;
14
- }
15
- return "";
16
- };
17
- const generateURLFromParams = (pathname, queryParams) => {
18
- const pathnameQueryParams = extractQueryParamsFromURL(pathname);
19
- const allQueryParams = { ...pathnameQueryParams, ...queryParams };
20
- const url = pathname.startsWith("/") ? `${window.location.origin}${pathname.split("?")[0]}` : `${window.location.origin}/${pathname.split("?")[0]}`;
21
- const path = `${url}${createSearch(allQueryParams)}`;
22
- return path;
23
- };
24
- const navigate = (path, { queryParams = {}, replace = false } = {}) => {
25
- if (typeof path === "number") {
26
- window.history.go(path);
27
- return;
28
- }
29
- const pathname = generateURLFromParams(path, queryParams);
30
- if (window.location.href === pathname) {
31
- return;
32
- }
33
- if (replace) {
34
- window.history.replaceState({}, "", pathname);
35
- }
36
- else {
37
- window.history.pushState({}, "", pathname);
38
- }
39
- window.dispatchEvent(new Event("popstate"));
40
- };
41
- export default navigate;
@@ -1,4 +0,0 @@
1
- import createStore from "../storage/index";
2
- export const location = createStore("location", { value: { params: {}, queryParams: {} } });
3
- export const activeRoute = createStore("activeRoute", { value: {} });
4
- export const globalRoutes = createStore("globalRoutes", { value: [] });
@@ -1,10 +0,0 @@
1
- import { computed } from "@preact/signals";
2
- import { globalRoutes, location } from "./navigation.store";
3
- const useLocationDetails = () => {
4
- if (globalRoutes.value.length === 0) {
5
- throw "useLocationDetails cannot be used without initializing routes, use createRoutes initialize routes";
6
- }
7
- const values = computed(() => location.value);
8
- return values.value;
9
- };
10
- export default useLocationDetails;
@@ -1,7 +0,0 @@
1
- import type { ComponentType } from "preact";
2
- import type { Route } from "./createRoutes";
3
- declare const Outlet: ({ routes, page404: Page404Page }: {
4
- routes: Route[];
5
- page404?: ComponentType;
6
- }) => import("preact").JSX.Element;
7
- export default Outlet;
@@ -1 +0,0 @@
1
- export declare const Page404: () => import("preact").JSX.Element;
@@ -1,8 +0,0 @@
1
- import type { ComponentType } from "preact/compat";
2
- export interface Route {
3
- pathname: string;
4
- component: ComponentType;
5
- index?: true | undefined | null;
6
- }
7
- declare const createRoutes: (routes: Route[]) => Route[];
8
- export default createRoutes;
@@ -1,5 +0,0 @@
1
- /**
2
- * @internal
3
- */
4
- declare const isRouteMatching: (routePath: string) => boolean;
5
- export default isRouteMatching;
@@ -1,6 +0,0 @@
1
- export interface NavigationProps {
2
- queryParams?: Record<string, unknown>;
3
- replace?: boolean;
4
- }
5
- declare const navigate: (path: string | number, { queryParams, replace }?: NavigationProps) => void;
6
- export default navigate;
@@ -1,46 +0,0 @@
1
- import type { Route } from "./createRoutes";
2
- export declare const location: {
3
- value: {
4
- params: {};
5
- queryParams: {};
6
- };
7
- } & {
8
- setState: (values: Partial<{
9
- value: {
10
- params: {};
11
- queryParams: {};
12
- };
13
- }>) => void;
14
- resetState: () => void;
15
- } & {
16
- __signal: import("@preact/signals").Signal<{
17
- value: {
18
- params: {};
19
- queryParams: {};
20
- };
21
- }>;
22
- };
23
- export declare const activeRoute: {
24
- value: Route;
25
- } & {
26
- setState: (values: Partial<{
27
- value: Route;
28
- }>) => void;
29
- resetState: () => void;
30
- } & {
31
- __signal: import("@preact/signals").Signal<{
32
- value: Route;
33
- }>;
34
- };
35
- export declare const globalRoutes: {
36
- value: Route[];
37
- } & {
38
- setState: (values: Partial<{
39
- value: Route[];
40
- }>) => void;
41
- resetState: () => void;
42
- } & {
43
- __signal: import("@preact/signals").Signal<{
44
- value: Route[];
45
- }>;
46
- };
@@ -1,5 +0,0 @@
1
- declare const useLocationDetails: () => {
2
- params: {};
3
- queryParams: {};
4
- };
5
- export default useLocationDetails;