aprog 2.2.95 → 2.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aprog",
3
- "version": "2.2.95",
3
+ "version": "2.3.0",
4
4
  "description": "Допоміжна JavaScript-бібліотека для проєктів",
5
5
  "main": "index.js",
6
6
  "exports": {
package/src/NotFound.js CHANGED
@@ -1,11 +1,22 @@
1
1
  import {div} from "./general.js";
2
2
 
3
- const NotFound = ({ message = "Page Not Found" }) => {
3
+ const NotFound = ({ colors = {
4
+ numberColor: "#ff2800",
5
+ textColor: "#c3e4fc",
6
+ backgroundColor: "#043458",
7
+ }, message = "Page Not Found" }) => {
4
8
  return div({
5
- style: style,
9
+ style: {
10
+ ...style,
11
+ color: colors.textColor,
12
+ backgroundColor: colors.backgroundColor
13
+ },
6
14
  value: [
7
15
  div({
8
- style: style2,
16
+ style: {
17
+ ...style2,
18
+ color: colors.numberColor
19
+ },
9
20
  value: "404"
10
21
  }),
11
22
  div({value: message})
@@ -20,15 +31,12 @@ const style = {
20
31
  flexDirection: "column",
21
32
  alignItems: "center",
22
33
  justifyContent: "center",
23
- fontSize: "1.875rem",
24
- color: "#c3e4fc",
25
- backgroundColor: "#043458"
34
+ fontSize: "1.875rem"
26
35
  };
27
36
 
28
37
  const style2 = {
29
38
  fontSize: "3rem",
30
- fontWeight: "bold",
31
- color: "#ff2800"
39
+ fontWeight: "bold"
32
40
  }
33
41
 
34
42
  export default NotFound;
package/src/router.js CHANGED
@@ -1,13 +1,24 @@
1
1
  import NotFound from "./NotFound.js";
2
2
 
3
- export const router = async ({ routes, main }) => {
3
+ /**
4
+ * Ініціалізація роутера.
5
+ */
6
+ export const router = async ({routes, main, message = "", props = {}}) => {
4
7
  const renderRoute = async () => {
5
- const { routeComponent, props } = await useRoutes(routes);
8
+ const {routeComponent, props: routeProps} = useRoutes(routes);
6
9
  main.innerHTML = "";
7
- if (routeComponent) {
8
- const component = await routeComponent(props);
9
- main.appendChild(component);
10
+
11
+ if (!routeComponent) {
12
+ return;
10
13
  }
14
+
15
+ const component = await routeComponent({
16
+ ...props,
17
+ ...routeProps,
18
+ message,
19
+ });
20
+
21
+ main.appendChild(component);
11
22
  };
12
23
 
13
24
  window.addEventListener('popstate', renderRoute);
@@ -16,21 +27,84 @@ export const router = async ({ routes, main }) => {
16
27
  await renderRoute();
17
28
  };
18
29
 
30
+ /**
31
+ * Перехід без рендеру.
32
+ */
19
33
  export const navigateTo = (path, props = {}) => {
20
34
  window.history.pushState(props, "", path);
21
35
  };
22
36
 
23
- export const navi = (path, props = {}) => {
37
+ /**
38
+ * Перехід + рендер.
39
+ */
40
+ export const navi = async (path, props = {}) => {
24
41
  window.history.pushState(props, "", path);
25
- window.renderRoute().then();
42
+
43
+ await window.renderRoute();
26
44
  };
27
45
 
28
- const useRoutes = async (routes) => {
46
+ /**
47
+ * Порівнює URL з шаблоном route
48
+ * і повертає параметри.
49
+ *
50
+ * /category/{id}
51
+ * /category/15
52
+ *
53
+ * => { id: "15" }
54
+ *
55
+ * /category/{category_id}/product/{product_id}
56
+ * /category/15/product/128
57
+ *
58
+ * => {
59
+ * category_id: "15",
60
+ * product_id: "128"
61
+ * }
62
+ */
63
+ const matchRoute = (routePath, path) => {
64
+ const keys = [];
65
+
66
+ const pattern = routePath.replace(/\{([^}]+)}/g, (_, key) => {
67
+ keys.push(key);
68
+
69
+ return '([^/]+)';
70
+ });
71
+
72
+ const match = path.match(new RegExp(`^${pattern}$`));
73
+
74
+ if (!match) {
75
+ return null;
76
+ }
77
+
78
+ return keys.reduce((params, key, index) => {
79
+ params[key] = decodeURIComponent(match[index + 1]);
80
+
81
+ return params;
82
+ }, {});
83
+ };
84
+
85
+ /**
86
+ * Знаходить поточний route.
87
+ */
88
+ const useRoutes = (routes) => {
29
89
  const path = window.location.pathname;
30
- const matchingRoute = routes.find(route => route.path === path);
31
- const props = window.history.state || {};
32
90
 
33
- return matchingRoute
34
- ? { routeComponent: matchingRoute.component, props }
35
- : { routeComponent: NotFound, props };
91
+ for (const route of routes) {
92
+ const params = matchRoute(route.path, path);
93
+ if (params !== null) {
94
+ return {
95
+ routeComponent: route.component,
96
+ props: {
97
+ ...(window.history.state || {}),
98
+ ...params,
99
+ },
100
+ };
101
+ }
102
+ }
103
+
104
+ return {
105
+ routeComponent: NotFound,
106
+ props: {
107
+ ...(window.history.state || {}),
108
+ },
109
+ };
36
110
  };