@jay-js/system
Version:
A powerful and flexible TypeScript library for UI, state management, lazy loading, routing and managing draggable elements in modern web applications.
101 lines • 4.07 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { routerOptions } from "../configuration";
import { getRoute } from "./get-route";
// Store for beforeNavigate functions - functions are automatically destroyed after execution
const navigationGuards = new Set();
/**
* Register a function to be executed before the next navigation.
* The navigation will only proceed if the function returns true.
* The function is automatically removed after being executed once.
*
* @param {Function} guardFn - Function that returns boolean or Promise<boolean>
* @param {Object} options - Additional options (reserved for future use)
* @returns {Function} - Function to manually remove the guard if needed
*
* @example
* // Prevent navigation if form has unsaved changes
* beforeNavigate(() => {
* if (formHasUnsavedChanges()) {
* return confirm('You have unsaved changes. Are you sure you want to leave?');
* }
* return true;
* });
*/
export function beforeNavigate(guardFn) {
navigationGuards.add(guardFn);
// Return a function to manually remove the guard if needed
return () => {
navigationGuards.delete(guardFn);
};
}
/**
* Executes all registered navigation guards.
* Returns true if all guards pass, false otherwise.
*/
function runNavigationGuards() {
return __awaiter(this, void 0, void 0, function* () {
// Convert to array to ensure we work with a fixed set even if guards modify the set
const guards = Array.from(navigationGuards);
for (const guard of guards) {
// Remove the guard as it should only run once
navigationGuards.delete(guard);
try {
// Execute the guard and await if it's a promise
const result = guard();
const canProceed = result instanceof Promise ? yield result : result;
if (!canProceed) {
return false;
}
}
catch (error) {
console.error("Navigation guard failed:", error);
return false;
}
}
return true;
});
}
/**
* Navigates to a specified path programmatically
*
* This function updates the browser URL and triggers route resolution without requiring a full page reload.
* If a prefix is configured in the router options, it will be automatically applied to the path.
*
* Before navigation occurs, any registered beforeNavigate guards are executed.
* The navigation will only proceed if all guards return true.
*
* @param {string} path - The target path to navigate to (without the prefix)
*
* @example
* // Navigate to the about page
* navigate('/about');
*
* // With a configured prefix of '/app', this would navigate to '/app/about'
*/
export function navigate(path) {
return __awaiter(this, void 0, void 0, function* () {
// Run navigation guards before proceeding
const canProceed = yield runNavigationGuards();
if (!canProceed) {
return; // Stop navigation if any guard returned false
}
const prefixOptions = routerOptions.prefix || "";
if (prefixOptions) {
path = [prefixOptions, path]
.join("/")
.replace(/\/+$/, "")
.replace(/\/{2,}/g, "/");
}
history.pushState(null, "", path);
getRoute();
});
}
//# sourceMappingURL=navigate.js.map