@@ -21,5 +22,5 @@ We recommend that you move through the topics in order since the documentation h
If you are versed in in `single-spa`, maybe you should give the migration guide a try. *CollageJS* was born from the concept of *single-spa parcels* and you'll find much of *CollageJS* familiar.
- Migration Guid for single-spa
-
\ No newline at end of file
+
Migration Guide for the
single-spa savvy
+
diff --git a/src/routes/(docs-like)/docs/collagejs-packages-and-repositories/+page.md b/src/routes/(docs-like)/docs/collagejs-packages-and-repositories/+page.md
new file mode 100644
index 0000000..e33e38a
--- /dev/null
+++ b/src/routes/(docs-like)/docs/collagejs-packages-and-repositories/+page.md
@@ -0,0 +1,36 @@
+---
+ title: CollageJS Packages & Repositories
+ description: |
+ List of all available GitHub repositories and NPM packages at https://npmjs.com.
+---
+
+
+
+For general knowledge and future reference, we present here all of the available NPM packages at [npmjs.com](https://npmjs.com/org/collagejs) as well as any other public repository that may be useful to you.
+
+## Packages
+
+| Package | Links | Description |
+| - | - | - |
+| `@collagejs/core` |
| Core functionality. Provides the general mounting and unmounting logic. |
+| `@collagejs/vite-css` |
| Vite plug-in that offers a CSS-mounting algorithm that is fully compatible with Vite's CSS bundling, including split CSS. It also features FOUC prevention, shadow root mounting and relocation. |
+| `@collagejs/vite-im` |
| Vite plug-in that injects an import map and optionally the `@collagejs/imo` package to define bare module identifiers for easy micro-frontend loading and debugging. |
+| `@collagejs/vite-aim` |
| Vite-plugin that auto-externalizes the module identifiers found in the application's import map. It receives the import map live (and with overrides) from the client. This enables static imports (no more dynamic `import()` calls). |
+| `@collagejs/imo` |
| Our version of `import-map-overrides` that does the usual overriding of import map entries, plus it transmits the final import map to Vite development servers found in it. |
+| `@collagejs/adapter` |
| NPM package that encapsulates code that is often used to create *CollageJS* framework adapters. |
+| `@collagejs/svelte` |
| Svelte component library that can be used to create `CorePiece`-compliant objects and to mount `CorePiece` objects (of any technology) by providing the `
` component. |
+| `@collagejs/react` | | React component library that can be used to create `CorePiece`-compliant objects and to mount `CorePiece` objects (of any technology) by providing the `` component. |
+| `@collagejs/solidjs` | | SolidJS component library that can be used to create `CorePiece`-compliant objects and to mount `CorePiece` objects (of any technology) by providing the `` component. |
+| `@collagejs/vue` | | **Next in line** VueJS component library that can be used to create `CorePiece`-compliant objects and to mount `CorePiece` objects (of any technology) by providing the `` component. |
+| `@collagejs/angular` | | **External help needed.** We don't have expertise in Angular, nor do we want to acquire it. If you're an Angular developer, please consider contributing. |
+
+## Other Repositories
+
+| Repository | Description |
+| - | - |
+| [Root Template](https://github.com/collagejs/root-template) | Root template repository that can be used to create new repositories for *CollageJS* root projects, with client-side routing already configured. |
+| [Gallery](https://github.com/collagejs/gallery) | Repository of *CollageJS* pieces made in various front-end technologies for your reference and inspiration. |
diff --git a/src/routes/(docs-like)/docs/primary-sidebar.json b/src/routes/(docs-like)/docs/primary-sidebar.json
index 91c50b9..c72572e 100644
--- a/src/routes/(docs-like)/docs/primary-sidebar.json
+++ b/src/routes/(docs-like)/docs/primary-sidebar.json
@@ -6,6 +6,10 @@
"title": "Introduction",
"href": "/docs/introduction"
},
+ {
+ "title": "CollageJS Packages & Repositories",
+ "href": "/docs/collagejs-packages-and-repositories"
+ },
{
"title": "Project Types",
"href": "/docs/project-types"
diff --git a/src/routes/(docs-like)/docs/root-projects-in-detail/+page.md b/src/routes/(docs-like)/docs/root-projects-in-detail/+page.md
new file mode 100644
index 0000000..f80ffb9
--- /dev/null
+++ b/src/routes/(docs-like)/docs/root-projects-in-detail/+page.md
@@ -0,0 +1,125 @@
+---
+ title: Root Projects in Detail
+ description: |
+ Detailed explanation of what is considered a CollageJS root project, which benefits it carries and how to configure its features.
+---
+
+
+
+Let's clarify things once more: Any web project can serve as root project for a *CollageJS*-powered application. It doesn't even need to be Vite-powered, as one can use the framework adapters under any and every bundler, and in the remote case where this wasn't possible, one should be able to use `@collagejs/core` directly to mount and handle `CorePiece` objects.
+
+However, *CollageJS* has made available Vite plug-ins that make life easier. Therefore, we can define a *CollageJS* root project as a Vite-powered project configured with the [Vite-IM plugin](/docs/vite-im-plugin) where import maps are used to fulfill externalization of both *CollageJS* piece modules and other related dependencies.
+
+With this formal definition, let's explain the available features and how to use them the best possible way. Let's just make sure we all know how to install and configure the plug-in.
+
+To install:
+
+```bash
+npm install @collagejs/vite-im
+```
+
+To configure:
+
+```typescript
+// An example from a Vite + Svelte project
+import { defineConfig } from 'vite';
+import { svelte } from '@sveltejs/vite-plugin-svelte';
+import { cjsImPlugin } from '@collagejs/vite-im';
+
+export default defineConfig({
+ plugins: [svelte(), cjsImPlugin()],
+});
+```
+
+## Import Maps
+
+*Import maps* are not an invention of *CollageJS*. They have been around for quite some time and you [should learn](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/script/type/importmap) as much about them as possible.
+
+In short, an import map is a substitution table, where a *bare module specifier* comes in, and the import map spits out its assigned value, which usually is in the form of a URL that browsers understand and can fetch from.
+
+*CollageJS*' `@collagejs/vite-im` Vite plug-in makes working with import maps a breeze. This plug-in:
+
+- Can merge multiple import maps into one
+- Injects the merged import map into the web application's HEAD HTML element
+- Injects `@collagejs/imo` that serves as a developer tool for overriding import map entries
+- Sets up and configure *CollageJS*' auto-extrnalization plug-in `@collagejs/vite-aim`
+
+There are several ways to specify import maps, but we'll only cover 2 here. For detailed information, refer to the **Import Maps** section of the documentation.
+
+### How to Use Import Maps
+
+Without making a single change to any of the plug-in configuration options, we can create the `src/importMap.json` file and the plug-in will inject it as an overridable import map. Furthermore, it will inject `@collagejs/imo` for import map entry overriding and will activate the `@collagejs/vite-aim` plug-in.
+
+That's right: All that just by adding the import map file. Try it out, even if you still don't have the need of an import map in your application:
+
+```json
+{
+ "imports": {
+ "@tutorial/first-piece": "http://localhost:6101/piece.js"
+ }
+}
+```
+
+Start your project's development server. Examine the HEAD element in Developer Tools. You should see several entries there:
+
+- A `
+
+We already know that we can use `npm create vite@latest` to produce a Vite-powered project using our preferred framework or library, be it React, Svelte, Vue, or anything else Vite can bundle.
+
+This is great for sure. The amount of freedom is something many people can agree upon. But there's one thing that people seem to (almost) always want when doing micro-frontends: Routing.
+
+Especially if you come from the `single-spa` environment, you're used to getting a client-side router provided to you, and *CollageJS* does **not** provide a client-side router. *CollageJS* is a bring-your-own-router kind of library, and we hope that this is great news to everyone. Now people can use their preferred routing package for their projects.
+
+Still, there will be people out there interested in a recommendation, and *CollageJS* happens to have a recommendation: [webJose's Svelte Router](https://svelte-router.dev) is a router unlike any other and it brings a lot of power to micro-frontend scenarios because:
+
+- It matches multiple routes simultaneously (like the `single-spa` router)
+- It does path routing and hash routing simultaneously
+- It can dissect the hashtag into multiple paths, allowing an application to have multiple, independent routes simultaneously
+
+To the best of our knowledge, no other router in the world can do the above, and it so happens to be a very useful thing in micro-frontends.
+
+Our [root template](https://github.com/collagejs/root-template) template is a *Vite + TS + Svelte* project with *webJose's Svelte Router* installed and configured.
+
+> ** Svelte Knowledge Required**
+>
+> To take full advantage of this root template project, one should know at least some Svelte v5. The basics regarding reactivity are of particular importance, as all data provided by the router library is a Svelte reactive signal.
+
+## Starting with the Root Template
+
+There are two, very easy ways to start. You can either degit the repository:
+
+```bash
+npx degit https://github.com/collagejs/root-template
+```
+
+Or you can [clone it into a new repository (by clicking this link)](https://github.com/new?template_name=root-template&template_owner=collagejs).
+
+Once you have cloned it, install dependencies and run Vite's development server
+
+```bash
+npm install
+npm run dev
+```
+
+## Project Description
+
+When you first run it, the homepage appears, boasting *CollageJS* logo at the center. On top, there is a navigation bar. The brand section in the upper left corner contains a small palette () icon that serves as a color picker. It will rotate through the four palettes of the *CollageJS* brand.
+
+You'll find the navigation links in the upper right corner. There are 5 links there:
+
+- **Home** -- takes you to the home page
+- **Intro** -- takes you to the introduction page
+- **PIN Pad** -- takes you to the *CollageJS* piece demonstration page and requires additional setup (explained in the page)
+- **Feature** -- is not really a defined route in the router, so what shows up is fallback content
+- **About** -- takes you to the About page
+
+Every valid route will show, on top and just below the navigation bar the source file's name. If you're interested about a particular something you saw in a page, open that file in your IDE and grab the knowledge you seek.
+
+## The PIN Pad Demonstration
+
+This is where we can see *CollageJS* in action, but requires extra steps.
+
+The `pieces/svelte-pinpad` folder contains another *Vite + TS + Svelte* project, but configured to be a piece project, not a root project. In order to be able to load the PIN Pad piece, build the project and start Vite's preview server.
+
+> ** Notes**
+>
+> - The PIN Pad project is a Svelte project just to keep the root template repository in one framework, but *CollageJS* can load pieces of any framework or library.
+> - We build and preview because shadow DOM mounting cannot be done using a Vite development server.
+
+Once the preview server for the PIN Pad project is up and running, we can reload the PIN Pad page of the root template to see it in action.
+
+## Host-Piece Interaction
+
+Once the PIN pad becomes visible, the host application (the root template application) can interact with it much like it was a regular component (Svelte component, in this case, because the root template is made with Svelte).
+
+There are 2 sets of controls present in the page. The ones labeled *Piece Properties* are actual properties for the PIN pad component and the list of properties for a *CollageJS* piece vary from component to component. The other set labeled *Container Settings* is a demonstration of the capabilities of the official Svelte adapter library. The library lets you mount the piece it is given to it in light DOM, open or closed shadow roots, and can even jump between options in runtime.
+
+The other "nicety" is that it forwards attributes to the container element. The controls allows the setting of the container's padding and background color.
+
+> ** Tip**
+>
+> There's a third feature in the page about the adapter that cannot be controlled with the provided controls: The ability to set event listeners. If you look closely, there's a tip just above the PIN pad component that disappears as soon as the PIN pad gains keyboard focus. This is achieved with container event listeners for the `focusin` and `focusout` bubbling events.
+
+## Enabling the IMO User Interface
+
+Root templates that use the [Vite-IM plugin](/docs/vite-im-plugin) have, by default, a hidden *CollageJS* piece injected in the page from the NPM package `@collagejs/imo`. This user interface is used to override import map entries, mostly for development purposes.
+
+To enable it, open *Developer Tools* in your browser for the root template's window/tab, then add the `imo-ui` key to local storage with the value `true`, and then reload the page. You'll see a semi-transparent overlay in the bottom-right corner of the application that becomes opaque when gaining keyboard focus or when the mouse hovers over it.
+
+If you would like to know more about how to use `@collagejs/imo` read about [root projects in detail](/docs/root-projects-in-detail).
\ No newline at end of file
diff --git a/src/routes/(docs-like)/guides/development-guide-for-adapters/+page.md b/src/routes/(docs-like)/guides/development-guide-for-adapters/+page.md
new file mode 100644
index 0000000..17e0d89
--- /dev/null
+++ b/src/routes/(docs-like)/guides/development-guide-for-adapters/+page.md
@@ -0,0 +1,325 @@
+---
+ title: Development Guide for Adapters
+ description: |
+ Describes the requirements and best practices to follow when creating a new CollageJS framework adapter.
+---
+
+
+
+The term *framework adapter* is used to refer to a library that provides developers the ability to do at least one of the following:
+
+- Create CollageJS `CorePiece` objects out of a user interface component
+- Mount CollageJS `CorePiece` components, usually imported from outside the current project
+
+> ** `@collagejs/sigle-spa` is an Exception**
+>
+> The NPM package `@collagejs/single-spa` is a compatibility adapter to assist in the migration from *single-spa*. It creates *single-spa* parcels out of *CollageJS* pieces.
+
+Official framework adapters attempt to expose a unified API so the learning curve is not increased by increasing the number of framework adapters. The ideal scenario is for all adapters to expose, as much as possible, an identical API. This way, developers need only to learn how to use one adapter, and this will carry over to every other adapter.
+
+We know for a fact that this is not 100% possible. We like having the ability to configure Svelte's `mount` function call, or React's `createRoot` function call. This is one place where we cannot provide the exact same interface.
+
+Despite our desire to standardize API, we also desire maximum flexibility. We value individual front-end framework abilities over the standard. Our stance is to never discard a great framework feature for the sake of standardization, and thus, we encourage adapter developers to make the most out of the front-end framework the adapter is for.
+
+## Public API
+
+> ** Adapter Library**
+>
+> The code examples above might import types and code from `@collagejs/adapter`. This is a helper library for adapter development.
+TODO: Add link to the documentation in the api/ route.
+
+Adapters should ideally fulfill the aforementioned 2 tasks. The public API to create a *CollageJS* piece should be a function called `buildPiece`, while the public API to mount *CollageJS* pieces should be a framework-specific component named `Piece`.
+
+### buildPiece
+
+The buildPiece function should have the following signature:
+
+```typescript
+import type { CorePiece, Relocate } from '@collagejs/core';
+
+declare function buildPiece<
+ TProps extends Record = Record,
+ TCap extends Record = {}
+>(component: FrameworkTypeForComponent, options?: OptionsType): CorePiece;
+```
+
+The `OptionsType` type should at least allow the specification of custom capabilities that correspond to the `TCap` type parameter. It is also OK if this type is dependant on the `TProps` type parameter as well.
+
+The other feature that an adapter should support in its option is `relocation?: 'supported' | 'unsupported' | Relocate`, which should trigger the creation of the `CorePiece` object with the requested relocation support.
+
+Summarizing, `OptionsType` should at least be:
+
+```typescript
+import type { CorePieceCapabilities } from '@collagejs/core';
+
+export type Options = {}> = {
+ relocation?: 'supported' | 'unsupported' | Relocate;
+ capabilities?: CorePieceCapabilities & TCap;
+}
+```
+
+Beyond this, adapter developers should make the most out of the framework the adapter is for. For example, the Svelte adapter allows specification of both mounting and unmounting options supported by Svelte v5's `mount` and `unmount` functions.
+
+> ** Disallow Target Specification**
+>
+> Every framework at some point has to determine a particular HTML element where to mount. Be 100% this cannot be specified during `CorePiece` creation. For example, the Svelte adapter emits a console warning if the `mount`'s `target` option is set by the caller.
+
+#### Implementation Details
+
+The goal is to return an object of type `CorePiece` with the specified capabilities and relocation support. Anything beyond this is optional, and developers should make full use of the front-end framework's features at their disposal.
+
+An implementation for `buildPiece` could look similar to this:
+
+```typescript
+import { preventRemount } from '@collagejs/core';
+
+export function buildPiece<
+ TProps extends Record = Record,
+ TCap extends Record = {}
+>(component: AmazingComponent, options?: Options) {
+ const instanceCtx = new SomeInstanceContextClass();
+ // A default value of 'supported' is encouraged, but framework nature and abilities
+ // should be taken into account to decide this default value.
+ const relocation = options?.relocation ?? 'supported';
+
+ return {
+ mount: options?.capabilities?.remountable === false ?
+ [preventRemount(), mount.bind(instanceCtx)] :
+ mount.bind(instanceCtx),
+ update: update.bind(instanceCtx),
+ relocate: typeof relocation === 'string' ? () => Promise.resolve(relocation) : relocation,
+ get capabilities() {
+ return options?.capabilities;
+ } satisfies CorePiece;
+ };
+
+ function mount(this: SomeInstanceContextClass, ...) { ... }
+ function update(this: SomeInstanceContextClass, ...) { ... }
+}
+```
+
+This is one possible way to implement that shows a few important things:
+
+- If the caller explicitly states that the piece cannot be remounted, add `preventRemount()` to the list of mounting functions.
+- If it is customary for the framework components to not care about their parent element, a default value of `'supported'` for the `relocaiton` option is encouraged.
+- We forward the capabilities object specified in the options.
+- All functions returned in the `CorePiece` object must not care about their context (the value of `this`) or must be pre-bound to a context, like the example shows.
+
+### Piece Component
+
+This is a difficult section because a particular framework could do things so differently to others that any code snippets presented here end up being worthless for said framework. However, we can still explain the concepts and best practices, and whether or not `@collagejs/adapter` provides help for something specific.
+
+Most front-end frameworks work with the concept of `Component` defined as a complete unit of code that produces zero or more DOM trees that end up mounted somewhere in an HTML document. With this definition, we want to create a `Piece` component (a unit of code that satisfies the definition of our front-end framework's `Component` term) that can accept a `CorePiece` object --usually through its "properties" mechanism-- and mounts it where we want it mounted.
+
+For the `Piece` component, we want to achieve a component that:
+
+- Doesn't affect the properties namespace
+- Provides the ability to mount in light DOM, open or closed shadow roots
+- Provides a method for specifying container element properties/attributes and event callbacks
+- Can inherit/transmit new parent-aware `mountPiece` function created by mounting the core piece down the DOM tree
+- Mounts the core piece given to it using the parent-aware `mountPiece` function
+- Marks the container element with the `data-cjs-piece-host` and `data-cjs-framework` attributes
+
+#### Tackling Properties Namespace, Shadow Mounting & Container Properties
+
+Most front-end frameworks and libraries allow data to their components in the form of a POJO. If this is the case for the framework at hand, we can achieve the trick by using a symbol:
+
+```typescript
+const pieceProps = symbol();
+```
+
+We can then accummulate any number of properties in the component's properties without consuming a property name. However, it would be a bit cumbersome for consumers of the adapter if they had to do the symbol syntax on their own.
+
+Because of this, official adapters export the `piece` (lowercase because the uppercase form is for the component itself) helper function that deals with the symbol-in-POJO syntax so consumers of the adapter library don't have to:
+
+```typescript
+export function piece<
+ TProps extends Record = Record,
+ TCap extends Record = {}
+>(piece: CorePiece, options?: PieceOptions) {
+ return {
+ [pieceProps]: {
+ piece,
+ ...options
+ },
+ };
+}
+```
+
+Where the `options` parameter is usually used to carry the shadow-mounting preference and the container element properties and event callbacks. The standardized typing for the options in official adapters is:
+
+```typescript
+export type PieceOptions {
+ shadow?: boolean | ShadowRootInit;
+ containerProps?: IdeallyAFrameworkProvidedTypeToTypeContainerProperties;
+ // Add any other options that might be frameworks-specific
+}
+```
+
+The typing for the `shadow` property is standard because `@collagejs/adapter` offers the `getPieceTarget` that defines a `shadow` parameter with this exact type, so this makes it simple (and standard) to use.
+
+> ** What if this trick is inapplicable?**
+>
+> We haven't encountered such case. If you have, please resolve it and let us know how you did it!
+>
+> Truthfully, if it cannot be done, it cannot be done. We would love for this to be doable in all cases as this is the standard API in official adapters, but we prefer a working adapter than no adapter at all. Let's just always think about the simplest possible API for the consumers.
+
+#### Tackling `mountPiece` Requirements
+
+All popular front-end solutions offer the concept of *component context*, which consists in storing and obtaining a labeled (named) piece of information that is "closest" to the component requesting it. Different information may be found from different positions in the DOM tree.
+
+This concept is perfect for tackling the `mountPiece` requirements and is the mechanism used in official adapters.
+
+To implement, we have to put the `buildPiece` function to work in tandem with the `Piece` component.
+
+On the `buildPiece` side, the *CollageJS* runtime guarantees that the parent-aware `mountPiece` function is hidden inside the properties POJO passed on to all core piece `mount` lifecycle functions, **if there's already a `CorePiece` parent**. It hides it using a named symbol. The symbol can be obtained by importing it from `@collagejs/core`:
+
+```typescript
+import { mountPieceKey } from '@collagejs/core';
+```
+
+The symbol is used as the property name in the properties POJO coming from the runtime in `mount` lifecycle functions:
+
+```
+export function buildPiece<...>(...) {
+ return {
+ mount: mount.bind(...),
+ ...
+ };
+
+ function mount(this: ..., props?: MountProps) {
+ // So this is of type MountPiece or undefined
+ const mountPieceFn = props?.[mountPieceKey];
+ }
+}
+```
+
+At this point, we should pass that value of `mountPieceFn` as context value for the component we are mounting. This is framework-specific, so we cannot really provide an example, as every front-end technology will have their own way of creating context.
+
+Once this is completed, we have taken care of the inheritance requirement.
+
+Next in line is to fulfill the usage requirement.
+
+In the `Piece` component we retrieve the `mountPiece` function stored in context. If the context is empty, then default to use `mountPiece` from `@collagejs/core`.
+
+#### Fulfilling the Attributes Requirement
+
+As mentioned before, we have a helper library available for adapter development: @collagejs/adapter
+TODO: Add link to API documentation
+
+One of the exported functions from `@collagejs/adapter` is `hostAttributes` and returns a POJO with the two attributes ready to be spreaded onto the container element (assuming spreading is possible for the front-end framework we're developing this for):
+
+```typescript
+import { hostAttributes } from '@collagejs/adapter';
+
+const containerAtts = hostAttributes({ shadow, 'framework name' });
+```
+
+The type for `shadow` is the one we mentioned already as standard: `boolean | ShadowRootInit`. Provide it along with the framework's name (i. e. React, Svelte, Lit, Angular, Ripple-TS, etc.) and the function returns the attributes ready to go.
+
+#### Piece Best Practices
+
+Perhaps the most critical one is avoiding race conditions when executing lifecycle functions. Let's remember that all lifecycle functions are asynchronous operations.
+
+In order to avoid race conditions, always execute lifecycle functions using the `CorePieceLcQueue` class provided by `@collagejs/adapter`:
+
+```typescript
+import { CorePieceLcQueue } from '@collagejs/adapter';
+
+const lc = new CorePieceLcQueue(corePiece, mountPieceFn, {
+ relocateFn: relocationFn, // Only if the algorithm cannot be the one provided by trivialRelocate
+ enableLcLogging: true,
+});
+```
+
+> ** What is `trivialRelocate`?**
+>
+> It is a function in `@collagejs/adapter` (that can be imported if needed), with the simplest algorithm to transfer root DOM elements from one DOM element to another. If a front-end framework doesn't need to do anything special to relocate the DOM trees a component produces, relocation can be delegated to `trivialRelocate`.
+
+Now `lc` is a class that enqueues asynchronous actions one after the other, and has an almost identical interface to that of `MountedPiece`, which is what `mountPiece` returns when used directly.
+
+This is how it is used:
+
+```typescript
+import { CorePieceLcQueue, getPieceTarget } from '@collagejs/adapter';
+
+const lc = new CorePieceLcQueue(corePiece, mountPieceFn, {
+ relocateFn: relocationFn, // Only if the algorithm cannot be the one provided by trivialRelocate
+ enableLcLogging: true,
+});
+
+// MOUNTING
+// --------
+const containerElement = getContainerElementSomehow();
+// shadow is the shadow option specified for the piece component of type boolean | ShadowRootInit.
+const target = getPieceTarget(containerElement, shadow);
+
+lc.mount(target, props);
+
+// UPDATING
+// --------
+lc.update(newProps);
+
+// UNMOUNTING
+// ----------
+lc.unmount();
+
+// relocating UI
+// -------------
+lc.relocate(currentTarget, newTarget);
+```
+
+Each one of these calls enqueue the work instead of synchronously doing it. They all return a promise that can be awaited for frameworks that allow top-level await, or for awaiting inside functions.
+
+The queue object also has a generic `enqueue` method to enqueue arbitrary logic. For example, it might be very possible that the `currentTarget` variable above is a component-level state variable that needs to be updated after the relocation process finishes. The new assignment needs to be queued instead of be done immediately:
+
+```typescript
+lc.relocate(currentTarget, newTarget);
+lc.enqueue(() => void (currentTarget = newTarget));
+```
+
+> ** Never Nest Enqueues!**
+>
+> Well, never say NEVER. Maybe there's are very rare edge case that might call for nested enqueues, who knows! But as a general rule, never do `lc.(...)` inside an enqueued function because most likely is not what we want. Instead, do enqueueing outside at the component level.
+
+Now, to finally complete the queueing lesson: The front-end framework might allow developers to change the core piece object at will without unmounting our `Piece` component. Because `CorePieceLcQueue` objects are tied to a corePiece object (and the parent `mountPiece` function shared in context), a new queue object must be created if either of these change (reactively in modern frameworks). If this happens, we don't just drop the current queue as it might have pending work enqueued. What we do is *transfer the internal queue*:
+
+```typescript
+const newLc = new CorePieceLcQueue(newPiece, newMountPieceFn, ...);
+const [oldCorePiece, oldMountPiece, oldMountedPiece] = lc.transferTo(newLc);
+// Use the "ejected" internal state to clean up. Most commonly, unmount.
+newLc.enqueue(oldMountedPiece.unmount);
+newLc.mount(currentTarget, props);
+lc = newLc;
+```
+
+#### When to Relocate
+
+Relocate exists primarily as an enhancement to developer experience. During the course of development, source code changes, which causes modules to reload, which might trigger updates to reactive properties on frameworks that feature them. Furthermore, code around properties could change that could cause a change of target element that might be patched by HMR as variable updates instead of module reloads.
+
+Errors that may occur in HMR scenarios can be mitigated or eliminated by relocating when the target changes instead of unmounting and remounting in the new target. As a general rule, the `Piece` component should attempt relocation before a mounting cycle for the cases where the target element changes.
+
+To provide some guidance as code, this is how the Svelte `Piece` component handles a reactive change in the `shadow` option:
+
+```typescript
+$effect(() => {
+ shadow;
+ if (firstRun || !target) {
+ return;
+ }
+ const newTarget = getPieceTarget(containerEl!, shadow);
+ if (newTarget === target) {
+ return;
+ }
+ lc.relocate(target, newTarget, restProps);
+ lc.enqueue(() => (target = newTarget));
+});
+```
+
+Note that `CorePieceLcQueue.relocate` automatically performs a mounting cycle if the underlying `CorePiece` object doesn't support relocation or relocation fails.
+
+Relocation is an advanced topic.
+TODO: Add the topic link here
diff --git a/src/routes/(docs-like)/guides/primary-sidebar.json b/src/routes/(docs-like)/guides/primary-sidebar.json
index fe51488..74ad2fc 100644
--- a/src/routes/(docs-like)/guides/primary-sidebar.json
+++ b/src/routes/(docs-like)/guides/primary-sidebar.json
@@ -1 +1,10 @@
-[]
+[
+ {
+ "title": "Migration From Single-SPA",
+ "href": "/guides/migration-from-single-spa"
+ },
+ {
+ "title": "Development Guide for Adapters",
+ "href": "/guides/development-guide-for-adapters"
+ }
+]
diff --git a/src/routes/DocsLinks/DocsLinks.svelte b/src/routes/DocsLinks/DocsLinks.svelte
index 14bf4aa..fac213a 100644
--- a/src/routes/DocsLinks/DocsLinks.svelte
+++ b/src/routes/DocsLinks/DocsLinks.svelte
@@ -1,4 +1,5 @@
@@ -9,7 +10,9 @@
diff --git a/src/scss/md-content.css b/src/scss/md-content.css
index 80bc0ae..a475041 100644
--- a/src/scss/md-content.css
+++ b/src/scss/md-content.css
@@ -1,8 +1,15 @@
.md-content {
- h1, h2, h3, h4, h5, h6 {
+
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6 {
margin-top: 2rem;
margin-bottom: 1.5rem;
}
+
p {
margin-top: 1.3rem;
margin-bottom: 1.3rem;
@@ -10,10 +17,11 @@
}
blockquote {
- & > p:first-child {
+ &>*:first-child {
margin-top: 0;
}
- & > p:last-child {
+
+ &>*:last-child {
margin-bottom: 0;
}
}
@@ -22,4 +30,50 @@
list-style: none;
padding-left: 1em;
}
+
+ details {
+ padding: 0.5rem 1rem;
+
+ &[open] {
+ border: 1px solid var(--cjs-primary);
+ border-radius: var(--cjs-radius)
+ }
+
+ &>summary {
+ font-weight: bold;
+ margin-bottom: 0.75rem;
+ }
+
+ &>*:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ table {
+ border: 1px solid var(--cjs-primary);
+
+ & thead {
+ background: var(--cjs-primary-gradient);
+
+ & tr>th {
+ font-weight: bold;
+ text-align: center;
+ }
+ }
+
+ & tbody {
+ tr:nth-child(even) {
+ background-color: rgba(var(--cjs-white-rgb), 0.05);
+ }
+
+ tr:hover {
+ background-color: rgba(var(--cjs-white-rgb), 0.15);
+ }
+ }
+
+ & tr>th,
+ & tr>td {
+ padding: 0.5rem 1rem;
+ }
+ }
}
\ No newline at end of file
diff --git a/vite.config.ts b/vite.config.ts
index 3503467..8c5d4d8 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -14,9 +14,6 @@ export default defineConfig({
runes: ({ filename }) => {
const parts = filename.split(/[/\\]/);
const fileName = parts[parts.length - 1];
- if (fileName.endsWith('.md')) {
- console.debug('runes mode for %s: %o', filename, parts);
- }
return parts.includes('node_modules') ||
fileName.endsWith('.md') ? undefined : true;
}