diff --git a/README.md b/README.md index 28993e2..1b10f56 100644 --- a/README.md +++ b/README.md @@ -6,17 +6,6 @@ [Full Documentation @ Hashnode Space](https://wjfe-n-savant.hashnode.space) -> **🚧 IMPORTANT NOTICE** -> -> We're in the process of re-branding the package as `@svelte-router/core`. This document has been updated to reflect -> this (future) new package name. In the meantime, continue using the soon-to-be-deprecated package name, -> `@wjfe/n-savant` when installing or importing. -> -> If you need to import stuff from `@svelte-router/core/kernel`, in the old package the path is `@wjfe/n-savant/core`. -> -> The full online documentation has already been updated, but the URL's cannot be changed. Alas, we'll have to deploy -> our own docs and stop using Hashnode Space. - ## Features + **Always-on path and hash routing**: Simultaneous, independent and always-on routing modes. @@ -40,6 +29,7 @@ routing universes. **Reactive Data**: + `location.url` ++ `location.path` + `location.hashPaths` + `location.getState()` + `RouterEngine.routes` @@ -70,7 +60,7 @@ de-synchronizing state. ### Install the package ```bash -npm i @svelte-router/core +npm i @svelte-router/core@beta // For now, until v1.0.0 is released ``` ### Initialize the Library @@ -96,8 +86,7 @@ init({ defaultHash: true }); #### Electron Variant -In Electron, we must immediately navigate to the homepage (or your preferred initial route) right after initializing -if you use path routing: +In Electron, perform immediate navigation to clean the environment's path: ```typescript import { init, location } from "@svelte-router/core"; @@ -114,9 +103,6 @@ details. ### Define the Routes -``s are added inside ``s. ``s can be nested inside other ``s. ``s can render -``s or other ``s, etc. You get the idea: You do as you wish. - ```svelte - - - {#await loadUsersComponent()} - Loading... - {:then Users} - - {:catch} -

Oops!

- {/await} -
-``` - -### Navigation Events - -There are no navigation events defined. Simply write effects or derived computations based on the global `location` -object's `url`, `state` or `hashPaths` properties, which are reactive. - -```typescript -import { location } from "@svelte-router/core"; - -// Or $derived, whichever you need. -$effect(() => { - // Read location.url to re-run on URL changes (navigation). - location.url; - // Read location.state to re-run on state changes. - location.state; - // Read location.hashPaths to re-run on hash changes (hash navigation). - // The route named "single" is the one you want if doing hash routing. - location.hashPaths.single; -}); -``` - -### Parameter Types - -There is no parameter type specification. All parameter values go through type parsing: - -+ If the value represents a number, then the parameter value will be a `number`. -+ If the value is the word `'true'` or `'false'`, then the parameter value will be a `boolean`. -+ If none of the above, the value will be a `string`. - -If the demand for parameter value types grow, this might be reconsidered, but know that this is easily achievable with -the `and` property on routes, or by specifying the path as a regular expression. - -In the context of the following code, the path `'/users/summary'` would match both routes, so the one that needs a -numeric parameter value uses the `and` property to type-check the value: - -```svelte - typeof rp.userId === 'number'}> - {#snippet children(rp)} - - {/snippet} - - - - -``` - -This is the version using a regular expression for the `path` property: - -```svelte -\d+)/i}> - {#snippet children(rp)} - - {/snippet} - - - - -``` - -### Reacting to Route Matching Events - -If you're interested in reacting whenever (a) particular route(~~s~~) match(es), you can get a hold of the `routeStatus` -property of router engines (which is reactive) by binding to a router's `router` property: - -```svelte - - - - ... - -``` - -## Navigation - -The recommended way of navigating is to create `` component instances to render links on the document(s). If -needed, however, there are 2 navigation functions in the `location` object: `navigate()` and `goTo()`. - -### `navigate(url, options)` - Routing Universe Aware - -This is the preferred method for programmatic navigation as it understands routing universes and properly manages state: - -```typescript -import { location } from "@svelte-router/core"; - -// Path routing navigation: -location.navigate('/new/path', { - replace: true, - state: { custom: 'Hi' }, - hash: false -}); - -// Hash routing navigation: -location.navigate('/new/path', { - replace: true, - state: { custom: 'Hi' }, - hash: true -}); - -// Multi-hash routing navigation: -location.navigate('/new/path', { - replace: true, - state: { custom: 'Hi' }, - hash: 'path1' -}); - -// Preserve existing query parameters: -location.navigate('/new/path', { - preserveQuery: true, - hash: false -}); -``` - -The `navigate()` method automatically: -- Associates state with the correct routing universe based on the `hash` option -- Preserves other routing universe states (e.g., when navigating `path1`, other named paths remain intact) -- Handles URL construction using the robust `calculateHref()` logic - -### `goTo(url, options)` - Direct URL Navigation - -This method provides direct URL navigation without routing universe awareness: - -```typescript -import { location } from "@svelte-router/core"; - -// Direct URL navigation: -location.goTo('https://example.com/new/path', { - replace: true, - state: { path: undefined, hash: {} } // Must provide complete State object -}); - -// Shallow routing (navigate to current URL): -location.goTo('', { replace: true }); - -// Preserve query parameters: -location.goTo('/new/path', { - preserveQuery: ['param1', 'param2'] -}); -``` - -**⚠️ Important:** `goTo()` requires you to provide a complete `State` object and does not understand routing -universes. Use `navigate()` unless you specifically need direct URL control. - -### Options Reference - -Both methods support these common options: - -- **`replace?: boolean`** - Replace current URL instead of pushing new entry (default: `false`) -- **`preserveQuery?: PreserveQuery`** - Preserve current query parameters (default: `false`) - - `true` - Preserve all query parameters - - `string` - Preserve specific parameter by name - - `string[]` - Preserve multiple specific parameters - -Additional `navigate()` options: -- **`hash?: Hash`** - Routing universe to associate with (`false`, `true`, or named hash) -- **`state?: any`** - State data to associate with the navigation - -Additional `goTo()` options: -- **`state?: State`** - Complete state object conforming to library expectations - -### Navigation Best Practices - -1. **Use `` components** for user-triggered navigation -2. **Use `navigate()`** for programmatic navigation within routing universes -3. **Use `goTo()`** only for direct URL manipulation -4. **Try to specify `hash`** in `navigate()` instead of relying on the default hash whenever possible - -Just in case you are wondering: This navigation logic is already there in `` components: - -```svelte - -Click Me! - - -Click Me! - - - -Click Me! -``` - -As seen, the value of the `href` property never changes. It's always a path, regardless of the routing universe. - -> **⚠️ Important:** Not setting the `hash` property is **not the same** as setting it to `false`. When `hash` is -> `undefined`, either because the property is not specified at all, or its value is set to `undefined` explicitly, the -> value of the `defaultHash` library option, which is set when the library is initialized, will be used instead. -> -> This is true for all components that support the `hash` property. - -## Playing with Fire - -At your own risk, you could use exported API like `getRouterContext()` and `setRouterContext()` to perform unholy acts -on the router layouts, again, **at your own risk**. - -## URL Redirection - -Create `Redirector` class instances to route users from deprecated URL's to new URL's. The redirection can even cross -the routing universe boundary. In other words, URL's from one routing universe can be redirected to a different -routing universe. - -This is a same-universe example: - -```svelte - -``` - -The constructor of the class sets a Svelte `$effect` up, so instances of this class must be created in places where -Svelte effects are acceptable, like the initialization code of a component (like in the example). - -Redirections are almost identical to route definitions, and even use the same matching algorithm. The `pattern` is -used to match the current URL (it defines the deprecated URL), while `href` defines the new URL users will be -redirected to. As seen in the example, parameters can be defined, and `href`, when written as a function, receives -the route parameters as the first argument. - -### Cross-Universe Redirection - -Crossing the universe boundary when redirecting is very simple, but there's a catch: Cleaning up the old URL. - -```svelte - -``` - -The modifications in the example are: - -1. Explicit hash value in the redirector's constructor. -2. Destination hash value specifications via options. - -Now comes the aforementioned catch: The "final" URL will be looking like this: `https://example.com/orders/123#/profile/my-orders/123`. - -There's no good way for this library to provide a safe way to "clean up" the path in the deprecated routing universe, -so it is up to consumers of this library to clean up. How? The recommendation is to tell the redirector to use -`location.goTo()` and provide a full HREF with all universes accounted for. - -See the [Redirecting](https://wjfe-n-savant.hashnode.space/wjfe-n-savant/navigating/redirecting) topic in the online -documentation for full details, including helper functions available to you. - --- [Issues Here](https://github.com/WJSoftware/svelte-router-core/issues)