ziko 0.50.2 → 0.51.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/dist/ziko.js +133 -34
- package/dist/ziko.mjs +133 -34
- package/package.json +1 -1
- package/src/__helpers__/checkers/index.js +1 -0
- package/src/events/binders/coordinates-based-event.js +25 -0
- package/src/events/binders/index.js +11 -6
- package/src/events/customizers/normalise-coordinates.js +0 -0
- package/src/events/details-setter/index.js +3 -1
- package/src/events/details-setter/mouse.js +35 -0
- package/src/events/details-setter/pointer.js +33 -31
- package/src/events/details-setter/touch.js +37 -0
- package/src/router/file-based-router/index.js +46 -0
- package/src/router/index.js +2 -0
- package/src/router/utils/dynamic-routes-parser.js +76 -0
- package/src/router/utils/get-root.js +16 -0
- package/src/router/utils/index.js +5 -0
- package/src/router/utils/normalize-path.js +17 -0
- package/src/router/utils/routes-grouper.js +22 -0
- package/src/router/utils/routes-matcher.js +60 -0
- package/types/index.d.ts +1 -0
- package/types/router/file-based-router/index.d.ts +20 -0
- package/types/router/index.d.ts +2 -0
- package/types/router/utils/dynamic-routes-parser.d.ts +14 -0
- package/types/router/utils/get-root.d.ts +11 -0
- package/types/router/utils/index.d.ts +5 -0
- package/types/router/utils/normalize-path.d.ts +15 -0
- package/types/router/utils/routes-grouper.d.ts +29 -0
- package/types/router/utils/routes-matcher.d.ts +1 -0
package/dist/ziko.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/*
|
|
3
3
|
Project: ziko.js
|
|
4
4
|
Author: Zakaria Elalaoui
|
|
5
|
-
Date : Wed Dec 03 2025 10:
|
|
5
|
+
Date : Wed Dec 03 2025 10:58:16 GMT+0100 (UTC+01:00)
|
|
6
6
|
Git-Repo : https://github.com/zakarialaoui10/ziko.js
|
|
7
7
|
Git-Wiki : https://github.com/zakarialaoui10/ziko.js/wiki
|
|
8
8
|
Released under MIT License
|
|
@@ -2026,38 +2026,137 @@
|
|
|
2026
2026
|
}
|
|
2027
2027
|
}
|
|
2028
2028
|
|
|
2029
|
-
function ptr_details_setter(){
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2029
|
+
function ptr_details_setter() {
|
|
2030
|
+
const rect = this.targetElement.getBoundingClientRect();
|
|
2031
|
+
const e = this.event;
|
|
2032
|
+
let x = (e.clientX - rect.left) | 0;
|
|
2033
|
+
let y = (e.clientY - rect.top) | 0;
|
|
2034
|
+
|
|
2035
|
+
if(this.cache.useNormalisedCoordinates){
|
|
2036
|
+
const w = this.targetElement.clientWidth;
|
|
2037
|
+
const h = this.targetElement.clientHeight;
|
|
2038
|
+
x = +((x / w) * 2 - 1).toFixed(8);
|
|
2039
|
+
y = +((y / h) * -2 + 1).toFixed(8);
|
|
2040
|
+
}
|
|
2041
|
+
switch (this.currentEvent) {
|
|
2042
|
+
|
|
2043
|
+
case "pointerdown":
|
|
2044
|
+
this.dx = x;
|
|
2045
|
+
this.dy = y;
|
|
2034
2046
|
this.isDown = true;
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
this.
|
|
2047
|
+
break;
|
|
2048
|
+
|
|
2049
|
+
case "pointermove":
|
|
2050
|
+
this.mx = x;
|
|
2051
|
+
this.my = y;
|
|
2039
2052
|
this.isMoving = true;
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
this.
|
|
2053
|
+
break;
|
|
2054
|
+
|
|
2055
|
+
case "pointerup":
|
|
2056
|
+
this.ux = x;
|
|
2057
|
+
this.uy = y;
|
|
2044
2058
|
this.isDown = false;
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2059
|
+
this.isMoving = false;
|
|
2060
|
+
break;
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
function mouse_details_setter() {
|
|
2065
|
+
const rect = this.targetElement.getBoundingClientRect();
|
|
2066
|
+
const e = this.event;
|
|
2067
|
+
let x = (e.clientX - rect.left) | 0;
|
|
2068
|
+
let y = (e.clientY - rect.top) | 0;
|
|
2069
|
+
|
|
2070
|
+
if(this.cache.useNormalisedCoordinates){
|
|
2071
|
+
const w = this.targetElement.clientWidth;
|
|
2072
|
+
const h = this.targetElement.clientHeight;
|
|
2073
|
+
x = +((x / w) * 2 - 1).toFixed(8);
|
|
2074
|
+
y = +((y / h) * -2 + 1).toFixed(8);
|
|
2075
|
+
}
|
|
2076
|
+
|
|
2077
|
+
switch (this.currentEvent) {
|
|
2078
|
+
|
|
2079
|
+
case "mousedown":
|
|
2080
|
+
this.dx = x;
|
|
2081
|
+
this.dy = y;
|
|
2082
|
+
this.isDown = true;
|
|
2083
|
+
break;
|
|
2084
|
+
|
|
2085
|
+
case "mousemove":
|
|
2086
|
+
this.mx = x;
|
|
2087
|
+
this.my = y;
|
|
2088
|
+
this.isMoving = true;
|
|
2089
|
+
break;
|
|
2090
|
+
|
|
2091
|
+
case "mouserup":
|
|
2092
|
+
this.ux = x;
|
|
2093
|
+
this.uy = y;
|
|
2094
|
+
this.isDown = false;
|
|
2095
|
+
this.isMoving = false;
|
|
2096
|
+
break;
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
function touch_details_setter() {
|
|
2101
|
+
const e = this.event;
|
|
2102
|
+
const touch = e.touches?.[0] || e.changedTouches?.[0];
|
|
2103
|
+
|
|
2104
|
+
if (!touch) return; // should never happen but safe
|
|
2105
|
+
|
|
2106
|
+
const rect = this.targetElement.getBoundingClientRect();
|
|
2107
|
+
let x = touch.clientX - rect.left;
|
|
2108
|
+
let y = touch.clientY - rect.top;
|
|
2109
|
+
|
|
2110
|
+
if(this.cache.useNormalisedCoordinates){
|
|
2111
|
+
const w = this.targetElement.clientWidth;
|
|
2112
|
+
const h = this.targetElement.clientHeight;
|
|
2113
|
+
x = +((x / w) * 2 - 1).toFixed(8);
|
|
2114
|
+
y = +((y / h) * -2 + 1).toFixed(8);
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2117
|
+
switch (this.currentEvent) {
|
|
2118
|
+
case "touchstart":
|
|
2119
|
+
this.dx = x;
|
|
2120
|
+
this.dy = y;
|
|
2121
|
+
this.isDown = true;
|
|
2122
|
+
break;
|
|
2123
|
+
|
|
2124
|
+
case "touchmove":
|
|
2125
|
+
this.mx = x;
|
|
2126
|
+
this.my = y;
|
|
2127
|
+
this.isMoving = true;
|
|
2128
|
+
break;
|
|
2129
|
+
|
|
2130
|
+
case "touchend":
|
|
2131
|
+
this.ux = x;
|
|
2132
|
+
this.uy = y;
|
|
2133
|
+
this.isDown = false;
|
|
2134
|
+
break;
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
|
|
2138
|
+
class CoordinatesBasedEvent extends ZikoEvent{
|
|
2139
|
+
constructor(signature, target = null, Events = [], details_setter, customizer){
|
|
2140
|
+
super(signature, target, Events, details_setter, customizer);
|
|
2141
|
+
Object.assign(this.cache,{
|
|
2142
|
+
useNormalisedCoordinates : false
|
|
2143
|
+
});
|
|
2144
|
+
this.isDown = false;
|
|
2145
|
+
this.isMoving = false;
|
|
2146
|
+
this.dx = 0;
|
|
2147
|
+
this.dy = 0;
|
|
2148
|
+
this.mx = 0;
|
|
2149
|
+
this.my = 0;
|
|
2150
|
+
this.ux = 0;
|
|
2151
|
+
this.uy = 0;
|
|
2152
|
+
}
|
|
2153
|
+
get isDragging(){
|
|
2154
|
+
return this.isDown && this.isMoving
|
|
2155
|
+
}
|
|
2156
|
+
useNormalisedCoordinates(enable = true){
|
|
2157
|
+
this.cache.useNormalisedCoordinates = enable;
|
|
2158
|
+
return this;
|
|
2057
2159
|
}
|
|
2058
|
-
// if(this.currentEvent==="click") this.dx = 0
|
|
2059
|
-
// else this.dx = 1
|
|
2060
|
-
// console.log(this.currentEvent)
|
|
2061
2160
|
}
|
|
2062
2161
|
|
|
2063
2162
|
class ClickAwayEvent extends Event {
|
|
@@ -2288,25 +2387,25 @@
|
|
|
2288
2387
|
key_details_setter,
|
|
2289
2388
|
customizer
|
|
2290
2389
|
);
|
|
2291
|
-
const bind_mouse_event = (target, customizer) => new
|
|
2390
|
+
const bind_mouse_event = (target, customizer) => new CoordinatesBasedEvent(
|
|
2292
2391
|
'mouse',
|
|
2293
2392
|
target,
|
|
2294
2393
|
EventsMap.Mouse,
|
|
2295
|
-
|
|
2394
|
+
mouse_details_setter,
|
|
2296
2395
|
customizer
|
|
2297
2396
|
);
|
|
2298
|
-
const bind_pointer_event = (target, customizer) => new
|
|
2397
|
+
const bind_pointer_event = (target, customizer) => new CoordinatesBasedEvent(
|
|
2299
2398
|
'ptr',
|
|
2300
2399
|
target,
|
|
2301
2400
|
EventsMap.Ptr,
|
|
2302
2401
|
ptr_details_setter,
|
|
2303
2402
|
customizer
|
|
2304
2403
|
);
|
|
2305
|
-
const bind_touch_event = (target, customizer) => new
|
|
2404
|
+
const bind_touch_event = (target, customizer) => new CoordinatesBasedEvent(
|
|
2306
2405
|
'touch',
|
|
2307
2406
|
target,
|
|
2308
2407
|
EventsMap.Touch,
|
|
2309
|
-
|
|
2408
|
+
touch_details_setter,
|
|
2310
2409
|
customizer
|
|
2311
2410
|
);
|
|
2312
2411
|
const bind_wheel_event = (target, customizer) => new ZikoEvent(
|
package/dist/ziko.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/*
|
|
3
3
|
Project: ziko.js
|
|
4
4
|
Author: Zakaria Elalaoui
|
|
5
|
-
Date : Wed Dec 03 2025 10:
|
|
5
|
+
Date : Wed Dec 03 2025 10:58:16 GMT+0100 (UTC+01:00)
|
|
6
6
|
Git-Repo : https://github.com/zakarialaoui10/ziko.js
|
|
7
7
|
Git-Wiki : https://github.com/zakarialaoui10/ziko.js/wiki
|
|
8
8
|
Released under MIT License
|
|
@@ -2020,38 +2020,137 @@ function key_details_setter(){
|
|
|
2020
2020
|
}
|
|
2021
2021
|
}
|
|
2022
2022
|
|
|
2023
|
-
function ptr_details_setter(){
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2023
|
+
function ptr_details_setter() {
|
|
2024
|
+
const rect = this.targetElement.getBoundingClientRect();
|
|
2025
|
+
const e = this.event;
|
|
2026
|
+
let x = (e.clientX - rect.left) | 0;
|
|
2027
|
+
let y = (e.clientY - rect.top) | 0;
|
|
2028
|
+
|
|
2029
|
+
if(this.cache.useNormalisedCoordinates){
|
|
2030
|
+
const w = this.targetElement.clientWidth;
|
|
2031
|
+
const h = this.targetElement.clientHeight;
|
|
2032
|
+
x = +((x / w) * 2 - 1).toFixed(8);
|
|
2033
|
+
y = +((y / h) * -2 + 1).toFixed(8);
|
|
2034
|
+
}
|
|
2035
|
+
switch (this.currentEvent) {
|
|
2036
|
+
|
|
2037
|
+
case "pointerdown":
|
|
2038
|
+
this.dx = x;
|
|
2039
|
+
this.dy = y;
|
|
2028
2040
|
this.isDown = true;
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
this.
|
|
2041
|
+
break;
|
|
2042
|
+
|
|
2043
|
+
case "pointermove":
|
|
2044
|
+
this.mx = x;
|
|
2045
|
+
this.my = y;
|
|
2033
2046
|
this.isMoving = true;
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
this.
|
|
2047
|
+
break;
|
|
2048
|
+
|
|
2049
|
+
case "pointerup":
|
|
2050
|
+
this.ux = x;
|
|
2051
|
+
this.uy = y;
|
|
2038
2052
|
this.isDown = false;
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2053
|
+
this.isMoving = false;
|
|
2054
|
+
break;
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
function mouse_details_setter() {
|
|
2059
|
+
const rect = this.targetElement.getBoundingClientRect();
|
|
2060
|
+
const e = this.event;
|
|
2061
|
+
let x = (e.clientX - rect.left) | 0;
|
|
2062
|
+
let y = (e.clientY - rect.top) | 0;
|
|
2063
|
+
|
|
2064
|
+
if(this.cache.useNormalisedCoordinates){
|
|
2065
|
+
const w = this.targetElement.clientWidth;
|
|
2066
|
+
const h = this.targetElement.clientHeight;
|
|
2067
|
+
x = +((x / w) * 2 - 1).toFixed(8);
|
|
2068
|
+
y = +((y / h) * -2 + 1).toFixed(8);
|
|
2069
|
+
}
|
|
2070
|
+
|
|
2071
|
+
switch (this.currentEvent) {
|
|
2072
|
+
|
|
2073
|
+
case "mousedown":
|
|
2074
|
+
this.dx = x;
|
|
2075
|
+
this.dy = y;
|
|
2076
|
+
this.isDown = true;
|
|
2077
|
+
break;
|
|
2078
|
+
|
|
2079
|
+
case "mousemove":
|
|
2080
|
+
this.mx = x;
|
|
2081
|
+
this.my = y;
|
|
2082
|
+
this.isMoving = true;
|
|
2083
|
+
break;
|
|
2084
|
+
|
|
2085
|
+
case "mouserup":
|
|
2086
|
+
this.ux = x;
|
|
2087
|
+
this.uy = y;
|
|
2088
|
+
this.isDown = false;
|
|
2089
|
+
this.isMoving = false;
|
|
2090
|
+
break;
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
|
|
2094
|
+
function touch_details_setter() {
|
|
2095
|
+
const e = this.event;
|
|
2096
|
+
const touch = e.touches?.[0] || e.changedTouches?.[0];
|
|
2097
|
+
|
|
2098
|
+
if (!touch) return; // should never happen but safe
|
|
2099
|
+
|
|
2100
|
+
const rect = this.targetElement.getBoundingClientRect();
|
|
2101
|
+
let x = touch.clientX - rect.left;
|
|
2102
|
+
let y = touch.clientY - rect.top;
|
|
2103
|
+
|
|
2104
|
+
if(this.cache.useNormalisedCoordinates){
|
|
2105
|
+
const w = this.targetElement.clientWidth;
|
|
2106
|
+
const h = this.targetElement.clientHeight;
|
|
2107
|
+
x = +((x / w) * 2 - 1).toFixed(8);
|
|
2108
|
+
y = +((y / h) * -2 + 1).toFixed(8);
|
|
2109
|
+
}
|
|
2110
|
+
|
|
2111
|
+
switch (this.currentEvent) {
|
|
2112
|
+
case "touchstart":
|
|
2113
|
+
this.dx = x;
|
|
2114
|
+
this.dy = y;
|
|
2115
|
+
this.isDown = true;
|
|
2116
|
+
break;
|
|
2117
|
+
|
|
2118
|
+
case "touchmove":
|
|
2119
|
+
this.mx = x;
|
|
2120
|
+
this.my = y;
|
|
2121
|
+
this.isMoving = true;
|
|
2122
|
+
break;
|
|
2123
|
+
|
|
2124
|
+
case "touchend":
|
|
2125
|
+
this.ux = x;
|
|
2126
|
+
this.uy = y;
|
|
2127
|
+
this.isDown = false;
|
|
2128
|
+
break;
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
class CoordinatesBasedEvent extends ZikoEvent{
|
|
2133
|
+
constructor(signature, target = null, Events = [], details_setter, customizer){
|
|
2134
|
+
super(signature, target, Events, details_setter, customizer);
|
|
2135
|
+
Object.assign(this.cache,{
|
|
2136
|
+
useNormalisedCoordinates : false
|
|
2137
|
+
});
|
|
2138
|
+
this.isDown = false;
|
|
2139
|
+
this.isMoving = false;
|
|
2140
|
+
this.dx = 0;
|
|
2141
|
+
this.dy = 0;
|
|
2142
|
+
this.mx = 0;
|
|
2143
|
+
this.my = 0;
|
|
2144
|
+
this.ux = 0;
|
|
2145
|
+
this.uy = 0;
|
|
2146
|
+
}
|
|
2147
|
+
get isDragging(){
|
|
2148
|
+
return this.isDown && this.isMoving
|
|
2149
|
+
}
|
|
2150
|
+
useNormalisedCoordinates(enable = true){
|
|
2151
|
+
this.cache.useNormalisedCoordinates = enable;
|
|
2152
|
+
return this;
|
|
2051
2153
|
}
|
|
2052
|
-
// if(this.currentEvent==="click") this.dx = 0
|
|
2053
|
-
// else this.dx = 1
|
|
2054
|
-
// console.log(this.currentEvent)
|
|
2055
2154
|
}
|
|
2056
2155
|
|
|
2057
2156
|
class ClickAwayEvent extends Event {
|
|
@@ -2282,25 +2381,25 @@ const bind_key_event = (target, customizer) => new ZikoEvent(
|
|
|
2282
2381
|
key_details_setter,
|
|
2283
2382
|
customizer
|
|
2284
2383
|
);
|
|
2285
|
-
const bind_mouse_event = (target, customizer) => new
|
|
2384
|
+
const bind_mouse_event = (target, customizer) => new CoordinatesBasedEvent(
|
|
2286
2385
|
'mouse',
|
|
2287
2386
|
target,
|
|
2288
2387
|
EventsMap.Mouse,
|
|
2289
|
-
|
|
2388
|
+
mouse_details_setter,
|
|
2290
2389
|
customizer
|
|
2291
2390
|
);
|
|
2292
|
-
const bind_pointer_event = (target, customizer) => new
|
|
2391
|
+
const bind_pointer_event = (target, customizer) => new CoordinatesBasedEvent(
|
|
2293
2392
|
'ptr',
|
|
2294
2393
|
target,
|
|
2295
2394
|
EventsMap.Ptr,
|
|
2296
2395
|
ptr_details_setter,
|
|
2297
2396
|
customizer
|
|
2298
2397
|
);
|
|
2299
|
-
const bind_touch_event = (target, customizer) => new
|
|
2398
|
+
const bind_touch_event = (target, customizer) => new CoordinatesBasedEvent(
|
|
2300
2399
|
'touch',
|
|
2301
2400
|
target,
|
|
2302
2401
|
EventsMap.Touch,
|
|
2303
|
-
|
|
2402
|
+
touch_details_setter,
|
|
2304
2403
|
customizer
|
|
2305
2404
|
);
|
|
2306
2405
|
const bind_wheel_event = (target, customizer) => new ZikoEvent(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ziko",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.51.0",
|
|
4
4
|
"description": "A versatile JavaScript library offering a rich set of Hyperscript Based UI components, advanced mathematical utilities, interactivity ,animations, client side routing and more ...",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"front-end",
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ZikoEvent } from "../ziko-event.js";
|
|
2
|
+
|
|
3
|
+
export class CoordinatesBasedEvent extends ZikoEvent{
|
|
4
|
+
constructor(signature, target = null, Events = [], details_setter, customizer){
|
|
5
|
+
super(signature, target, Events, details_setter, customizer)
|
|
6
|
+
Object.assign(this.cache,{
|
|
7
|
+
useNormalisedCoordinates : false
|
|
8
|
+
})
|
|
9
|
+
this.isDown = false;
|
|
10
|
+
this.isMoving = false;
|
|
11
|
+
this.dx = 0;
|
|
12
|
+
this.dy = 0;
|
|
13
|
+
this.mx = 0;
|
|
14
|
+
this.my = 0;
|
|
15
|
+
this.ux = 0;
|
|
16
|
+
this.uy = 0;
|
|
17
|
+
}
|
|
18
|
+
get isDragging(){
|
|
19
|
+
return this.isDown && this.isMoving
|
|
20
|
+
}
|
|
21
|
+
useNormalisedCoordinates(enable = true){
|
|
22
|
+
this.cache.useNormalisedCoordinates = enable;
|
|
23
|
+
return this;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -2,8 +2,13 @@ import { ZikoEvent } from "../ziko-event.js";
|
|
|
2
2
|
import { EventsMap } from "../events-map/index.js";
|
|
3
3
|
import {
|
|
4
4
|
ptr_details_setter,
|
|
5
|
-
key_details_setter
|
|
5
|
+
key_details_setter,
|
|
6
|
+
mouse_details_setter,
|
|
7
|
+
touch_details_setter
|
|
6
8
|
} from '../details-setter/index.js'
|
|
9
|
+
import {
|
|
10
|
+
CoordinatesBasedEvent
|
|
11
|
+
} from './coordinates-based-event.js'
|
|
7
12
|
import {
|
|
8
13
|
register_click_away_event,
|
|
9
14
|
register_view_event,
|
|
@@ -48,25 +53,25 @@ export const bind_key_event = (target, customizer) => new ZikoEvent(
|
|
|
48
53
|
key_details_setter,
|
|
49
54
|
customizer
|
|
50
55
|
);
|
|
51
|
-
export const bind_mouse_event = (target, customizer) => new
|
|
56
|
+
export const bind_mouse_event = (target, customizer) => new CoordinatesBasedEvent(
|
|
52
57
|
'mouse',
|
|
53
58
|
target,
|
|
54
59
|
EventsMap.Mouse,
|
|
55
|
-
|
|
60
|
+
mouse_details_setter,
|
|
56
61
|
customizer
|
|
57
62
|
);
|
|
58
|
-
export const bind_pointer_event = (target, customizer) => new
|
|
63
|
+
export const bind_pointer_event = (target, customizer) => new CoordinatesBasedEvent(
|
|
59
64
|
'ptr',
|
|
60
65
|
target,
|
|
61
66
|
EventsMap.Ptr,
|
|
62
67
|
ptr_details_setter,
|
|
63
68
|
customizer
|
|
64
69
|
);
|
|
65
|
-
export const bind_touch_event = (target, customizer) => new
|
|
70
|
+
export const bind_touch_event = (target, customizer) => new CoordinatesBasedEvent(
|
|
66
71
|
'touch',
|
|
67
72
|
target,
|
|
68
73
|
EventsMap.Touch,
|
|
69
|
-
|
|
74
|
+
touch_details_setter,
|
|
70
75
|
customizer
|
|
71
76
|
);
|
|
72
77
|
export const bind_wheel_event = (target, customizer) => new ZikoEvent(
|
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function mouse_details_setter() {
|
|
2
|
+
const rect = this.targetElement.getBoundingClientRect();
|
|
3
|
+
const e = this.event;
|
|
4
|
+
let x = (e.clientX - rect.left) | 0;
|
|
5
|
+
let y = (e.clientY - rect.top) | 0;
|
|
6
|
+
|
|
7
|
+
if(this.cache.useNormalisedCoordinates){
|
|
8
|
+
const w = this.targetElement.clientWidth;
|
|
9
|
+
const h = this.targetElement.clientHeight;
|
|
10
|
+
x = +((x / w) * 2 - 1).toFixed(8);
|
|
11
|
+
y = +((y / h) * -2 + 1).toFixed(8);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
switch (this.currentEvent) {
|
|
15
|
+
|
|
16
|
+
case "mousedown":
|
|
17
|
+
this.dx = x;
|
|
18
|
+
this.dy = y;
|
|
19
|
+
this.isDown = true;
|
|
20
|
+
break;
|
|
21
|
+
|
|
22
|
+
case "mousemove":
|
|
23
|
+
this.mx = x;
|
|
24
|
+
this.my = y;
|
|
25
|
+
this.isMoving = true;
|
|
26
|
+
break;
|
|
27
|
+
|
|
28
|
+
case "mouserup":
|
|
29
|
+
this.ux = x;
|
|
30
|
+
this.uy = y;
|
|
31
|
+
this.isDown = false;
|
|
32
|
+
this.isMoving = false;
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -1,33 +1,35 @@
|
|
|
1
|
-
export function ptr_details_setter(){
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
export function ptr_details_setter() {
|
|
2
|
+
const rect = this.targetElement.getBoundingClientRect();
|
|
3
|
+
const e = this.event;
|
|
4
|
+
let x = (e.clientX - rect.left) | 0;
|
|
5
|
+
let y = (e.clientY - rect.top) | 0;
|
|
6
|
+
|
|
7
|
+
if(this.cache.useNormalisedCoordinates){
|
|
8
|
+
const w = this.targetElement.clientWidth;
|
|
9
|
+
const h = this.targetElement.clientHeight;
|
|
10
|
+
x = +((x / w) * 2 - 1).toFixed(8);
|
|
11
|
+
y = +((y / h) * -2 + 1).toFixed(8);
|
|
12
|
+
}
|
|
13
|
+
switch (this.currentEvent) {
|
|
14
|
+
|
|
15
|
+
case "pointerdown":
|
|
16
|
+
this.dx = x;
|
|
17
|
+
this.dy = y;
|
|
18
|
+
this.isDown = true;
|
|
19
|
+
break;
|
|
20
|
+
|
|
21
|
+
case "pointermove":
|
|
22
|
+
this.mx = x;
|
|
23
|
+
this.my = y;
|
|
24
|
+
this.isMoving = true;
|
|
25
|
+
break;
|
|
26
|
+
|
|
27
|
+
case "pointerup":
|
|
28
|
+
this.ux = x;
|
|
29
|
+
this.uy = y;
|
|
16
30
|
this.isDown = false;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const delta_y=(this.dy-this.uy)/this.target.height;
|
|
20
|
-
const HORIZONTAL_SWIPPE=(delta_x<0)?"left":(delta_x>0)?"right":"none";
|
|
21
|
-
const VERTICAL_SWIPPE=(delta_y<0)?"bottom":(delta_y>0)?"top":"none";
|
|
22
|
-
this.swippe={
|
|
23
|
-
h:HORIZONTAL_SWIPPE,
|
|
24
|
-
v:VERTICAL_SWIPPE,
|
|
25
|
-
delta_x,
|
|
26
|
-
delta_y
|
|
27
|
-
}
|
|
28
|
-
}; break;
|
|
31
|
+
this.isMoving = false;
|
|
32
|
+
break;
|
|
29
33
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
// console.log(this.currentEvent)
|
|
33
|
-
}
|
|
34
|
+
}
|
|
35
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export function touch_details_setter() {
|
|
2
|
+
const e = this.event;
|
|
3
|
+
const touch = e.touches?.[0] || e.changedTouches?.[0];
|
|
4
|
+
|
|
5
|
+
if (!touch) return; // should never happen but safe
|
|
6
|
+
|
|
7
|
+
const rect = this.targetElement.getBoundingClientRect();
|
|
8
|
+
let x = touch.clientX - rect.left;
|
|
9
|
+
let y = touch.clientY - rect.top;
|
|
10
|
+
|
|
11
|
+
if(this.cache.useNormalisedCoordinates){
|
|
12
|
+
const w = this.targetElement.clientWidth;
|
|
13
|
+
const h = this.targetElement.clientHeight;
|
|
14
|
+
x = +((x / w) * 2 - 1).toFixed(8);
|
|
15
|
+
y = +((y / h) * -2 + 1).toFixed(8);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
switch (this.currentEvent) {
|
|
19
|
+
case "touchstart":
|
|
20
|
+
this.dx = x;
|
|
21
|
+
this.dy = y;
|
|
22
|
+
this.isDown = true;
|
|
23
|
+
break;
|
|
24
|
+
|
|
25
|
+
case "touchmove":
|
|
26
|
+
this.mx = x;
|
|
27
|
+
this.my = y;
|
|
28
|
+
this.isMoving = true;
|
|
29
|
+
break;
|
|
30
|
+
|
|
31
|
+
case "touchend":
|
|
32
|
+
this.ux = x;
|
|
33
|
+
this.uy = y;
|
|
34
|
+
this.isDown = false;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import {
|
|
2
|
+
get_root,
|
|
3
|
+
normalize_path,
|
|
4
|
+
routes_matcher,
|
|
5
|
+
is_dynamic,
|
|
6
|
+
dynamic_routes_parser
|
|
7
|
+
} from "../utils/index.js"
|
|
8
|
+
export async function createSPAFileBasedRouter(
|
|
9
|
+
pages,
|
|
10
|
+
target = globalThis?.document?.body
|
|
11
|
+
) {
|
|
12
|
+
if(!(target instanceof HTMLElement) && target?.element instanceof HTMLElement) target = target?.element;
|
|
13
|
+
if (!(target instanceof HTMLElement)) {
|
|
14
|
+
throw new Error("Invalid mount target: must be HTMLElement or UIElement");
|
|
15
|
+
}
|
|
16
|
+
let path = decodeURIComponent(globalThis.location.pathname.replace(/\/$/, ''));
|
|
17
|
+
const routes = Object.keys(pages);
|
|
18
|
+
const root = get_root(routes);
|
|
19
|
+
|
|
20
|
+
const pairs = {};
|
|
21
|
+
for (const route of routes) {
|
|
22
|
+
const module = await pages[route]();
|
|
23
|
+
const modComponent = await module.default;
|
|
24
|
+
pairs[normalize_path(route, root)] = modComponent;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let mask = null;
|
|
28
|
+
let component = null;
|
|
29
|
+
|
|
30
|
+
for (const [routePath, comp] of Object.entries(pairs)) {
|
|
31
|
+
if (routes_matcher(routePath, `/${path}`)) {
|
|
32
|
+
mask = routePath;
|
|
33
|
+
component = comp;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!mask) return; // no route matched
|
|
39
|
+
|
|
40
|
+
const params = is_dynamic(mask) ? dynamic_routes_parser(mask, path) : undefined;
|
|
41
|
+
const mounted = params ? await component(params) : await component();
|
|
42
|
+
|
|
43
|
+
if(mounted instanceof HTMLElement) target.append(mounted);
|
|
44
|
+
else mounted.mount(target);
|
|
45
|
+
|
|
46
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export function dynamic_routes_parser(mask, route) {
|
|
2
|
+
const maskSegments = mask.split("/").filter(Boolean);
|
|
3
|
+
const routeSegments = route.split("/").filter(Boolean);
|
|
4
|
+
const params = {};
|
|
5
|
+
let i = 0, j = 0;
|
|
6
|
+
while (i < maskSegments.length && j < routeSegments.length) {
|
|
7
|
+
const maskSegment = maskSegments[i];
|
|
8
|
+
const routeSegment = routeSegments[j];
|
|
9
|
+
if (maskSegment.startsWith("[...") && maskSegment.endsWith("]")) {
|
|
10
|
+
const paramName = maskSegment.slice(4, -1);
|
|
11
|
+
const remainingMaskSegments = maskSegments.length - i - 1;
|
|
12
|
+
if (remainingMaskSegments === 0) {
|
|
13
|
+
params[paramName] = routeSegments.slice(j).join("/");
|
|
14
|
+
break;
|
|
15
|
+
}
|
|
16
|
+
let requiredSegments = 0;
|
|
17
|
+
for (let k = i + 1; k < maskSegments.length; k++) {
|
|
18
|
+
if (!maskSegments[k].endsWith("]+")) requiredSegments++;
|
|
19
|
+
}
|
|
20
|
+
const remainingRouteSegments = routeSegments.length - j;
|
|
21
|
+
const segmentsToConsume = remainingRouteSegments - requiredSegments;
|
|
22
|
+
if (segmentsToConsume >= 1) {
|
|
23
|
+
params[paramName] = routeSegments
|
|
24
|
+
.slice(j, j + segmentsToConsume)
|
|
25
|
+
.join("/");
|
|
26
|
+
j += segmentsToConsume;
|
|
27
|
+
}
|
|
28
|
+
else return {};
|
|
29
|
+
i++;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (maskSegment.startsWith("[") && maskSegment.endsWith("]+")) {
|
|
33
|
+
const paramName = maskSegment.slice(1, -2);
|
|
34
|
+
if (routeSegment) {
|
|
35
|
+
params[paramName] = routeSegment;
|
|
36
|
+
j++;
|
|
37
|
+
}
|
|
38
|
+
i++;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (maskSegment.startsWith("[") && maskSegment.endsWith("]")) {
|
|
42
|
+
const paramName = maskSegment.slice(1, -1);
|
|
43
|
+
params[paramName] = routeSegment;
|
|
44
|
+
}
|
|
45
|
+
else if (maskSegment !== routeSegment) return {};
|
|
46
|
+
i++;
|
|
47
|
+
j++;
|
|
48
|
+
}
|
|
49
|
+
return params;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
// console.log("\n=== PARSER TESTS ===");
|
|
54
|
+
// console.log(dynamic_routes_parser("/user/[id]+", "/user"));
|
|
55
|
+
// // 👉 {}
|
|
56
|
+
|
|
57
|
+
// console.log(dynamic_routes_parser("/user/[id]+", "/user/42"));
|
|
58
|
+
// // 👉 { id: "42" }
|
|
59
|
+
|
|
60
|
+
// console.log(dynamic_routes_parser("/blog/[...slug]", "/blog/2025/oct/post"));
|
|
61
|
+
// // 👉 { slug: "2025/oct/post" }
|
|
62
|
+
|
|
63
|
+
// console.log(
|
|
64
|
+
// dynamic_routes_parser("/product/[category]/[id]+", "/product/electronics"),
|
|
65
|
+
// );
|
|
66
|
+
// // 👉 { category: "electronics" }
|
|
67
|
+
|
|
68
|
+
// console.log("\n=== FIX TEST ===");
|
|
69
|
+
// console.log(dynamic_routes_parser("/[...slug]/[id]", "/sl1/sl2/9"));
|
|
70
|
+
// // 👉 { slug: "sl1/sl2", id: "9" }
|
|
71
|
+
|
|
72
|
+
// console.log(dynamic_routes_parser("/[slug]/[...id]", "/sl1/id1/id2"));
|
|
73
|
+
// // 👉 { slug: "sl1", id: "id1/id2" }
|
|
74
|
+
|
|
75
|
+
// console.log(dynamic_routes_parser("/blog/lang/[lang]/id/[id]", "/blog/lang/en/id/10"));
|
|
76
|
+
// // 👉 { lang: "en", id: "10" }
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function get_root(paths) {
|
|
2
|
+
if (paths.length === 0) return '';
|
|
3
|
+
const splitPaths = paths.map(path => path.split('/'));
|
|
4
|
+
const minLength = Math.min(...splitPaths.map(parts => parts.length));
|
|
5
|
+
let commonParts = [];
|
|
6
|
+
for (let i = 0; i < minLength; i++) {
|
|
7
|
+
const part = splitPaths[0][i];
|
|
8
|
+
if (splitPaths.every(parts => parts[i] === part || parts[i].startsWith('['))) {
|
|
9
|
+
commonParts.push(part);
|
|
10
|
+
}
|
|
11
|
+
else break;
|
|
12
|
+
|
|
13
|
+
}
|
|
14
|
+
const root = commonParts.join('/') + (commonParts.length ? '/' : '');
|
|
15
|
+
return root;
|
|
16
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function normalize_path(inputPath, root = './src/pages', extensions = ['js', 'ts']) {
|
|
2
|
+
if(root.at(-1)==="/") root = root.slice(0, -1)
|
|
3
|
+
const normalizedPath = inputPath.replace(/\\/g, '/')
|
|
4
|
+
// .replace(/\[(\w+)\]/g, '$1/:$1');
|
|
5
|
+
const parts = normalizedPath.split('/');
|
|
6
|
+
const rootParts = root.split('/');
|
|
7
|
+
const rootIndex = parts.indexOf(rootParts[rootParts.length - 1]);
|
|
8
|
+
if (rootIndex !== -1) {
|
|
9
|
+
const subsequentParts = parts.slice(rootIndex + 1);
|
|
10
|
+
const lastPart = subsequentParts[subsequentParts.length - 1];
|
|
11
|
+
const isIndexFile = lastPart === 'index.js' || lastPart === 'index.ts';
|
|
12
|
+
const hasValidExtension = extensions.some(ext => lastPart === `.${ext}` || lastPart.endsWith(`.${ext}`));
|
|
13
|
+
if (isIndexFile) return '/' + (subsequentParts.length > 1 ? subsequentParts.slice(0, -1).join('/') : '');
|
|
14
|
+
if (hasValidExtension) return '/' + subsequentParts.join('/').replace(/\.(js|ts)$/, '');
|
|
15
|
+
}
|
|
16
|
+
return '';
|
|
17
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function is_dynamic(path) {
|
|
2
|
+
const DynamicPattern = /(:\w+|\[\.\.\.\w+\]|\[\w+\]\+?)/;
|
|
3
|
+
return DynamicPattern.test(path);
|
|
4
|
+
}
|
|
5
|
+
export function routes_grouper(routeMap) {
|
|
6
|
+
const grouped = {
|
|
7
|
+
static: {},
|
|
8
|
+
dynamic: {},
|
|
9
|
+
};
|
|
10
|
+
for (const [path, value] of Object.entries(routeMap)) {
|
|
11
|
+
if (is_dynamic(path)) {
|
|
12
|
+
const segments = path.split("/").filter(Boolean);
|
|
13
|
+
const optionalIndex = segments.findIndex(seg => seg.endsWith("]+"));
|
|
14
|
+
const hasInvalidOptional =
|
|
15
|
+
optionalIndex !== -1 && optionalIndex !== segments.length - 1;
|
|
16
|
+
if (hasInvalidOptional) throw new Error(`Invalid optional param position in route: "${path}" — optional parameters can only appear at the end.`);
|
|
17
|
+
grouped.dynamic[path] = value;
|
|
18
|
+
}
|
|
19
|
+
else grouped.static[path] = value;
|
|
20
|
+
}
|
|
21
|
+
return grouped;
|
|
22
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export function routes_matcher(mask, route) {
|
|
2
|
+
const maskSegments = mask.split("/").filter(Boolean);
|
|
3
|
+
const routeSegments = route.split("/").filter(Boolean);
|
|
4
|
+
let i = 0, j = 0;
|
|
5
|
+
while (i < maskSegments.length && j < routeSegments.length) {
|
|
6
|
+
const maskSegment = maskSegments[i];
|
|
7
|
+
const routeSegment = routeSegments[j];
|
|
8
|
+
if (maskSegment.startsWith("[...") && maskSegment.endsWith("]")) {
|
|
9
|
+
const remainingMaskSegments = maskSegments.length - i - 1;
|
|
10
|
+
if (remainingMaskSegments === 0) return true;
|
|
11
|
+
// Calculate minimum required route segments for remaining mask
|
|
12
|
+
let requiredSegments = 0;
|
|
13
|
+
for (let k = i + 1; k < maskSegments.length; k++) {
|
|
14
|
+
if (!maskSegments[k].endsWith("]+")) {
|
|
15
|
+
requiredSegments++;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const remainingRouteSegments = routeSegments.length - j;
|
|
19
|
+
if (remainingRouteSegments < requiredSegments) return false;
|
|
20
|
+
const segmentsToConsume = remainingRouteSegments - requiredSegments;
|
|
21
|
+
if (segmentsToConsume < 1) return false;
|
|
22
|
+
j += segmentsToConsume;
|
|
23
|
+
i++;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (maskSegment.startsWith("[") && maskSegment.endsWith("]+")) {
|
|
27
|
+
if (routeSegment) j++;
|
|
28
|
+
i++;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (maskSegment.startsWith("[") && maskSegment.endsWith("]")) {
|
|
32
|
+
i++;
|
|
33
|
+
j++;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (maskSegment !== routeSegment) return false;
|
|
37
|
+
i++;
|
|
38
|
+
j++;
|
|
39
|
+
}
|
|
40
|
+
while (i < maskSegments.length) {
|
|
41
|
+
const seg = maskSegments[i];
|
|
42
|
+
if (seg.endsWith("]+")) {
|
|
43
|
+
i++;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
return i === maskSegments.length && j === routeSegments.length;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
// // DEMO
|
|
53
|
+
// console.log("=== EXISTING TESTS ===");
|
|
54
|
+
// console.log(routes_matcher("/user/[id]+", "/user")); // true
|
|
55
|
+
// console.log(routes_matcher("/user/[id]+", "/user/42")); // true
|
|
56
|
+
// console.log(routes_matcher("/blog/[...slug]", "/blog/a/b")); // true
|
|
57
|
+
// console.log(routes_matcher("/blog/[id]", "/blog")); // false
|
|
58
|
+
// console.log(routes_matcher("/product/:id", "/product/99")); // true
|
|
59
|
+
|
|
60
|
+
|
package/types/index.d.ts
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// createSPAFileBasedRouter.d.ts
|
|
2
|
+
|
|
3
|
+
import { UIElement } from '../../../src/ui/constructors/UIElement.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates a SPA (Single Page Application) file-based router.
|
|
7
|
+
* Automatically loads and mounts the component corresponding to the current path.
|
|
8
|
+
* Supports dynamic routes and parameter extraction.
|
|
9
|
+
*
|
|
10
|
+
* @param pages - An object mapping route paths to async module functions that return a component.
|
|
11
|
+
* Example: { "/user/[id]": () => import("./pages/user/[id].js") }
|
|
12
|
+
* @param target - Optional DOM element to mount the component. Defaults to `document.body`.
|
|
13
|
+
*/
|
|
14
|
+
export function createSPAFileBasedRouter(
|
|
15
|
+
pages: Record<
|
|
16
|
+
string,
|
|
17
|
+
() => Promise<{ default: (param? : Record<string, string>) => UIElement }>
|
|
18
|
+
>,
|
|
19
|
+
target?: HTMLElement | UIElement
|
|
20
|
+
): Promise<void>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// dynamic_routes_parser.d.ts
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Parses a route according to a dynamic mask and returns extracted parameters.
|
|
5
|
+
*
|
|
6
|
+
* @param mask - The dynamic route mask (e.g., "/user/[id]+", "/blog/[...slug]").
|
|
7
|
+
* @param route - The actual route to parse (e.g., "/user/42", "/blog/2025/oct/post").
|
|
8
|
+
* @returns An object mapping parameter names to their corresponding values.
|
|
9
|
+
* Returns an empty object if the route does not match the mask.
|
|
10
|
+
*/
|
|
11
|
+
export declare function dynamic_routes_parser(
|
|
12
|
+
mask: string,
|
|
13
|
+
route: string
|
|
14
|
+
): Record<string, string>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// get_root.d.ts
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Finds the common root path among an array of paths.
|
|
5
|
+
* Dynamic segments (e.g., `[id]`) are considered as matching any segment.
|
|
6
|
+
*
|
|
7
|
+
* @param paths - An array of route paths (e.g., ["/user/42", "/user/99"]).
|
|
8
|
+
* @returns The common root path as a string (e.g., "/user/").
|
|
9
|
+
* Returns an empty string if no common root exists.
|
|
10
|
+
*/
|
|
11
|
+
export declare function get_root(paths: string[]): string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// normalize_path.d.ts
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Normalizes a file path into a route path.
|
|
5
|
+
*
|
|
6
|
+
* @param inputPath - The file path to normalize (e.g., "./src/pages/user/[id].ts").
|
|
7
|
+
* @param root - The root directory to consider as the base (default: "./src/pages").
|
|
8
|
+
* @param extensions - Array of valid file extensions (default: ["js", "ts"]).
|
|
9
|
+
* @returns A normalized route path (e.g., "/user/[id]") or an empty string if it cannot be normalized.
|
|
10
|
+
*/
|
|
11
|
+
export declare function normalize_path(
|
|
12
|
+
inputPath: string,
|
|
13
|
+
root?: string,
|
|
14
|
+
extensions?: string[]
|
|
15
|
+
): string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// routes_utils.d.ts
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Checks if a route path is dynamic.
|
|
5
|
+
* Dynamic segments include:
|
|
6
|
+
* - Parameters like "[id]"
|
|
7
|
+
* - Catch-all segments like "[...slug]"
|
|
8
|
+
* - Optional segments like "[id]+"
|
|
9
|
+
*
|
|
10
|
+
* @param path - The route path to check.
|
|
11
|
+
* @returns `true` if the path is dynamic, otherwise `false`.
|
|
12
|
+
*/
|
|
13
|
+
export function is_dynamic(path: string): boolean;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Groups routes into static and dynamic categories.
|
|
17
|
+
* Throws an error if an optional parameter appears anywhere but the end of the path.
|
|
18
|
+
*
|
|
19
|
+
* @param routeMap - An object mapping route paths to their handlers/values.
|
|
20
|
+
* @returns An object with two properties:
|
|
21
|
+
* - `static`: Routes with no dynamic segments.
|
|
22
|
+
* - `dynamic`: Routes with dynamic segments.
|
|
23
|
+
*/
|
|
24
|
+
export function routes_grouper<T>(
|
|
25
|
+
routeMap: Record<string, T>
|
|
26
|
+
): {
|
|
27
|
+
static: Record<string, T>;
|
|
28
|
+
dynamic: Record<string, T>;
|
|
29
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function routes_matcher(mask: string, route: string): boolean;
|