@svelteuse/router
Version:
Useful svelte router helper
283 lines (278 loc) • 7.64 kB
JavaScript
import {
__privateAdd,
__privateGet,
__privateSet
} from "./chunk-ME6M5CRB.mjs";
// node_modules/regexparam/dist/index.mjs
function parse(str, loose) {
if (str instanceof RegExp)
return { keys: false, pattern: str };
var c, o, tmp, ext, keys = [], pattern = "", arr = str.split("/");
arr[0] || arr.shift();
while (tmp = arr.shift()) {
c = tmp[0];
if (c === "*") {
keys.push("wild");
pattern += "/(.*)";
} else if (c === ":") {
o = tmp.indexOf("?", 1);
ext = tmp.indexOf(".", 1);
keys.push(tmp.substring(1, !!~o ? o : !!~ext ? ext : tmp.length));
pattern += !!~o && !~ext ? "(?:/([^/]+?))?" : "/([^/]+?)";
if (!!~ext)
pattern += (!!~o ? "?" : "") + "\\" + tmp.substring(ext);
} else {
pattern += "/" + tmp;
}
}
return {
keys,
pattern: new RegExp("^" + pattern + (loose ? "(?=$|/)" : "/?$"), "i")
};
}
// node_modules/svelte/internal/index.mjs
function noop() {
}
function run(fn) {
return fn();
}
function run_all(fns) {
fns.forEach(run);
}
function is_function(thing) {
return typeof thing === "function";
}
function safe_not_equal(a, b) {
return a != a ? b == b : a !== b || (a && typeof a === "object" || typeof a === "function");
}
function is_empty(obj) {
return Object.keys(obj).length === 0;
}
var resolved_promise = Promise.resolve();
var globals = typeof window !== "undefined" ? window : typeof globalThis !== "undefined" ? globalThis : global;
function destroy_component(component, detaching) {
const $$ = component.$$;
if ($$.fragment !== null) {
run_all($$.on_destroy);
$$.fragment && $$.fragment.d(detaching);
$$.on_destroy = $$.fragment = null;
$$.ctx = [];
}
}
var SvelteElement;
if (typeof HTMLElement === "function") {
SvelteElement = class extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
}
connectedCallback() {
const { on_mount } = this.$$;
this.$$.on_disconnect = on_mount.map(run).filter(is_function);
for (const key in this.$$.slotted) {
this.appendChild(this.$$.slotted[key]);
}
}
attributeChangedCallback(attr, _oldValue, newValue) {
this[attr] = newValue;
}
disconnectedCallback() {
run_all(this.$$.on_disconnect);
}
$destroy() {
destroy_component(this, 1);
this.$destroy = noop;
}
$on(type, callback) {
const callbacks = this.$$.callbacks[type] || (this.$$.callbacks[type] = []);
callbacks.push(callback);
return () => {
const index = callbacks.indexOf(callback);
if (index !== -1)
callbacks.splice(index, 1);
};
}
$set($$props) {
if (this.$$set && !is_empty($$props)) {
this.$$.skip_bound = true;
this.$$set($$props);
this.$$.skip_bound = false;
}
}
};
}
// node_modules/svelte/store/index.mjs
var subscriber_queue = [];
function writable(value, start = noop) {
let stop;
const subscribers = /* @__PURE__ */ new Set();
function set(new_value) {
if (safe_not_equal(value, new_value)) {
value = new_value;
if (stop) {
const run_queue = !subscriber_queue.length;
for (const subscriber of subscribers) {
subscriber[1]();
subscriber_queue.push(subscriber, value);
}
if (run_queue) {
for (let i = 0; i < subscriber_queue.length; i += 2) {
subscriber_queue[i][0](subscriber_queue[i + 1]);
}
subscriber_queue.length = 0;
}
}
}
}
function update(fn) {
set(fn(value));
}
function subscribe2(run2, invalidate = noop) {
const subscriber = [run2, invalidate];
subscribers.add(subscriber);
if (subscribers.size === 1) {
stop = start(set) || noop;
}
run2(value);
return () => {
subscribers.delete(subscriber);
if (subscribers.size === 0) {
stop();
stop = null;
}
};
}
return { set, update, subscribe: subscribe2 };
}
// src/index.ts
function exists(x) {
return x === void 0 || x === null ? false : true;
}
var _destination, _logic;
var Guard = class {
constructor(logic = "and", destination = "/") {
__privateAdd(this, _destination, void 0);
__privateAdd(this, _logic, void 0);
__privateSet(this, _logic, logic);
__privateSet(this, _destination, destination);
}
goTo(href) {
__privateSet(this, _destination, href);
return this;
}
_navigate() {
useRouter.update((storeData) => {
storeData.navigate(__privateGet(this, _destination));
return storeData;
});
}
check(...args) {
if (__privateGet(this, _logic) === "and" && args.some((check) => check == false)) {
this._navigate();
}
return this;
}
};
_destination = new WeakMap();
_logic = new WeakMap();
function useGuard() {
return new Guard();
}
function link(node) {
node.addEventListener("click", function(event) {
event.preventDefault();
const href = node.getAttribute("href");
useRouter.update((storeData) => {
storeData.navigate(href?.toString() || "");
return storeData;
});
});
return {
destroy() {
}
};
}
var useRouter = writable({
routes: [],
mode: "history",
root: "/",
props: {},
component: void 0,
layout: void 0,
matchRoute: function(path) {
const routes = this.routes;
let match;
for (const route of routes) {
const { pathname, search } = new URL("https://test.org" + path);
const router = parse(route.path);
const isRoute = router.pattern.test(pathname);
if (isRoute)
match = route;
if (router.keys.length > 0) {
const matches = router.pattern.exec(pathname);
if (matches) {
let i = 0;
while (i < router.keys.length) {
const key = router.keys[i].toString();
const value = matches[++i];
this.props[key] = value;
}
}
}
if (search.length > 0) {
this.props["queryparams"] = Object.fromEntries(new URLSearchParams(search));
}
if (isRoute)
break;
}
return match;
},
getFragment: () => {
return decodeURI(window.location.pathname + window.location.search);
},
updateSelf: async function() {
if (this.routes) {
const currentPath = this.getFragment();
const svelteComponent = this.matchRoute(currentPath);
if (!svelteComponent) {
const errorCode = 404;
this.navigate(`${this.getFragment().split("/")[1]}/errors/${errorCode}`);
return;
} else {
const component = await svelteComponent.loader();
useRouter.update((storeData) => {
storeData.component = component;
storeData.layout = svelteComponent.layout;
return storeData;
});
}
} else {
throw new Error("routes are not registered correctly");
}
},
getProps: function() {
return this.props;
},
navigate: function(path, track = true) {
useRouter.update((storeData) => {
switch (true) {
case (storeData.mode === "history" && track === true):
window.history.pushState(void 0, "", this.root + path.replace(/\/$/, "").replace(/^\//, ""));
break;
case (storeData.mode === "history" && track === false):
window.history.replaceState(void 0, "", this.root + path.replace(/\/$/, "").replace(/^\//, ""));
break;
default:
break;
}
storeData.updateSelf();
return storeData;
});
}
});
export {
exists,
link,
useGuard,
useRouter
};