{
  "schemaVersion": 1,
  "packageName": "marionette",
  "packageVersion": "5.0.0",
  "channel": "latest",
  "archivedChannel": "latest",
  "publication": "stable release (published on npm)",
  "sourceRepository": "https://github.com/marionettejs/marionette",
  "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
  "sourceDirty": false,
  "sourceContentSha256": "44c0d535fd36d11f31d909246f4ee7c6592eae3f25fb7513c61af65842593a90",
  "publicationEditsSha256": "d64ea741551883d1778a34e21cfd747458425eda995a92fce3e25fdce361328f",
  "supplementalManifestSha256": "7658f9fd2dc68ec9bdb8da224faa7a72e99e21e3063de8b7e903b0e9dffe6979",
  "documents": [
    {
      "id": "docs/readme.md",
      "title": "Marionette v5 documentation",
      "section": "Start here",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/",
      "markdownUrl": "https://marionettejs.com/docs/index.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/readme.md",
      "sourceSha256": "3b7c4110a8e7b519bbf762b753f94a29282fde17e0f4545d45d1a1259eb2f4bd",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "3d34fd8baf3ac9326ad04402c68ac93bc1b5887d4a4ecb74fa213e7d70769287",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 3b7c4110a8e7b519bbf762b753f94a29282fde17e0f4545d45d1a1259eb2f4bd; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Marionette v5 documentation\n\nThese guides target **`marionette` 5.0.0**, whose core is independent of\nBackbone and jQuery. Choose the bundled guides for your installed package and\nversion; applications using legacy **`backbone.marionette`** need their own\ncontracts. When upgrading from v4, start with the [migration guide](/docs/guides/migration.md).\n\n## Choose a starting point\n\n- New project: [quick start](/docs/quick-start.md) for the first render; use the optional progression below as the feature grows.\n- Existing application: choose a task or class reference below; follow additional contracts when needed.\n- Agent work: [task routing and lookup](/docs/agents.md), with optional [skill/plugin setup](/docs/tooling.md#agent-installation).\n\n### Learn as the feature grows\n\n1. [Render a View in a Region](/docs/quick-start.md).\n2. [Handle DOM events](/docs/api/shared/view-bindings.md#dom-events), then [edit local data](/docs/guides/local-editing.md). A View can save its own model when its data or API layer provides persistence.\n3. [Add observable data](/docs/integrations/setup.md) and [compose Views with Regions](/docs/architecture.md#choose-a-responsibility), or [display a list](/docs/guides/lists.md). Optional `@mnjs/data` supplies observation; fetching and persistence require a separate API layer or another data solution.\n4. When the feature needs readiness or an independent lifetime, [prepare and activate an Application](/docs/architecture.md#prepare-a-feature-then-activate-its-ui). [Retained restart](/docs/guides/retained-restart.md) repeats readiness while preserving the shell and local input. Child Applications are started or restarted explicitly. [Records](/docs/records.md) brings these pieces together.\n\n## Common tasks\n\n- [Migrate from another framework](/docs/guides/framework-migration.md): preserve journeys and design native ownership.\n- [Migrate from v4](/docs/guides/migration.md): update configuration and lifecycle boundaries.\n- [Test an application](/docs/guides/testing.md): run interaction, replacement, readiness and teardown checks.\n- [Use TypeScript](/docs/guides/typescript.md): typed options, DOM handlers, state and lifecycle results.\n- [Edit a View’s own model](/docs/guides/local-editing.md): live edits, local drafts, and API saves.\n- [Restart readiness while retaining UI](/docs/guides/retained-restart.md): repeat preparation without rebuilding the shell or draft.\n- [Add behavior to existing HTML](/docs/guides/existing-html.md): enhance existing markup and manage its lifetime.\n- [Integrate with existing UI](/docs/guides/existing-ui.md): mount, communicate, and clean up under another UI owner.\n- [Connect navigation](/docs/guides/routing.md): synchronous or asynchronous destinations, a retained shell, and browser subscriptions.\n- [Work with lists](/docs/guides/lists.md): row identity, sorting, filtering, and empty presentation.\n- [Integrate a control](/docs/guides/widgets.md): connect an imperative DOM API to View lifetime.\n- [Accessibility and rendering](/docs/guides/accessibility-rendering.md): keyboard interaction, focus, and text/HTML boundaries.\n- [Build and deploy](/docs/guides/production.md): installed packages, startup ownership, and production delivery checks.\n\n## Core reference\n\n- [API index](/docs/api.md): classes, shared contracts, and current coverage.\n- [Application](/docs/api/application.md): feature readiness, child Applications, root ownership, and restart.\n- [View](/docs/api/view.md): rendering, bindings, child Regions, and lifecycle.\n- [CollectionView](/docs/api/collection-view.md): repeated children, sorting, filtering, and empty presentation.\n- [Region](/docs/api/region.md): showing, replacing, retaining, and destroying Views.\n- [Behavior](/docs/api/behavior.md): reusable host interactions and lifecycle.\n- [MnObject](/docs/api/mnobject.md): nonvisual state, communication, and cleanup.\n\n### Shared contracts and configuration\n\n- [Events](/docs/api/shared/events.md), [state](/docs/api/shared/state.md), [common methods](/docs/api/shared/common.md), and [rendering/View bindings](/docs/api/shared/view-bindings.md) apply across classes.\n- [Runtime configuration](/docs/api/runtime.md) explains setters and configuration scope.\n- [Rendering/DOM providers](/docs/api/providers/dom.md) and [data/state providers](/docs/api/providers/data.md) define interfaces for supplying integrations.\n\n## Companion packages and integration\n\n- [@mnjs/data: Model and Collection](/docs/packages/data.md): an optional observable data layer with its own operations, events, identity, and disposal. Fetching and persistence require an API layer or another data solution.\n- [@mnjs/radio: channels and requests](/docs/packages/radio.md): scoped communication, request/reply handlers, and cleanup.\n- [@mnjs/utils](/docs/packages/utils.md): standalone component and object utilities.\n- [@mnjs/adapters](/docs/packages/adapters.md): optional Backbone, XState, Lit, Morphdom, and jQuery contracts.\n- [Renderer and data setup](/docs/integrations/setup.md): configure Lit and `@mnjs/data`.\n\nThe [records source](/docs/source/examples/records/src/main.js) is included for reading alongside the lesson. Its [README](/docs/source/examples/records/README.md) explains the repository development commands.\n\n## Check and debug\n\n[Application tooling](/docs/tooling.md) sets up lint and TypeScript checks and shows diagnostic lookup. Use [errors and diagnostics](/docs/api/errors.md) for the error contract.\n\n## Find these docs from an installed package\n\nFrom your application's directory:\n\n```sh\nnode -p \"require.resolve('marionette/package.json')\"\n```\n\nOpen `docs/readme.md` beside that package.json. Follow the relative Markdown links to the reference or lesson you need. This works without a documentation server or framework-specific retrieval tool.\n\n\n[Canonical source](/docs/markdown/docs/readme.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/quick-start.md",
      "title": "Install and render a View",
      "section": "Start here",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/quick-start/",
      "markdownUrl": "https://marionettejs.com/docs/quick-start.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/quick-start.md",
      "sourceSha256": "736de9440dab3eebfa734084ac7190629be008ea183b55146ab354e655306f5f",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "948bf55302abfe62b870d3a7583aca671578459e4995f4a1c4b65cca27b2ae7f",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 736de9440dab3eebfa734084ac7190629be008ea183b55146ab354e655306f5f; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Install and render a View\n\nThis guide targets Marionette 5.0.0 and is verified on the supported Node LTS lines: Node 22.22.2+ (22.x) or 24.15.0+ (24.x). Use the latest patch of either line. Newer Node versions may install; Node 26 remains advisory until its LTS support is verified. The [documentation index](/docs/index.md) identifies this package version.\n\n## Install matching packages\n\nUse matching `5.0.0` versions of `marionette` and the companion packages: `@mnjs/utils`, `@mnjs/radio`, `@mnjs/adapters`, and optional `@mnjs/data`. Pin the versions explicitly when installing these packages.\n\n## Create the project\n\nCreate a project directory:\n\n```sh\nmkdir marionette-example\ncd marionette-example\nnpm init -y\nnpm pkg set type=module scripts.dev=\"vite\" scripts.build=\"vite build\"\nnpm install --ignore-scripts --save-exact marionette@5.0.0 @mnjs/utils@5.0.0 @mnjs/radio@5.0.0 @mnjs/adapters@5.0.0 lit-html@3.3.3\nnpm install --ignore-scripts --save-dev --save-exact vite@8.3.0\n```\n\nThis first UI uses `marionette`, the Lit adapter from `@mnjs/adapters`, and `lit-html`. Core also depends on `@mnjs/utils` and `@mnjs/radio`; the command pins those dependencies to the same release. `@mnjs/data` is optional and is added in the [data setup guide](/docs/integrations/setup.md).\n\nCreate `index.html`:\n\n```html\n<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Marionette example</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/main.js\"></script>\n  </body>\n</html>\n```\n\nCreate `main.js`:\n\n```js\nimport { Region, View, setDomApi } from 'marionette';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\n\nsetDomApi(LitDomApi);\n\nconst WelcomeView = View.extend({\n  template: () => html`<h1>Hello, Marionette</h1>`\n});\n\nconst region = new Region({ el: '#app' });\nregion.show(new WelcomeView());\n```\n\n## Run it\n\n```sh\nnpm run dev\n```\n\nOpen the address Vite prints. You should see “Hello, Marionette”. `npm run build` produces a production bundle in `dist`.\n\nThe View describes the content. The Region renders and mounts it, then owns replacement and destruction. Calling `region.show(anotherView)` replaces the previous View; `region.empty()` destroys the displayed View.\n\nThe Lit DOM adapter is configured once before creating Views. The default renderer calls each template function with its data.\n\nContinue with the [learning progression](/docs/index.md#learn-as-the-feature-grows) for local interaction, data, composition, and Application readiness.\n\n\n[Canonical source](/docs/markdown/docs/quick-start.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/architecture.md",
      "title": "Building features",
      "section": "Start here",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/architecture/",
      "markdownUrl": "https://marionettejs.com/docs/architecture.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/architecture.md",
      "sourceSha256": "498361c4fe03d4322995e9c93a98368ab033dfe66da219145bef694c109b2f10",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "00127ee0bf8a03f203d621eb00654bfa2715c4911918c187751045e63cf7ce4d",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 498361c4fe03d4322995e9c93a98368ab033dfe66da219145bef694c109b2f10; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Building features\n\nMarionette organizes UI around ownership: who prepares a feature, who presents its data, and who removes it. This guide explains those choices for **5.0.0**. Start with the [quick start](/docs/quick-start.md) for renderer setup; use the [API reference](/docs/api.md) for exact method contracts.\n\n## Choose a responsibility\n\n| Responsibility | Use |\n| --- | --- |\n| Present data and handle local interaction | A [View](/docs/api/view.md). A disclosure or form control can keep its own local state. |\n| Place, replace, or remove a child View | A named [Region](/docs/api/region.md), usually declared on the containing View. |\n| Present a collection as managed child Views | A [CollectionView](/docs/api/collection-view.md), with a child View for each record. |\n| Prepare and coordinate a feature with a start/stop lifetime | An [Application](/docs/api/application.md), owning its UI, shared decisions, and service effects. |\n| Reuse interaction behavior across Views | A [Behavior](/docs/api/behavior.md), whose lifetime follows its host View. |\n| Own nonvisual state or communication | An [MnObject](/docs/api/mnobject.md), with events, state access, and explicit destruction. |\n\nA View with Regions is enough for visual composition. Add an Application when a feature needs readiness, coordinated effects, or an independently managed lifetime. A parent Application can own the page and start child features even when the parent has no asynchronous preparation. Registering a child establishes ownership; starting it is an explicit decision.\n\nA View can save an edit to its own model when the chosen data layer provides that operation. Keep [local interaction](/docs/api/view.md#local-interaction-and-feature-coordination) in its View and shared workflow decisions with their feature owner.\n\n## Read the ownership tree\n\n```text\nFeature Application\n├── root View\n│   ├── named Region → detail View\n│   └── named Region → CollectionView → row Views\n└── registered child Application → its own UI\n```\n\nEach owner cleans up its children. For an embedded feature, its **host** is the surrounding UI or owner receiving it; the Application's **destination** is the specific Region used by `showView()`. A Behavior's **host** is the View or CollectionView it augments. A destination supplied as an existing Region is borrowed. Owning a root or registering a child Application does not itself show or start it. Models supplied to Views are borrowed data, not branches of this UI ownership tree.\n\n## Prepare a feature, then activate its UI\n\nWhen a feature needs asynchronous readiness, use an Application and put the required service call in `prepareStart(options, { signal })`. Return the prepared data, then consume it in `onStart(app, options, result)` to create and connect the ready UI. The [Application example](/docs/api/application.md#prepare-before-showing-ui) demonstrates this sequence.\n\nFor these feature requests, the Application calls a service/API module; Views receive data and emit user intent. This keeps request decisions at the feature lifetime while individual panels can be replaced. For a composed layout, use the Application's `setView`, populate the layout's Regions with `showChildView`, then mount it with the Application's `showView`.\n\nShow loading or error presentation through Views and Regions. The caller of `start()` handles rejection. When abandoning a failed initial start, call synchronous `stop()` before showing an error View. A failed active restart can show feedback alongside its retained UI.\n\nNotification hooks such as `onStart` do not await returned Promises. If a child must be ready before the parent activates, include that work in parent preparation and handle cleanup if preparation fails. If the page can be ready while its child loads, start the child from the active parent and handle its failure there. See [child Application ownership](/docs/api/application.md#child-applications).\n\nPass the preparation signal to the service where supported. Marionette prevents a cancelled preparation result from activating the Application. Additional side effects after an `await` must also respect cancellation. Once preparation finishes, that signal is no longer a feature-lifetime signal; later requests need their own policy.\n\n## Choose what survives an operation\n\n| Operation | Lifetime decision |\n| --- | --- |\n| Replace a panel | Show another View in its Region. The Region destroys the previous View; keep shared data outside that disposable View. |\n| Reconstruct a feature | Call `stop()`, then await `start(options)`. The root and child Views are destroyed and startup creates the intended replacement. |\n| Restart a feature | `restart()` repeats preparation while retaining the active root, child Applications and state. Successful completion code selects what to update. |\n| End a feature permanently | `destroy()` ends its lifetime and destroys owned UI and children. The configured state provider handles owned-state disposal when supported. |\n\nUse `restart()` to repeat feature readiness while retaining its active UI, children, and state event delivery. Apply prepared data in `onStart`, creating the shell only when absent. Current failure leaves the active feature in place; superseded preparation cannot commit. Use stop/start for reconstruction. Independent domain operations, such as saving, still need their own concurrency and cancellation policy.\n\nRetain state at the lifetime that needs it. A local control's state can live in that View. Drafts or pending work that must survive panel replacement belong to a surviving owner. Closing a panel can empty its Region while the feature Application stays active; completions update retained data, and a replacement panel reads that data. Application stop removes its root UI and retains state; restart retains both. See [readiness and ongoing effects](/docs/api/application.md#readiness-and-ongoing-effects) for how ongoing requests use that shared data.\n\n## Share data and communicate intent\n\nKeep one authority for each shared decision. For example, a feature Application can own selection while list and detail Views receive the data they need. A View emits a selection event; the Application listens, changes selection, and chooses which detail View its Region shows. [Child event forwarding](/docs/api/shared/view-bindings.md#child-events) and `listenTo(view, { ... })` connect these boundaries without sibling Views reaching into each other's markup.\n\nObservable data lets several Views respond to the same change. Configure compatible [DataApi and StateApi providers](/docs/integrations/setup.md#configure-once); use model/collection bindings or `stateEvents` for the relevant source. Initialize a new View from current data as well as observing subsequent changes. Application `stateEvents` deliver while active and do not replay changes made while stopped.\n\nPlain data is sufficient when observation is unnecessary. Use [observable data and API access](/docs/integrations/setup.md#observable-data-and-api-access) to choose a data solution and its provider.\n\nState supplied to another object is borrowed. State created through `createState` belongs to its owner; destruction calls the configured provider's disposal method when provided. A View's `model`, `collection`, and state are separate inputs; state is not automatically template data. See [state ownership](/docs/api/shared/state.md#ownership-and-disposal).\n\n## Let Views and Regions manage presentation\n\nUse templates for presentation, CollectionView for repeated children, and Regions for child placement and teardown.\n\nChoose updates at the boundary that changed. Rendering a containing View can destroy child Views, so preserve an active editor when updating an independent status or panel. Bounded changes to a View's own controls, such as a button's disabled state, are appropriate. Keep those updates inside the owning View. The [View rendering contract](/docs/api/view.md) explains child cleanup; the [CollectionView reference](/docs/api/collection-view.md) explains record and child identity.\n\n## Clean up at the ownership boundary\n\nRegions destroy replaced Views. CollectionView destroys removed children. Destroying a Marionette object releases its event subscriptions and incoming callbacks; a retained listener needs no per-View `destroy` handler to call `stopListening(view)`.\n\nApplication `stop()` retains the Application, its state, and subscriptions to surviving sources. Explicitly end subscriptions whose purpose lasts only for that run. Release external resources such as timers, service requests, or widget handles at the lifetime that owns them; attaching a resource to an arbitrary property does not make it framework-owned. See [event cleanup](/docs/api/shared/events.md#cleanup).\n\nFor a runnable feature using preparation, selection, child Applications, and retry, continue with the [records lesson](/docs/records.md).\n\n\n[Canonical source](/docs/markdown/docs/architecture.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/agents.md",
      "title": "Agent workflow",
      "section": "Start here",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/agents/",
      "markdownUrl": "https://marionettejs.com/docs/agents.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/agents.md",
      "sourceSha256": "98bc711d194bb8f842f4987620b1c965762ad0f4c3288b19b8ac6d8f451df3ca",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "5f6c1f9a747519c49931b5090439b1a19fc0248a02707e8cd19d63c44001bd7c",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 98bc711d194bb8f842f4987620b1c965762ad0f4c3288b19b8ac6d8f451df3ca; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Work with an agent\n\nUse the docs bundled with the application's installed Marionette package. For framework changes, follow the repository's contributor guidance.\n\n## Find the installed contract\n\nCheck the installed package name and version first: **`marionette`** is the v5\npackage; **`backbone.marionette`** is the legacy package. V5 core requires neither\nBackbone nor jQuery; Backbone Models and Collections integrate through optional\nadapters. For installed `backbone.marionette` 4.x, preserve v4 contracts unless\nupgrading; older releases need their own version-specific guidance. If both\npackages are installed, check which entrypoint the feature imports.\n\nFrom the application directory, resolve the package the feature imports. For v5:\n\n```sh\nnode -p \"require.resolve('marionette/package.json')\"\n```\n\nFor the legacy package instead:\n\n```sh\nnode -p \"require.resolve('backbone.marionette/package.json')\"\n```\n\nRead the selected package's version and use its matching documentation. The paths\nbelow apply only to v5 and are relative to the installed `marionette` package's\n`docs/` directory. For rendering, observation or persistence changes, check the\nconfigured renderer or data provider. Choose one starting page or use an exact API\nlookup; follow additional references when the task needs their contract.\n\nShared API names such as `View.extend`, regions, triggers, `modelEvents`, and\n`CollectionView` remain valid in v5, but do not guarantee shared behavior: verify\nthe v5 contract. For v4 upgrades, read the [migration guide](/docs/guides/migration.md).\n\nIf installed docs are absent, obtain the exact release or known source revision. Current website docs may describe a different version.\n\n<!-- task-routes:start -->\n| Task | Start with |\n| --- | --- |\n| Install and render a first View | [Quick start](/docs/quick-start.md) |\n| Migrate from another UI framework | [Framework migration](/docs/guides/framework-migration.md) |\n| Migrate an existing v4 application | [Migration guide](/docs/guides/migration.md) |\n| Test interaction, readiness, or teardown | [Consumer testing](/docs/guides/testing.md) |\n| Choose ownership and lifetimes | [Architecture](/docs/architecture.md) |\n| Bind a DOM event or trigger | [DOM events](/docs/api/shared/view-bindings.md#dom-events) |\n| Read or rebind named DOM elements | [UI bindings](/docs/api/shared/view-bindings.md#ui-bindings) |\n| Edit a model or retain a draft | [Local editing](/docs/guides/local-editing.md) |\n| Prepare, start, restart, or stop a feature | [Application](/docs/api/application.md) |\n| Restart while retaining a draft or shell | [Retained restart](/docs/guides/retained-restart.md) |\n| Enhance existing markup | [Existing HTML](/docs/guides/existing-html.md) |\n| Embed a feature in another UI | [Existing UI](/docs/guides/existing-ui.md) |\n| Connect URLs and destination lifetimes | [Navigation](/docs/guides/routing.md) |\n| Show, replace, or retain child UI | [Region](/docs/api/region.md) |\n| Render, filter, or sort repeated children | [Lists](/docs/guides/lists.md) |\n| Share observable data and state | [state](/docs/api/shared/state.md) |\n| Connect events and clean up subscriptions | [Events](/docs/api/shared/events.md) |\n| Connect channels and request/reply handlers | [Radio](/docs/packages/radio.md) |\n| Configure a renderer or another data layer | [Configuration scope](/docs/api/runtime.md#choose-a-configuration-scope) |\n| Write typed options, handlers, or lifecycle hooks | [TypeScript guide](/docs/guides/typescript.md) |\n| Check types, lint, or diagnose a failure | [Application tooling](/docs/tooling.md) |\n| Integrate an imperative control | [Widgets](/docs/guides/widgets.md) |\n| Check keyboard, focus, or rendering safety | [Accessibility and rendering](/docs/guides/accessibility-rendering.md) |\n| Build and deploy an application | [Production](/docs/guides/production.md) |\n| Apply the concepts in a composed feature | [Records lesson](/docs/records.md) |\n<!-- task-routes:end -->\n\n## Apply the contract\n\nKeep local interaction in its View when that fits the task. An asynchronous call alone does not require an Application. A View may save its own model when the configured data layer supplies that operation. `@mnjs/data` supplies observable Models and Collections; fetching and persistence require an API layer or another provider. It does not supply `Model.save()`.\n\nUse Application preparation for feature readiness and `restart()` to repeat it while retaining active UI. Apply the current result in `onStart`; construct retained shells once. Coordinate shared decisions and work that survives panel replacement at the lifetime that owns them. Read [architecture](/docs/architecture.md) when deciding that ownership.\n\nRead method signatures, event payloads and cleanup for the APIs you change. Verify the affected interaction, including replacement, cancellation or teardown when relevant. A successful build does not establish those outcomes.\n\n## Local contract lookup\n\nDirect Markdown reading is supported. If using the installed skill's helper, choose one lookup from the application directory:\n\n```sh\nnode <skill>/scripts/docs.mjs --section docs/api/view.md#local-interaction-and-feature-coordination\n```\n\nReplace `<skill>` with the installed or copied skill directory. A section link reads that contract directly. You can also select a named section with `--page docs/api/shared/view-bindings.md --section 'UI bindings'`. Use `--symbol Export.member` for signatures and primary section IDs in `primarySections`, `--search 'query'` when the location is unknown, or `--page SOURCE` for a full page. `--list` lists pages; it is optional. An external package store needs `--package-root <physical-directory>`.\n\nA symbol result lists primary contract section IDs in `primarySections` and incidental code mentions in `sections`. Primary routes can span several sections. An empty primary list means no member route has been assigned. `contracts` retains all applicable section IDs and diagnostic codes, including general guidance. Pass a section ID to `--section` to read it.\n\nThe helper checks the bundled manifest and hashes and reports the installed version and source revision. These identify the docs read; they do not verify the implementation.\n\nFor [skill/plugin installation](/docs/tooling.md#agent-installation) or [hosted MCP identity checks](/docs/tooling.md#hosted-documentation-mcp), follow application tooling.\n\n\n[Canonical source](/docs/markdown/docs/agents.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/api.md",
      "title": "API reference",
      "section": "Start here",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/api/",
      "markdownUrl": "https://marionettejs.com/docs/api.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/api.md",
      "sourceSha256": "8357766ee95ecae6a5f130b1cc2865b140cad6414eba13d2aa6459954aba65aa",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "59c7302f667e88687d1ae5756b5a55fb1a604a516208446204d9d5167e2a8f60",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 8357766ee95ecae6a5f130b1cc2865b140cad6414eba13d2aa6459954aba65aa; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# API reference\n\nThese references target **5.0.0**. Use the page for the class or contract you need. Class pages define supported APIs and link shared contracts; task guides show how to use them.\n\n## Core classes\n\n| Class | Reference scope |\n| --- | --- |\n| [View](/docs/api/view.md) | Construction, rendering, UI bindings, named Regions, lifecycle, ownership, and extension points. |\n| [Region](/docs/api/region.md) | Showing, replacing, detaching and emptying Views; element configuration and lifecycle. |\n| [Application](/docs/api/application.md) | Preparation, lifecycle results/cancellation, restart, child Applications, root ownership, state and Radio bindings. |\n| [CollectionView](/docs/api/collection-view.md) | Collection observation, sorting/filtering, empty presentation, child lookup/ownership, rendering and lifecycle. |\n| [Behavior](/docs/api/behavior.md) | Host composition, reusable local interaction, UI/data bindings, forwarded events, and teardown. |\n| [MnObject](/docs/api/mnobject.md) | Nonvisual objects, construction, state/Radio bindings, and synchronous destruction. |\n\n## Shared class contracts\n\nThese behaviors apply across several classes. Class pages link to the relevant contracts.\n\n- [Common class methods](/docs/api/shared/common.md): construction, extension, options and binding helpers.\n- [Events](/docs/api/shared/events.md): subscription methods, notification arguments and cleanup.\n- [Errors and diagnostics](/docs/api/errors.md): error properties, diagnostic codes, and installed lookup.\n- [State](/docs/api/shared/state.md): creating, borrowing, observing and disposing state.\n- [Rendering and View bindings](/docs/api/shared/view-bindings.md): templates, UI, DOM/entity events and child event forwarding shared by View and CollectionView.\n\n## Runtime configuration\n\n[Runtime configuration](/docs/api/runtime.md) covers defaults, configuration scope, setters, and isolated class families.\n\n## Provider interfaces\n\nUse these contracts when implementing or adapting an integration. For configuration with supplied packages, start with the [setup guide](/docs/integrations/setup.md).\n\n- [Rendering and DOM providers](/docs/api/providers/dom.md): Renderer, DomApi, and EventDelegator authoring contracts.\n- [Data and state providers](/docs/api/providers/data.md): reading, identity, collection notifications, subscriptions, and disposal.\n\n## Companion packages\n\n[@mnjs/data: Model and Collection](/docs/packages/data.md) is an optional observable data solution. Its reference covers operations, events, identity, disposal, and exported types. API access and persistence require a separate solution. Marionette can use another data layer through its core provider contracts.\n\n[@mnjs/radio: channels and requests](/docs/packages/radio.md) covers channel registries, events, replies, cleanup, logging, and standalone use.\n\n[@mnjs/utils: shared utilities](/docs/packages/utils.md) covers standalone component methods, callbacks, object helpers, and exports. Shared Events and class methods remain at their canonical references.\n\n[@mnjs/adapters](/docs/packages/adapters.md) covers optional data and DOM integrations, their imports, configuration, observation, and cleanup.\n\n## Integration and task guides\n\n[Renderer and data setup](/docs/integrations/setup.md) connects Lit and `@mnjs/data` to Marionette. Integration guides explain configuration and use; package references define the APIs supplied by each package.\n\n[Check and debug an application](/docs/tooling.md) covers consumer lint, declaration checks, and diagnostic lookup. [Practical TypeScript](/docs/guides/typescript.md) covers options, handlers, state and lifecycle results. [Migration](/docs/guides/migration.md) and [consumer testing](/docs/guides/testing.md) provide upgrade and verification paths.\n\n[Existing UI](/docs/guides/existing-ui.md) and [navigation](/docs/guides/routing.md) cover mounting and destination ownership. [Lists](/docs/guides/lists.md), [imperative controls](/docs/guides/widgets.md), [accessibility/rendering](/docs/guides/accessibility-rendering.md), and [production](/docs/guides/production.md) provide further task paths.\n\nClass pages link to the relevant [shared configuration contracts](/docs/api/shared/view-bindings.md#class-configuration); Region documents its own DOM setter.\n\nFor a first runnable result, use the [quick start](/docs/quick-start.md). For composition guidance, see [architecture](/docs/architecture.md).\n\nDetailed coverage still pending: a complete custom immutable-store integration. The [provider contracts](/docs/api/providers/data.md) describe the integration boundary. Application lifecycle details include [destination binding order](/docs/api/application.md#destination-binding-order) and [restart from start completion](/docs/api/application.md#restart-from-start-completion).\n\n\n[Canonical source](/docs/markdown/docs/api.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/api/application.md",
      "title": "Application",
      "section": "Core classes",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/api/application/",
      "markdownUrl": "https://marionettejs.com/docs/api/application.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/api/application.md",
      "sourceSha256": "602a37e92b020739cf4ee62228a8f8e3205e94f7399cc62757d28aaa8fc57331",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "efe451d101c2b3d8a1da78910ac833fe8b0d80132412d8f29044a98388ba9c9a",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 602a37e92b020739cf4ee62228a8f8e3205e94f7399cc62757d28aaa8fc57331; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Application\n\n[API index](/docs/api.md) · [View](/docs/api/view.md) · [Region](/docs/api/region.md)\n\nApplication coordinates readiness, composition, and state for a feature lifetime. It can own a root View, registered child Applications, and a destination Region. A local control can remain a View; use an Application when shared workflow or lifetime needs an owner.\n\n## Prepare before showing UI\n\nThis standalone TypeScript example loads a summary before showing it. `/summary.json` returns `{ \"title\": string }`. Application owns the request; View renders the result.\n\n```ts\nimport { Application, View, type ApplicationInstance, type LifecycleContext } from 'marionette';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\n\ntype Summary = { title: string };\nconst SummaryView = View.extend({\n  template: ({ title }: Summary) => html`<h1>${title}</h1>`,\n}).setDomApi(LitDomApi);\n\nconst SummaryApplication = Application.extend({\n  async prepareStart(_options: unknown, { signal }: LifecycleContext): Promise<Summary> {\n    const response = await fetch('/summary.json', { signal });\n    if (!response.ok) throw new Error('Could not load the summary.');\n    return response.json();\n  },\n  onStart(_app: ApplicationInstance, _options: unknown, summary: Summary) {\n    this.showView(new SummaryView({ model: summary }));\n  },\n});\n\nconst mount = document.createElement('section');\ndocument.body.append(mount);\nconst app = new SummaryApplication({ region: { el: mount } });\nawait app.start();\n```\n\n`prepareStart` may return a value or Promise. Its current successful result reaches `onStart`; failure rejects the requesting `start()` or `restart()`. The caller handles that rejection. `stop()` cancels pending preparation and tears down owned UI synchronously.\n\n`restart()` repeats preparation while retaining the current presentation and active children. This example explicitly replaces SummaryView in `onStart` after success. To keep a shell, input, and child identity through completion too, see [retained restart](/docs/guides/retained-restart.md).\n\nPlain response data uses the default DataApi. For observable data, configure [native data](/docs/integrations/setup.md#observable-data-and-api-access) or another integration. API access and persistence remain separate.\n\n## Construction and options\n\n`new Application(options?)` creates a stopped instance. Construction calls `preinitialize(options)`, configures Region, Radio and state, constructs declared children, calls `initialize(options)`, then binds state events. Neither hook starts the Application. `getState()` is available inside `initialize`.\n\n| Option | Contract |\n| --- | --- |\n| `region` | Selector string, Region options object, Region constructor, or existing Region instance. Optional without mounted UI. See [root ownership](#root-view-and-region). |\n| `regionClass` | Default constructor when building a Region from configuration; defaults to the runtime's Region. Individual definitions can override it. |\n| `childApps` | Map of names to Application constructors, or a function returning that map. Children are constructed once without arguments. Constructor/subclass maps replace rather than merge. |\n| `state`, `stateEvents` | Borrowed state and declarative observation. `createState(options)` supplies owned state; see [state](/docs/api/shared/state.md). |\n| `viewEvents` | Event-handler map, or function returning one, bound to each selected root View. Values are callbacks or Application method names. See [View events](#view-events). |\n| `channelName` | Channel name, or function returning one. A falsy name disables declarative Radio setup. |\n| `radioEvents`, `radioRequests` | Event/reply handler maps, or functions returning maps. Values are callbacks or Application method names. See [Radio bindings](#radio-bindings). |\n\nResolvers run with the Application as `this`. A Region constructor is a class to instantiate; a function supplied as `state` remains the source itself. `options` merges class and constructor options. Custom options are read with `getOption(name)` and are not automatically instance fields.\n\n`Application.extend(prototypeProperties?, staticProperties?)` creates a subclass. `preinitialize` and `initialize` default to no-ops. `cid` uses the class's `cidPrefix` (`'mna'` by default). See [class utilities](/docs/api/shared/common.md) for shared options and custom constructors.\n\n## Lifecycle methods and results\n\n| Method | Behavior |\n| --- | --- |\n| `start(options?)` → `Promise<boolean>` | Prepares and activates. An active Application resolves `true` without repeating preparation or applying new options. Pending initial starts share the first preparation's Promise and options. |\n| `restart(options?)` → `Promise<boolean>` | Repeats preparation without stopping. Retains the root, active children, state, and subscriptions unless application code replaces them. Each call supersedes pending preparation. When stopped, prepares and activates using the retained destination. |\n| `stop(options?)` → boolean | Cancels pending preparation, stops registered children, destroys prepared/displayed roots, and returns `true` synchronously. Retains the Application, state, children and destination for reuse. |\n| `destroy(options?)` → boolean | Deactivates immediately, cancels preparation, stops descendants and destroys roots, then destroys child Applications and owned resources. Returns `true` synchronously. |\n| `isRunning()` → boolean | Reports this Application's activity, independently of its descendants. |\n| `isDestroyed()` → boolean | True when terminal destruction commits, before `onDestroy`. |\n\nInitial preparation is inactive. Restart of an active Application stays active, including `stateEvents` delivery. Ordinary stop deactivates after `before:stop` and child stops, before root teardown. Destroy deactivates immediately.\n\nStart/restart resolve `false` when superseded or cancelled, or when a stop/terminal owner prevents activation. Current preparation and startup callback failures reject. A hook returning `false` is not a veto: it may be a successful preparation result.\n\nStop is synchronous and cannot be superseded during cleanup. Start/restart during stop or destruction resolve `false`. `onStop` runs after successful cleanup and may explicitly start the next run. Calling stop on a stopped owner still cleans roots and stops descendants without repeating that owner's stop notifications. Repeated stop/destroy after successful destruction return `true`.\n\n`ApplicationStartOptions` accepts an existing Region and feature options. `ApplicationRestartOptions` forwards feature options, including any `region`, unchanged to hooks, but restart never changes its destination. Stop/destroy forward arbitrary options to notifications and child operations. None of these arguments merge into constructor `options`.\n\n```text\nstopped → start() → prepareStart → active → onStart\nstopped → restart() → prepareStart → active → onStart (retained destination)\nactive  → restart() → prepareStart → onStart → active\n                       │\n                       └── preparation rejects → existing active UI retained\nactive  → stop() → stopped (root destroyed; Application/state retained)\nlive    → destroy() → destroyed (owned UI, children and resources disposed)\n```\n\nAn active restart retains its UI during preparation; `onStart` chooses what to update. Initial preparation failure leaves the Application stopped. A newer restart, stop or destroy cancels pending preparation, preventing its obsolete result from reaching `onStart`. This diagram describes successful synchronous callbacks; the failure boundary below still applies.\n\n## Preparation, cancellation, and failure\n\n`prepareStart(options, { signal })` is the only awaited lifecycle hook. Its result reaches `onStart(app, options, result)` and `start` subscribers. Notification hooks run synchronously and ignore returned Promises. Await required business work before teardown, for example `await app.saveDraft(); app.stop()`.\n\nA newer restart, stop, or destroy cancels pending preparation: the prior call resolves `false`, its signal is aborted, and its obsolete result cannot reach `onStart`. Pass the signal to dependencies. Cancellation cannot undo completed work; return ready data from preparation and apply it in `onStart`. Check `signal.throwIfAborted()` after an await before additional side effects if a dependency ignores cancellation. A completed preparation signal is not a lifetime signal and is not aborted by a later stop.\n\nA failed initial preparation leaves the Application stopped. A failed restart of an active Application leaves it active with its existing UI and children. Display errors without stopping that retained feature. Children or Views explicitly created during initial preparation may need cleanup when abandoning a failed start. A throw from `onStart` rejects after activation; synchronous callback failures do not roll back completed work.\n\nSynchronous construction or teardown failures throw and abort remaining steps. Marionette promises no rollback, attempt-all cleanup, or retry of a partial instance. See [event cleanup](/docs/api/shared/events.md#cleanup) for the same failure boundary.\n\n## Readiness and ongoing effects\n\nUse preparation for data and prerequisites needed before activation or before applying a restarted result. Use `onStart` to commit that result. When retaining UI, construct and connect the shell once, then update the source or child Region that changed; avoid recreating it unconditionally in every `onStart`.\n\nLong-lived effects such as Window listeners or timers need explicit activation and cleanup. Install them once for the active run and release them in `onStop`; restart calls `onStart` again without calling `onStop`. Persistence and other domain operations have their own concurrency and lifetime policy. Marionette does not automatically cancel work started outside preparation. See [retained restart](/docs/guides/retained-restart.md) and [lifetime choices](/docs/architecture.md#choose-what-survives-an-operation).\n\n## Child Applications\n\n`childApps: { summary: SummaryApplication }` constructs a child once with its parent. For per-instance arguments, construct and register it explicitly.\n\n| Method | Contract |\n| --- | --- |\n| `addChildApp(name, child)` | Registers and returns the instance without starting it. |\n| `getChildApp(name)` | Returns the registered instance or `undefined`. |\n| `hasChildApp(name)` | Reports whether the name is registered. |\n| `getChildApps()` | Returns a new name-to-instance map; changing it does not change registration. |\n| `getName()` | Returns the registered name or `undefined`. |\n| `removeChildApp(name, options?)` | Destroys the child synchronously and returns it, or `undefined` for an unknown name. A callback failure throws. |\n\nNames must be nonempty. Children must share the parent's runtime and have one owner/name. Self/ancestor registration, conflicting names and multiple owners throw `MN0031`. Repeating the same registration is harmless. A destroying/destroyed parent or child cannot acquire a new registration. Successful child destruction unregisters it automatically.\n\nRegistration owns lifetime, not readiness. Parent start does not start or await children. Start prerequisites explicitly in preparation when their readiness is required; handle the separate Promise when starting a child from a notification. Parent restart leaves children active. To reprepare a child too, call its `restart()` explicitly.\n\nParent stop traverses children in registration order, including descendants beneath stopped intermediate owners. Child instances remain registered for reuse. Parent destruction stops descendants before `before:destroy`, which can inspect stopped, live children; it then destroys children in registration order. Descendant start/restart is blocked during an ancestor's stop or terminal phase. There are no Application add/remove-child notification events.\n\n### Child operations during lifecycle notifications\n\nThese phase rules apply to both method hooks and event listeners: `onBefore…` / `on('before:…', callback)`, and `onStop` / `on('stop', callback)`. Hooks run first; listeners then run synchronously in registration order. A notification is not an awaited coordination step.\n\n| Parent notification | Child operation and consequence |\n| --- | --- |\n| `before:start` | An explicit child `start()` or `restart()` can begin, but its Promise is not awaited by the parent, even if the callback returns it. An explicit child `stop()` completes synchronously; it does not cancel parent startup. |\n| `before:stop` | The parent is already stopping. Descendant `start()` and `restart()` resolve `false`, including from descendant cleanup callbacks. Explicitly stopping a child early is safe; normal parent teardown still stops the remaining descendants. |\n| `before:destroy` | Descendants have already been stopped and are about to be destroyed. Inspect or release external resources here; descendant activation resolves `false`. New child registration is ignored and leaves the supplied instance owned by the caller. |\n| `stop` after ordinary stop | Cleanup has finished, so an explicitly requested next run can start if no ancestor is still stopping. A child can run while its parent remains stopped; starting the parent does not start children automatically. When an ancestor is stopping this parent, descendant activation still resolves `false` during the parent's `stop` callback. During destruction, terminal ownership still blocks activation. |\n\nWhen child readiness is required for parent success, await it in `prepareStart`, check the preparation signal after the await, and handle a canceled child result explicitly. This recipe assumes parent preparation is the only code that starts this child. Do not use it to join an independently pending child start: `isRunning()` is false during preparation, so the abort handler would cancel work this attempt did not initiate. Give independently started work its own coordinator and cancellation policy:\n\n```js\nimport { Application } from 'marionette';\n\nconst Feature = Application.extend({\n  childApps: { results: Application },\n  async prepareStart(options, { signal }) {\n    const child = this.getChildApp('results');\n    if (!child) { throw new Error('Required child is missing'); }\n    if (child.isRunning()) { return; }\n    signal.addEventListener('abort', () => child.stop(), { once: true });\n    const started = await child.start();\n    signal.throwIfAborted();\n    if (!started) { throw new Error('Required child did not start'); }\n  },\n});\n\nconst feature = new Feature();\nawait feature.start();\n```\n\nThis recipe explicitly cancels a child started for the pending parent attempt, including the interval after the child starts but before the parent commits. It preserves an already-running child during restart. Keep the abort listener connected until the attempt settles; a committed preparation's signal is not aborted by later lifecycle operations. This is the recipe's coordination policy, not automatic rollback by Application.\n\nUse the child's `restart()` in preparation only when it should reprepare too; `start()` preserves an already-running child. Parent stop cancels pending child readiness. A rejected parent preparation does not roll back already-started children; explicitly stop or destroy the parent when abandoning that startup.\n\nCalling parent `stop()` from its `before:start` callback is supported cancellation, but it does not cancel the remaining notification listeners. A later listener can still perform side effects or independently start a child after that stop has finished. Keep required child activation in `prepareStart`, which only begins if the parent preparation is still current, instead of distributing dependent lifecycle actions across notification callbacks. Starting an optional child from a notification remains explicit independent work: handle its Promise and rejection yourself.\n\nDo not unconditionally call the same Application's `restart()` from its `before:start` callback: restart emits `before:start` again and supersedes the outer attempt. A conditional redirect must terminate; for ordinary refresh, request restart from the coordinating caller. A repeated `start()` during initial preparation joins that pending preparation instead. These rules do not prohibit synchronous preparation of state or inspection in before hooks.\n\n## Root View and Region\n\n| API | Contract |\n| --- | --- |\n| Constructor `region` | Builds an owned Region or borrows an existing instance. See [Region construction](/docs/api/region.md#construction-and-options). |\n| `start({ region })` | Binds an existing Region from the same runtime before startup preparation. An active or pending start ignores newly supplied options. Use `stop(); await start({ region })` to move hosts. |\n| `restart({ region })` | Forwards the option to hooks while retaining the current destination. |\n| `getRegion()` | Returns the current destination or `undefined`. |\n| `setView(view)` | Owns a prepared root without rendering/mounting it and returns it. Replacing a prepared root destroys that root. |\n| `getView()` | Returns this Application's prepared root, otherwise its displayed root, or `undefined`. |\n| `showView(view?, options?)` | Selects a supplied root and shows it through the destination with Region `ShowOptions`. Returns the root, or `undefined` if none exists. A destination is required when a root exists. If the root is already displayed, returns it without showing again; supplied options have no effect. |\n\n`setView` → the root's `showChildView` → `showView` allows composition before attachment. A prepared replacement leaves the displayed root in place until shown. Display transfers ownership to Region; Application tracks its displayed root. Stop/destroy clean prepared and displayed roots. Restart does neither automatically. `Region.empty()` clears displayed content and its Application association; it does not stop the Application or destroy a separate prepared root.\n\nA selected View must be live and unowned (`MN0007` for destroyed, `MN0003` for another owner). Selecting the same root is harmless. Reselecting the displayed root destroys any prepared replacement. Content shown directly through a Region is Region-owned and cannot be adopted. During/after Application destruction, set/show methods return their supplied View without adopting it; its caller remains responsible.\n\nAn Application can own [existing markup](/docs/api/view.md#existing-elements) with `setView(new PageView({ el, template: false }))`, without rendering or a destination. Stop removes that View's element; a later start needs markup again. Applications can also have no root UI.\n\nStop retains the destination. Destroy disposes a Region built from configuration; a borrowed Region survives. Stop leaves another owner's replacement in a borrowed Region alone. An owned Region's current content is cleaned. Moving to a new destination disposes the old owned Region; old borrowed Regions survive.\n\n### Destination binding order\n\nInitial startup binds the requested Region before `before:start` and `prepareStart`. Omitting `region` keeps the current host. A failed or cancelled preparation does not roll back host binding already completed. Restart uses the current host, including when its forwarded options contain another Region.\n\n### View events\n\n`viewEvents: { submit: 'saveDraft' }` observes events from roots selected with `setView` or `showView`, including a prepared View before display. A function declaration resolves with the Application as `this`; handlers also receive that context and the View event arguments unchanged.\n\nBindings are made once per selected View through ordinary `listenTo`. They remain active while stopped, during preparation, and when a live View is detached. They end when the View or Application is destroyed, or when explicitly removed with `stopListening`. Reselecting a View does not duplicate or restore explicitly removed bindings. A live replaced source retains ordinary listener lifetime; bind manually if a narrower scope is needed.\n\n## State and Radio\n\nState comes from owned `createState(options)` or borrowed `state`; read it with `getState()`. Start/stop/restart retain the source. Declarative `stateEvents` deliver while `isRunning()` is true, including an active restart; stopped/initial preparation changes are not replayed. Ordinary `listenTo` subscriptions retain their source lifetime. See [state ownership](/docs/api/shared/state.md).\n\n`Application.setStateApi(api)` overlays the receiving class's provider and returns it. `State` is the provider. Configure it before construction; see [StateApi](/docs/api/shared/state.md#configure-the-stateapi).\n\n### Radio bindings\n\n`channelName`, `radioEvents`, `radioRequests`, `getChannel()` and `Radio` follow [declarative Radio bindings](/docs/api/shared/common.md#declarative-radio-bindings). They are active while stopped or running. Destruction releases this Application's bindings while preserving the shared channel.\n\n## Lifecycle hooks and events\n\nEvents dispatch their hook first, then subscribers, through [triggerMethod](/docs/api/shared/events.md). Hook and subscriber arguments match.\n\n| Event | Hook | Arguments and timing |\n| --- | --- | --- |\n| `before:start` | `onBeforeStart` | `(app, options)` before preparation; inactive for initial start, still active for a running restart. |\n| `start` | `onStart` | `(app, options, result)` after current preparation succeeds and activity is true. |\n| `before:stop` | `onBeforeStop` | `(app, options)` before child stops and root cleanup. Ordinary stop is still active here; destroy has deactivated. |\n| `stop` | `onStop` | `(app, options)` after successful child/root cleanup, while inactive. May start the next run. |\n| `before:destroy` | `onBeforeDestroy` | `(app, options)` after stop/root cleanup, before child destruction. |\n| `destroy` | `onDestroy` | `(app, options)` after terminal state, child/owned-Region disposal, parent unregistration and Radio/state cleanup. Subscriptions are cleared afterward. |\n\nRestart has no separate event and uses only the startup notifications. `preinitialize` and `initialize` are constructor hooks.\n\n### Restart from start completion\n\nThe current preparation is complete before `onStart` and `start` subscribers. A restart requested there starts a new preparation with its own options and Promise. The completed outer call resolves `true`, describing its own successful completion, even if the new preparation fails or is superseded later.\n\n## TypeScript\n\nImport `ApplicationOptions`, `ApplicationStartOptions`, `ApplicationRestartOptions`, `LifecycleContext`, `ApplicationInstance`, and `ApplicationConstructor` from `marionette`. Constructor and per-operation options are separate. `LifecycleContext` contains the preparation signal. `ApplicationInstance<Options, State, StartResult>` describes constructor options, state and the successful result. `extend` carries the awaited return type of `prepareStart` into that contract. Annotate overridden hook parameters as in the example.\n\nStart destinations use `RegionInstance`; constructor definitions use `RegionDefinition`/`RegionClass`. Root methods preserve a supplied View's type. Child lookup/removal returns the common Application interface; narrow it for child-specific methods. Shared types are listed with their [state](/docs/api/shared/state.md) and [event](/docs/api/shared/events.md) contracts.\n\n\n[Canonical source](/docs/markdown/docs/api/application.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/api/view.md",
      "title": "View",
      "section": "Core classes",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/api/view/",
      "markdownUrl": "https://marionettejs.com/docs/api/view.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/api/view.md",
      "sourceSha256": "170bfb72a2b669f569758f2ef4a4a428f9d63e8486f42b43862273b458fc1cce",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "3cb4f074ee914aa5692a65dff64a95638e88fb347d5c74c24ca5850e97d0657d",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 170bfb72a2b669f569758f2ef4a4a428f9d63e8486f42b43862273b458fc1cce; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# View\n\n[API index](/docs/api.md) · [Region](/docs/api/region.md) · [Shared View runtime](/docs/api/shared/view-bindings.md)\n\nA View owns one fixed DOM element, renders supplied data, and can compose child Views through named [Regions](/docs/api/region.md). Use it for an individual control or a layout. [CollectionView](/docs/api/collection-view.md) manages a set of children instead.\n\nImport `View` from `marionette`. Shared rendering, DOM, UI, data bindings, and child forwarding are defined in [View runtime](/docs/api/shared/view-bindings.md). Inherited [common methods](/docs/api/shared/common.md), [events](/docs/api/shared/events.md), and [state](/docs/api/shared/state.md) are part of this API.\n\n## Local interaction and feature coordination\n\nA View can own local input state and save an edit to its model when the data layer supplies that operation. Calling `this.model.save(...)` from an input handler can be appropriate. With `@mnjs/data`, a local edit can instead call the application's API layer and update the model with `set`; the package supplies no persistence method. Having other Views observe the same model does not make that handler responsible for their presentation; each consumer handles its own updates.\n\nUse an [Application](/docs/api/application.md) to coordinate feature readiness and shared workflow decisions. For these actions, the View emits intent; the Application decides what work to start and where its result belongs. Starting a feature's initial load in `onRender` ties readiness to rendering and can repeat the request on rerender. Put that readiness in [Application preparation](/docs/api/application.md#prepare-before-showing-ui).\n\nFor shared records or selection that change over time, receive an observable source and use [model/collection bindings](/docs/api/shared/view-bindings.md#data-bindings) or [state bindings](/docs/api/shared/state.md). A replacement View reads current data and subscribes for later changes. Its owner can then replace it without coordinating each presentation update.\n\n## Construction and options\n\n`new View(options?)` creates the element, delegates DOM events, prepares state access and Behaviors, registers Regions, and calls `initialize(options)`. It does not evaluate the template. `View.extend(prototypeProperties?, staticProperties?)` returns a subclass; see [class extension](/docs/api/shared/common.md).\n\nOptions below can be declared on the class or supplied at construction. The table identifies which declarations accept resolver functions; those resolvers run with the View as `this`. The renderer controls template invocation. Model, collection, and borrowed state values are used as sources, not invoked as resolvers.\n\n| Option | Accepted value and default |\n| --- | --- |\n| `el` | An `Element` or function returning one. Otherwise Marionette creates a root from `tagName`. Pass an actual element, not a selector string. |\n| `tagName` | String or function returning one; default `'div'`. Used only when creating a root. |\n| `id`, `className` | String, `null`, or function returning a string, `null`, or `undefined`. Applied when creating a root; see [attributes](/docs/api/shared/view-bindings.md#root-attributes). |\n| `attributes` | Attribute map or function returning one. `id` and `className`, when declared, take precedence over its `id` and `class` entries. |\n| `template` | A template understood by the configured renderer, or `false` to preserve existing contents. The default renderer expects a function. No default template is supplied. |\n| `templateContext` | Object or function returning an object, merged over serialized data on each render. |\n| `model`, `collection` | Sources understood by the configured DataApi. A View serializes the model when both are present. Supplying either does not enable automatic rendering on change. |\n| `ui` | Map of names to selectors, or function returning that map. See [UI bindings](/docs/api/shared/view-bindings.md#ui-bindings). |\n| `events`, `triggers` | DOM event maps or functions returning them. See [DOM events](/docs/api/shared/view-bindings.md#dom-events). |\n| `modelEvents`, `collectionEvents` | Source event maps or functions returning them. See [data bindings](/docs/api/shared/view-bindings.md#data-bindings). |\n| `state`, `stateEvents` | Borrowed state and its event bindings. `createState(options)` can supply owned state instead. See [state](/docs/api/shared/state.md). |\n| `regions` | Map of names to Region definitions, or function returning that map; default empty. Definitions are described below. |\n| `regionClass` | Default Region constructor for this View's definitions; default `Region` from its Marionette runtime. Individual definitions may override it. |\n| `childViewEvents`, `childViewTriggers`, `childViewEventPrefix` | Parent handlers, event remapping, and optional prefix; see [child forwarding](/docs/api/shared/view-bindings.md#child-events). Prefix forwarding defaults to `false`. |\n| `behaviors` | Array or object of Behavior definitions, or function returning either. See [Behavior composition](/docs/api/shared/view-bindings.md#behavior-composition). |\n\n`preinitialize(options)` runs before the element, Behaviors, and Regions are initialized; `cid`, `options`, and recognized constructor declarations are already available. `initialize(options)` runs after those resources exist and before state/entity event bindings become active. Both hooks are no-ops by default. Constructor values for root-element configuration, model, collection, and DOM events take precedence over assignments made in `preinitialize`.\n\n`options` contains merged class and constructor options. Custom options remain accessible through `getOption(name)`; they are not automatically assigned as instance properties. Declare `cidPrefix` on the class to change the default `'mnv'`; `cid` is the generated instance identifier.\n\n## Existing elements\n\nConstruction adopts the supplied element without replacing its contents or applying root attributes. An element with child nodes starts with `isRendered() === true`; an element already inside its document starts attached. Construction does not emit render or attach lifecycle events. UI bindings are available immediately when existing contents are detected.\n\nUse `template: false` to preserve existing HTML. `render()` then returns the View without rendering, resetting Regions, or emitting render events. Destroying the View still removes its element and destroys managed children. The root stays fixed for the View's lifetime; construct a new View to use a different root.\n\nThis standalone TypeScript example adopts markup and adds a child without rendering the parent:\n\n```ts\nimport { View, type ViewConfiguration } from 'marionette';\n\nconst el = document.createElement('section');\nel.innerHTML = '<h2>Preview</h2><div class=\"content\"></div>';\ndocument.body.append(el);\n\nconst options: ViewConfiguration = {\n  el,\n  template: false,\n  regions: { content: '.content' },\n};\nconst page = new View(options);\nconst message = document.createElement('p');\nmessage.textContent = 'Ready';\nconst child = new View({ el: message, template: false });\n\npage.showChildView('content', child);\npage.destroy(); // Removes the adopted section and destroys the child.\n```\n\n## Rendering and status\n\n| Method or property | Contract |\n| --- | --- |\n| `el` | The resolved, fixed root `Element`. |\n| `render()` → `this` | Resolves `getTemplate()`, emits `before:render`, resets existing Regions when already rendered, renders into the root, binds UI, sets rendered state, and emits `render`. Reset destroys current children but keeps Region registrations. Destroyed Views and `template: false` do not render. |\n| `isRendered()` → boolean | Whether rendered contents have been established or were present at construction. Becomes false on destruction. |\n| `isAttached()` → boolean | Attachment state maintained by Marionette's lifecycle. Direct DOM moves do not update it automatically. |\n| `isDestroyed()` → boolean | Whether destruction has reached its terminal state. |\n| `destroy(options?)` → `this` | Removes the root, destroys Regions and their current children, releases bindings/Behaviors/owned state, emits destruction notifications, and releases incoming and outgoing event subscriptions. Repeated calls do nothing. Model and collection sources are not destroyed by the View. |\n\nFor template selection, serialization, `renderAttributes`, and renderer customization, see [rendering contracts](/docs/api/shared/view-bindings.md#templates-and-data). `render()` does not refresh root attributes or automatically redelegate changed DOM event maps.\n\n## Named Regions\n\nA `regions` map accepts a selector string, Region constructor, Region instance, or options object such as `{ el: '.content', replaceElement: true }`. An options object can include `regionClass`. Supply options as own enumerable properties; inherited and non-enumerable option properties are not copied. Use a Region subclass for prototype defaults. String selectors resolve inside the View's root by default; `@ui.name` is accepted in selectors and the `el` field. Full Region options are in [Region](/docs/api/region.md). Registration copies the definition map and options objects before resolving UI selectors, so shared declarations remain unchanged and each View uses its own UI map. Supplied Region instances and constructors retain their identity.\n\nRegions are created before `initialize`; their elements can resolve later when content exists. A Region has one owner/name and must belong to the same Marionette runtime. Names must be nonempty strings. Re-registering the same instance under its existing name is harmless; a different definition under an occupied name throws. Remove the old Region before replacing its definition.\n\n| Method | Result and effects |\n| --- | --- |\n| `addRegion(name, definition)` | Returns the registered Region. Does not render the parent. |\n| `addRegions(definitions?)` | Returns a map of the added Regions, or `undefined` for no definitions. Does not render the parent. |\n| `hasRegion(name)` | Returns whether that name is registered; no rendering. |\n| `getRegion(name)` | Returns the Region or `undefined`; no rendering or element resolution. |\n| `getRegions()` | Returns a new map containing current Region instances; no rendering. Changing this map does not change registrations. |\n| `showChildView(name, view, options?)` | Renders the parent if needed, shows the child through the named Region, and returns the supplied child. Accepts Region `ShowOptions`. A skipped show with `allowMissingEl` still returns the child but leaves it unowned; the caller must show it elsewhere or destroy it. |\n| `getChildView(name)` | Renders the parent if needed, then returns the Region's current child or `undefined`. |\n| `detachChildView(name)` | Renders the parent if needed, detaches and releases the current child, and returns it or `undefined`. The child remains alive and becomes the caller's responsibility. |\n| `emptyRegions()` | Renders the parent if needed, empties each Region, and returns a map of them. Keeps Region registrations. |\n| `removeRegion(name)` | Destroys and unregisters the Region, including its current child; returns the destroyed Region. |\n| `removeRegions()` | Destroys/unregisters every Region; returns a map of the destroyed Regions. |\n\nThe child operations and `removeRegion` throw for a missing Region. Region registration/removal emits no View `add:region` or `remove:region` events; observe the Region's lifecycle when needed. Rendering an existing layout resets Regions and destroys their children, so render a smaller child when the surrounding composition should remain alive. An allowed missing-element lookup leaves the Region usable for this reset and for parent destruction.\n\n## Lifecycle hooks and events\n\nEach event below uses `triggerMethod`: the corresponding hook runs first, then event subscribers receive the same arguments. The shared monitor can emit nested child/DOM notifications while an event is being delivered; the phases below describe lifecycle order rather than the ordering of every subscriber. See [event dispatch](/docs/api/shared/events.md).\n\n| Event | Hook | Arguments and timing |\n| --- | --- | --- |\n| `before:render` | `onBeforeRender` | `(view)` before existing Regions reset or template output changes. |\n| `render` | `onRender` | `(view)` after output, UI binding, and rendered state are ready. |\n| `before:attach` | `onBeforeAttach` | `(view)` before an owning Region/CollectionView inserts the root into the document. |\n| `attach` | `onAttach` | `(view)` after insertion and attached state update. |\n| `dom:refresh` | `onDomRefresh` | `(view)` when an attached View renders or a rendered View attaches. |\n| `before:detach` | `onBeforeDetach` | `(view)` before removal of an attached root. |\n| `dom:remove` | `onDomRemove` | `(view)` during `before:detach` or `before:render` when currently attached and rendered. |\n| `detach` | `onDetach` | `(view)` after removal and attached state update. |\n| `before:destroy` | `onBeforeDestroy` | `(view, options)` while `isDestroyed()` is false, before root/child cleanup. |\n| `destroy` | `onDestroy` | `(view, options)` after root/child cleanup and destroyed state update; event subscriptions are cleared afterward. |\n\nFor a newly constructed View with a rendering template shown in an attached Region, the usual successful path is:\n\n```text\nconstructed → render → attach → dom:refresh\n                         │\n                         ├── before:render → dom:remove → render → dom:refresh\n                         └── detach → alive, reusable → attach → dom:refresh\n\nlive View → before:destroy → detach if attached → child cleanup → destroy\n```\n\nExisting markup can start rendered or attached without emitting those construction-time events. With `template: false`, `View.render()` is a no-op and emits no render events. For an initially empty View, `Region.show()` still marks it rendered, so attachment can emit `dom:refresh`. Detachment keeps the View alive; destruction is terminal.\n\nShowing an initially unrendered detached View in an attached Region normally proceeds through render, then attach, then DOM refresh. A direct destroy normally proceeds through `before:destroy`, detach phases if attached, child destruction, and `destroy`. Managed children receive attach/detach propagation; during parent destruction they are destroyed after the parent root is detached. A CollectionView owner may detach a child before destroying it, so its child ordering differs; see [Region replacement](/docs/api/region.md#replacing-a-collectionview).\n\nLifecycle callbacks are synchronous. A thrown callback interrupts the operation; these phases describe successful completion, not rollback guarantees.\n\nSet `monitorViewEvents: false` on the class to disable descendant attachment propagation and generated `dom:refresh`/`dom:remove` notifications. This is a class property, not a recognized constructor option. Ordinary application code should retain monitoring. `monitorViewEvents(view)` is the exported installer used by Marionette; it returns `undefined` and installs handlers only once, unless monitoring is disabled before installation. Native View and CollectionView construction installs it automatically. A custom integration must satisfy `ViewLifecycle`, including event methods, rendered/attached flags and immediate-child traversal. The installer propagates existing lifecycle events; it does not watch external DOM changes.\n\n### Compose children after rendering\n\nUse `onBeforeRender` or a `before:render` listener to prepare template inputs or inspect the existing UI. Avoid operations that render an unrendered parent: `showChildView()`, `getChildView()`, `detachChildView()`, and `emptyRegions()` each reenter the same notification. An unconditional callback recurses; a one-time callback can complete an inner render. If it shows a child, the outer render then resets the Region and destroys that child. Showing children here is also unsafe on later renders, because existing Region children are still reset after `before:render`. `getRegion()` itself is a pure lookup and does not render.\n\nCompose children in `onRender` or a `render` listener, after the parent's template and Regions are ready:\n\n```js\nimport { View } from 'marionette';\n\nconst Page = View.extend({\n  template: () => '<section class=\"content\"></section>',\n  regions: { content: '.content' },\n  onRender() {\n    this.showChildView('content', new View({ template: () => 'Ready' }));\n  },\n});\n\nconst page = new Page().render();\n```\n\nEach full parent render destroys the previous child and composes a new one; parent destruction destroys the current child. Do not call the parent's `render()` again from that completion callback. For `template: false`, no render notification occurs: compose explicitly after establishing the existing markup, as in [existing elements](#existing-elements). CollectionView has a corresponding [manual-child boundary](/docs/api/collection-view.md#compose-manual-children-after-rendering).\n\n## Configuration and inherited API\n\nThe class methods `setRenderer`, `setDomApi`, `setDataApi`, `setStateApi`, and `setEventDelegator` return the receiving class. Their [configuration contracts](/docs/api/shared/view-bindings.md#class-configuration) apply to subclasses as well. Configure before constructing Views.\n\nThe following methods are shared with other classes; their canonical definitions are linked rather than repeated:\n\n- [Common](/docs/api/shared/common.md): `getOption`, `mergeOptions`, `normalizeMethods`, `bindEvents`, `unbindEvents`, `bindRequests`, `unbindRequests`, `extend` and constructor inheritance.\n- [Events](/docs/api/shared/events.md): `on`, `once`, `off`, `trigger`, `triggerMethod`, `listenTo`, `listenToOnce`, `stopListening`.\n- [State](/docs/api/shared/state.md): `createState`, `getState`, `state`, `stateEvents`, and the `State` provider.\n- [View runtime](/docs/api/shared/view-bindings.md): `$`, `getUI`, UI normalization/binding, DOM/entity delegation, template serialization, `attachElContent`, root attributes, Behaviors, and child events.\n\n## TypeScript\n\n`ViewConfiguration` describes recognized options. `ViewInstance<Options, State, Query>` describes instances; `Query` defaults to `ArrayLike<Element>` and follows the DOM provider. `ViewConstructor<Props, Args, State, Statics, Query>` describes constructors and preserves properties, arguments, state, static members, and fluent returns through `extend`. Normal application code can use inferred subclasses instead of spelling out these generics.\n\nRegion definitions use exported `RegionDefinition` and `RegionClass`; child methods accept `SupportedView` and `ShowOptions`. These are structural contracts, not a promise that an arbitrary object with `render()` is a fully managed child. DOM maps, UI maps, and renderer types are listed in [View runtime](/docs/api/shared/view-bindings.md#types).\n\n\n[Canonical source](/docs/markdown/docs/api/view.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/api/collection-view.md",
      "title": "CollectionView",
      "section": "Core classes",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/api/collection-view/",
      "markdownUrl": "https://marionettejs.com/docs/api/collection-view.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/api/collection-view.md",
      "sourceSha256": "8859a50e33bfa983f35addb06aad95b8452799059499562aa5c7fef07cdd37ae",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "be175dc9d8e98bf327ce9094f07f28fa4906560722364fd1028ec76c119b74b8",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 8859a50e33bfa983f35addb06aad95b8452799059499562aa5c7fef07cdd37ae; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# CollectionView\n\n[API index](/docs/api.md) · [View](/docs/api/view.md) · [Shared View runtime](/docs/api/shared/view-bindings.md)\n\nCollectionView owns repeated child Views and their placement, order, and lifetime. Supply a collection for one child per model, or add View instances directly. Use a View with named Regions for a layout containing distinct pieces of UI.\n\n## Render a collection\n\nThis standalone TypeScript example uses `@mnjs/data` for observable membership and Lit for text rendering. API access and persistence remain separate concerns; see [data setup](/docs/integrations/setup.md#observable-data-and-api-access).\n\n```ts\nimport { CollectionView, Region, View } from 'marionette';\nimport { Collection, DataApi } from '@mnjs/data';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\n\nconst Item = View.extend({\n  tagName: 'li',\n  template: ({ label }: { label: string }) => html`${label}`,\n  modelEvents: { change: 'render' },\n}).setDataApi(DataApi).setDomApi(LitDomApi);\n\nconst Empty = View.extend({\n  tagName: 'li',\n  template: () => 'No items',\n});\n\nconst List = CollectionView.extend({\n  tagName: 'ul',\n  childView: Item,\n  emptyView: Empty,\n  viewComparator: 'label',\n}).setDataApi(DataApi);\n\nconst items = new Collection([\n  { id: 'b', label: 'Blueberry', available: false },\n]);\nconst list = new List({ collection: items });\nconst mount = document.createElement('section');\ndocument.body.append(mount);\nconst region = new Region({ el: mount });\nregion.show(list);\n\nitems.add({ id: 'a', label: 'Apricot', available: true });\n// Apricot sorts before Blueberry; the existing row keeps its View.\nlist.setFilter('available'); // Hides Blueberry; its child View stays alive.\nlist.removeFilter();        // Shows that same child again.\n```\n\nThe Region owns the list; the list owns its rows and empty View. `region.destroy()` destroys that composition. It does not destroy `items` or its Models. Child model changes render through the child's `modelEvents`; they do not automatically rerun the list's comparator or filter. Call `list.sort()` or `list.filter()` when those criteria depend on changed attributes.\n\n## Construction and options\n\n`new CollectionView(options?)` establishes its fixed root, children storage, Behaviors, state access and event bindings. It calls `preinitialize(options)` before those resources, then `initialize(options)` after child storage and Behaviors exist. `getState()` is available inside `initialize`; state bindings, the empty Region, and entity bindings initialize afterward. Construction does not create rows or subscribe to collection membership; the first `render()` does.\n\nCollectionView accepts View's root, template, data, UI/DOM, entity-event, state, Behavior and child-forwarding options. Their shared contracts are in [View runtime](/docs/api/shared/view-bindings.md), [state](/docs/api/shared/state.md), and [View construction](/docs/api/view.md#construction-and-options). It has no named-Region methods or `regions`/`regionClass` options. Custom options use [common option methods](/docs/api/shared/common.md#options-and-initialization).\n\n| CollectionView option | Value and default |\n| --- | --- |\n| `collection` | Source understood by the configured DataApi. The default accepts a plain array; the native DataApi accepts a `Collection`. May be omitted for manually managed children. |\n| `childView` | View/CollectionView class, or `function(model)` returning a class. Required when collection models need children; no default. |\n| `childViewOptions` | Options object or `function(model)` returning one. Default construction uses `{ model, ...childViewOptions }`, so an explicit `model` option overrides the source model. Normally retain the supplied model. |\n| `childViewContainer` | Descendant selector or function returning one; defaults to the root. Resolved after template rendering. A selector with no match throws `MN0013`. |\n| `emptyView` | View/CollectionView class, or function returning a class, `null`, `undefined`, or `false`. Defaults to no empty View. |\n| `emptyViewOptions` | Options object or function called without arguments. Falls back to `childViewOptions`, also called without a model. |\n| `RegionClass` | Region constructor for the list-owned empty Region; defaults to `Region`. A supplied constructor option overrides the prototype value; omission or `undefined` preserves it. |\n| `sortWithCollection` | Boolean, default `true`. Follows source reorder notifications and uses collection order when no custom comparator is selected. |\n| `viewComparator` | Model attribute name, one-argument key function, or two-argument comparison function; default is collection order. `false` disables the comparator. See [sorting](#sorting). |\n| `viewFilter` | Model attribute name, attribute-value object, or predicate; default no filter. See [filtering](#filtering). |\n\nResolver functions and comparator/filter callbacks run with the CollectionView as `this`. `childView` and `emptyView` constructors are instantiated, not called as resolvers. Use `CollectionView.extend(prototypeProperties?, staticProperties?)` to declare defaults and overrides.\n\n`cid` is generated with the class's `cidPrefix` (`'mncv'` by default). `options` contains merged class and constructor options. `RegionClass` is copied before `initialize`, which can still override it before the empty Region is created. Configure it through a constructor option, prototype property, or `initialize`; native subclass fields are initialized after the empty Region has already been created. This hook affects only empty presentation, not ordinary rows or their named Regions.\n\n## Rendering and collection updates\n\n| Operation | Child identity and presentation |\n| --- | --- |\n| `render()` → `this` | Destroys all managed rows, creates children from the current collection, renders an optional template, resolves the container, then sorts, filters and presents children. Emits render lifecycle notifications. A destroyed list does nothing. |\n| Observable addition/removal | Creates added rows and destroys removed rows; retains unaffected child instances. Reapplies sorting/filtering and presentation. |\n| Source reorder | Sorts/presents existing rows when `sortWithCollection` is true. Does not recreate surviving rows. |\n| Source reset | Destroys/rebuilds rows from the new snapshot, even if the same Models or keys occur again. Does not rerender the list's own template. |\n| Adapter update of the same model object | Retains its child, marks it for rendering, then sorts/filters. A hidden child renders when next presented. |\n| Adapter replacement with a different object under the same key | Creates a replacement child and destroys the previous child. Stable keys do not imply rebinding an existing View to a different model. |\n\nA plain array is not observed. After changing it, `render()` rebuilds the list. Observable sources let additions and ordering changes preserve surviving Views and their DOM; do not call full `render()` merely to apply a filter or comparator. Use a new CollectionView when changing the collection source; assigning `collection` does not transfer an existing observer to that source.\n\nThe DataApi supplies models and stable, unique, non-null keys. The default uses each array value as its key; `@mnjs/data` uses Model `cid`, not `id`. Missing, duplicate or changing keys throw `MN0039`. Full adapter authoring is a separate reference area; normal consumers use a compatible [DataApi setup](/docs/integrations/setup.md#configure-once).\n\n`template` is optional. With no template or `template: false`, `render()` still manages rows and emits events; it only skips rendering the list's own template. A supplied root is adopted, but existing markup does not mark a CollectionView rendered or bind its UI automatically. With no template, call `bindUIElements()` when you need UI queries against that markup. Place children in a dedicated `childViewContainer` when the root also contains persistent markup.\n\n## Sorting\n\nSorting changes View order without changing the source collection. Comparators operate on child Views:\n\n- A string reads that attribute from each child's model through the DataApi.\n- `function(view)` returns a sort key. Equal keys retain their current ordering; missing (`undefined`) keys sort last.\n- `function(left, right)` returns a negative, zero, or positive number. Use two declared parameters: function arity distinguishes this form from a key function.\n\n| Method | Contract |\n| --- | --- |\n| `getComparator()` | Returns the explicit truthy comparator, the source-order comparator, or `false`. Override for a computed comparator. |\n| `sort()` → `this` | Sorts managed children, then filters and renders the resulting presentation. Already rendered survivors keep their elements. |\n| `setComparator(value, options?)` → `this` | Stores the value and calls `sort()` if its identity changed, unless `preventRender` is true. |\n| `removeComparator(options?)` → `this` | Clears the explicit comparator. With a collection and `sortWithCollection: true`, this restores the source-order comparator. |\n\n`viewComparator: false` disables comparator sorting. To ignore source reorder notifications as well, use `sortWithCollection: false`. With `sortWithCollection: true`, source updates establish source order before custom comparison, so equal-key ties follow the source. The default source-order comparator places manual children before collection rows when their model is missing or absent from the collection. Use an explicit comparator or indexed insertion when you need another order.\n\nConfigure initial options before rendering. The setters do not check readiness: their default behavior immediately runs a presentation pass. Use `{ preventRender: true }` to defer a changed setting. Apply a deferred comparator with `sort()`; a deferred filter with `filter()` or `sort()`. Full rendering applies both.\n\n## Filtering\n\nFiltering controls presentation; it does not remove models or destroy their children. Hidden children keep state and subscriptions and remain owned by the list. `children` exposes the presented set after a filter pass.\n\n| Filter value | Meaning |\n| --- | --- |\n| `function(view, index, children)` | Keep the View for a truthy result. The index and array describe all managed children in current sorted order. |\n| `'available'` | Keep Views whose model has a truthy `available` attribute according to the DataApi. |\n| `{ available: true }` | Keep Views whose model has every listed attribute with the matching value, using strict equality. |\n| Falsy value | No filter. |\n\n| Method | Contract |\n| --- | --- |\n| `getFilter()` | Returns `viewFilter`; override for a computed filter. |\n| `filter()` → `this` | Recomputes presentation and renders/attaches included children, without sorting first. Detaches excluded rows without destroying them. |\n| `setFilter(value, options?)` → `this` | Stores the value and filters immediately when its identity changed, unless `preventRender` is true. |\n| `removeFilter(options?)` → `this` | Clears the filter using the same setter rules. |\n\nChanging values captured by a predicate does not change the predicate's identity. Call `filter()` explicitly to apply those changes. Hidden Views can be shown again as the same instances; they are still destroyed when removed from the source, on full render/reset, or when the list is destroyed.\n\n## Empty presentation\n\n`isEmpty()` reports whether `children` has no presented rows. All rows can be filtered out while the source still has models. The `emptyView` appears for this presentation state, through the Region returned by `getEmptyRegion()`.\n\nThe empty View is separate from `children`. It receives `emptyViewOptions`, or the `childViewOptions` fallback, with no automatic model. Give it a root suitable for the child container, such as `li` inside `ul`. Each empty presentation pass creates a new empty View and replaces the previous one; it is destroyed when rows appear or the list is destroyed. Its events use the same [child forwarding](/docs/api/shared/view-bindings.md#child-events) as rows.\n\n`getEmptyRegion()` returns the list-owned Region for the current child container, with replacement disabled. It is created during construction and reused while live; its owner is this CollectionView. If explicitly destroyed while the list is live, the next call recreates it. After list destruction, the getter returns the destroyed Region. Use it to inspect `currentView`; configure empty presentation through `emptyView` and `emptyViewOptions`.\n\n## Find and inspect children\n\n`children` is an iterable child container for the current presentation. It excludes filtered-out rows and the empty View. Newly adopted manual children enter it immediately, including when rendering is deferred; the next filter pass establishes the presented subset. Query this container; change ownership through the CollectionView methods below.\n\n| Member | Result |\n| --- | --- |\n| `length`, `isEmpty()` | Presented count and whether it is zero. |\n| `findByModel(model)`, `findByKey(key)` | View indexed by `Data.key(model)` or an explicit key, or `undefined`. Model lookup is by provider key, not necessarily object identity. |\n| `findByCid(cid)`, `findByIndex(index)` | View by its own `cid` or presentation index, or `undefined`. |\n| `findIndexByView(view)` | Index, or `-1` if absent. |\n| `hasView(view)`, `contains(view)` | Whether that exact instance is present. |\n| `toArray()`, `[Symbol.iterator]()` | A copied array, or iteration over the presentation. |\n| `each(callback, context?)` | Calls `(view, index)` for each child; returns the container. |\n| `map(callback, context?)`, `pluck(property)` | Array of callback results or View property values. `pluck` reads the View, not its model. |\n| `find`, `filter`, `reject`, `every`, `some`, `partition` | Accept `(view, index)` predicates and optional context. Return the first match, matching array, rejected array, boolean, boolean, or `[matching, rejected]`. |\n| `reduce(callback, initialValue?, context?)` | Reduces using `(accumulator, view, index)`. Omitting the initial value uses the first View; an empty container then throws. |\n| `first(count?)`, `last(count?)` | One View (or `undefined`) when count is omitted; an array when supplied. |\n| `initial(count = 1)`, `rest(count = 1)` | Array excluding the last or first count Views. Counts must be nonnegative integers. |\n| `without(...views)` | Copied array excluding those instances. |\n| `invoke(methodName, ...args)` | Calls each child's named method with that child as `this`; returns its results. |\n\nThe container's `Data` is its lookup provider. Public query helpers do not change membership.\n\n## Manage View instances directly\n\nThese operations do not change the source collection. For collection-backed rows, normally change the collection; direct removal does not remove the model and a later rebuild can recreate its View.\n\n| Method | Ownership and return |\n| --- | --- |\n| `addChildView(view, index?, options?)` | Adopts and returns the supplied View, rendering the parent first if needed. A View must be unowned. Without a numeric index, sorts/filters; a numeric index inserts directly and skips those steps for this addition. Also accepts an options object as the second argument. |\n| `detachChildView(view)` | Removes a managed View from storage and DOM, releases ownership/forwarding, and returns it alive. The caller must give it a new owner or destroy it. |\n| `removeChildView(view)` | Destroys a managed View, removes its entry, and returns it. A missing/falsy or unmanaged View is returned unchanged. |\n| `swapChildViews(first, second)` → `this` | Swaps two managed children without changing the collection. Both must belong to this list (`MN0015` otherwise). If only one is currently presented, reapplies filtering. A later sort can override the swap. |\n\nFor addition, `{ index, preventRender }` may be supplied as options; a non-null options index takes precedence over the positional index. `preventRender` defers child presentation, not adoption or the parent's initial render. Destroyed/falsy incoming Views and additions to a destroying/destroyed list return unchanged. Already owned incoming Views throw `MN0003`.\n\nA child that destroys itself is removed from the list automatically. Full `render()` destroys manual children too and rebuilds only collection rows.\n\nA same-key source update inserts its replacement View at the old child's position before sorting. Unaffected manual children retain identity; their placement follows the [sorting rules](#sorting), including preceding collection rows under the default source-order comparator.\n\n## Lifecycle and extension points\n\nCollectionView has the shared View attach/detach, DOM and destruction notifications described in [View lifecycle](/docs/api/view.md#lifecycle-hooks-and-events). `isRendered()`, `isAttached()` and `isDestroyed()` report those states. `destroy(options?)` returns the list, removes its root, destroys all managed rows (including hidden rows) and its empty Region, and releases observation, bindings, Behaviors and owned state. Repeated destruction does nothing; it does not destroy the supplied model or collection.\n\nEvery event below dispatches its matching `on…` hook before subscribers. Child operations and observed changes can emit these events without a full list render.\n\n| Event pair | Hooks | Arguments and boundary |\n| --- | --- | --- |\n| `before:render`, `render` | `onBeforeRender`, `onRender` | `(list)` around full rendering. The final event sees `isRendered() === true`. |\n| `before:add:child`, `add:child` | `onBeforeAddChild`, `onAddChild` | `(list, child)` around adoption/indexing, before presentation by this list. |\n| `before:remove:child`, `remove:child` | `onBeforeRemoveChild`, `onRemoveChild` | `(list, child)` around removal from child storage. These are not a universal before/after boundary for child destruction. |\n| `before:sort`, `sort` | `onBeforeSort`, `onSort` | `(list)` around sorting when there are managed children and an active comparator. |\n| `before:filter`, `filter` | `onBeforeFilter`, `onFilter` | Before: `(list)`. After: `(list, included, excluded)`. Only emitted with managed children and an active filter. |\n| `before:render:children`, `render:children` | `onBeforeRenderChildren`, `onRenderChildren` | `(list, presentedChildren)` around child/empty presentation. The array contains row Views, not the empty View; it is live storage, so copy it if retaining a snapshot. |\n| `before:destroy:children`, `destroy:children` | `onBeforeDestroyChildren`, `onDestroyChildren` | `(list)` around bulk managed-row destruction, when rows exist. Bulk destruction does not emit individual remove-child events. |\n\nA full render runs: `before:render` → old-row destruction → new-row additions → template/container setup → sort → filter → child/empty presentation → `render`. A collection reset omits the outer render and template phases. Direct removal tears down the child before remove-child notifications; observable removal drops its entry, updates presentation, then destroys the removed child. [Region replacement](/docs/api/region.md#replacing-a-collectionview) explains the outer owner's teardown order. Callbacks are synchronous; a thrown callback can interrupt an operation.\n\n| Extension point | Default behavior |\n| --- | --- |\n| `buildChildView(model, ChildClass, options?)` | Constructs `new ChildClass({ model, ...options })` and returns it. Does not itself adopt/render the child. |\n| `attachHtml(elements, container)` | Appends the supplied Element/DocumentFragment to the child container; no defined return value. |\n| `detachHtml(view)` | Detaches the child's element through the DOM provider; no defined return value. |\n| `getComparator()`, `getFilter()`, `isEmpty()` | Can be overridden to compute ordering, filtering, or empty presentation. |\n\nDOM extension points perform placement only; ownership and lifecycle remain the job of the enclosing operations. Keep the fixed root. Shared `getTemplate`, serialization, UI, delegation, attributes, Behavior composition, child events and their methods are defined in [View runtime](/docs/api/shared/view-bindings.md). Class setters `setRenderer`, `setDomApi`, `setDataApi`, `setStateApi`, and `setEventDelegator` use its [configuration contracts](/docs/api/shared/view-bindings.md#class-configuration). Inherited object APIs are in [common methods](/docs/api/shared/common.md), [events](/docs/api/shared/events.md), and [state](/docs/api/shared/state.md).\n\n### Compose manual children after rendering\n\nDo not call `addChildView()` from `onBeforeRender` or a `before:render` listener. It renders an unrendered list before adopting the child, so that callback reenters itself. Even with a one-time callback, the outer render destroys the newly adopted child. On a later full render, children added during `before:render` are also included in the following old-row destruction. `{ preventRender: true }` does not avoid either problem: it defers the child's presentation, not the parent's initial render or adoption.\n\nPrepare collection inputs before rendering. For manual children, compose in `onRender` or a `render` listener, after the full-render child destruction and container setup:\n\n```js\nimport { CollectionView, View } from 'marionette';\n\nconst ManualList = CollectionView.extend({\n  onRender() {\n    this.addChildView(new View({ template: () => 'Ready' }));\n  },\n});\n\nconst list = new ManualList().render();\n```\n\nThis creates a fresh child after each full render; the next full render, a collection reset, or parent destruction destroys it. A collection reset does not emit `render`, so a manual child composed in `onRender` is not recreated afterward. Do not invoke another full parent render from the completion callback. For collection-backed rows, configure `collection` and `childView` instead of manually recreating those rows. See the related [View composition boundary](/docs/api/view.md#compose-children-after-rendering).\n\n## TypeScript\n\nImport `CollectionViewConfiguration`, `CollectionViewInstance`, `CollectionViewConstructor`, `CollectionChild`, and `ChildRenderOptions` from `marionette`. Configuration describes accepted options; `ChildRenderOptions` contains `index` and `preventRender`. `CollectionChild` describes a managed View with container identity. Instance generics describe child type, options, state, collection source and query type. Constructor inference carries supplied child/source types and subclass properties through `extend`; normal applications can use that inference as in the example.\n\nThe `children` container interface is reachable through the instance type; its constructor is not a top-level Marionette export.\n\n\n[Canonical source](/docs/markdown/docs/api/collection-view.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/api/region.md",
      "title": "Region",
      "section": "Core classes",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/api/region/",
      "markdownUrl": "https://marionettejs.com/docs/api/region.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/api/region.md",
      "sourceSha256": "ef0d045faa1351e38f35e5ccb2b3654f8930346e5f754e885b8fd63fded6429e",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "9a02d1332b7bbba89b889275946a04462eca747485360f63a5412105c5b0b4ba",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 ef0d045faa1351e38f35e5ccb2b3654f8930346e5f754e885b8fd63fded6429e; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Region\n\n[API index](/docs/api.md) · [View](/docs/api/view.md) · [Shared events](/docs/api/shared/events.md)\n\nA Region owns the placement and lifetime of one View or CollectionView. Showing another View destroys the current one. Detaching releases it for reuse. A View can own named Regions for composition; an Application can use a Region to display its root View.\n\n## Construction and options\n\n`new Region(options?)` configures the Region and calls `initialize(options)`. It does not resolve a selector, render a View, or change the DOM. Supply `el` before showing content. Unlike View, Region has no `preinitialize` hook.\n\n| Option / class property | Contract |\n| --- | --- |\n| `el` | A native `Element` or selector string. A selector is resolved when an operation needs the element, then the resulting element is cached. A detached element is valid. |\n| `parentEl` | An `Element`, `Document`, or function returning either; scopes selector lookup to descendants of that node. Defaults to `document` when absent or the function returns no node. |\n| `allowMissingEl` | Boolean or function returning a boolean; false by default. Allows a supplied selector to have no match. It does not allow an omitted `el`. |\n| `replaceElement` | Boolean or function returning a boolean; false by default. Replaces the Region's placeholder with the shown View's root instead of inserting the root inside it. |\n\nFunctions run with the Region as `this`. Constructor options take precedence over class defaults. Use [common option methods](/docs/api/shared/common.md) for custom options.\n\nThis example moves a live View between two Regions without rendering it again:\n\n```ts\nimport { Region, View, type RegionOptions } from 'marionette';\n\nconst options: RegionOptions = { el: document.createElement('section') };\nconst first = new Region(options);\nconst second = new Region({ el: document.createElement('aside') });\nconst content = document.createElement('p');\ncontent.textContent = 'Account settings';\nconst view = new View({ el: content, template: false });\n\nfirst.show(view);\nconst retained = first.detachView();\nif (retained) second.show(retained);\n\nfirst.destroy();\nsecond.destroy(); // Destroys the View now owned by this Region.\n```\n\nSee [View](/docs/api/view.md) for named Region definitions, including selector, constructor, instance, and options-object forms.\n\n## Showing a View\n\n### `show(view, options?)`\n\nAccepts a View or CollectionView instance and returns the Region. It returns `undefined` when an unmatched selector is allowed by `allowMissingEl`. Both `allowMissingEl` and `replaceElement` can be overridden for this call with boolean values in `options`.\n\nOn a successful show, the Region:\n\n1. Resolves its element and checks the incoming View.\n2. Emits `before:show`, empties the outgoing View, and takes ownership of the incoming View.\n3. Renders the incoming View if it is not already rendered.\n4. Inserts its element, emitting attach notifications if the Region is in the document and monitoring is enabled.\n5. Emits `show`.\n\nShowing the current View again does not rerender it or repeat show events. A destroyed View cannot be shown. A View already owned by an Application, Region, or CollectionView must first be detached from that owner. A View adopting existing attached markup does not receive another attach notification just because a Region shows it.\n\nAn unmatched selector produces `MN0005` unless allowed; no configured element produces `MN0004`. A destroyed incoming View produces `MN0007`, and an already owned View produces `MN0003`. `allowMissingEl` skips that show attempt without taking ownership of the View. A later explicit operation retries an unresolved selector; the Region does not watch for DOM changes.\n\nAn unmatched lookup clears the cached `el` but retains the original selector. A later `show()` retries that selector and applies its missing-element options. With no current View, `empty()` also needs to resolve the element; `reset()` and `destroy()` use that emptying path. When a current View exists, cleanup releases it using the resolved element without another selector lookup. A skipped show leaves the Region usable for cleanup or a later explicit show.\n\nOperations are synchronous. Lifecycle callbacks that throw interrupt the operation; Region does not roll back partially completed work.\n\n## Empty, detach, reset, and destroy\n\n| Method | Child and DOM behavior | Return |\n| --- | --- | --- |\n| `empty(options?)` | Destroys the current View and releases ownership. With no View, clears the Region element's contents. Keeps the Region usable and its resolved element cached. | Region |\n| `detachView()` | Removes the current View from the DOM, releases ownership and parent event forwarding, and keeps the View alive. Emits the Region's empty events. | Detached View, or `undefined` |\n| `reset(options?)` | Empties, then restores the original `el` reference. An initial selector is queried again on the next operation; an initial Element is reused. Requires emptying to succeed under the supplied missing-element options. | Region |\n| `destroy(options?)` | Runs destroy notifications around reset/empty cleanup, unlinks a named View-owned Region, and releases its incoming and outgoing event subscriptions. | Region |\n\n`empty()`, `reset()`, and `destroy()` use `ShowOptions` for element checking. `empty()` without options tolerates an unmatched selector when there is no child; supplying `allowMissingEl: false` makes that check strict. These options are not passed to the outgoing View's `destroy()`.\n\nKeep a reference to a detached View and either give it a new owner or destroy it when finished. Detachment preserves the View's own listeners and state; its [View owner](/docs/api/view.md) stops forwarding its events. See [event cleanup](/docs/api/shared/events.md#cleanup) for native destruction and subscription ownership.\n\nRepeated destruction is a no-op. Once destruction begins, `show()` does nothing and returns the Region; `detachView()` returns `undefined`. After destruction completes, `empty()` and `reset()` also do nothing and return the Region. Destruction leaves the Region's own element in place, with its owned View removed.\n\n### Replacing the Region element\n\nWith `replaceElement: true`, the Region retains its original placeholder as `region.el` while the View's element occupies that position in the DOM. Emptying or detaching restores the placeholder. Replacement also works per call with `show(view, { replaceElement: true })`.\n\nUse a placeholder that has a parent node: replacement exchanges nodes in that parent. `isReplaced()` reports whether the Region is currently using replacement mode. The placeholder is restored before the outgoing View is destroyed, which changes detach ordering as described below.\n\n## Properties and queries\n\n| Member | Result / purpose |\n| --- | --- |\n| `currentView` | The owned View or CollectionView, or `undefined`. Read this property; use lifecycle methods to change ownership. |\n| `hasView()` | Boolean indicating whether `currentView` exists. Does not render or inspect the DOM. |\n| `getOwner()` | The owning View, including a CollectionView for its empty-view Region, or `undefined`. This reports View registration; an Application's root Region does not report the Application here. |\n| `getName()` | Name registered on the owning View, or `undefined` for standalone and unnamed Regions. |\n| `isSwappingView()` | True during replacement, including `before:show`, empty, and `show` callbacks. False after a successful show finishes. |\n| `isReplaced()` | Whether the placeholder is currently replaced by the View's root. |\n| `isDestroyed()` | False before destruction completes; true before `destroy` notifications run. |\n| `el` | Initial selector/Element, resolved Element after lookup, or `undefined` after an unmatched lookup. A successful `reset()` restores the initial reference. An unresolved selector is retried on the next element-dependent operation. |\n| `options` | Merged constructor options. See [common options](/docs/api/shared/common.md). |\n| `cid`, `cidPrefix` | Unique instance identifier and its class-level prefix (`'mnr'` by default). |\n| `Dom` | DOM provider used for lookup, insertion, detachment, and replacement. Configure through `setDomApi`. |\n\n## Lifecycle events and hooks\n\nEach event uses `triggerMethod`: its matching hook runs first, then registered event listeners receive the same arguments. See [shared events](/docs/api/shared/events.md). Hook methods are supplied on a subclass, for example `onBeforeShow(region, view, options)`.\n\n| Region event | Hook | Arguments |\n| --- | --- | --- |\n| `before:show` | `onBeforeShow` | `(region, incomingView, options)` |\n| `show` | `onShow` | `(region, incomingView, options)` |\n| `before:empty` | `onBeforeEmpty` | `(region, outgoingView)` |\n| `empty` | `onEmpty` | `(region, outgoingView)` |\n| `before:destroy` | `onBeforeDestroy` | `(region, options)` |\n| `destroy` | `onDestroy` | `(region, options)` |\n\n`options` is the object passed to `show()` or `destroy()`, or `undefined`. Empty events have no options argument. The current View is still present at `before:empty` and released by `empty`. Emptying a Region that has no View clears content without emitting empty events. When a child destroys itself, the Region releases it and emits empty events too.\n\nFor an occupied Region, `destroy()` runs: Region `before:destroy` → Region `before:empty` → child teardown → Region `empty` → Region `destroy`. The last notification observes `isDestroyed() === true` and cleared View-owner/name references.\n\n### Replacing a CollectionView\n\nReplacement follows the same Region sequence: `before:show` → `before:empty` → outgoing child teardown → `empty` → incoming render/attach → `show`. The outgoing CollectionView destroys its managed children during its teardown; its `before:destroy:children` and `destroy:children` notifications belong to the CollectionView.\n\nNormally the outgoing View receives `before:destroy` before detach. With `replaceElement`, restoring the placeholder detaches it before `before:destroy`. An already rendered incoming View skips rendering. Descendant notifications follow the [View lifecycle](/docs/api/view.md#lifecycle-hooks-and-events); monitoring and attachment state determine which detach/attach notifications occur.\n\n## Customization and inherited methods\n\nUse `Region.extend(prototypeProperties?, staticProperties?)` or subclass Region. `initialize(options)` is the constructor hook; the default does nothing. For custom constructors and `Region.call` / `Region.apply`, see [class construction](/docs/api/shared/common.md).\n\n| Extension point | Default contract |\n| --- | --- |\n| `getEl(selector)` | Returns the first matching native Element under `parentEl` or `document`, or `undefined`. Does not include the parent node itself in selector matching. |\n| `attachHtml(view)` | Appends `view.el` inside `region.el`. Used for ordinary insertion; replacement uses the DOM provider's `replaceEl` instead. Returns `undefined`. |\n| `detachHtml()` | Removes the contents of `region.el`. Returns `undefined`. Used for ordinary detachment and clearing unmanaged HTML. |\n| `removeView(view)` | Calls `destroyView(view)` when emptying a live owned View. Returns `undefined`. Override only when intentionally replacing the default teardown policy. |\n| `destroyView(view)` | Destroys a View unless it is already destroyed, respecting the owner's detach-monitoring policy. Returns that View. |\n\nThese methods are called by lifecycle operations. Calling DOM hooks directly does not perform the ownership bookkeeping of `show`, `empty`, or `detachView`. If overriding a lifecycle method, delegate to `Region.prototype` to retain the standard cleanup and event contract.\n\n`Region.setDomApi(partialApi)` merges DOM methods into that class's provider and returns the class. Call it on a Region subclass to scope the override to that subclass. See [runtime configuration](/docs/api/runtime.md#choose-a-configuration-scope) for setter scope and [DomApi](/docs/api/providers/dom.md#domapi) for the provider-authoring contract.\n\nRegion inherits [common utilities](/docs/api/shared/common.md): `getOption`, `mergeOptions`, `normalizeMethods`, `bindEvents`, `unbindEvents`, `bindRequests`, and `unbindRequests`. It also inherits [event methods](/docs/api/shared/events.md): `on`, `once`, `off`, `trigger`, `triggerMethod`, `listenTo`, `listenToOnce`, and `stopListening`. Region has no state, model, collection, renderer, or Radio-channel initialization of its own.\n\n## TypeScript types\n\nAll of these types are exported from `marionette`:\n\n| Type | Use |\n| --- | --- |\n| `RegionOptions` | Constructor options from the first table. |\n| `ShowOptions` | Per-operation boolean options and extra application-defined keys. |\n| `RegionInstance<Options>` | Region instance contract, with its constructor-options type. |\n| `RegionConstructor<Props, Args, Statics>` | Constructor, subclass properties, constructor arguments, and static members. `extend` carries these into derived classes. |\n| `RegionDefinition`, `RegionClass` | Accepted named Region definition forms and the constructor type used by View/Application configuration. |\n| `RegionOwner` | Structural type returned by `getOwner()`. Actual owners are Views; internal forwarding members on this type support the framework's ownership contract. |\n| `SupportedView`, `ViewLifecycle` | Contracts used by Region and other composition owners. Native View and CollectionView satisfy them, including lifecycle state and child traversal. `SupportedView` adds `render()` and `destroy()`. |\n\n`show()` is typed as the Region or `undefined`; `detachView()` returns `SupportedView | undefined`. `empty()`, `reset()`, and `destroy()` preserve the derived instance type for chaining. Private lifecycle fields in `ViewLifecycle` are framework integration details, not fields to mutate in application code.\n\n\n[Canonical source](/docs/markdown/docs/api/region.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/api/behavior.md",
      "title": "Behavior",
      "section": "Core classes",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/api/behavior/",
      "markdownUrl": "https://marionettejs.com/docs/api/behavior.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/api/behavior.md",
      "sourceSha256": "45df12d32d15caf9d69849957f476bc90d6c0ab1a89186384618943f68c0ee48",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "122379e902f0374a3f7128d3d139c2552f1142d0e82348a82e77fe36dcaa117c",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 45df12d32d15caf9d69849957f476bc90d6c0ab1a89186384618943f68c0ee48; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Behavior\n\n[API index](/docs/api.md) · [View](/docs/api/view.md) · [CollectionView](/docs/api/collection-view.md)\n\nBehavior adds reusable local interaction to a View or CollectionView. It shares the host's element and lifetime. Use a View method for one-off interaction; extract a Behavior when multiple hosts need the same behavior. Feature requests, navigation and application composition belong with their owner, not in a DOM helper.\n\n## Reuse a local interaction\n\nThis Behavior turns Escape into a host event. The owner of the host decides how to dismiss it.\n\n```ts\nimport { Behavior, View } from 'marionette';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\n\nconst DismissOnEscape = Behavior.extend({\n  events: { keydown: 'handleKeydown' },\n  handleKeydown(event: KeyboardEvent) {\n    if (event.key === 'Escape') {\n      this.view.triggerMethod('dismiss', this.view);\n    }\n  },\n});\n\nconst SearchPanel = View.extend({\n  behaviors: [DismissOnEscape],\n  template: () => html`<input aria-label=\"Search\">`,\n}).setDomApi(LitDomApi);\n\nconst panel = new SearchPanel();\npanel.render();\n```\n\nThe host owns the Behavior. Destroying the host removes the Behavior's DOM and data subscriptions too. Rendering the host again retains the Behavior instance.\n\n## Declare and construct\n\nDeclare Behaviors through the host's `behaviors` option: an array or named map of Behavior constructors or `{ behaviorClass: SomeBehavior, ...options }` definitions. A function can return that array/map. See [composition](/docs/api/shared/view-bindings.md#behavior-composition). The host constructs and manages these instances; declaration names are not a public lookup API.\n\n`new Behavior(options, host)` requires a host. Prefer host declarations for automatic composition and teardown; constructing an instance directly does not register it in the host's managed Behavior list. A class entry receives an empty options object; an object definition, including `behaviorClass`, is passed to its constructor as options. Behavior options do not inherit the host's options.\n\nConstruction establishes `view`, `el`, options, `cid`, and state access before `initialize(options, host)`. UI selectors are resolved before this hook; state and DOM bindings initialize afterward. The host's `initialize` runs after its Behaviors are constructed. Behavior has no `preinitialize` hook.\n\n| Option | Contract |\n| --- | --- |\n| `events`, `triggers` | DOM event maps or functions returning maps; selectors may use `@ui.name`. See [DOM interaction](#dom-interaction-and-ui). |\n| `ui` | Named selector map or function returning one. Merged with host UI; host entries win on matching names. |\n| `modelEvents`, `collectionEvents` | Event-to-handler maps or functions returning maps. Observe the host's model/collection through its DataApi. |\n| `state`, `stateEvents` | Borrowed state and declarative observation, independent of the host's state. See [state](/docs/api/shared/state.md). |\n\nMaps use functions or Behavior method-name strings for handlers, except `triggers`, whose values name host events. Custom options remain in `options` and are read with `getOption`. Recognized maps replace inherited maps, with the special host UI merge described above.\n\n`Behavior.extend(prototypeProperties?, staticProperties?)` creates a subclass. `cidPrefix` defaults to `'mnb'`. `view` is the host; `el` is its fixed root element. There is no separate Behavior element, template, render method, or Region. Common extension and option methods are in [class utilities](/docs/api/shared/common.md).\n\n## DOM interaction and UI\n\n`events` callbacks run with the Behavior as `this` and receive the DOM event. `triggers` call the **host's** `triggerMethod`, passing `(host, DOMEvent, ...extraArgs)`. A string trigger prevents default and stops propagation; use `{ event, preventDefault: false, stopPropagation: false }` to opt out. See the shared [DOM event contract](/docs/api/shared/view-bindings.md#dom-events).\n\n| Method | Contract |\n| --- | --- |\n| `$(selector)` | Forwards to the host's scoped query method. Returns the host's query collection. |\n| `getUI(name)` | Returns the bound query collection, or `undefined` for an unknown name. Throws `MN0023` before UI binding. Read it after UI binding, usually in `onRender`. |\n| `bindUIElements()` | Resolves the Behavior's selectors against the host; returns this Behavior. |\n| `unbindUIElements()` | Releases bound UI references; returns this Behavior. |\n| `normalizeUIString(value, bindings?)` | Expands `@ui.name` tokens in a selector string. |\n| `normalizeUIKeys(map, bindings?)` | Returns a map with UI tokens expanded in its keys. |\n| `normalizeUIValues(map, property?, bindings?)` | Mutates and returns the map, expanding tokens in string values or the named property of object values. See [UI helpers](/docs/api/shared/view-bindings.md#ui-bindings). |\n\nThe host coordinates UI rebinding during rendering. A saved query still points at its previous elements after a rerender; call `getUI` again. Do not assume Behavior UI is bound in `initialize`. A template-less CollectionView does not automatically bind Behavior UI; call the host's `bindUIElements()` when using existing elements. The Behavior shares the host's [fixed root](/docs/api/view.md#existing-elements).\n\n`Behavior.setEventDelegator(provider)` replaces that class's DOM event provider and returns the class. `EventDelegator` is the provider slot. It is configured on the Behavior class independently from a host-specific override; runtime-wide configuration can configure both. There is no Behavior `setRenderer`, `setDomApi`, or `setDataApi`.\n\n## Host events and data\n\nHost events are forwarded to each Behavior's `triggerMethod` with their original arguments. A host `save` event invokes Behavior `onSave` and its `save` subscribers. The host's hook runs first when the host uses `triggerMethod`. Calling a Behavior's own `triggerMethod` only notifies that Behavior; use `this.view.triggerMethod(...)` to emit host intent as above. That host event is forwarded back to the sending Behavior too; an `onDismiss` hook must not re-emit the same host event recursively.\n\n`initialize(options, host)` initializes the Behavior itself. The separate `onInitialize(host, options)` notification runs after the host's initialization. View lifecycle hooks such as `onRender`, `onAttach`, `onDetach`, `onBeforeDestroy`, and `onDestroy` receive the **host** and its event arguments. See the host's [View lifecycle](/docs/api/view.md#lifecycle-hooks-and-events) or [CollectionView lifecycle](/docs/api/collection-view.md#lifecycle-and-extension-points) for event-specific contracts.\n\n`modelEvents` and `collectionEvents` bind after host initialization. Handlers use the Behavior as context and preserve the source's arguments. Access sources as `this.view.model` and `this.view.collection`. `delegateEntityEvents()` releases previous entity bindings and binds the current declarations to those sources; `undelegateEntityEvents()` removes those bindings. Both return the Behavior. Repeated delegation replaces bindings. Reassigning a host model, collection, or declaration does not automatically rebind it; call `delegateEntityEvents()` afterward.\n\n`createState(options)`, `getState()`, `stateEvents`, `State`, and `Behavior.setStateApi(api)` follow the shared [state contract](/docs/api/shared/state.md). The Behavior's StateApi is independent of its host's provider. State observation does not require rendering or attachment. A host's state is not automatically the Behavior's state; pass a borrowed source deliberately when sharing it.\n\n## Destruction and nested Behaviors\n\nHost destruction invokes `destroy()` on its managed Behaviors. Behavior cleanup removes DOM handlers, state observation/owned state, host subscriptions, and host model/collection subscriptions. It releases its outgoing subscriptions; callbacks registered on the Behavior itself follow the ordinary `off`/`stopListening` ownership rules. Behavior cleanup does not destroy the host or borrowed sources.\n\nDirect `behavior.destroy()` returns the Behavior and removes it from the host's managed list. It emits **no independent `before:destroy` or `destroy` notification** and has no public `isDestroyed()` method. `onBeforeDestroy`/`onDestroy` are forwarded host notifications: a removed Behavior no longer receives them. When the host destroys a managed Behavior, its final `onDestroy(host, options)` notification arrives after Behavior resource cleanup. If a Behavior must release an extra resource on both direct and host teardown, override `destroy` and delegate to `Behavior.prototype.destroy.call(this)` as part of that cleanup. Make the extra cleanup safe to repeat, since direct Behavior destruction has no once-only guard; do not rely only on `onDestroy`.\n\nA Behavior subclass may declare nested `behaviors` using the same definitions as a host. Those instances share the original host and are owned by it. Destroying the declaring Behavior alone leaves its nested Behaviors alive. Use nesting to group host interactions, not to model a child lifetime.\n\n## TypeScript\n\nImport `BehaviorOptions`, `BehaviorHost`, `BehaviorInstance`, and `BehaviorConstructor` from `marionette`. `BehaviorInstance<Options, Host, State, Query>` describes custom options, host, state source and query collection. `BehaviorHost` is a structural host contract; View and CollectionView satisfy it. `BehaviorDefinition`, `BehaviorDefinitions`, and `BehaviorOptionsDefinition` describe host declarations. `DOMEvents`, `DOMTriggers`, `UISelectors`, and `UIBindings` describe shared maps.\n\nUse [common methods](/docs/api/shared/common.md), [events](/docs/api/shared/events.md) and [state](/docs/api/shared/state.md) for inherited contracts.\n\n\n[Canonical source](/docs/markdown/docs/api/behavior.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/api/mnobject.md",
      "title": "MnObject",
      "section": "Core classes",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/api/mnobject/",
      "markdownUrl": "https://marionettejs.com/docs/api/mnobject.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/api/mnobject.md",
      "sourceSha256": "89cfe4ac212de4ac5fd966cb427c1391749a2be623ccc9b6f16bb4c3497313bc",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "2f94f67ed1fa89ed84f9b23725e43aee4265da11622b19209523e445d86fb9f7",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89cfe4ac212de4ac5fd966cb427c1391749a2be623ccc9b6f16bb4c3497313bc; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MnObject\n\n[API index](/docs/api.md) · [Application](/docs/api/application.md) · [Shared utilities](/docs/api/shared/common.md)\n\nMnObject gives a nonvisual object Marionette's events, options, state, Radio bindings and synchronous destruction. Use it when an object needs these lifetime services. A plain function or object is enough without them; an Application is appropriate when work needs start/stop, asynchronous preparation, or owned UI.\n\n## Track draft changes\n\nThis object records whether a borrowed draft has changed since the last `markSaved()` call. It owns its tracking state and releases its draft subscription when destroyed. It does not save data or compare the draft with a server snapshot.\n\n```js\nimport { MnObject } from 'marionette';\nimport { Model, StateApi } from '@mnjs/data';\n\nconst DraftChanges = MnObject.extend({\n  createState() { return new Model({ dirty: false }); },\n  initialize({ draft }) {\n    this.listenTo(draft, { change: () => this.getState().set('dirty', true) });\n  },\n  markSaved() { this.getState().set('dirty', false); },\n}).setStateApi(StateApi);\n\nconst draft = new Model({ title: 'Untitled' });\nconst changes = new DraftChanges({ draft });\ndraft.set('title', 'Quarterly summary');\nchanges.getState().get('dirty'); // true\nchanges.markSaved();\nchanges.destroy();\n```\n\nThe draft remains available after `changes.destroy()`. Its owner disposes it when finished. `@mnjs/data` supplies observable data here; API access and persistence require a [separate solution](/docs/integrations/setup.md#observable-data-and-api-access).\n\n## Construction and options\n\n`new MnObject(options?)` merges options, assigns `cid`, configures Radio and state access, calls `initialize(options)`, then binds `stateEvents`. Radio bindings are available during initialization. State is created lazily; calling `getState()` in `initialize` is supported. There is no `preinitialize` hook.\n\n| Option | Contract |\n| --- | --- |\n| `state` | Exact borrowed source, taking precedence over the class's state source and `createState`. A function remains the source itself. |\n| `stateEvents` | Event-to-handler map or function returning one. Values are callbacks or MnObject method names. Observation begins after `initialize`. |\n| `channelName` | Radio channel name or function returning one. Falsy disables declarative Radio setup. |\n| `radioEvents`, `radioRequests` | Event/reply maps or functions returning maps, with callbacks or MnObject method names as values. See [Radio bindings](/docs/api/shared/common.md#declarative-radio-bindings). |\n\nResolver functions run with the object as `this`. Custom options remain in `options` and are available through `getOption(name)`; they do not automatically become instance properties. `modelEvents` and `collectionEvents` are not built-in MnObject declarations. Use `listenTo` or `bindEvents` to observe a separate source.\n\n`MnObject.extend(prototypeProperties?, staticProperties?)` defines a subclass. `cidPrefix` defaults to `'mno'`. `initialize` defaults to a no-op. Common constructors, custom constructor invocation, option utilities and binding helpers are documented in [class utilities](/docs/api/shared/common.md).\n\n## State and communication\n\n| Member | Contract |\n| --- | --- |\n| `createState(options)` | Override to create owned state. Receives original constructor options; defaults to a plain object. |\n| `getState()` | Returns the same owned or borrowed source for the object's lifetime. |\n| `State` | StateApi provider, not the source. |\n| `MnObject.setStateApi(api)` | Overlays the receiving class's StateApi and returns that class. Configure before construction. |\n| `getChannel()` | Returns the configured Radio channel, or `undefined`. |\n| `Radio` | Radio provider on the class/prototype; not a recognized constructor option. |\n\n[State](/docs/api/shared/state.md) defines observation and owned/borrowed disposal. [Events](/docs/api/shared/events.md) covers `on`, `once`, `off`, `trigger`, `triggerMethod`, `listenTo`, `listenToOnce`, and `stopListening`. State and declarative Radio bindings stay active throughout the live object's lifetime. MnObject has no running/stopped state.\n\nUse [declarative Radio bindings](/docs/api/shared/common.md#declarative-radio-bindings) when the object's lifetime owns channel subscriptions/replies. Destruction removes all replies on the configured channel registered with this object as context, including manual `bindRequests` calls. Replies on other channels or with another context need explicit cleanup; `stopListening` only handles event subscriptions.\n\n## Destruction and ownership\n\n`destroy(options?)` is synchronous and returns the object. `isDestroyed()` is false until destruction commits and true before `onDestroy`. Repeated or reentrant destruction returns the same object without repeating the lifecycle.\n\n| Event | Hook | Arguments and timing |\n| --- | --- | --- |\n| `before:destroy` | `onBeforeDestroy` | `(object, options)` before Radio/state cleanup, while `isDestroyed()` is false. |\n| `destroy` | `onDestroy` | `(object, options)` after marking destroyed and releasing Radio bindings and owned state. Event subscriptions are cleared afterward. |\n\nHooks run before event subscribers. Returned Promises are ignored; complete required asynchronous work before calling `destroy()`. Exceptions propagate; destruction is not transactional. A throw in `before:destroy` interrupts cleanup and leaves destruction marked in progress, so calling `destroy()` again does not retry it. Keep teardown hooks synchronous and reliable.\n\nNormal destruction releases outgoing `listenTo` subscriptions and incoming event subscriptions automatically. Other subscribers on a shared data source/channel remain intact. State produced by `createState` is disposed through the configured StateApi; supplied state is borrowed and survives.\n\nMnObject does not own arbitrary fields or constructor arguments. Assigning it to an Application field does not register it for destruction: that owner must call its `destroy()` when finished. Similarly, extra resources created by a MnObject need explicit cleanup in its lifecycle hooks. An overridden `destroy` must call the parent implementation to retain these guarantees.\n\nThere are no rendering, Region, child Application, `start`, `stop`, or `restart` methods on MnObject.\n\n## TypeScript\n\nImport the runtime constructor as `MnObject` and the instance contract as `MnObjectInstance` from `marionette`. `MnObjectInstance<Options, State>` describes custom options and the state source. `MnObjectConstructor` describes the extensible constructor; `extend` preserves declared methods and state inference. There is no exported `MnObjectOptions` alias. Channel and state provider types are linked from their shared contracts.\n\n\n[Canonical source](/docs/markdown/docs/api/mnobject.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/api/shared/common.md",
      "title": "Shared class utilities",
      "section": "Shared class contracts",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/api/shared/common/",
      "markdownUrl": "https://marionettejs.com/docs/api/shared/common.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/api/shared/common.md",
      "sourceSha256": "8982228a2345240414e35ba4f0967e95530f5966fe1254efd9a09575706d5b6a",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "bc8615336f373bcc36ab50fce29ea3edc862f9cc2df9231f741f147eed6ff2ae",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 8982228a2345240414e35ba4f0967e95530f5966fe1254efd9a09575706d5b6a; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Shared class utilities\n\nApplication, View, CollectionView, Region, Behavior, and MnObject share the class and instance utilities below. The Radio section applies specifically to Application and MnObject. See the [API index](/docs/api.md) for class-specific constructor options and lifecycle hooks.\n\n## Define a class\n\n`Parent.extend(prototypeProperties?, staticProperties?)` returns a child constructor. Prototype properties become instance methods and defaults; static properties belong to the constructor. The child inherits the parent's prototype and receives its enumerable static properties, including `extend`. Child properties override matching parent properties. Objects and arrays are shared values unless you create them per instance.\n\n```js\nimport { View } from 'marionette';\n\nconst Panel = View.extend({\n  template: false,\n  title: 'Untitled',\n  initialize() {\n    this.el.setAttribute('aria-label', this.getOption('title'));\n  }\n});\n\nconst panel = new Panel({ title: 'Settings' });\n```\n\nWithout a `constructor` property, the child forwards construction to its parent. A supplied `constructor` replaces that call: it must call `Parent.call(this, options)` or `Parent.apply(this, arguments)` when it needs the parent's initialization. Marionette's constructors support these calls. Prefer the class's initialization hooks for ordinary setup. An override does not automatically invoke the parent's method; call `Parent.prototype.method.call(this, ...)` when both are needed. `Child.__super__` also refers to `Parent.prototype`.\n\n## Options and initialization\n\nConstruction creates `this.options` by shallowly combining the class's `options` object (or the result of its `options()` function) with supplied constructor options. Supplied values take precedence. The source objects are not modified. Each class copies its recognized configuration keys onto the instance; custom options remain available through `getOption`.\n\n`initialize(...)` is a no-op extension hook called during construction with the constructor arguments, including the host View for a Behavior. It does not render a View or start an Application. Application, View, and CollectionView also expose `preinitialize(...)`; their class references describe its position in construction. Region, Behavior, and MnObject do not call a `preinitialize` hook.\n\n| Instance method | Contract and return value |\n| --- | --- |\n| `getOption(name)` | Accepts a string, number, or symbol property key. Returns `this.options[name]` when it is not `undefined`; otherwise returns `this[name]`. Preserves `false`, `0`, `''`, and `null`. Does not invoke a function-valued option. An omitted/null name returns `undefined`. |\n| `mergeOptions(options, keys)` | Copies listed own enumerable string properties from `options` onto this instance, skipping `undefined` values. Use an array of option names. Returns `undefined`; nullish options do nothing. |\n| `normalizeMethods(bindings)` | Returns a new map with each function value preserved and each method-name string resolved on this instance/prototype. Does not bind the functions or modify the input. Falsy input returns `undefined`. A missing/nonfunction handler throws `MN0019`. |\n\nDefaults and passed options are merged only one level deep. For example, supplying an `events` map replaces the inherited map rather than combining its keys. Resolve a combined map explicitly when that is your intent.\n\n## Binding helpers\n\nThese helpers accept maps from a literal event/request name to a function or an instance method-name string. They resolve names using `normalizeMethods`; [Events](/docs/api/shared/events.md) methods such as `listenTo` accept function references directly.\n\n| Instance method | Contract |\n| --- | --- |\n| `bindEvents(source, bindings)` | Registers through `this.listenTo`, with this instance as callback context. The source needs compatible `on` and `off` methods. |\n| `unbindEvents(source, bindings?)` | Removes this instance's matching subscriptions. Without bindings, removes all of its `listenTo` subscriptions to that source. Other listeners remain. |\n| `bindRequests(channel, bindings)` | Registers request replies through `channel.reply(bindings, this)`, with this instance as reply context. |\n| `unbindRequests(channel, bindings?)` | Removes matching replies owned by this instance. Without bindings, removes all of this instance's replies on that channel. Other owners' replies remain. |\n\nAll four return the receiver. A missing/falsy source or channel does nothing. A missing/falsy bindings map makes either bind method a no-op and either unbind method remove all matching bindings owned by the receiver. Event-binding helpers reject an own enumerable `__proto__` event key (`MN0026`).\n\n`bindEvents` has the lifetime tracking of `listenTo`. `bindRequests` does not add request cleanup to `stopListening`; pair manually registered replies with `unbindRequests` when their owner is finished. Application/MnObject [declarative Radio configuration](#declarative-radio-bindings) has its own lifecycle integration.\n\nSee [Events and cleanup](/docs/api/shared/events.md#cleanup) for subscription ownership and [state](/docs/api/shared/state.md) for owned versus borrowed state.\n\n## Declarative Radio bindings\n\nApplication and MnObject support `channelName`, `radioEvents`, and `radioRequests`. A channel name or binding map may be supplied by a function called with the owner as `this`. Map handlers are callbacks or owner method names. A falsy channel name disables setup.\n\n`channelName` selects a channel through the owner's `Radio` provider during construction. `getChannel()` returns it, or `undefined` when no channel was configured. `radioEvents` uses event-to-handler bindings and `radioRequests` registers request replies with the owner as callback context.\n\nOn an Application, these bindings stay active while stopped as well as running; they are not gated like its `stateEvents`. On MnObject, they stay active for its live lifetime. Destruction removes all replies on the configured channel registered with this owner as context, including manual replies, and releases its subscriptions. The shared channel and other owners' registrations remain. Replies on other channels or with another context need explicit cleanup. Reassigning the declarations later does not reinitialize them. `Radio` is a prototype/provider slot, not a recognized constructor option. Use [runtime configuration](/docs/api/runtime.md#isolation-and-composition) for isolated Radio instances. See the [Radio reference](/docs/packages/radio.md) for channel scope, events, request/reply methods, and logging. Use [binding methods](#binding-helpers) for explicit owner bindings.\n\n\n[Canonical source](/docs/markdown/docs/api/shared/common.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/api/shared/events.md",
      "title": "Events",
      "section": "Shared class contracts",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/api/shared/events/",
      "markdownUrl": "https://marionettejs.com/docs/api/shared/events.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/api/shared/events.md",
      "sourceSha256": "d32469eb9dab26b77b94615c8bc337fc360536dd3e0489e12ad1ebb086f685f0",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "228e10eb741afbbc67aeaad4a9268184950430eac2eb4101effc15182fa51823",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 d32469eb9dab26b77b94615c8bc337fc360536dd3e0489e12ad1ebb086f685f0; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Events\n\nApplication, View, CollectionView, Region, Behavior, and MnObject provide these synchronous event APIs. This page describes object events; see [View runtime](/docs/api/shared/view-bindings.md) for DOM bindings and child event forwarding, and [state](/docs/api/shared/state.md) for provider-based state observation.\n\n## Names, maps, and callback context\n\nAn event name is one literal string. Colons are a naming convention; spaces do **not** separate multiple events. Use a map to register several names. Map keys are own enumerable string properties and map values must be functions, not method-name strings. The [binding helpers](/docs/api/shared/common.md#binding-helpers) additionally accept method names.\n\n```js\nimport { View } from 'marionette';\n\nconst listener = new View({ template: false });\nconst source = new View({ template: false });\n\nlistener.listenTo(source, {\n  selected(view) { this.selectedView = view; },\n  cleared() { this.selectedView = undefined; }\n});\n\nsource.trigger('selected', source);\nsource.destroy();\nlistener.destroy();\n```\n\n`on`/`once` call ordinary functions with the supplied context, or the source as `this` when no truthy context is supplied. `listenTo`/`listenToOnce` use the listening object as context. Arrow functions retain their lexical `this`.\n\n## Subscribe and unsubscribe\n\n| Method | Contract |\n| --- | --- |\n| `on(name, callback, context?)` / `on(map, context?)` | Adds callbacks to this source. Repeated registrations add repeated calls. |\n| `once(name, callback, context?)` / `once(map, context?)` | Registers a separate one-time callback per name. Each is removed before being invoked, including if it throws or triggers the same event recursively. |\n| `off(name?, callback?, context?)` / `off(map, context?)` | Removes callbacks on this source that match all supplied filters. An omitted/null name matches every name. `off()` removes all callbacks, including other objects' subscriptions to this source. |\n| `listenTo(source, name, callback)` / `listenTo(source, map)` | Subscribes to another source and records the subscription on this listener. The source must implement compatible `on(name, callback, context)` and `off(name, callback, context)` methods. A nullish source does nothing. |\n| `listenToOnce(source, name, callback)` / `listenToOnce(source, map)` | The tracked form of `once`. Each mapped name has an independent one-time callback. |\n| `stopListening(source?, name?, callback?)` / `stopListening(source, map)` | Removes this listener's matching subscriptions. Omit the name to remove all its subscriptions to the source; omit the source to select all its sources. `stopListening()` removes every tracked subscription. |\n\nAll methods in this table return the receiver. Removing a one-time callback can use the original function reference. For selective removal, retain the same function reference used to subscribe; creating a new arrow function does not match the old one. The map forms of `on`, `once`, and `off` also accept a third explicit context argument, which takes precedence over the second when it is not `undefined`.\n\n## Trigger events and hooks\n\n| Method | Contract and return value |\n| --- | --- |\n| `trigger(name, ...args)` | Synchronously calls that event's listeners with the supplied arguments, followed by `all` listeners with `(name, ...args)`. Returns the source. |\n| `triggerMethod(name, ...args)` | Calls the matching instance/prototype hook, then triggers the event with the same arguments. Returns the hook's result, or `undefined` if no callable hook exists. |\n\n`triggerMethod('before:render', view)` calls `onBeforeRender(view)` before emitting `before:render`. Each colon-separated segment begins with a capital letter in the hook name. Hooks come from the instance/prototype, not from `options`.\n\nCalling `triggerMethod` with that same name inside its hook invokes the hook again. Forward a distinct intent, or use `trigger` when only listeners should be notified.\n\nDelivery is synchronous and follows registration order for each event. Callback return values do not cancel an event. A synchronous exception stops the dispatch and propagates to the caller. If the hook throws, `triggerMethod` does not emit the event. Returned Promises are not awaited: an asynchronous hook's result is returned while event listeners run immediately.\n\nAn `all` subscription observes event names as well as payloads. It is useful for event forwarding; ordinary feature subscriptions should name the intent they need.\n\n## Cleanup\n\nSuccessful destruction of a MnObject, View/CollectionView, Region or Application removes its outgoing `listenTo` subscriptions and its incoming callbacks after its final destruction notifications. Native listener bookkeeping is released too: a retained Application does not need a `destroy` handler that calls `stopListening(view)` for each replaced View. Native `@mnjs/data` Models and Collections also release events on destruction.\n\nApplication `stop()` preserves subscriptions to surviving sources; it is not Application destruction. Use `stopListening(source, ...)` when a subscription's useful lifetime ends before either object is destroyed. `off()` removes incoming callbacks; `stopListening()` removes outgoing subscriptions. Neither is a substitute for the other's direction.\n\nExternal sources follow their own cleanup contracts. If an external source can end while its Marionette listener survives, release the listener's subscription explicitly unless the source's integration guarantees equivalent cleanup. Emitting an event named `destroy` alone does not destroy an object or clear subscriptions.\n\n[API index](/docs/api.md) · [Shared utilities](/docs/api/shared/common.md) · [View runtime configuration](/docs/api/shared/view-bindings.md)\n\n\n[Canonical source](/docs/markdown/docs/api/shared/events.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/api/shared/state.md",
      "title": "State",
      "section": "Shared class contracts",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/api/shared/state/",
      "markdownUrl": "https://marionettejs.com/docs/api/shared/state.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/api/shared/state.md",
      "sourceSha256": "51b4ff2bee1d7b908801062778efc3d45c1873a9f3d4f454360cdd3476a20f25",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "604ad1126c34067fd167c08da4f9e809523457eb4139270152d3509f5a6f82fb",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 51b4ff2bee1d7b908801062778efc3d45c1873a9f3d4f454360cdd3476a20f25; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# State\n\nApplication, View, CollectionView, Behavior, and MnObject can own state or borrow a supplied source. Region has no state API. State is separate from a View's `model` and `collection`; it is not automatically included in template data.\n\n## Create or supply state\n\n| Member | Contract |\n| --- | --- |\n| `createState(options)` | Override to create state owned by this instance. Receives the original constructor options. The default returns a new plain object. |\n| `getState()` | Returns the same state source for the owner's lifetime. Calls `createState` lazily on first access when no state was supplied. |\n| Constructor `state` | Supplies the exact borrowed source. A non-`undefined` supplied value takes precedence over a class's `state` property and `createState`. |\n| Prototype/instance `state` | Supplies a borrowed source when no non-`undefined` constructor state is supplied. A function is treated as the source itself; use `createState` for a factory. |\n| `stateEvents` | An event-to-handler map, or function returning one. Values are functions or instance method-name strings. Can be defined on the class or passed as a constructor option. |\n\nCalling `getState()` in `initialize` is supported. Declaring `stateEvents` requests the state during construction, after `initialize`, so observable state is often created then. Rendering or restarting does not create new state.\n\n```js\nimport { View } from 'marionette';\nimport { Model, StateApi } from '@mnjs/data';\n\nconst Disclosure = View.extend({\n  template: false,\n  createState() { return new Model({ expanded: false }); },\n  stateEvents: { 'change:expanded': 'updateExpanded' },\n  initialize() { this.updateExpanded(); },\n  updateExpanded() {\n    this.el.setAttribute('aria-expanded', String(this.getState().get('expanded')));\n  }\n});\n\nDisclosure.setStateApi(StateApi);\n\nconst disclosure = new Disclosure({ tagName: 'button' });\ndisclosure.getState().set('expanded', true);\ndisclosure.destroy();\n```\n\nThis uses native data only for observable state. API access and persistence remain separate concerns; see [data setup](/docs/integrations/setup.md#observable-data-and-api-access).\n\n## Observe state\n\nThe configured StateApi subscribes to each literal event name and calls its handler with the owner as `this`. Callback arguments come from the state source unchanged. For `@mnjs/data` Model's `change:expanded`, those arguments are `(model, value, change)`, with mutation options plus `changed` and `previous` properties in `change`. Another state source can have a different event contract. The bindings are initialized once; assigning a new `state` or `stateEvents` property later does not replace them.\n\nThe default StateApi cannot observe the plain-object default state. Configure a compatible StateApi before constructing an owner with `stateEvents`; otherwise subscription throws `MN0037`. Changing a plain object's property does not synthesize an event.\n\n| Owner | When `stateEvents` deliver |\n| --- | --- |\n| View, CollectionView, Behavior, MnObject | After their state bindings initialize, until destruction releases them. View delivery does not require render or DOM attachment; detaching a View keeps its state observation. |\n| Application | Only while `isRunning()` is true, including `onStart` and preparation during an active restart. Delivery stops before root View teardown. Startup, stopped, and failed-start writes are not replayed when the Application later activates. |\n\nApplication's activity rule applies to configured `stateEvents`. An explicit `app.listenTo(state, ...)` subscription has the ordinary [Events lifetime](/docs/api/shared/events.md#cleanup) and is not automatically gated by `isRunning()`.\n\n## Ownership and disposal\n\nState returned by `createState` belongs to its owner. Destruction first releases that owner's state subscriptions, then calls the configured `State.disposeOwned(source)` when provided. The native data StateApi calls the source's `destroy()` method if it has one. A borrowed source is never disposed by the borrower; multiple Views can share it and release their subscriptions independently.\n\nApplication stop/restart retains state. View rendering retains state. Destruction is the disposal boundary; it does not dispose arbitrary fields attached to the owner. If state has never been requested, destruction does not create it. A later first `getState()` on a destroyed owner creates and immediately disposes its owned state.\n\n## Configure the StateApi\n\n`OwnerClass.setStateApi(api)` shallowly overlays that class's `State` provider and returns the class. It applies to Application, View, CollectionView, Behavior, and MnObject. A class's overlay does not mutate its parent's or sibling's provider. Configure before constructing instances. A global `setStateApi(api)` or an isolated runtime's `setStateApi(api)` configures its state-capable classes together; see [setup](/docs/integrations/setup.md#configure-once) and [View runtime configuration](/docs/api/shared/view-bindings.md).\n\nThe provider members used by an owner are `subscribe(source, name, callback, context)`, which returns an unsubscribe function, and optional `disposeOwned(source)`. The public `State` property is the configured provider, not the state source returned by `getState()`. The [provider reference](/docs/api/providers/data.md#stateapi) covers authoring; alternative integrations have their own source/disposal policies.\n\n[API index](/docs/api.md) · [View](/docs/api/view.md) · [Shared utilities](/docs/api/shared/common.md)\n\n\n[Canonical source](/docs/markdown/docs/api/shared/state.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/api/shared/view-bindings.md",
      "title": "Rendering and View bindings",
      "section": "Shared class contracts",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/api/shared/view-bindings/",
      "markdownUrl": "https://marionettejs.com/docs/api/shared/view-bindings.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/api/shared/view-bindings.md",
      "sourceSha256": "2e33651d6e04d88cc40809013f36a881247085be1b72b1f174ec21098cf37128",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "a92e7f63e6694b92b894ddd56b01e01e627810e71ebc7a3b391566dcd6667d68",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 2e33651d6e04d88cc40809013f36a881247085be1b72b1f174ec21098cf37128; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Rendering and View bindings\n\n[View](/docs/api/view.md) and [CollectionView](/docs/api/collection-view.md) share the contracts on this page. Their rendering/composition lifecycles remain class-specific. For common object methods, event subscriptions, and state ownership, see [common](/docs/api/shared/common.md), [events](/docs/api/shared/events.md), and [state](/docs/api/shared/state.md).\n\n## Templates and data\n\n`template` is a value understood by the renderer. The default renderer calls a template function as `template(data)`; it does not compile template strings. `template: false` disables template rendering. The default DOM provider inserts renderer output as HTML; choose a renderer/DOM integration appropriate to the output. [Setup](/docs/integrations/setup.md#configure-once) shows the Lit integration, whose ordinary interpolations render values as text.\n\n| Method | Default contract and extension use |\n| --- | --- |\n| `getTemplate()` | Returns `this.template`. Override to choose a template for the current View. |\n| `serializeData()` | Serializes `model` if present; otherwise returns `{ models: serializeCollection() }` for a collection, or `undefined`. Override to supply a different template data shape. |\n| `serializeModel()` | Returns `this.Data.serialize(this.model)`. |\n| `serializeCollection()` | Returns `this.Data.models(this.collection).map(model => this.Data.serialize(model))`. |\n| `mixinTemplateContext(data)` | Resolves `templateContext`, then shallow-merges its own enumerable properties over data. Does not mutate either input. Returns either input directly when the other is falsy. |\n| `attachElContent(output)` | Sends renderer output to `this.Dom.setContents(this.el, output)`. Override for a specialized insertion strategy that keeps the View's root. Returns no defined value. |\n\nRendering obtains the template, prepares serialized data plus template context, calls the configured renderer with the View as `this`, and passes its return value to `attachElContent`. Falsy final template data becomes `{}`. The default template function itself receives no View context; use `templateContext` or serialization for View-derived values.\n\nThis standalone example configures a subclass with Lit, renders plain supplied data, and cleans up:\n\n```js\nimport { View } from 'marionette';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\n\nconst Greeting = View.extend({\n  template: ({ name }) => html`<p>Hello, ${name}</p>`,\n});\nGreeting.setDomApi(LitDomApi);\n\nconst greeting = new Greeting({ model: { name: 'Sam' } });\ngreeting.render();\ngreeting.destroy();\n```\n\nThis uses the default DataApi, which serializes plain values unchanged. Observable Models/Collections need their [DataApi configuration](/docs/integrations/setup.md#configure-once). Data changes do not automatically render a View; select the events and response explicitly.\n\n## Root attributes\n\n`renderAttributes()` reevaluates `attributes`, `id`, and `className`, applies them to `el`, and returns the View. It does not render a template, rebuild children, rebind UI, or emit render events. It does nothing while destroying or destroyed.\n\nWhen creating a root, Marionette applies these declarations once. A supplied root is untouched until an explicit `renderAttributes()`. The native DomApi removes attributes whose value is `null`, leaves `undefined` and omitted keys unchanged, and stringifies other values. `id` and `className` override the corresponding entries in `attributes` when declared. Calling `render()` does not refresh these root declarations.\n\n## UI bindings\n\nDeclare `ui` as `{ name: 'selector' }` or a function returning that map. After binding, `ui` contains query results; Marionette retains the selectors for rebinding. Use `@ui.name` in DOM event/trigger keys and View Region selectors to reuse them.\n\n| Method | Contract |\n| --- | --- |\n| `$(selector)` | Queries descendants of `el`; the root itself is excluded by the native DomApi. Returns the provider's query type (native: static `NodeList`). |\n| `getUI(name)` | Returns the bound query result or `undefined` for an unknown name. Throws if no UI map was declared or it has not been bound. Use `[0]` when the first native element is needed. |\n| `bindUIElements()` → `this` | Resolves the UI map and queries the current DOM, including Behavior UI. Normally automatic after rendering or construction with existing contents. No-op while destroying/destroyed. |\n| `unbindUIElements()` → `this` | Releases query bindings and restores the selector declarations, including Behavior UI. Destruction does this automatically. |\n| `normalizeUIString(value, bindings?)` | Returns a string with `@ui.name` references replaced by selectors. |\n| `normalizeUIKeys(map, bindings?)` | Returns a new map with normalized keys; nullish input returns `{}`. |\n| `normalizeUIValues(map, property?, bindings?)` | Normalizes string values or a named property of object values **in place** and returns the same map. |\n\nNormalization uses the View's original selector map unless an explicit map is provided. An empty or undeclared `@ui` name throws. Bound queries are snapshots; manually changed contents need rebinding before querying through `getUI` again.\n\n## DOM events\n\n`events` maps `'event selector'` to a callback or View method name. For example, `events: { 'click .save': 'save' }` calls the View's `save` handler for a delegated click. Omit the selector to listen on the root. Callbacks run with the View as `this` and receive the DOM event.\n\nWith the native delegator, `event.currentTarget` is the View's root element. `event.delegateTarget` is the nearest matching descendant on the event path: use it to read the control matched by the selector, even when a click originated inside that control. The root is not a selector match. `focus` and `blur` use capture.\n\n`triggers` maps the same DOM keys to a View event name or `{ event, preventDefault, stopPropagation }`. A trigger calls `view.triggerMethod(eventName, view, domEvent, ...extraArguments)`. Both prevention flags default to `true`; set either to `false` to allow that browser behavior. `events` handlers do not receive these automatic prevention calls.\n\nBoth maps may be functions evaluated on the View. `@ui` selectors are resolved before delegation. A missing named handler is an error.\n\n| Method | Contract |\n| --- | --- |\n| `delegateEvents(events?)` → `this` | Removes existing View/Behavior DOM handlers, refreshes child event maps, then binds the explicit event map or current `events`, plus current `triggers` and Behavior DOM handlers. Use after changing declarations. |\n| `undelegateEvents()` → `this` | Releases View and Behavior DOM handlers. |\n\nBoth methods are no-ops while destroying/destroyed. Construction delegates automatically; destruction releases handlers automatically. Detaching a live View preserves its DOM bindings. Rendering does not reread changed event declarations.\n\n## Data bindings\n\n`modelEvents` and `collectionEvents` map source event names to callback functions or View method names; either map may be returned from a function. Bindings use the configured `Data.subscribe`, preserve source arguments, and invoke callbacks with the View as `this`. A plain object/array can supply template data, but the default DataApi requires an `on`/`off` source when an event map is present. Use the appropriate adapter for observable data.\n\n`delegateEntityEvents()` releases previous model/collection bindings, then binds current declarations, including Behaviors, and returns the View. `undelegateEntityEvents()` releases those subscriptions and returns the View. Construction binds them after `initialize`; destruction releases them.\n\nReplacing a View's model or collection after construction does not change its existing subscriptions. Assign the new source or event map, then call `delegateEntityEvents()` to release the old bindings and observe the current declarations. Repeated delegation replaces bindings rather than accumulating them. Use `undelegateEntityEvents()` when observation should stop without rebinding. Render explicitly if the new source should be displayed immediately.\n\nObservable model changes do not automatically update the View's rendered contents. Choose the response in `modelEvents` or `collectionEvents`: for a small View, `modelEvents: { change: 'render' }` rerenders on change. On a layout View, that also resets its Regions and destroys their children; see [View rendering](/docs/api/view.md#rendering-and-status).\n\nThese bindings do not own or destroy the model/collection. State bindings have separate ownership and delivery rules: see [state](/docs/api/shared/state.md).\n\n## Child events\n\nThe owning View/CollectionView can handle events from its immediate managed children:\n\n| Declaration | Behavior |\n| --- | --- |\n| `childViewEvents: { eventName: handler }` | Calls a parent method name or callback with the parent as `this` and the child's original event arguments. |\n| `childViewTriggers: { eventName: parentEvent }` | Calls `parent.triggerMethod(parentEvent, ...originalArguments)`. |\n| `childViewEventPrefix: 'child'` | Forwards every child event as `child:eventName` through `triggerMethod`. Defaults to `false`; set `false` to disable prefix forwarding. |\n\nEach declaration may be a function evaluated on the parent. When all apply, the order is the mapped handler, mapped parent event, then prefixed event. No child argument is added: a DOM `triggers` event already supplies its View, while `child.trigger('selected', id)` supplies only `id`. Define explicit mappings at each level when forwarding through nested composition.\n\nThe maps are prepared during construction and refreshed by `delegateEvents()`. Region/CollectionView ownership establishes forwarding and releases it when the child leaves. See [subscription cleanup](/docs/api/shared/events.md#cleanup) for native destruction and listener ownership.\n\n## Behavior composition\n\n`behaviors` accepts an array or named object containing Behavior constructors or `{ behaviorClass: BehaviorClass, ...options }` entries. A function can return either shape. Names organize the definitions; the View does not expose a public lookup-by-name API. Nested Behavior definitions are composed onto the same host.\n\nMarionette constructs each Behavior with `(options, view)`. Behaviors share the host's fixed element and data sources; their DOM events, triggers, UI and entity bindings join the host's lifecycle. Host UI selectors override Behavior selectors with the same name. Behavior DOM triggers emit on the host. Host events are forwarded through each Behavior's `triggerMethod`, including an initialization notification after the host is initialized. Host destruction releases Behaviors and their owned state; it delivers the host's destroy notification to them.\n\nThis defines the View's accepted composition option. The [Behavior reference](/docs/api/behavior.md) covers its own APIs, forwarded hooks, and direct versus host destruction.\n\n## Class configuration\n\nConfigure a subclass before creating its instances. Each setter returns that class and changes its prototype configuration. Descendants inherit configuration unless they override it; changing a subclass does not modify the parent class.\n\n| Static method | Effect |\n| --- | --- |\n| `setRenderer(renderer)` | Replaces `_renderHtml` with a function `(template, data) → output`, invoked with the View as `this`. Pass a usable renderer; omitting it assigns `undefined` and does not restore the default. |\n| `setDomApi(mixin)` | Shallow-merges methods over the class's existing `Dom` provider, preserving unspecified methods. Controls root creation, queries, attributes, content insertion, and DOM attachment operations. |\n| `setDataApi(mixin)` | Shallow-merges methods over `Data`. A View uses `serialize`, `models`, and `subscribe`; CollectionView also uses collection identity/observation operations. |\n| `setStateApi(mixin)` | Shallow-merges methods over `State`. See [state configuration](/docs/api/shared/state.md). |\n| `setEventDelegator(delegator)` | Replaces `EventDelegator`. Its `delegate({ eventName, selector, handler, rootEl })` must return the cleanup function used when undelegating/destroying. |\n\n`Dom`, `Data`, `State`, `EventDelegator`, and `_renderHtml` are the instance-visible configuration slots. Prefer setters for class configuration; `Dom`, `Data`, `State`, `EventDelegator`, `_renderHtml`, and `monitorViewEvents` are not recognized constructor options. `_renderHtml` is the renderer extension slot despite its underscore; `attachElContent` is the insertion extension point.\n\nThe [setup recipe](/docs/integrations/setup.md#configure-once) uses top-level setters to configure all relevant default classes together. See [runtime configuration](/docs/api/runtime.md) for isolated families and setter scope, [rendering/DOM providers](/docs/api/providers/dom.md) for authoring interfaces, and [data/state providers](/docs/api/providers/data.md) for observation and disposal.\n\n## Types\n\nImport these types from `marionette`:\n\n- `DOMEvents`: event-key map to callbacks or method names. `DOMTriggers`: event-key map to `TriggerDefinition`; `TriggerOptions` describes object triggers.\n- `UISelectors`: string selector map. `UIBindings`: that map or a function returning it. Query results follow `ViewInstance`'s `Query` type.\n- `Bindings`: source event map used by model, collection, and state bindings.\n- `BehaviorDefinition`, `BehaviorDefinitions`, `BehaviorOptionsDefinition`: the constructor/options entry, collection of entries, and object-entry shape.\n- `Renderer<Receiver, Template, Data, Output>`: renderer signature. `DomApiContract`, `DataApiContract`, `StateApiContract`: provider interfaces; setters accept partial overlays for these three APIs.\n- `EventDelegator`, `DelegateOptions`, `DelegatedEvent`: the DOM delegation provider, registration arguments, and native event with optional `delegateTarget`.\n\nThese types expose configuration and integration boundaries. The complete interfaces are in [rendering/DOM providers](/docs/api/providers/dom.md) and [data/state providers](/docs/api/providers/data.md).\n\n\n[Canonical source](/docs/markdown/docs/api/shared/view-bindings.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/api/errors.md",
      "title": "Errors and diagnostics",
      "section": "Shared class contracts",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/api/errors/",
      "markdownUrl": "https://marionettejs.com/docs/api/errors.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/api/errors.md",
      "sourceSha256": "f4efcdd5da9dcf053b936fab32d6e200f8223f799e2517dee7753823b89946b2",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "505ae9a0a118e9a06e6ad57a84df138a2cba860f05d4efa5dbf18350bf712daf",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 f4efcdd5da9dcf053b936fab32d6e200f8223f799e2517dee7753823b89946b2; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Errors and diagnostics\n\nMarionette reports invalid framework configuration with `MarionetteError`. Inspect the error's `code` to identify the contract, then read the matching diagnostic from the installed version. Application failures, such as a rejected API request, can remain ordinary errors handled by the application that owns that work.\n\n## MarionetteError\n\nImport `MarionetteError` from `marionette` or `@mnjs/utils`; within the same module format they export the same constructor. Use `new MarionetteError(options)`. Each call creates a native `Error` instance with a stack; `instanceof Error` and `instanceof MarionetteError` both work. Calling it as a plain function is unsupported.\n\n```js\nimport { MarionetteError } from 'marionette';\n\nconst error = new MarionetteError({\n  code: 'MN0019',\n  message: 'The configured handler must resolve to a function.'\n});\nconst diagnosticCode = error.code;\nconst description = error.toString();\n```\n\nThe example constructs an error for inspection. Framework operations create their own errors; do not use Marionette's `MN` codes for unrelated application failures.\n\n| Field or method | Contract |\n| --- | --- |\n| `message`, `name` | Supplied values override native Error values. With no supplied name, the inherited name is `Error`. |\n| `code` | A string code selects `https://marionettejs.com/errors/<encoded-code>/`, overriding an explicitly supplied `url`. |\n| `url` | Without a string code, the supplied suffix (default `''`) is appended to `urlRoot`, whose default is `https://marionettejs.com/docs/`. |\n| `description`, `fileName`, `lineNumber`, `number` | Optional metadata copied from the options object. |\n| `toString()` | Returns `name: message See: url`. |\n| `captureStackTrace(fallbackError)` | Captures a native stack when supported; otherwise copies `fallbackError.stack`. Construction already calls it. |\n\nOnly the listed metadata fields (`code`, `description`, `fileName`, `lineNumber`, `name`, `message`, `number`, `url`) are copied from options. They become ordinary own fields; other option fields are ignored. Values are preserved rather than validated or coerced. Construction and formatting are synchronous, with no ownership or cleanup lifecycle. Extend the constructor with native `class extends` when a distinct application error type is useful.\n\n## Find a diagnostic\n\nUse the package's [local documentation helper](/docs/agents.md#local-contract-lookup) from the application's directory. Replace `<skill>` with the installed or copied `skills/marionette` directory:\n\n```sh\nnode <skill>/scripts/docs.mjs --diagnostic MN0019\n```\n\nThe result includes the installed version, code status, affected objects, remediation, diagnostic URL, and `docsSection`. Read that section with `--section` to stay inside the installed documentation. Retired codes remain discoverable, but are no longer emitted by that release. Follow the installed contract before changing code: the website can describe a different release. Unknown codes are not evidence of a framework bug; first check which package/version produced the error.\n\nDiagnostics identify invalid inputs and configuration. They do not replace application error handling, and they do not catch every possible misuse. Synchronous callback exceptions propagate through dispatch. An Application's asynchronous preparation rejection is part of its [start lifecycle](/docs/api/application.md); handle failure at the owning workflow boundary.\n\n<!-- diagnostics:start -->\n\n## MN0001\n\nview-el-must-be-dom-element. Status: **retired**. Applies to CollectionView, View.\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n## MN0002\n\nregion-el-type-invalid. Status: **retired**. Applies to Region.\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n## MN0003\n\nview-already-owned. Status: **active**. Applies to Application, CollectionView, Region, View.\n\nUse the owning Application to display its prepared root. Detach a displayed view from its Region or CollectionView before adopting it elsewhere, or create a new view instance.\n\n## MN0004\n\nregion-el-required. Status: **active**. Applies to Region.\n\nConfigure the Region with an el selector or DOM element before using it.\n\n## MN0005\n\nregion-el-not-found. Status: **active**. Applies to Region.\n\nRender the parent View before direct selector-backed Region operations, ensure the selector resolves within its parent element, or explicitly allow a missing element where supported.\n\n## MN0006\n\nregion-view-required. Status: **retired**. Applies to Region.\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n## MN0007\n\nregion-view-destroyed. Status: **active**. Applies to Application, Region, View.\n\nCreate a new View instance instead of attempting to show a destroyed view.\n\n## MN0008\n\nregion-definition-invalid. Status: **retired**. Applies to Application, Region, View.\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n## MN0009\n\nevent-bindings-invalid. Status: **retired**. Applies to Application, Behavior, CollectionView, MnObject, Region, View.\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n## MN0010\n\nrequest-bindings-invalid. Status: **retired**. Applies to Application, Behavior, CollectionView, MnObject, Region, View.\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n## MN0011\n\ncollection-view-child-view-required. Status: **active**. Applies to CollectionView.\n\nConfigure childView with a View class or a function that returns a View class.\n\n## MN0012\n\ncollection-view-child-view-invalid. Status: **retired**. Applies to CollectionView.\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n## MN0013\n\ncollection-view-container-not-found. Status: **active**. Applies to CollectionView.\n\nEnsure childViewContainer resolves to an element within the rendered CollectionView.\n\n## MN0014\n\ncollection-view-filter-invalid. Status: **retired**. Applies to CollectionView.\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n## MN0015\n\ncollection-view-swap-non-children. Status: **active**. Applies to CollectionView.\n\nPass two views currently owned by the CollectionView to swapChildViews.\n\n## MN0016\n\nbehavior-definition-invalid. Status: **retired**. Applies to Behavior, CollectionView, View.\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n## MN0017\n\nradio-channel-name-required. Status: **active**. Applies to Radio.\n\nPass a non-empty channel name when creating or accessing a Radio channel.\n\n## MN0018\n\nui-reference-invalid. Status: **active**. Applies to Behavior, CollectionView, View.\n\nUse @ui.<name> with a non-empty own key whose value is a string selector, or replace the reference with a literal selector.\n\n## MN0019\n\nhandler-not-callable. Status: **active**. Applies to Application, Behavior, CollectionView, MnObject, Region, View.\n\nProvide a function or the string name of a callable method on the binding context.\n\n## MN0020\n\nnamed-region-not-found. Status: **active**. Applies to View.\n\nDefine the named Region before using child-View or Region-removal operations, or use getRegion or hasRegion for optional lookup.\n\n## MN0021\n\nradio-channel-not-found. Status: **active**. Applies to Radio.\n\nCreate the named channel with Radio.channel(name) before resetting it, or call Radio.reset() with no arguments to reset all existing channels.\n\n## MN0022\n\ncollection-view-empty-view-invalid. Status: **retired**. Applies to CollectionView.\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n## MN0023\n\nui-elements-unavailable. Status: **active**. Applies to Behavior, CollectionView, View.\n\nDeclare a ui map, then render the View or explicitly bind its UI elements before calling getUI; bind them again before calling getUI after unbinding.\n\n## MN0024\n\nchild-container-argument-invalid. Status: **active**. Applies to CollectionView.\n\nPass nonnegative integer counts. Reducing an empty child container requires an initial value.\n\n## MN0025\n\nchild-container-method-not-callable. Status: **retired**. Applies to CollectionView.\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n## MN0026\n\nentity-event-name-unsafe. Status: **active**. Applies to Application, Behavior, CollectionView, MnObject, Region, View.\n\nRename an own __proto__ entry in an entity-event map before binding or selectively unbinding it.\n\n## MN0027\n\nfeature-name-invalid. Status: **retired**. Applies to Behavior, CollectionView, View.\n\nThe v5 feature registry is removed. Configure child event prefixes per View, trigger behavior per trigger, and application values through State or explicit configuration.\n\n## MN0028\n\nregion-destroyed-operation. Status: **retired**. Applies to Region.\n\nCalls to show, empty, or reset after Region destruction are lifecycle-safe no-ops. Use a live Region when the operation must take effect.\n\n## MN0029\n\nview-destroyed-set-element. Status: **retired**. Applies to CollectionView, View.\n\nCalls to setElement after View or CollectionView destruction begins are lifecycle-safe no-ops. Use a live instance when element replacement must take effect.\n\n## MN0030\n\nregion-registration-conflict. Status: **active**. Applies to Region, View.\n\nRegister a live, unowned Region under an unused name; remove an existing named Region before replacing it and use a fresh Region instance for a different owner.\n\n## MN0031\n\napplication-registration-conflict. Status: **active**. Applies to Application.\n\nRegister a live, unowned Application instance under an unused non-empty string name; use hasChildApp before constructing a dynamic child when allocation must be avoided.\n\n## MN0032\n\nregion-name-invalid. Status: **active**. Applies to View.\n\nPass a non-empty string name to a named Region operation.\n\n## MN0033\n\nmerge-options-keys-invalid. Status: **retired**. Applies to Application, Behavior, CollectionView, MnObject, Region, View.\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n## MN0034\n\nstate-key-invalid. Status: **retired**. Applies to StateApi.\n\nThe concrete v5 alpha State key validation is removed. Use the selected source's native key contract.\n\n## MN0035\n\nstate-ownership-conflict. Status: **retired**. Applies to Behavior, CollectionView, MnObject, View.\n\nThe concrete v5 alpha State ownership rule is removed. Supplied sources are borrowed and may be shared by multiple owners; createState results are owned and disposed by their owner.\n\n## MN0036\n\nevent-delegator-contract-invalid. Status: **retired**. Applies to Behavior, CollectionView, View.\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n## MN0037\n\nadapter-observation-unsupported. Status: **active**. Applies to Application, Behavior, CollectionView, MnObject, View.\n\nConfigure a StateApi or DataApi that can observe the selected source, or remove the declarative event map.\n\n## MN0038\n\nadapter-cleanup-invalid. Status: **retired**. Applies to Application, Behavior, CollectionView, MnObject, View.\n\nDataApi and StateApi adapters must return cleanup functions. Core no longer wraps or validates cleanup on each registration.\n\n## MN0039\n\ncollection-data-contract-invalid. Status: **active**. Applies to CollectionView.\n\nReturn an ordered array with unique stable keys and emit a valid reorder, reset, or update structural record.\n\n## MN0040\n\nprivate-framework-member-access. Status: **active**. Applies to Application, Behavior, CollectionView, MnObject, Region, View.\n\nUse the documented public Marionette API instead of reading or calling this private framework member.\n\n<!-- diagnostics:end -->\n\n\n[Canonical source](/docs/markdown/docs/api/errors.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/api/runtime.md",
      "title": "Runtime configuration",
      "section": "Runtime configuration",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/api/runtime/",
      "markdownUrl": "https://marionettejs.com/docs/api/runtime.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/api/runtime.md",
      "sourceSha256": "b82fc651c2ae6c076b7b8600310ba7e908d699f9bb2a817851be6b22fc8c2e6f",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "1b655ba7127c2dabbe9cc91618e0ede13589f03a6c5fafc686c07f36c6d39025",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 b82fc651c2ae6c076b7b8600310ba7e908d699f9bb2a817851be6b22fc8c2e6f; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Runtime configuration\n\n[API index](/docs/api.md) · [Rendering and DOM providers](/docs/api/providers/dom.md) · [Data and state providers](/docs/api/providers/data.md)\n\nA Marionette runtime is a family of classes with shared configuration choices and a Radio instance. The named imports from `marionette` use the default family. Configure that family once for an ordinary application; use `createMarionette()` when independently configured parts or tests must coexist. An [Application](/docs/api/application.md) manages a feature lifetime within either family.\n\n## Configure the default runtime\n\nImport the named setters in your application's setup module, before constructing Views. For example, install the Lit DOM adapter once:\n\n```js\nimport { View, setDomApi } from 'marionette';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\n\nsetDomApi(LitDomApi);\n\nconst Heading = View.extend({\n  template: () => html`<h1>Overview</h1>`,\n});\nconst heading = new Heading().render();\n```\n\nThe default renderer already calls the template function with its data. Configure a different renderer only when the template engine needs one. The [quick start](/docs/quick-start.md) mounts a View in the page; [setup](/docs/integrations/setup.md) adds observable data when needed.\n\n## Configure an isolated runtime\n\n`createMarionette()` takes no arguments and returns a new runtime. Configure it, then define classes from its constructors. Imports of adapters alone do not install them.\n\n```ts\nimport { createMarionette } from 'marionette';\nimport { Model, DataApi } from '@mnjs/data';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\n\nconst runtime = createMarionette();\nruntime.setDataApi(DataApi);\nruntime.setDomApi(LitDomApi);\n\nconst Heading = runtime.View.extend({\n  template: ({ title }: { title: string }) => html`<h1>${title}</h1>`,\n  modelEvents: { 'change:title': 'render' },\n});\n\nconst title = new Model({ title: 'Overview' });\nconst heading = new Heading({ model: title });\nheading.render();\ntitle.set('title', 'Updated overview');\n```\n\nThe default renderer evaluates the function; Lit inserts its result. DataApi supplies the Model's attributes and subscriptions. Configure StateApi separately if an owner's `stateEvents` or owned-state disposal needs it. The View borrows the Model; its owner manages the Model's lifetime. See [observable data and API access](/docs/integrations/setup.md#observable-data-and-api-access) for the boundary between observation and persistence.\n\n## Choose a configuration scope\n\n| Scope | Effect and return value |\n| --- | --- |\n| Named `setDomApi`, `setDataApi`, `setStateApi`, `setRenderer`, `setEventDelegator` imports | Configure the affected default classes. Return `undefined`. |\n| The same methods on a `createMarionette()` result | Configure only the affected classes in that runtime. Return `undefined`. |\n| `SomeClass.set…(...)` | Configure the receiving class's prototype. Return that class for chaining. Descendants inherit unless they have their own override. |\n\n| Setter | Classes configured by a top-level/runtime call | Operation |\n| --- | --- | --- |\n| `setDomApi(mixin)` | View, CollectionView, Region | Shallow overlay on each class's `Dom`. |\n| `setDataApi(mixin)` | View, CollectionView | Shallow overlay on each class's `Data`. |\n| `setStateApi(mixin)` | Application, Behavior, View, CollectionView, MnObject | Shallow overlay on each class's `State`. |\n| `setRenderer(renderer)` | View, CollectionView | Replace the renderer function. |\n| `setEventDelegator(provider)` | View, CollectionView, Behavior | Replace the DOM delegation provider. |\n\nOnly the classes listed in each row provide that static setter. Configure before constructing consumers. Setters change prototype configuration, not an instance's already-created element, cached data, or installed subscriptions. They do not rebuild existing instances. A live instance that inherits the slot can use the new provider on its next operation while retaining earlier subscriptions or renderer-owned contents. This can mix incompatible configurations; configuration is not a live migration API. A parent setter can affect subclasses still inheriting that slot; a subclass overlay creates its own provider object and no longer inherits later parent changes to that slot. Configure both a CollectionView and its child View classes when both consume an integration.\n\nOverlays preserve unspecified methods, with the last supplied value winning. They are shallow: nested values and function closures are shared. Explicit `undefined` can remove a required method; an empty overlay does not restore defaults. `setRenderer()` assigns `undefined`, also not a reset. Supply valid providers; setters do not certify runtime compatibility.\n\n## Defaults and exports\n\n| Runtime member | Default and reference |\n| --- | --- |\n| `Application`, `Behavior`, `CollectionView`, `MnObject`, `Region`, `View` | Constructors in this family. See the [class index](/docs/api.md#core-classes). |\n| `DomApi` | Native DOM operations, static descendant queries and HTML-string insertion. [DOM contract](/docs/api/providers/dom.md#domapi). |\n| `DataApi` | Plain values for rendering and static arrays for collection membership; compatible `on`/`off` sources for explicit entity events. [Data contract](/docs/api/providers/data.md#dataapi). |\n| `StateApi` | No observable-state support or owned disposal by default. `subscribe` throws `MN0037`. [State contract](/docs/api/providers/data.md#stateapi). |\n| `Radio` | Default exported Radio for the default family; a new Radio instance for each isolated runtime. [Owner bindings](/docs/api/shared/common.md#declarative-radio-bindings). |\n| `VERSION` | The package version string, also available as a named import. |\n| `Events`, `extend`, `MarionetteError`, `monitorViewEvents` | Shared utilities, not newly isolated copies. [Events](/docs/api/shared/events.md), [extension](/docs/api/shared/common.md#define-a-class), and [View lifecycle monitoring](/docs/api/view.md#lifecycle-hooks-and-events) describe the relevant contracts; the [utilities reference](/docs/packages/utils.md) and [errors reference](/docs/api/errors.md) cover the standalone exports. |\n\n`createMarionette` is a named export of `marionette`. The package has no default export, and a created runtime does not itself have a `createMarionette` method. `EventDelegator` and `Renderer` are type exports, not provider values. Configure those behaviors through their setters.\n\n`DataApi`, `DomApi`, and `StateApi` expose the initial provider objects. Setters replace class slots with overlays; they do not update these exported objects into a registry of the active configuration. Inspect a class's `prototype.Data`, `prototype.Dom`, or `prototype.State` when needed. Prefer setters over direct mutation.\n\n## Isolation and composition\n\nEach `createMarionette()` starts from copied native defaults, even after configuring the default family. It has separate constructors, provider objects and Radio channels. Changing one family's configured slots or resetting its Radio does not reset another family's configuration/channels. Native Regions created by its Views and Applications, and the CollectionView empty Region, use its own Region class.\n\nUse the appropriate family's constructors for composition:\n\n- A View/Application Region definition cannot borrow a Region or Region class from another runtime (`MN0030`).\n- Application child registration requires a child from the same runtime (`MN0031`); a start destination must be a Region from the same runtime (`MN0030`).\n- `Region.show(view)` supports a View from another runtime through its supported View lifecycle. It does not convert the View's renderer/data providers or move the Region into that other runtime.\n\nThis is configuration isolation. Classes inherit from the library's base classes, utilities and the document remain shared, and providers may close over shared resources. It is not a security boundary or a deep clone of application data. There is no runtime-wide destroy/reset method; destroy the Applications, Regions, Views and other owners you create.\n\n## TypeScript\n\nUse `ReturnType<typeof createMarionette>` for the returned runtime type; there is no named public Runtime type. Runtime methods expose the same class/provider contracts as named imports. Types are structural, so they do not brand objects by runtime; ownership checks still run at runtime.\n\nProvider registration accepts concrete source/output types through an intentionally opaque class slot. It does not prove that every model, template, DOM result, child class or supplied state matches that provider. Keep the concrete adapter typed, configure a coherent class family, and test its consumers. See [DOM types](/docs/api/providers/dom.md#typescript) and [data types](/docs/api/providers/data.md#typescript).\n\n\n[Canonical source](/docs/markdown/docs/api/runtime.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/api/providers/dom.md",
      "title": "Rendering and DOM providers",
      "section": "Provider interfaces",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/api/providers/dom/",
      "markdownUrl": "https://marionettejs.com/docs/api/providers/dom.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/api/providers/dom.md",
      "sourceSha256": "7445ee9633d751c9220c9c725040383632f56d06f946f9a60181023ce42a3b8c",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "f2e20c19076728f35ff798faac59414dcffdd2ea0740224082a3c749a5665496",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 7445ee9633d751c9220c9c725040383632f56d06f946f9a60181023ce42a3b8c; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Rendering and DOM providers\n\n[API index](/docs/api.md) · [Runtime configuration](/docs/api/runtime.md) · [View rendering](/docs/api/shared/view-bindings.md#templates-and-data)\n\nChoose an existing integration when it fits. A renderer evaluates a template; DomApi applies the output and performs DOM operations; EventDelegator installs DOM listeners. These independent boundaries let a View keep its lifecycle and ownership rules while changing its integration.\n\n## Renderer\n\n`setRenderer(renderer)` accepts a synchronous function `(template, data) → output`, invoked with the View as `this`. The default calls `template(data)` without binding the template function to the View. It does not compile strings. `template: false` skips template rendering.\n\nMarionette serializes data and applies template context before calling the renderer; a falsy final data value becomes `{}`. It passes every return value to `attachElContent`, whose default calls `Dom.setContents(el, output)`. A Promise is not awaited, and `undefined` does not mean “skip insertion.” If a renderer performs insertion itself, override `attachElContent` to match that strategy and keep the View's fixed root. Usually, putting insertion in DomApi keeps the responsibilities simpler.\n\nThe native `setContents` treats strings as HTML. Choose an integration such as [Lit](/docs/integrations/setup.md#configure-once) for templated UI with ordinary text interpolation. This small text-only class demonstrates a typed DomApi overlay without building a new template engine:\n\n```ts\nimport { View, type DomApiContract } from 'marionette';\n\nconst TextDom = {\n  setContents(el: Element, value: string) {\n    el.textContent = value;\n  },\n} satisfies Partial<DomApiContract<ArrayLike<Element>, string>>;\n\nconst Label = View.extend({\n  template: ({ label }: { label: string }) => label,\n}).setDomApi(TextDom);\n\nconst label = new Label({ model: { label: '<Draft>' } });\nlabel.render();\n```\n\nOnly content insertion changes; native root creation, queries and placement remain inherited. This class displays literal text, not HTML templates. The [scope rules](/docs/api/runtime.md#choose-a-configuration-scope) explain when to configure a class or a whole family.\n\n## DomApi\n\n`setDomApi(mixin)` overlays methods on `Dom`. Methods are called on that provider object. Implement only the operations being replaced, while keeping their inputs/outputs compatible with the remaining methods. Publicly import the default value as `DomApi`; import the interface as `DomApiContract`.\n\n| Method | Required behavior and native default |\n| --- | --- |\n| `createElement(tagName) → Element` | Create a root element. Native uses `document.createElement`. |\n| `createBuffer() → DocumentFragment` | Create a buffer for batch child insertion. |\n| `getDocumentEl(el) → Element \\| null` | Return the document root used for attachment checks. Native uses `el.ownerDocument.documentElement`. |\n| `findEl(el, selector) → Query` | Return an array-like collection of matching descendants. Native returns a static `NodeList`; excludes the root. |\n| `hasEl(el, childEl) → boolean` | Test strict containment. Native checks the child's parent, so an element does not contain itself for this operation. Nullish child returns false. |\n| `detachEl(el)` | Remove the element from its parent while preserving the element and listeners for possible reuse. |\n| `replaceEl(newEl, oldEl)` | Replace the old element in its parent. Native does nothing for identical elements or a parentless old element. |\n| `setContents(el, output)` | Apply renderer output within the root. Native uses `innerHTML`, with nullish output clearing contents. Match this method to the renderer's output. |\n| `setAttributes(el, attributes)` | Apply attributes. Native uses own enumerable keys, removes `null` values, ignores `undefined`, and stringifies other values. Unmentioned attributes remain. |\n| `appendContents(el, contents)` | Native default: append an Element/DocumentFragment to the parent Element/DocumentFragment. The jQuery adapter also accepts HTML strings, element arrays and jQuery collections. |\n| `moveEl(el, parent, before?)` | Insert or move the element before the reference node; append when omitted/null. Native uses `moveBefore` for an existing child of that parent when available, otherwise `insertBefore`. |\n| `hasContents(el) → boolean` | Report child-node presence. Native returns false for a nullish element. |\n| `detachContents(el)` | Remove contents while retaining the root. Native clears `textContent`. This operation does not establish View destruction by itself. |\n| `notifyAttach(el)` | Notify content integration that the View's element has attached. Native does nothing. |\n| `notifyDetach(el)` | Notify content integration that the View's element has detached. Native does nothing. |\n\nMarionette owns View/Region lifecycle and child cleanup around these operations. Providers must preserve the root identity and must not destroy unrelated Views or borrowed sources. Preserve renderer markers when moving child elements; a provider must support the actual content it created. The Lit adapter implements content insertion and attachment notifications so its directive connection state follows View attachment.\n\nAttachment notifications follow monitored Marionette lifecycle, including construction on an attached root. `monitorViewEvents: false` on the View class disables that monitoring. Integrations such as Lit rely on these notifications for directive connection state, so disabling monitoring also disables that integration behavior. Arbitrary external DOM movement is not observed.\n\nDOM methods are synchronous; they are not lifecycle preparation hooks. View/Region ownership and notifications remain defined in their class references. `notifyAttach`/`notifyDetach` communicate connection changes, not ownership transfer or a general-purpose resource disposer.\n\n## EventDelegator\n\n`setEventDelegator(provider)` replaces the entire provider. Its required method is:\n\n`delegate({ eventName, selector, handler, rootEl }) → cleanup`\n\nInstall the listener on `rootEl` and return a function that releases exactly that subscription. Preserve the event passed to `handler`; the View/Behavior binding layer already selects the callback context. An empty selector represents the root listener. Marionette calls the cleanup on undelegation/destruction; detaching a live View preserves its bindings.\n\nThe native provider:\n\n- Uses capture for `focus` and `blur`, and normal bubbling for other events.\n- With a selector, walks from the event target toward the root and calls the handler once for the nearest matching descendant. The root is excluded.\n- Sets `event.delegateTarget` to that matched descendant. `event.target` retains the original target.\n- Without a selector, invokes the handler for events reaching the root listener, without adding a matched delegate target.\n\nA custom provider controls its event matching behavior. Keep [View DOM events and triggers](/docs/api/shared/view-bindings.md#dom-events) compatible with what consumers expect. Behavior has its own configured EventDelegator; changing only a host View subclass's provider does not change its Behavior classes. Family-wide setters configure both.\n\n## TypeScript\n\nImport `Renderer<Receiver, Template, Data, Output>`, `DomApiContract<Query, Content>`, `EventDelegator`, `DelegateOptions`, and `DelegatedEvent` from `marionette`.\n\n`Query` extends `ArrayLike<Element>`. The default DomApi's direct `findEl` returns `NodeListOf<Element>` and also accepts DocumentFragment; the `DomApiContract` interface accepts Element or Document. The content parameter defaults to `never`, keeping an unconfigured content slot opaque. Specify your output type when authoring a concrete provider, as above. Configuration does not infer or enforce a matching renderer/output/query type across all consumers.\n\n`DelegateOptions` supplies a string selector and a handler accepting arbitrary arguments; `DelegatedEvent` adds optional `delegateTarget` to the native Event type. Use the [configuration setters](/docs/api/runtime.md#choose-a-configuration-scope) or the class's current provider when composing integrations.\n\n\n[Canonical source](/docs/markdown/docs/api/providers/dom.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/api/providers/data.md",
      "title": "Data and state providers",
      "section": "Provider interfaces",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/api/providers/data/",
      "markdownUrl": "https://marionettejs.com/docs/api/providers/data.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/api/providers/data.md",
      "sourceSha256": "bfdc9fcac45390611b75d28d7cc12fd256325463355fd338abfc6be503844275",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "f0197e04cc9f92d0a7b55017ee8af03e9156f23431315e5225746a1e2874c0cd",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 bfdc9fcac45390611b75d28d7cc12fd256325463355fd338abfc6be503844275; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Data and state providers\n\n[API index](/docs/api.md) · [Runtime configuration](/docs/api/runtime.md) · [State ownership](/docs/api/shared/state.md)\n\nDataApi lets Views read and observe supplied data. StateApi lets an owner observe and dispose its own state. Configure them separately: a View's `model`/`collection` and an owner's state may use different sources. Neither contract supplies API requests or persistence. For an optional implementation, see the [`@mnjs/data` providers](/docs/packages/data.md#providers) and [setup guide](/docs/integrations/setup.md).\n\n## DataApi\n\n`setDataApi(mixin)` overlays the provider on View and CollectionView at the selected [configuration scope](/docs/api/runtime.md#choose-a-configuration-scope). Behavior entity bindings use their host's DataApi. A CollectionView's children use their own class configuration; configuring the parent alone does not configure its children.\n\n| Method | Contract | Built-in default |\n| --- | --- | --- |\n| `key(model) → key` | Stable, non-null unique identity within the observed collection. See [identity](#collection-identity-and-observation). | Returns the model itself. Plain object identity is its key. |\n| `get(model, attribute) → value` | Read an attribute used by filtering/comparison and other consumers. | Own-property lookup; missing returns `undefined`. Nullish model is invalid for this method. |\n| `has(model, attribute) → boolean` | Test attribute presence. | Own-property existence, independent of truthiness; nullish returns false. |\n| `serialize(model) → data` | Return data for template rendering. It need not be a copy. | Returns the source unchanged. |\n| `models(collection) → readonly model[]` | Return the current ordered model snapshot. Keep model identities stable when they represent retained entities. | Returns the supplied array itself; array mutation is not observed. |\n| `subscribe(source, name, callback, context?) → cleanup` | Subscribe to one literal source event, preserving callback arguments and supplied context. | Requires compatible `on`/`off`, otherwise throws `MN0037`. |\n| `observeCollection(collection, callback, context?) → cleanup` | Observe membership/order/update notifications described below, calling the callback with its context. | Accepts only arrays, returns a no-op cleanup; other sources throw `MN0037`. |\n\nThe default supports plain values and static arrays. Explicit entity event maps still need observable sources. The default StateApi does not reuse DataApi's `on`/`off` support automatically.\n\nFor either subscription method, return cleanup that releases only the registered callback/context and prevents further delivery. Do not destroy shared data or clear other consumers' subscriptions. An owner may have multiple subscriptions to the same source. DataApi has no disposal method: View destruction releases observation while leaving its model/collection alive.\n\n## Collection identity and observation\n\nCollectionView reads a snapshot and subscribes during its first render. The provider must publish notifications **after** the source reflects that change, so `models(collection)` already returns the corresponding order and membership. Subscribe to subsequent changes; do not synchronously emit an initial notification during registration. Use these callback shapes:\n\n| Notification | Required payload and meaning |\n| --- | --- |\n| Reset | `{ kind: 'reset' }` — destroy all existing children and build from the current snapshot, even when model identities remain. |\n| Reorder | `{ kind: 'reorder' }` — source order changed with membership retained. CollectionView follows it according to `sortWithCollection` and its comparator. |\n| Update | `{ kind: 'update', added: [...], removed: [...], updated: [{ previous, current }, ...] }` — report additions/removals as actual model values, and changed/replaced models as pairs. All three arrays are required, even when empty. |\n\n`previous` refers to the previously observed model and `current` to the current model for the same stable key. A same-object pair marks its existing child for rendering. A different-object pair replaces and destroys the old child even when the key is unchanged. Added/removed entries must correspond to the before/after snapshots. Emit a coherent change for each structural source change; notifications describe completed changes, not commands for Marionette to mutate the collection.\n\nEvery model must occur once. Keys must be non-null, unique and unchanged while that model remains observed; CollectionView raises `MN0039` for these key violations. These key checks are not comprehensive validation of malformed notification payloads. Equality follows JavaScript Map/Set semantics, which compares object keys by identity. A domain ID is suitable only if it meets those lifetime constraints. A retained key does not grant a new model object the previous child's identity.\n\nKeep source events separate from collection notifications. A Model's `change` event can drive a row's `modelEvents`; it does not by itself mean the collection observer emits an update, sorts, or refilters. See [`@mnjs/data` providers](/docs/packages/data.md#providers) for that package's collection event translation. Reporting one mutation both as a same-object update pair and as a row render event can render that row twice. Use the [CollectionView reference](/docs/api/collection-view.md) for display/lifetime operations.\n\nA custom provider may use stable opaque references, such as entity IDs, and read their current attributes from an immutable store. Keeping those references stable allows existing Views to react through source events; retaining a View does not itself preserve its input nodes or drafts. DOM retention depends on that View's renderer and update strategy.\n\n## StateApi\n\n| Method | Contract |\n| --- | --- |\n| `subscribe(source, name, callback, context?) → cleanup` | Observe one literal state event. Preserve source callback arguments and context; return cleanup that releases only this subscription. |\n| `disposeOwned(source)` | Optional synchronous disposal for a source returned by `createState`. Called after that owner's state subscriptions are released. |\n\nThe default `StateApi.subscribe` always throws `MN0037`; configure a compatible provider before using `stateEvents`. The default has no `disposeOwned`. Plain default state can still be read and changed without declarative observation.\n\nState returned by `createState` is owned; constructor/prototype `state` is borrowed. Disposal is never called for borrowed state. Unrequested lazy state is not created just to destroy it. Application start/stop/restart retain state, and Marionette gates Application `stateEvents` by activity; the provider does not implement that gate. Other state owners observe throughout their live lifetime. See the shared [state reference](/docs/api/shared/state.md) for owner methods and lifecycle.\n\nDo not use `disposeOwned` to issue server deletion or dispose resources owned elsewhere. It is a local ownership boundary. It is not awaited. DataApi and StateApi can share subscription code while retaining different disposal responsibilities.\n\n## TypeScript\n\nImport `DataApiContract<Model, Collection, Attribute>` and `StateApiContract<Source>` from `marionette`. Data parameters default to `never`; StateApi's standalone source parameter defaults to `unknown`, while configured class state slots are opaque. Specify concrete source types on a provider you author. `subscribe` and `observeCollection` must return cleanup functions; `models` must return an array.\n\nThe public `observeCollection` callback parameter is currently typed `unknown`; the notification shapes above are a runtime contract, not an exported core change union. The optional [`@mnjs/data` package](/docs/packages/data.md#typescript) exports its own `CollectionChange` type. A provider's declaration alone does not validate notification consistency.\n\nClass setters accept concrete partial providers without inferring a universal model/state type for every consumer. Keep direct adapter values typed and validate them through the intended View/CollectionView/state owners. Registering a provider does not change source ownership, add transport, or install it on other independently configured classes.\n\n\n[Canonical source](/docs/markdown/docs/api/providers/data.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/packages/data.md",
      "title": "@mnjs/data: Model and Collection",
      "section": "Companion packages",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/packages/data/",
      "markdownUrl": "https://marionettejs.com/docs/packages/data.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/packages/data.md",
      "sourceSha256": "ed9e5b76a3a67a459c0e88ab092b200790aff7a0aeb9c24f1e8f5129f9a1efe4",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "1dc66c78b9b20c93727780ecdd54cf8a398a298364df5ae53924dd2750e46fd5",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 ed9e5b76a3a67a459c0e88ab092b200790aff7a0aeb9c24f1e8f5129f9a1efe4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Model and Collection (`@mnjs/data`)\n\n[API index](/docs/api.md) · [Setup](/docs/integrations/setup.md) · [Data and state providers](/docs/api/providers/data.md)\n\n`@mnjs/data` is an optional companion package supplying observable Models, ordered Collections, and Marionette providers. It works independently of Marionette core and the DOM. Fetching, persistence, validation, and server synchronization belong to an API layer or another data solution. It has no `fetch`, `save`, or HTTP deletion methods. Marionette can use a different source through a compatible provider.\n\n## Model\n\n`new Model(attributes?, options?)` makes an observable set of attributes. Construction combines prototype `defaults` with supplied attributes, assigns a unique client ID, and then calls `initialize(attributes, options)`. Supplied attributes win, including an explicit `undefined`. Initial attributes do not emit change events; mutations inside `initialize` do.\n\n```js\nimport { Model } from '@mnjs/data';\n\nconst Preferences = Model.extend({\n  defaults() { return { compact: false }; },\n});\n\nconst preferences = new Preferences({ theme: 'light' });\nconst changes = [];\npreferences.on('change:theme', (model, theme) => changes.push(theme));\npreferences.set('theme', 'dark');\npreferences.get('theme'); // 'dark'\npreferences.reset({ theme: 'system' }); // Reapplies compact: false.\n```\n\n### Model configuration and properties\n\n| Member | Contract |\n| --- | --- |\n| `defaults` | Prototype object or function returning initial attributes. A function runs with the Model as `this`, on construction and `reset`. Use it to create fresh nested values per instance. |\n| `idAttribute` | Prototype attribute name used for `id`; defaults to `'id'`. Set it before construction. |\n| `initialize(attributes, options)` | Optional setup hook after attributes and identity exist. Options are passed through; they are not merged or stored as `this.options`. |\n| `attributes` | Current attribute object. Read through `get`/`has` and write through mutation methods so changes notify observers. |\n| `changed` | Sparse map for the most recent mutation. An unchanged write clears it. Use an event's change payload when inspecting that particular mutation. |\n| `id` | Value of the `idAttribute` attribute, updated by attribute mutations. Change it with `set`, rather than assigning `model.id`. |\n| `cid` | Unique client ID, stable for this instance. Used by the native DataApi to identify CollectionView children independently of server IDs. Treat it as read-only. |\n\nDefine `defaults` through `Model.extend`, a prototype method, or a getter. A native class field initializes after `super()` and therefore cannot provide construction defaults.\n\n### Read and mutate attributes\n\n| Method | Result and behavior |\n| --- | --- |\n| `get(key)` | Attribute value, or `undefined` if absent. |\n| `has(key)` | Own-property presence, including attributes containing `undefined`, `null`, or `false`. |\n| `set(attributes, options?)` / `set(key, value, options?)` | Update supplied attributes; leave others unchanged. Return the Model. |\n| `unset(key, options?)` | Remove that attribute. Return the Model. |\n| `clear(options?)` | Remove all attributes, including defaults. Return the Model. |\n| `reset(attributes?, options?)` | Replace attributes with defaults plus supplied attributes; remove keys absent from that result. Return the Model. |\n| `toObject()` | New shallow attribute object. Nested values remain shared references. Use this result for JSON serialization; the Model has no automatic `toJSON` hook. |\n| `isDestroyed()` / `destroy(options?)` | Inspect or end the local lifetime; see [destruction](#destruction-and-ownership). |\n\nValues are compared with `Object.is`. A fresh object is a change even when its contents match. Mutating a nested object in place does not notify; set a replacement value to publish its change. Mutation options are event metadata, not validation or transport settings. There is no `silent` mode.\n\n## Model events\n\nAll effective mutations finish updating attributes and `id` before publishing synchronously:\n\n| Event | Callback arguments | Hook |\n| --- | --- | --- |\n| `change:<attribute>` | `(model, value, change)` | For example, `onChangeTheme(model, value, change)` |\n| `change` | `(model, change)` after attribute events | `onChange(model, change)` |\n| `destroy` | `(model, options)` once on destruction | `onDestroy(model, options)` |\n\nThe `change` argument contains the supplied metadata plus `changed` and `previous` sparse maps. `changed` contains affected attributes and their new values; removal is represented by `undefined`. `previous` contains only affected attributes that existed before the write. It is not a complete snapshot; use `has` to check current presence. A write with no effective changes emits nothing.\n\nNested writes complete as independent synchronous changes. An event's `change.changed` describes that event; `model.changed` may already reflect a subsequent nested write. Exceptions from listeners or hooks propagate to the caller and stop the remaining delivery.\n\nModels and Collections share the [Events methods](/docs/api/shared/events.md): `on`, `once`, `off`, `trigger`, `triggerMethod`, `listenTo`, `listenToOnce`, and `stopListening`. Event maps contain function callbacks; names are literal strings. `triggerMethod` invokes the named hook before event listeners.\n\n## Collection\n\n`new Collection(models?, options?)` creates ordered membership. Supply one Model/attribute object or an array; omitted or null input starts empty. Raw attribute objects use the configured `model` constructor. Supplied native Model instances retain their identity and subclass, even when that constructor differs.\n\n```js\nimport { Collection, Model } from '@mnjs/data';\n\nconst first = new Model({ id: 'a', label: 'Alpha' });\nconst items = new Collection([first, { id: 'b', label: 'Beta' }]);\nitems.add({ id: 'c', label: 'Gamma' }, { at: 1 });\nitems.move('b', 0);\nitems.get('a').set('label', 'Updated Alpha'); // Retains the Model.\nconst labels = items.map(model => model.get('label'));\nconst plainItems = items.toArray(); // Attribute objects, not Models.\n```\n\n### Collection configuration and properties\n\n| Member | Contract |\n| --- | --- |\n| `model` | Constructor for raw attributes; defaults to `Model`. Set on the prototype or pass `{ model: ModelClass }` as constructor options. The constructor option wins. Supplied Models do not change this factory for later additions. |\n| `comparator` | Optional prototype attribute name or two-Model comparison function, used by `sort()` when no comparator is passed. Adding or resetting data does not automatically sort it. |\n| `initialize(models, options)` | Optional hook after membership is seeded without mutation events. Options are passed through; the Collection does not create `this.options`. |\n| `models` | Current ordered array of Models. Use membership methods to change it. For your own array of references use `[...collection]` or `collection.models.slice()`. |\n| `length` | Current number of Models. |\n\n### Read and iterate\n\n| Method | Result |\n| --- | --- |\n| `at(index)` | Model at the index; negative indexes count from the end. Out of range returns `undefined`. |\n| `get(identity)` | Contained Model resolved by exact member instance, then current non-null ID, then client ID. Missing/nullish identity returns `undefined`. |\n| `indexOf(model)` | Position of that exact Model instance, or `-1`. |\n| `forEach(callback, context?)` | Calls `(model, index, models)` in order; returns `undefined`. |\n| `map(callback, context?)` | Calls the same signature and returns an array of results. |\n| `[Symbol.iterator]()` | Iterates Model instances, supporting `for...of` and spread. |\n| `toArray()` | New array of shallow attribute copies, equivalent to mapping `toObject()`. Use this for JSON serialization. |\n\n### Membership and ordering\n\n| Method | Result and notifications |\n| --- | --- |\n| `add(modelOrAttributes, options?)` / `add(array, options?)` | Add new membership, optionally at integer `options.at` (clamped to the list); otherwise append. Return the added Model or array of added Models. An ignored single addition returns `undefined`. Emit `add` per Model, then one `update`. |\n| `remove(identity, options?)` / `remove(identities, options?)` | Resolve like `get`; remove matching members without destroying them. Return the removed Model or an array in input order. Missing/repeated matches are skipped; a missing single match returns `undefined`. Emit `remove` per Model, then one `update`. |\n| `reset(models?, options?)` | Replace all membership; return the Collection and emit `reset`, even for unchanged input. Raw attributes create new Models. Supplied Models are retained as instances. No per-Model `add`/`remove` events. |\n| `move(identity, index, options?)` | Move an existing Model; clamp an integer index to the list. Return the Model, or `undefined` if absent. Emit `sort` when its position changes. A noninteger index for an existing Model throws `TypeError`. |\n| `sort(comparator?, options?)` | Sort by attribute name or `(left, right) => number`, with the Collection as callback `this`. Defaults to prototype `comparator`. Return the Collection and emit `sort`, even if order is unchanged. Without a valid comparator, do nothing. |\n| `isDestroyed()` / `destroy(options?)` | Inspect or end the local lifetime; see [destruction](#destruction-and-ownership). |\n\n`add` ignores existing instances or non-null IDs. Construction and `reset` reject duplicate instances or non-null IDs with `TypeError`, before replacing membership. Keep IDs unique when updating Models: a later ID change does not enforce uniqueness; lookup then selects the first current matching member. ID equality follows Map/Set equality. Nullish IDs do not identify members.\n\nBatch related membership changes with `add([...])` or `remove([...])`. Each call that changes membership emits one aggregate `update`, so CollectionView reconciles once per call instead of once per item. Per-Model `add`/`remove` events still fire for changed members. Empty, duplicate-only additions and unmatched removals emit no `update`.\n\n`reset` is a whole-list replacement. With CollectionView it destroys and rebuilds child Views, including children whose Model instances remain. For retained items, update the existing Model with `set`, change membership with `add`/`remove`, and change order with `move`/`sort`. There is no `Collection.set` merge operation. See [CollectionView](/docs/api/collection-view.md) for display filtering, ordering, and child ownership.\n\n## Collection events\n\n| Event | Callback arguments | Hook |\n| --- | --- | --- |\n| `add` | `(model, collection, options)` | `onAdd(model, collection, options)` |\n| `remove` | `(model, collection, options)` | `onRemove(model, collection, options)` |\n| `update` | `(collection, change)` | `onUpdate(collection, change)` |\n| `reset` | `(collection, options)` | `onReset(collection, options)` |\n| `sort` | `(collection, options)` | `onSort(collection, options)` |\n| `destroy` | `(collection, options)` for its own destruction | `onDestroy(collection, options)` |\n\n`update` supplies metadata plus `changes: { kind: 'update', added, removed, updated }`. Native membership operations populate `added` or `removed`; `updated` is empty. Membership reflects the entire mutation before listeners run. No-op additions/removals and unchanged moves emit nothing. Options are metadata except for `add`'s `at`; they do not suppress notifications.\n\nCollections also forward contained Models' events with their original arguments. On a Model's `destroy`, each containing Collection emits its `remove` and `update` events as it removes that Model, then forwards `destroy(model, options)` to its own listeners. Thus a Collection's `destroy` event may refer to a member or the Collection itself; inspect the first argument when that distinction matters. `add`/`remove` originate on the Collection, not the Model.\n\nA Model attribute change does not emit a structural update, resort, or refilter a list. A row can observe it through [modelEvents](/docs/api/view.md); parent filtering and sorting are separate operations. Complete one structural mutation before starting another from its listeners or child lifecycle hooks. Notifications are synchronous, not queued or replayed by the data package.\n\n## Destruction and ownership\n\n`destroy(options?)` returns the source and is idempotent. It marks the source destroyed, emits `destroy`, releases outgoing `listenTo` subscriptions and incoming event callbacks, and makes subsequent data mutations no-ops rather than throwing. It performs no server request. The retained attribute/membership snapshots remain readable.\n\nDestroying a Model removes it from every containing Collection. Destroying a Collection releases its member subscriptions but does not destroy the Models. A Model may belong to multiple Collections. Removing or replacing membership does not transfer ownership or destroy the previous members.\n\nMarionette Views borrow their `model` and `collection`: destroying a View releases observation without destroying its data. State returned by `createState` is owned and disposed through StateApi; supplied state is borrowed. See [state ownership](/docs/api/shared/state.md). Local data without external subscriptions or resources needs no explicit destruction once it becomes unreachable.\n\n## Providers\n\nImport `DataApi` and `StateApi` from `@mnjs/data` and configure Marionette before constructing consumers, as shown in [setup](/docs/integrations/setup.md#configure-once). These optional providers implement the core [DataApi and StateApi contracts](/docs/api/providers/data.md); they are distinct from core's plain-data defaults.\n\n| Provider method | Package behavior |\n| --- | --- |\n| `DataApi.key(model)` | Returns the Model's client ID (`cid`), preserving child identity when its server ID changes. |\n| `DataApi.get(model, attribute)` / `has(model, attribute)` | Use native Model methods; otherwise read/test own properties. Nullish sources return `undefined` / `false`. |\n| `DataApi.serialize(model)` | Returns a native Model's live attributes; otherwise returns the source unchanged. |\n| `DataApi.models(collection)` | Requires a native Collection and returns a shallow copy of its ordered Models. Arrays and other collection implementations throw `TypeError`. |\n| `DataApi.observeCollection(collection, callback, context?)` | Collection `update` events deliver their normalized `changes` payload; `reset` and `sort` become reset/reorder notifications. Calls the callback with the supplied context and returns cleanup. |\n| `DataApi.subscribe(...)` / `StateApi.subscribe(...)` | Observe compatible `on`/`off` sources, preserving event arguments and context. Missing event methods throw `TypeError`. |\n| `StateApi.disposeOwned(source)` | Calls the source's `destroy()` when present. Native destruction is local cleanup: no server request, and destroying a Collection does not destroy its Models. |\n\nBoth providers accept `subscribe(source, name, callback, context?)` and `subscribe(source, eventMap, context?)`. Map values are function callbacks. Both forms return an idempotent cleanup function that removes only those registrations.\n\nModel change events remain separate from structural collection notifications. Use a row's `modelEvents` for attribute changes; changing attributes does not automatically sort or refilter a list. See [Collection events](#collection-events).\n\nConfigure DataApi and StateApi separately for the sources each owner uses. Installing these providers does not add persistence or change ownership: Views borrow Models and Collections; only state returned by `createState` is owned. A different data solution can supply its own implementation of the same core contracts.\n\n## TypeScript\n\n```ts\nimport { Collection, Model } from '@mnjs/data';\nimport type { CollectionChange, MutationOptions } from '@mnjs/data';\n\ntype Preferences = { theme: string; compact: boolean };\nconst preferences = new Model<Preferences>({ theme: 'light' });\npreferences.set('compact', true);\nconst theme: string | undefined = preferences.get('theme');\nconst copies: Partial<Preferences> = preferences.toObject();\nconst selections = new Collection<Model<Preferences>>([preferences]);\nconst metadata: MutationOptions = { source: 'settings' };\nselections.add({ theme: 'dark' }, metadata);\nconst change: CollectionChange<Model<Preferences>> = { kind: 'reorder' };\n```\n\nAttributes and `toObject()` are partial because construction and mutation can leave keys absent. Known `set` keys check value types; dynamic string keys remain open. `toArray()` currently returns `ModelAttributes[]` rather than preserving the attribute generic. Types do not validate server responses.\n\n| Exported type | Meaning |\n| --- | --- |\n| `Model<Attributes>` / `Collection<Member>` | Generic instance types sharing names with the constructors. Collection member types include supplied Models and the factory used for raw attributes. |\n| `ModelAttributes` | `Record<string, unknown>`. |\n| `MutationOptions` | Open metadata object. Event-specific `changed`, `previous`, and `changes` fields are runtime payloads; this type does not infer their contents. |\n| `ModelInput<Member>` | A member Model or its attributes, used by Collection construction and mutation. |\n| `CollectionOptions<Member>` | Optional `model` constructor. `comparator` belongs on the prototype or in `sort`, not constructor options. |\n| `CollectionChange<Member>` | Discriminated union of `{ kind: 'reset' }`, `{ kind: 'reorder' }`, and `{ kind: 'update', added, removed, updated }`, where `updated` contains `{ previous, current }` member pairs. |\n| `EventCallback` / `EventSource` | Re-exported callback and event-method types from `@mnjs/utils`. Event names do not statically validate payload types. |\n\n`Model.extend` and `Collection.extend` use the shared [class extension mechanism](/docs/api/shared/common.md#define-a-class), preserving added methods and static properties in their types. Prefer `initialize` for setup. An explicit constructor replaces parent initialization and owns its return contract. Unlike core owners, these classes do not supply `getOption`, binding helpers, or Radio configuration.\n\nThe package also re-exports the standalone `triggerMethod` helper. Call it with an event-capable receiver, for example `triggerMethod.call(model, 'selected', model)`. Its hook/event behavior is documented in [Events](/docs/api/shared/events.md#trigger-events-and-hooks). ESM imports and CommonJS `require('@mnjs/data')` have matching declarations; import from the package root rather than internal files.\n\n\n[Canonical source](/docs/markdown/docs/packages/data.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/packages/radio.md",
      "title": "@mnjs/radio: channels and requests",
      "section": "Companion packages",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/packages/radio/",
      "markdownUrl": "https://marionettejs.com/docs/packages/radio.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/packages/radio.md",
      "sourceSha256": "b598cc4f4f721358e7513d1556cf2c6da04bb8d104a335e006d317c8233c4270",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "0a4a8bbb8070e6eb001b3250f5f5e32184db1ed85983aa2649261b297c5559e7",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 b598cc4f4f721358e7513d1556cf2c6da04bb8d104a335e006d317c8233c4270; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# @mnjs/radio\n\nRadio provides named channels for events and request/reply messaging. An event\nnotifies subscribers; a request calls one reply handler and returns its result.\nUse a channel when participants need a shared messaging address. Direct method\ncalls and [object events](/docs/api/shared/events.md) remain useful when the\nparticipants already hold references to one another.\n\n## Imports and registry scope\n\n`marionette` exports the default `Radio` instance from `@mnjs/radio`. Core uses\nRadio for Application and MnObject's declarative channel bindings. The package\ncan also be used without core or a DOM; it depends on `@mnjs/utils`.\n\n```js\nimport { Radio } from '@mnjs/radio';\n\nconst preferences = Radio.channel('preferences');\nconst changes = [];\npreferences.on('theme:changed', theme => changes.push(theme));\npreferences.reply('theme', 'dark');\n\nconst theme = preferences.request('theme');\npreferences.trigger('theme:changed', theme);\n```\n\nWithin the same installed package copy and module format, importing `Radio` from\ncore or the companion package reaches the same registry. ESM and CommonJS have\nseparate default instances. Separate installed copies also do not share state.\n\n`createRadio()` returns an independent `RadioApi`, with its own channels and\nlogging configuration. Each `createMarionette()` runtime has its own `Radio` too:\nuse `runtime.Radio` to communicate with objects from that runtime. See\n[runtime isolation](/docs/api/runtime.md#isolation-and-composition).\n\n| Registry API | Contract |\n| --- | --- |\n| `radio.channel(name)` | Returns the existing channel or creates it. Names are nonempty strings. A missing/falsy name throws `MN0017`. |\n| `radio.Channel` | The constructor used for new channels in this registry. Channels already created keep their identity. |\n| `radio.reset(name)` | Resets an existing registered channel. An unknown name throws `MN0021`; a supplied falsy name (including `undefined`) throws `MN0017`. Returns `undefined`. |\n| `radio.reset()` | Resets all registered channels. Returns `undefined`. |\n\nReset clears handlers but preserves registered channel objects: later\n`radio.channel(name)` calls return the same channel.\n\n## Channel events\n\nA channel provides the complete [Events API](/docs/api/shared/events.md): `on`,\n`once`, `off`, `listenTo`, `listenToOnce`, `stopListening`, `trigger`, and\n`triggerMethod`. Names are literal strings, including spaces; maps register\nmultiple names. Events run synchronously and ignore callback return values.\n`triggerMethod` calls the channel's matching `onEventName` hook before emitting\nthe event and returns that hook's result.\n\nEvery Events and Requests method is also available on the registry, with the\nchannel name as its first argument. For example,\n`radio.trigger('preferences', 'theme:changed', 'dark')` forwards to the named\nchannel. Forwarded methods create a missing channel and return the channel\nmethod's result. Registration methods return the **channel**, so chaining\n`radio.on(...)` continues on that channel rather than on the registry.\n\nChannels expose `channelName`, the name supplied at construction. They have no\nApplication start/stop lifecycle or automatic destruction. Use the owner and\ncleanup rules below when their useful lifetime ends.\n\n## Requests and replies\n\nA request name has one active reply handler. A later `reply` or `replyOnce` for\nthe same name replaces the earlier registration. Request names, like event\nnames, are literal strings. Replies and event subscriptions are separate: an\n`on('theme', handler)` subscription does not answer `request('theme')`.\n\n| Channel or Requests method | Contract and return value |\n| --- | --- |\n| `reply(name, callbackOrValue, context?)` / `reply(map, context?)` | Registers a function or a constant value. Returns the receiver. |\n| `replyOnce(name, callbackOrValue, context?)` / `replyOnce(map, context?)` | Registers a reply removed before its first invocation, including when it throws. Each mapped name has its own one-time reply. Returns the receiver. |\n| `request(name, ...args)` | Calls the matching reply with the supplied arguments and returns its result unchanged. Returns `undefined` when neither a matching nor default reply exists. |\n| `request(map, ...extraArgs)` | Requests each own enumerable string key, passing its mapped value first, then the extra arguments. Returns an object keyed by request name. |\n| `stopReplying(name?, callbackOrValue?, context?)` / `stopReplying(map, context?)` | Removes replies matching all supplied filters. Omit the name or pass `null` to select all names. With no filters, removes all replies. Returns the receiver. |\n\nFunctions use the supplied truthy context, or the receiver as `this`. Arrow\nfunctions keep their lexical context. Registration/removal maps also accept an\nexplicit third context argument; a truthy third argument takes precedence over\nthe second. Map values can be functions or constants, including `false`, `0`,\n`null`, and `undefined`. In `stopReplying`, falsy callback/context arguments mean\nno filter; use the name to remove a reply registered with a falsy constant.\nRemoving a one-time reply may use its original function reference.\n\n```js\nimport { createRadio } from '@mnjs/radio';\n\nconst catalog = createRadio().channel('catalog');\nconst titles = new Map([['a', 'Overview'], ['b', 'Release notes']]);\ncatalog.reply({\n  title: id => titles.get(id),\n  count: () => titles.size,\n});\n\nconst summary = catalog.request({ title: 'b', count: undefined });\ncatalog.replyOnce('welcome', 'Welcome back');\nconst welcome = catalog.request('welcome');\nconst repeatedWelcome = catalog.request('welcome');\n```\n\nA reply named `default` handles requests with no exact match. It receives\n`(requestedName, ...args)`; an exact match takes precedence. Requesting the name\n`default` itself is an exact match, so it receives only the caller's arguments.\n\nDispatch is synchronous. A thrown exception propagates to the caller. A reply\nmay return a Promise, which `request` returns without awaiting, cancelling, or\nretrying it. A request map returns an object of results, not a Promise combining\nthem. The owner of an operation remains responsible for its completion and\nlifetime.\n\n## Lifetime and cleanup\n\nUse `listenTo(channel, ...)` to tie subscriptions to a Marionette object's\nlifetime. Destroying that object removes its event subscriptions. Request\nreplies have separate ownership: `stopListening()` does not remove them. Pair\nmanual replies with `stopReplying` or the owner's\n[`unbindRequests`](/docs/api/shared/common.md#binding-helpers).\n\nApplication and MnObject provide\n[`channelName`, `radioEvents`, and `radioRequests`](/docs/api/shared/common.md#declarative-radio-bindings).\nTheir destruction removes the configured channel's replies whose context is\nthat owner and releases its subscriptions. Application `stop()` retains those\nbindings. The shared channel survives; other participants' handlers remain.\n\n`channel.reset()` calls `off()`, `stopListening()`, and `stopReplying()`, then\nreturns the channel. It removes incoming event callbacks, outgoing subscriptions,\nand replies. Use it when the whole channel's handlers should be cleared, such as\nat the end of an isolated test. Selective cleanup is appropriate when other\nparticipants still use the channel. Reset neither cancels returned Promises nor\nemits a destruction event.\n\n### Standalone channels and Requests\n\n```js\nimport { Channel, Requests } from '@mnjs/radio';\n\nconst local = new Channel('preview');\nlocal.reply('title', 'Preview');\nconst previewTitle = local.request('title');\nlocal.reset();\n\nconst service = Object.assign({ ready: true }, Requests);\nservice.reply('ready', function() { return this.ready; });\nconst ready = service.request('ready');\nservice.stopReplying();\n```\n\n`new Channel(name)` creates an independent channel without registering it with\nRadio. Two standalone channels with the same name are different objects, and\n`Radio.reset()` does not reach them. The named `Channel` export is the default\n`Radio.Channel`; `new radio.Channel(name)` uses that instance's logging\nconfiguration.\n\n`Requests` is a method mixin, not a constructor. Assign it to an object or a\nprototype to add `reply`, `replyOnce`, `request`, and `stopReplying`. Each receiver\nstores its own replies. It adds no Events API, channel registry, reset method,\nor destruction lifecycle. Its warnings use the default Radio configuration.\n\n## Logging\n\n```js\nimport { createRadio } from '@mnjs/radio';\n\nconst radio = createRadio();\nconst activity = [];\nconst warnings = [];\nradio.log = (channel, name, ...args) => activity.push({ channel, name, args });\nradio.debugLog = (warning, name, channel) => warnings.push({ warning, name, channel });\nradio.setDebug();\nradio.tuneIn('settings');\nradio.trigger('settings', 'opened');\nradio.request('settings', 'missing');\nradio.tuneOut('settings');\n```\n\n| Registry member | Contract |\n| --- | --- |\n| `tuneIn(name)` | Creates/gets the channel and logs its events and requests. Event logging subscribes to `all`. Returns this Radio instance. |\n| `tuneOut(name)` | Creates/gets the channel and stops its activity logging. Returns this Radio instance. |\n| `setDebug(enabled = true)` | Enables/disables warning delivery for unhandled requests and overwritten replies. Initially disabled. Returns `undefined`. |\n| `log(channelName, name, ...args)` | Assignable activity hook; defaults to console logging. Tuning is independent of `setDebug`. |\n| `debugLog(warning, name, channelName?)` | Assignable warning hook; defaults to console warnings. Standalone Requests receivers may have no channel name. |\n\nHooks run with the Radio instance as `this`; existing channels use the current\nhook even after replacement. Hook exceptions propagate. Disabling debug also\nsuppresses automatic calls to custom warning hooks.\n\nCall `tuneIn` once per logging session; repeated calls add repeated event\nsubscriptions. Pair it with `tuneOut` before resetting a tuned channel: reset\nremoves the `all` subscription but does not clear the request-logging flag.\n\n## Types and entrypoints\n\nThe package root supports ESM named imports and CommonJS destructuring. Its\nruntime exports are `Radio`, `createRadio`, `Channel`, and `Requests`; it has no\ndefault package export. Types include `RadioApi`, `ChannelConstructor`, `Channel`,\nand `Requests`. The latter two names have both type and runtime meanings.\n`marionette` re-exports the `Radio` value and the `RadioApi`, `Channel`, and\n`Requests` types; import the other runtime values from `@mnjs/radio`.\n\n```ts\nimport { createRadio, type RadioApi, type Channel } from '@mnjs/radio';\n\nconst radio: RadioApi = createRadio();\nconst channel: Channel = radio.channel('settings');\nchannel.reply('theme', 'dark');\nconst result = channel.request('theme');\nconst theme = typeof result === 'string' ? result : 'system';\n```\n\nDynamic request names do not define a result schema: `request(name)` returns\n`unknown`, and map requests return `Record<string, unknown>`. Narrow the result\nat the boundary or put a typed function around a known channel contract.\nFluent registration/removal methods preserve the receiver; registry forwarding\nreturns a Channel rather than Radio. `channel.reset()` returns the channel,\nwhile `radio.reset()` returns `void`.\n\n[Reference index](/docs/api.md) · [Events](/docs/api/shared/events.md) · [Owner bindings](/docs/api/shared/common.md#declarative-radio-bindings)\n\n\n[Canonical source](/docs/markdown/docs/packages/radio.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/packages/utils.md",
      "title": "@mnjs/utils: shared utilities",
      "section": "Companion packages",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/packages/utils/",
      "markdownUrl": "https://marionettejs.com/docs/packages/utils.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/packages/utils.md",
      "sourceSha256": "158e2051ee438acd7e235f0f29ce45f42ad798bb6d460a871efd29904e2728ec",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "9d275193ee9646cfded96c20ab9bfd9ee337c5690655e013d1486847482c8ec5",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 158e2051ee438acd7e235f0f29ce45f42ad798bb6d460a871efd29904e2728ec; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# @mnjs/utils\n\nShared utilities for components that need Marionette's conventions without importing its UI classes. Marionette, Radio, and native data use these same implementations. Add `@mnjs/utils` as a direct dependency when your code imports it, using the same version as core; see [installation](/docs/quick-start.md#install-matching-packages).\n\n## Component methods\n\n`Events` supplies the [shared Events contract](/docs/api/shared/events.md). The other methods below use their receiver as the owner. Mix them into a component or call them with `.call(owner, ...)`. A plain component has no automatic destruction lifecycle: release the subscriptions and replies it owns when it is finished.\n\n```js\nimport { Events, getOption, triggerMethod, bindEvents, unbindEvents } from '@mnjs/utils';\n\nconst source = Object.assign({}, Events);\nconst component = {\n  ...Events, getOption, triggerMethod, bindEvents, unbindEvents,\n  options: { label: 'Inbox' },\n  onOpen() { return this.getOption('label'); },\n  onChanged(label) { this.options.label = label; }\n};\ncomponent.bindEvents(source, { changed: 'onChanged' });\nsource.trigger('changed', 'Archive');\nconst label = component.triggerMethod('open');\ncomponent.unbindEvents(source);\n```\n\n| Export | Contract |\n| --- | --- |\n| `getOption(name)` | [Option lookup](/docs/api/shared/common.md#options-and-initialization): defined values in `this.options` take precedence over `this[name]`; functions are returned, not invoked. Accepts string, number, or symbol keys, including `0` and `''`. A nullish/omitted name returns `undefined`. |\n| `mergeOptions(options, keys)` | [Selected option copying](/docs/api/shared/common.md#options-and-initialization). Returns `undefined`; an own enumerable `__proto__` option is copied as a data property without changing the receiver's prototype. |\n| `normalizeMethods(bindings)` | [Method-name resolution](/docs/api/shared/common.md#options-and-initialization). Returns a new function map or `undefined` for falsy input; resolves own enumerable entries without binding or subscribing. |\n| `triggerMethod(event, ...args)` | Calls the matching `onEvent` hook before triggering the event; returns the hook's result without awaiting it. See [hook dispatch](/docs/api/shared/events.md#trigger-events-and-hooks). |\n| `bindEvents(source, bindings)` / `unbindEvents(source, bindings?)` | [Event binding helpers](/docs/api/shared/common.md#binding-helpers), requiring the receiver's `listenTo` / `stopListening`. Return the receiver. |\n| `bindRequests(channel, bindings)` / `unbindRequests(channel, bindings?)` | [Request binding helpers](/docs/api/shared/common.md#binding-helpers), registering replies with the receiver as context. Return the receiver; `stopListening` does not remove replies. |\n\n## Value and method resolution\n\n| Export | Arguments and result |\n| --- | --- |\n| `getValue(object?, key?, fallback?)` | Reads `object[key]`; only `undefined` selects the fallback. If the selected value is a function, calls it with `object` as `this` and no arguments. A nullish object selects the fallback. |\n| `resolveMethod(context, method, name)` | Returns a supplied function unchanged, or resolves a string/boxed-string method name on the context/prototype. `name` identifies the binding in the `MN0019` error when resolution fails. Does not bind the function. |\n| `normalizeBindings(context, bindings)` | Returns a resolved function map, without subscribing. Like `normalizeMethods.call(context, bindings)`, but rejects an own enumerable `__proto__` event key with `MN0026`. Pass a bindings object. |\n\nThese operations are synchronous. Getters and callbacks can throw; errors propagate to the caller.\n\n```js\nimport { getValue, resolveMethod, normalizeBindings } from '@mnjs/utils';\n\nconst settings = { prefix: 'Team', title() { return `${this.prefix} inbox`; } };\nconst title = getValue(settings, 'title');\nconst fallback = getValue(settings, 'missing', 'Inbox');\nconst handler = resolveMethod(settings, 'title', 'read:title');\nconst bindings = normalizeBindings(settings, { 'read:title': 'title' });\n```\n\n## Constructors and errors\n\n`extend.call(Parent, prototypeProperties?, staticProperties?)` creates a child function constructor. See [class extension](/docs/api/shared/common.md#define-a-class) for forwarding, initialization, shared prototype values, and `__super__`. Prototype/static copying evaluates enumerable accessors. Inherited enumerable parent statics are copied too. Extending a native `class` requires an explicit constructor that constructs the parent; the default forwarding uses `Parent.apply`, which native classes do not support. Prefer ordinary `class extends` for native classes.\n\n`MarionetteError` is the same constructor exported by core; see [errors and diagnostics](/docs/api/errors.md).\n\n## Small standalone helpers\n\n| Export | Arguments and result |\n| --- | --- |\n| `isString(value)` | Returns whether the value has the String tag, including primitive and boxed strings. Does not coerce the value to a string. |\n| `setProperty(target, key, value)` | Assigns a property and returns `undefined`. For `__proto__`, defines an own writable, enumerable, configurable data property without replacing the target prototype. |\n| `uniqueId(prefix?)` | Returns the next decimal sequence ID as a string, with an optional string prefix. One counter belongs to each loaded utils module instance, independent of other libraries. It is not a persistent or globally unique ID. |\n\n## Event-building helpers\n\nMost components should use `Events` directly. These exports support custom event implementations; they do not register subscriptions or create an owner lifetime.\n\n| Export | Arguments and result |\n| --- | --- |\n| `buildEventArgs(nameOrMap, callback?, context?, listener?)` | Returns descriptors shaped `{ name, callback, context, listener }`. A literal name produces one descriptor; an object produces one for each own enumerable key in key order. Names are not split on whitespace. For map input, the second argument supplies context when the third is `undefined`. |\n| `callHandler(callback, context, args?)` | Calls the function with the supplied receiver and an array or `arguments` object, defaulting to no arguments. Returns its result. |\n| `onceWrap(callback, offCallback)` | Returns a wrapper that calls `offCallback(wrapper)` before its first callback invocation, forwarding its receiver and arguments. Later calls return the saved result. It is consumed before cleanup, so recursive calls or calls after cleanup/callback failure do not retry. Errors propagate; until a result is saved, repeated calls return `undefined`. |\n\n```js\nimport { buildEventArgs, callHandler, onceWrap, uniqueId, setProperty, isString } from '@mnjs/utils';\n\nconst receiver = { prefix: 'Hello' };\nconst greet = function(name) { return `${this.prefix}, ${name}`; };\nconst descriptors = buildEventArgs({ greet }, receiver);\nconst greeting = callHandler(greet, receiver, ['Ada']);\nconst removals = [];\nconst greetOnce = onceWrap(greet, wrapper => removals.push(wrapper));\nconst first = greetOnce.call(receiver, 'Ada');\nconst repeated = greetOnce.call(receiver, 'Grace');\nconst key = uniqueId('component-');\nconst values = {};\nsetProperty(values, key, first);\nconst isLabel = isString(first);\n```\n\n## Types and entrypoints\n\nThe package supplies ESM, CommonJS, and TypeScript declarations and has no runtime dependencies. Import from `@mnjs/utils`; there are no public helper subpaths. Bundlers can retain imported helpers because the package declares no side effects.\n\nType exports include `Bindings`, `EventCallback`, `EventMap`, `EventSource`, `EventMethods`, `EventsContract`, `MarionetteErrorInstance`, `MarionetteErrorConstructor`, and the extension composition types `Merge`, `Constructed`, and `CallableParent`. `Bindings` accepts method-name maps whose handlers are checked at runtime. Value-resolution helpers return `unknown`; narrow their results before using them as application values.\n\n```ts\nimport { getValue, callHandler, type EventMap } from '@mnjs/utils';\n\nconst value: unknown = getValue({ label: 'Inbox' }, 'label');\nconst label: string = typeof value === 'string' ? value : '';\nconst handlers: EventMap = { open() {} };\nconst count: number = callHandler((value: number) => value + 1, undefined, [1]);\nvoid [label, handlers, count];\n```\n\n\n[Canonical source](/docs/markdown/docs/packages/utils.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/packages/adapters.md",
      "title": "@mnjs/adapters: optional integrations",
      "section": "Companion packages",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/packages/adapters/",
      "markdownUrl": "https://marionettejs.com/docs/packages/adapters.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/packages/adapters.md",
      "sourceSha256": "c4b60a10fbb121b252c99d51e0a3e99e05843b06f65a3b11609a321d62573e35",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "dc3c36d6c2e96e49ddfc804e02dd0bd5ec453adc6856bd685f007a566041777d",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 c4b60a10fbb121b252c99d51e0a3e99e05843b06f65a3b11609a321d62573e35; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# @mnjs/adapters\n\nOptional integrations for existing data sources and DOM libraries. Import the subpath you use; the package has no root export. Imports do not configure Marionette or load other adapters. Install the matching Marionette version and only the peers needed by your integration; see [package installation](/docs/quick-start.md#install-matching-packages).\n\n| Subpath | Default export | Peer used by the application |\n| --- | --- | --- |\n| `@mnjs/adapters/backbone` | `BackboneApi` | Backbone `^1.3.1`; TypeScript also needs `@types/backbone` `^1.4.23`. |\n| `@mnjs/adapters/xstate` | `createXStateActorApi` | XState v5 actors; the integration is tested with `5.33.2`. It uses structural actor interfaces and does not import XState. |\n| `@mnjs/adapters/dom/jquery` | `JQueryDomApi` | jQuery `^4.0.0`; TypeScript also needs `@types/jquery` `^4.0.1`. |\n| `@mnjs/adapters/dom/morphdom` | `MorphdomDomApi` | Morphdom `^2.7.8`. |\n| `@mnjs/adapters/dom/lit-html` | `LitDomApi` | Lit HTML `^3.3.3`. |\n\nEach subpath has ESM, CommonJS, and TypeScript entrypoints. These adapters implement the existing [data/state](/docs/api/providers/data.md) or [DOM](/docs/api/providers/dom.md) contracts. Configure them before constructing consumers. [Runtime configuration](/docs/api/runtime.md) explains application-wide, subclass, and isolated scopes. The examples use subclasses to make the affected classes explicit.\n\nData and state configuration are independent. Choosing a data adapter does not require changing state, Radio, or DOM providers. See [observable data and API access](/docs/integrations/setup.md#observable-data-and-api-access) when selecting a data solution.\n\n## Backbone\n\n`BackboneApi` implements both DataApi and StateApi without modifying Backbone sources or prototypes. Configure a CollectionView and its child View class when both consume Backbone data. Configure StateApi separately for owners whose state uses Backbone.\n\nBackbone 1.3.1 is the runtime minimum: collection observation reads the added and removed model arrays from the `update` event's `options.changes` payload. Backbone 1.2.3 emits `update` without that payload and cannot supply this contract. The Backbone data adapter does not require jQuery; the jQuery DOM adapter has its own peer requirement.\n\n```js\nimport Backbone from 'backbone';\nimport BackboneApi from '@mnjs/adapters/backbone';\nimport { View } from 'marionette';\n\nconst LabelView = View.extend({\n  template: ({ label }) => label,\n  modelEvents: { 'change:label': 'render' }\n});\nLabelView.setDataApi(BackboneApi);\nconst model = new Backbone.Model({ label: 'Inbox' });\nconst view = new LabelView({ model }).render();\nmodel.set('label', 'Archive');\n```\n\n| Method | Contract |\n| --- | --- |\n| `key(model)` | Returns `model.cid`, preserving each model's identity independently of its server ID. |\n| `get(model, name)` / `has(model, name)` | Read/check own attributes. `get` returns `undefined` when absent; `has` includes attributes whose value is `undefined`. |\n| `serialize(model)` | Returns the current `model.attributes` object, without copying it. |\n| `models(collection)` | Returns a shallow copy of the ordered `collection.models` array. |\n| `subscribe(source, nameOrMap, callback?, context?)` | Uses native Backbone events and preserves their names, payload arguments, and callback context. Returns an idempotent function that removes only these registrations. |\n| `observeCollection(collection, notify, context?)` | Translates native collection events into the structural changes below. Returns an idempotent disposer. |\n| `disposeOwned(source)` | Does nothing to the source itself. Owner subscriptions have already been released by StateApi cleanup. |\n\nFor event maps, use Backbone's map form with the context as the following argument. Standalone subscriptions do not add framework ownership; call the returned disposer when finished.\n\nA standalone `sort` reports `reorder`, retaining surviving child Views and DOM. `update` reports added/removed models; removals destroy those children. Merges retain the model and do not request a child rerender through collection observation—use the child's model events. `reset` reports `reset` and rebuilds children. The adapter treats sort events with truthy `add`, `remove`, or `merge` options as mutation-related and suppresses them. It relies on the `update` emitted by ordinary non-silent additions, removals and merges; reorder-only `set()` and explicit `sort()` do not provide that update.\n\n**Reorder-only limitation:** `collection.set([second, first])` can reorder existing Model instances without adding, removing, or merging any models. Backbone then emits `sort` with its default mutation options but no `update`, so the adapter leaves the CollectionView in its previous order. This replacement occurs with `add` and `remove` enabled when comparator sorting is inactive: no comparator, `sort: false`, or a supplied `at` option. In particular, `at` does not prevent full order replacement under those conditions; it is not a reliable way to move an existing model to a position. Attribute objects normally count as merges and produce an `update`; with `merge: false`, they can also take the reorder-only path.\n\nAfter a known reorder-only operation, use `collection.trigger('sort', collection, {})` to notify observing CollectionViews of the already-established order. For example, follow `collection.set([second, first])` with that notification when replacing the order of an unsorted collection. The notification does not sort or mutate the collection itself; with default CollectionView ordering (`sortWithCollection: true`), consumers reconcile the current order while retaining surviving child Views. Pass the explicit empty options object; do not reuse the `set()` mutation options. Do not add this notification after every `set()`, since ordinary additions, removals and merges already reconcile through `update`.\n\nFor an explicit comparator sort, call `collection.sort()` without forwarding truthy `add`, `remove`, or `merge` flags. Passing those flags suppresses that standalone sort notification too.\n\nMultiple consumers can share a source. Destroying one consumer removes its subscriptions and children while survivors continue receiving updates. Even factory-owned Backbone state is not destroyed by this adapter: source-wide `off()`, `stopListening()`, and persistence-capable `Model.destroy()` are not called.\n\n## XState actors\n\n`createXStateActorApi(options?)` returns a DataApi/StateApi for actors with synchronous snapshots containing an object `context`.\n\n| Option | Contract |\n| --- | --- |\n| `snapshotEvent` | Optional nonempty event name mapped to `actor.subscribe`. This name is reserved within that adapter. Other event names use `actor.on` and observe emitted events, not events sent to the actor. |\n| `select(snapshot)` | Required for collection use; returns ordered, distinct, non-null child actor references from a parent snapshot. Omit for model/state-only use. |\n\n```js\nimport { assign, createActor, createMachine } from 'xstate';\nimport createXStateActorApi from '@mnjs/adapters/xstate';\nimport { View } from 'marionette';\n\nconst actor = createActor(createMachine({\n  context: { label: 'Inbox' },\n  on: { rename: { actions: assign({ label: ({ event }) => event.label }) } }\n})).start();\nconst ActorApi = createXStateActorApi({ snapshotEvent: 'actor:snapshot' });\nconst ActorView = View.extend({\n  template: ({ label }) => label,\n  modelEvents: { 'actor:snapshot': 'render' }\n});\nActorView.setDataApi(ActorApi);\nconst view = new ActorView({ model: actor }).render();\nactor.send({ type: 'rename', label: 'Archive' });\n```\n\n`key(actor)` returns the actor reference. `get` and `has` read own context properties; `serialize` returns the current context object without copying. An already-started actor does not replay its current snapshot when subscribed; initial rendering reads `getSnapshot()` directly. Missing synchronous snapshots or non-object contexts raise `TypeError`.\n\n`subscribe(actor, eventName, callback, context?)` delivers the native snapshot or emitted-event payload, with the supplied callback context, and returns an idempotent unsubscribe function. Configure the reserved snapshot name when `modelEvents` or `stateEvents` should observe state changes.\n\nWith `select`, the returned adapter also supplies `models(parentActor)` and `observeCollection(parentActor, notify, context?)`. Replace the selected array when membership or order changes. Reusing its identity skips comparison; a fresh array requires a scan, but identical members/order produce no notification. Reorder retains child Views and DOM; removal destroys the removed child. Child context changes belong to child subscriptions. Respawning an actor with the same `id` creates a new model identity.\n\nObservers are independent. Releasing one removes only its subscription. Supplied data and state actors are borrowed and remain active after consumer destruction. An actor returned by `createState()` is owned: subscriptions are released first, then `disposeOwned(actor)` calls `actor.stop()`. The application must stop borrowed actors when their own lifetime ends.\n\n## DOM contents\n\nLit and Morphdom update contents synchronously and preserve the View's root element. They do not change template evaluation; [Renderer](/docs/api/providers/dom.md#renderer) produces the value that `setContents` receives. Root attributes remain under View control; use `renderAttributes()` to refresh them.\n\nParent rendering still destroys its Region children before updating contents. Keep Region placeholders empty in templates so only the Region manages their children. Configure a content adapter before the first render, and do not switch content adapters or independently replace their managed contents afterward.\n\n```js\nimport { View } from 'marionette';\nimport { html } from 'lit-html';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport MorphdomDomApi from '@mnjs/adapters/dom/morphdom';\n\nconst LitMessage = View.extend({\n  template: ({ message }) => html`<p>${message}</p>`,\n  templateContext() { return { message: this.message }; }\n});\nLitMessage.setDomApi(LitDomApi);\nconst MorphMessage = View.extend({\n  template: () => '<p id=\"message\">Hello</p>'\n});\nMorphMessage.setDomApi(MorphdomDomApi);\nconst lit = new LitMessage();\nlit.message = 'Hello';\nlit.render();\nconst morph = new MorphMessage().render();\n```\n\n### Morphdom\n\n`MorphdomDomApi` supplies `setContents(el, html)` for an HTML string, `null`, or `undefined`; nullish values clear the contents. An empty root receives the HTML directly. Existing contents are reconciled with Morphdom's `childrenOnly` behavior and normal matching rules, including element IDs. Matching elements can survive repeated renders; the root always remains. Use trusted HTML or an application template system that handles untrusted values safely.\n\n### Lit HTML\n\n`LitDomApi` supplies `setContents(el, value)`, `notifyAttach(el)`, and `notifyDetach(el)`. Templates can return Lit values such as `html` results. The first explicit render replaces existing contents; it does not hydrate them. Subsequent renders update the same marked range.\n\nThe notification methods connect/disconnect Lit directives through the stored root part. Marionette's attachment monitoring calls them when managed through Regions; keep `monitorViewEvents` enabled on the View and its ancestors. If monitoring is disabled or its handlers are removed, the application must deliver these notifications itself. Overrides of lifecycle methods must preserve parent behavior.\n\nDetach and destruction disconnect directive resources. Destruction can also release resources from a failed explicit render; failed construction does not roll back initialization. Release the previous View owner before adopting its element in another View. Lit event handlers use Lit's element receiver; use a closure when a handler needs View or application state.\n\n## jQuery\n\n`JQueryDomApi` overlays these DOM operations; it does not create `$el` or change View ownership. `getUI(name)` returns a jQuery collection under this adapter. If the application needs `$el`, initialize it with `$(this.el)`; the root is fixed for the View's lifetime.\n\n| Method | Contract |\n| --- | --- |\n| `findEl(el, selector)` | Returns a jQuery collection of descendants. Supports `Element` or `Document` roots. |\n| `detachEl(el)` | Detaches the element while retaining jQuery data and listeners. |\n| `setContents(el, html)` | Uses jQuery `.html()`; a nullish value clears contents. |\n| `appendContents(el, contents)` | Appends accepted jQuery HTML/node/collection content to an Element or DocumentFragment. |\n| `detachContents(el)` | Detaches children while retaining their jQuery data and listeners; keeps the root. |\n\n```js\nimport { View } from 'marionette';\nimport $ from 'jquery';\nimport JQueryDomApi from '@mnjs/adapters/dom/jquery';\n\nconst Controls = View.extend({\n  template: () => '<button>Open</button>',\n  ui: { open: 'button' }\n});\nControls.setDomApi(JQueryDomApi);\nconst view = new Controls().render();\nconst button = view.getUI('open');\nbutton.attr('aria-label', 'Open details');\n```\n\nTo combine jQuery query/attachment operations with Lit or Morphdom contents, call `setDomApi` with jQuery first and the content adapter second. Setters overlay supplied methods; the last supplied implementation wins. Other DOM operations retain their configured defaults.\n\n## TypeScript\n\nThe default exports carry their provider method types. XState additionally exports `XStateActorEventOptions` and `XStateActorApiOptions<ParentSnapshot, Actor>`; adding a typed selector exposes the collection methods in the factory result. Actor/source lifetimes still require runtime ownership decisions.\n\n```ts\nimport BackboneApi from '@mnjs/adapters/backbone';\nimport createXStateActorApi, { type XStateActorEventOptions } from '@mnjs/adapters/xstate';\nimport JQueryDomApi from '@mnjs/adapters/dom/jquery';\nimport { View } from 'marionette';\n\nconst LabelView = View.extend();\nLabelView.setDataApi(BackboneApi);\nconst options: XStateActorEventOptions = { snapshotEvent: 'actor:snapshot' };\nconst actorApi = createXStateActorApi(options);\nconst root = document.createElement('div');\nroot.innerHTML = '<button>Open</button>';\nconst buttons: JQuery<HTMLButtonElement> = JQueryDomApi.findEl<HTMLButtonElement>(root, 'button');\nvoid actorApi;\n```\n\n\n[Canonical source](/docs/markdown/docs/packages/adapters.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/integrations/setup.md",
      "title": "Setup and data",
      "section": "Integration guides",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/integrations/setup/",
      "markdownUrl": "https://marionettejs.com/docs/integrations/setup.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/integrations/setup.md",
      "sourceSha256": "da7a99e5bf1288b4762b1b37ec17ff8f289e1d634308401cc4d1694925854336",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "d5a3e20dd05c2a25a97e3d74d803d371fe45aff722a8a993f479021d78a56266",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 da7a99e5bf1288b4762b1b37ec17ff8f289e1d634308401cc4d1694925854336; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Setup and data\n\nContinue from the [quick start](/docs/quick-start.md). This page adds `@mnjs/data` for observable data and retains the Lit rendering configuration; those are independent integration choices. Core framework methods are covered in the [API reference](/docs/api.md).\n\n## Add observable data\n\nFrom the example project, install the data package at the same version as core:\n\n```sh\nnpm install --ignore-scripts --save-exact @mnjs/data@5.0.0\n```\n\nUse a different source with its compatible provider when it better fits your application. Views using plain template data do not require this package.\n\n## Configure once\n\nImport a setup module before constructing Applications or Views:\n\n```js\n// setup.js\nimport { setDataApi, setDomApi, setStateApi } from 'marionette';\nimport { DataApi, StateApi } from '@mnjs/data';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\n\nsetDataApi(DataApi);\nsetStateApi(StateApi);\nsetDomApi(LitDomApi);\n```\n\nThese setters configure the default class family. Standalone reference examples instead use `View.extend(...).setDomApi(...)` or `.setDataApi(...)` to keep their configuration local to a subclass. Both scopes are supported; configure the chosen scope before constructing instances. Use [runtime configuration](/docs/api/runtime.md) for class-specific or isolated setup, and the [provider references](/docs/api/providers/data.md) when connecting a different data solution. `DataApi` connects Models and Collections to Views; `StateApi` connects observable state to [state owners](/docs/api/runtime.md#choose-a-configuration-scope). The renderer calls a template function with its data, and the Lit DOM adapter places the result in the View's element.\n\n```js\nimport './setup.js';\nimport { View } from 'marionette';\nimport { html } from 'lit-html';\n\nexport const DetailView = View.extend({\n  template: ({ title, description }) => html`\n    <h3>${title}</h3>\n    <p>${description}</p>\n  `,\n});\n```\n\nOrdinary Lit interpolation renders these values as text, including characters such as `<`. No HTML escaping helper is needed. A View supplied with a Model receives its attributes as template data.\n\nA **provider** implements a Marionette contract such as DataApi, StateApi or DomApi. An **adapter** connects a particular library to that contract; for example, `LitDomApi` adapts Lit rendering. Installing an adapter does not configure it.\n\n## Observable data and API access\n\n`@mnjs/data` provides local observable Models and Collections. Use it alongside an API layer for fetching and persistence, or replace it with another data solution and the corresponding Marionette integration. Models and Collections do not provide an HTTP client, server synchronization, or a complete application data architecture.\n\nFor [initial feature data](/docs/api/application.md#prepare-before-showing-ui), an Application can import its API module directly, await the request in `prepareStart`, and return a Collection built from the response attributes. The successful result reaches `onStart`. If the API layer already supplies a compatible observable source, use it directly.\n\n```js\nimport { Model, Collection } from '@mnjs/data';\n\nconst item = new Model({ id: 'alpha', title: 'First item' });\nconst items = new Collection([item]);\nitem.set('title', 'Updated item');\n```\n\nUse [Model and Collection](/docs/packages/data.md) for attribute updates, membership, identity, events, and local disposal. A View can observe Model changes through `modelEvents`; CollectionView observes membership changes through DataApi. Reading data into a template alone does not subscribe to later attribute changes.\n\nUse [state ownership](/docs/api/shared/state.md) when an Application or View needs its own observable state. With StateApi configured, `createState` can return a Model whose disposal belongs to the owner. Passing `{ state }` borrows an existing source instead.\n\n\n[Canonical source](/docs/markdown/docs/integrations/setup.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/guides/framework-migration.md",
      "title": "Migrate from another UI framework",
      "section": "Guides",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/guides/framework-migration/",
      "markdownUrl": "https://marionettejs.com/docs/guides/framework-migration.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/guides/framework-migration.md",
      "sourceSha256": "cc41122b1459a8390ae30e9523c97cfb0b6eb328174b597d8429067001d77101",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "b28384f7a8cc0397c46b4e6b65206e2e58cb9cd92dc55ee204360bb6d7ec29c2",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 cc41122b1459a8390ae30e9523c97cfb0b6eb328174b597d8429067001d77101; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Migrate from another UI framework\n\nPreserve the application's observable behavior while designing a native Marionette\nownership tree. Translating each Vue component, React hook, or store into a similar\nMarionette file can preserve the old architecture's problems. Decide who owns data,\nUI, readiness, and mutations before choosing the order of implementation.\n\nThis guide targets **5.0.0**.\nUse [matching packages](/docs/quick-start.md#install-matching-packages) and their\ninstalled contracts. For an existing Marionette v4 app, use the separate\n[v4 migration guide](/docs/guides/migration.md).\n\n## 1. Inventory behavior before implementation\n\nBuild a journey matrix from the running original app and its public contracts.\nFor each journey, record the entry URL, role/permissions, inputs, visible outcomes,\nAPI methods/payloads, failure cases, and evidence. Include direct links, navigation,\nsearch/filter/sort, edits, uploads, empty states, keyboard/focus, persistence after\nreload, and work interrupted by navigation. Identify cross-feature behavior such\nas a rename appearing in both a list and an open detail panel.\n\nKeep known baseline bugs explicit: record the reproduction and decide whether to\npreserve it temporarily or fix it intentionally with a changed expectation. A\nfailing original journey is evidence, not permission to omit the feature. Separate\nobserved behavior from intended behavior where they differ.\n\nRun the original through its **public UI against a controlled backend** before\nbuilding the replacement. Reuse those same journey tests against the replacement\nby changing its base URL and startup configuration. Prefer accessible roles,\nlabels, URLs, visible state, and recorded API contracts. Avoid Vue component\ninstances, React internals, store getters, private Marionette fields, or selectors\nthat encode the old component tree. A small public test-id contract can identify\ncontrols without making their component layout part of the specification.\n\nControl test accounts, permissions, fixture reset, request delays, rejection,\nand out-of-order completion. Check that a successful edit survives reload and\nthat forbidden edits fail at the backend as well as being unavailable in the UI.\nKeep backend contract tests alongside browser journeys; local mocks cannot prove\nserver permissions or real payload compatibility. Review test changes separately:\ndo not weaken assertions or add skips to make the replacement pass. Deliberately\nbreak a representative response or interaction and confirm the test fails.\n\n## 2. Draw the final ownership tree independently\n\nUse [architecture](/docs/architecture.md) to define the target tree from domain\nlifetimes and user journeys. The old source is evidence for business rules and\nedge cases; its folders and component boundaries do not decide the final tree.\n\nFor a record workspace, distinguish lifetime ownership from screen placement:\n\n```text\nLifetime owners\nWorkspaceApplication\n├─ ShellView — persistent root UI\n└─ registered RecordApplication\n   ├─ draft — shared workflow state\n   └─ RecordPageView — feature root UI\nRecordService — transport, serialization and persistence contracts\n\nScreen placement\nShellView\n└─ destination Region ← RecordApplication.showView()\n   └─ RecordPageView\n      ├─ editor Region → TitleEditorView (borrows draft)\n      └─ summary Region → SummaryView (latest loaded title)\n```\n\nWorkspaceApplication registers RecordApplication and explicitly starts/stops it;\nregistration alone neither starts nor awaits a child. ShellView owns the destination\nRegion used to place the feature's root View. Emptying that Region removes UI but\ndoes not stop the Application or end its ongoing authority: the feature owner must\nstop or destroy it when ending the run. After showing the ShellView instance `shell`, pass\n`shell.getRegion('destination')` as `region` to the child instance's\n`start({ region, id })`. The\n[asynchronous routing example](/docs/guides/routing.md#route-to-asynchronous-features) shows the\ncomplete shell-to-child handoff;\n[child Application ownership](/docs/api/application.md#child-applications) explains\nregistration and cleanup.\n\nAn Application coordinates a feature lifetime; a View owns presentation and local\ninteraction; a Region places and disposes its child. Use CollectionView for repeated\nrecords that need independent children. A View can call its model/API layer to save\na local edit; an async call alone does not justify an Application. Put shared\nworkflow decisions and work that survives panel replacement with a surviving owner.\n\nFor every source or operation, record:\n\n| Decision | Example |\n| --- | --- |\n| Owner and borrowers | RecordApplication owns its draft; editor borrows it. A shared record cache belongs to the session/service lifetime. |\n| Mutation authority | Editor updates draft title; feature coordinates publishing; service persists. Siblings emit intent instead of editing each other's DOM. |\n| Readiness | `prepareStart(options, { signal })` loads required data; `onStart` applies only the current result. |\n| Retention | Restart preserves shell/input; Region replacement destroys its outgoing View; stop destroys root UI but retains Application state. |\n| Cancellation and release | Pass preparation signal to transport. Give ongoing saves their own cancellation/concurrency policy and end external effects at their owner. |\n\n`start()` and `restart()` resolve `true` on success, `false` when superseded or\ncancelled, or when a stopping/terminal owner prevents activation. Current\npreparation or startup-callback failures reject; synchronous failures do not roll\nback completed work. `stop()` and `destroy()` are synchronous;\nnotification hooks do not await Promises. The preparation signal ends with that\noperation, so it is not an ongoing feature-lifetime signal. Avoid application side\neffects during preparation that could commit after cancellation. See\n[Application](/docs/api/application.md), [retained restart](/docs/guides/retained-restart.md), and\n[routing](/docs/guides/routing.md) for complete lifecycle/error boundaries.\n\nA supplied state source is borrowed; `createState()` establishes owned state.\nDeclare what survives panel replacement, route exit, stop, and reload separately.\nChoose one writer or an explicit conflict policy for each shared mutation. Model\nobservation and server persistence are separate capabilities: optional [@mnjs/data](/docs/packages/data.md)\nhas no `Model.save()` or `fetch()` contract. Do not assume Backbone methods.\n\n## 3. Choose the migration strategy deliberately\n\nA replacement branch can have incomplete routes while the correct architecture is\nbeing built. Full parity is the final goal; keeping a hybrid app functional at\nevery intermediate checkpoint is not a default requirement. Preserve the runnable\noriginal as the baseline and record unavailable replacement journeys honestly.\n\nChoose **leaf-first** when a leaf has a clean DOM/data boundary and its replacement\nwill be reused unchanged in the target tree. A date picker or independent panel\nmay qualify. Do not start there merely because leaves are small: dependencies on\nold stores, parent effects, or component conventions can turn every leaf into a\ncompatibility project. Build those leaves inside the replacement shell when\ncoexistence is unnecessary; hosting a leaf in the running original requires the\nbridge ownership and deletion criteria below.\n\nChoose a **native feature-family replacement** when the old tree obscures ownership\nor when no production coexistence is required. Establish the shell, service boundary,\nand one representative journey, then migrate related behavior in broad batches:\nrecord list/filter/detail; editing/validation/persistence; permission-sensitive\ncommands; navigation/recovery. Each batch includes its data, UI, effects and tests,\nrather than converting files individually. This avoids repeatedly inventing the\nsame authority and cleanup rules across dozens of components.\n\nPilot a representative risk early: an editable record with a shared list/detail,\na permission boundary, delayed readiness, navigation away, and retry. Use it to\nchallenge the ownership plan before scaling. A trivial static page is useful for\ninstallation, but does not validate migration architecture.\n\nIf production must run both frameworks, use [existing UI](/docs/guides/existing-ui.md) for an\nexplicit host boundary: one owner per DOM subtree, public inputs/events, cleanup\nbefore removing the mount, and no sibling DOM access. Record the bridge owner,\nwhy coexistence is required, the consuming routes, and the concrete condition for\ndeleting the bridge and its dependencies. Keep the bridge at that boundary rather\nthan teaching every new View the old framework's store or lifecycle.\n\n## 4. Work through a native ownership example\n\nThis invented Vue-like sketch combines readiness, UI and draft authority in a\ncomponent. It is illustrative pseudocode, not an executable Vue recipe:\n\n```text\nRecordPage.vue\n  setup(): obtain route id and global store\n  watch(route.id): fetch record, overwrite store, reset form\n  component state: title draft and request/loading flags\n  template: title editor + summary + reload button\n  child callbacks: write global store and query parent's DOM\n  unmount(): cancel component request\n```\n\nThe native replacement below separates readiness from local interaction. It uses\nLit for safe text interpolation and stable input updates, and observable state\nfrom `@mnjs/data`. Follow [setup](/docs/integrations/setup.md) for matching companion\npackages. `GET /records/42.json` returns `{ \"title\": string }`; API access stays in\n`loadRecord`, which can move into the application's service module. See\n[production deployment](/docs/guides/production.md#serve-direct-links-deliberately) for HTTPS\nand direct-link requirements.\n\n```js\nimport { Application, View } from 'marionette';\nimport { Model, DataApi, StateApi } from '@mnjs/data';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\nimport { live } from 'lit-html/directives/live.js';\n\nasync function loadRecord(id, signal) {\n  const response = await fetch(`/records/${encodeURIComponent(id)}.json`, { signal });\n  if (!response.ok) throw new Error('Could not load record.');\n  return response.json();\n}\nconst PageView = View.extend({\n  template: () => html`\n    <button type=\"button\" class=\"reload\">Reload</button>\n    <section class=\"editor\"></section><section class=\"summary\"></section>`,\n  regions: { editor: '.editor', summary: '.summary' },\n  triggers: { 'click .reload': 'reload' },\n}).setDomApi(LitDomApi);\nconst TitleEditorView = View.extend({\n  template: ({ title }) => html`\n    <label>Title <input class=\"title\" .value=${live(title)}></label>`,\n  ui: { title: '.title' },\n  events: { 'input @ui.title': 'editTitle' },\n  modelEvents: { 'change:title': 'render' },\n  editTitle() { this.model.set('title', this.getUI('title')[0].value); },\n}).setDataApi(DataApi).setDomApi(LitDomApi);\nconst SummaryView = View.extend({\n  template: ({ loadedTitle, error }) => html`\n    <p>Loaded title: ${loadedTitle}</p><p role=\"status\">${error}</p>`,\n  modelEvents: { 'change:loadedTitle': 'render', 'change:error': 'render' },\n}).setDataApi(DataApi).setDomApi(LitDomApi);\n\nconst RecordApplication = Application.extend({\n  createState() { return new Model({ title: '', loadedTitle: '', error: '' }); },\n  viewEvents: { reload: 'reloadRecord' },\n  prepareStart({ id }, { signal }) { return loadRecord(id, signal); },\n  onStart(_app, { id }, record) {\n    this.recordId = id;\n    const state = this.getState();\n    state.set({ loadedTitle: record.title, error: '' });\n    if (this.getView()) return;\n    state.set('title', record.title);\n    const page = this.setView(new PageView());\n    page.showChildView('editor', new TitleEditorView({ model: state }));\n    page.showChildView('summary', new SummaryView({ model: state }));\n    this.showView();\n  },\n  reloadRecord() {\n    return this.restart({ id: this.recordId }).catch(error => {\n      this.getState().set('error', error.message);\n    });\n  },\n}).setStateApi(StateApi);\n\nconst mount = document.createElement('main');\ndocument.body.append(mount);\nconst app = new RecordApplication({ region: { el: mount } });\nawait app.start({ id: '42' });\n```\n\nReload repeats readiness for the **same record**. Only SummaryView updates; the\npage and editor stay owned by their Regions, and unfinished input survives. The\neditor's `ui` map gives its owned control one name instead of repeated\n`querySelector` calls. Read `getUI('title')[0]` after binding; bindings rebind on\nrender and are snapshots, so do not keep a stale element across replacement.\nThe editor observes title changes so external updates also appear. Its rerender\nretains the input through the chosen Lit integration and `live()` binding; verify\nfocus and caret behavior before substituting another renderer.\n\nCalling `start({ id: next })` on an active Application resolves `true` without\nrepeating preparation or applying the new options. This example supports restart\nonly for its current record; a different-id restart would retain the old draft\nbeside the new loaded title.\n\nA route to another record needs a deliberate draft policy: retain drafts by id,\nask before discarding, or stop/start to reconstruct. Do not use this same-record\nreload as an implicit navigation policy. This example resets the draft from loaded\ndata after stop/start, although the Application retains its state source. Preserving\ndrafts across reconstruction requires an explicit policy, such as drafts keyed by id.\nFor initial readiness failure, the caller\nhandles rejection and stops the failed run before error presentation; the\n[routing example](/docs/guides/routing.md#route-to-asynchronous-features) supplies that boundary.\n`reloadRecord` reports current lifecycle rejections, including startup-callback\nfailures; it is not a load-only error classifier. Reporting feedback does not roll\nback partial updates or establish safe recovery from callback bugs. Follow the\n[Application failure contract](/docs/api/application.md#preparation-cancellation-and-failure)\nwhen deciding the application's recovery and diagnostic policy.\n\nThis example has no save operation: adding one requires the service's write\ncontract and a decision about cancellation, duplicate submissions, conflict, and\nwhich surviving owner receives completion. See [local editing](/docs/guides/local-editing.md).\n\n## 5. Use separate architecture and behavior gates\n\nAt each feature-family checkpoint, review **source** for the intended ownership,\nmutation authority, cancellation, stable UI bindings, and removed compatibility\npaths. Then run the reusable **behavior tests** against the integrated replacement.\nPassing interactions can hide a replacement that still delegates to the old app;\na clean source tree can still break a journey. Neither gate replaces the other.\n\nKeep one short checkpoint record in the application's existing project notes:\n\n```text\nBatch: record editing\nDecisions: feature owns draft; service persists; same-record reload retains editor\nEvidence: exact revision/packages, commands, environment, journey results\nOpen failures: permission revocation during save; unimplemented bulk edit route\nCoverage boundary: real backend tested for save; conflict path still mocked\nNext: resolve conflict policy, complete bulk edit, rerun list/detail/save together\n```\n\nExercise true integration across feature families: direct URL → readiness → edit\n→ save → list/detail update → navigation → reload; also auth expiry and permission\nchanges, rapid route changes, slow responses, stop/start, and repeated attachment\nwhere widgets/listeners depend on it. Use a real browser for focus, keyboard,\nhistory and editable-state behavior. Component tests and screenshots support this\ncoverage but do not establish it. Report baseline failures separately from new\nregressions and explicitly unimplemented routes. Test counts and converted file\ncounts are progress measures, never completion claims.\n\n## 6. Audit the final replacement\n\nThe replacement is complete when every required journey passes its recorded\nexpectation, updated for documented intentional changes, and every baseline bug\nhas a recorded disposition. No required route remains unimplemented; checkpoint\nfailures are resolved or recorded as intentional behavior changes. Re-run the full\njourney matrix and backend contract checks against the production entrypoint and controlled backend, including the interruption and\nfailure cases. Review changed expectations independently from implementation.\nAudit source imports,\ndynamic imports, route lazy chunks, build plugins, manifests/lockfile, and the\nactual generated bundle/module graph. Remove the old framework, adapters, stores,\nbridges, obsolete entrypoints, unused styles, and dependencies when no required\nconsumer remains. A green suite does not prove removal; verify the new app cannot\nreach or invoke the old implementation, including through lazy routes.\n\nPreserve applicable public licenses and attribution for reused source/assets.\nUse public examples or authorized project code; do not copy private application\nsource into public documentation or fixtures. The public\n[Marionette RealWorld example at a pinned revision](https://github.com/marionettejs/marionette-realworld-example-app/tree/34ceaa5987c1e80dfa6b6f2285cb9fcb5296ce04)\nis a reference to inspect, not proof of parity for another application.\n\n## Agent checklist\n\n- Pin original/replacement revisions, package contract, backend fixtures and known bugs.\n- Run portable journey tests on the original; check their ability to catch breakage.\n- Define target owners, borrowers, writers and cancellation before converting code.\n- Choose leaf-first or native feature batches with a reason; document bridge deletion only if needed.\n- Pilot representative risk, then complete related behavior in broad batches.\n- Review architecture and test changes separately from integrated behavior results.\n- Record decisions, exact evidence, incomplete routes and open failures at checkpoints.\n- Complete every required journey against recorded expectations, documenting intentional changes; resolve open failures and prove old-framework removal in imports, dependencies and bundles.\n\n## Further reading\n\n[Playwright best practices](https://playwright.dev/docs/best-practices) covers\nuser-facing locators, isolated test state, controlled data, and retrying assertions\nfor the reusable browser journeys.\n\n[Addy Osmani's Brownfield Agentic Engineering](https://addyosmani.com/blog/brownfield-agentic-engineering/)\nexplains characterization, durable context, and completing migration units with\nold dependencies removed.\n[Anthropic's migration guide](https://claude.com/blog/ai-code-migration)\ndescribes a portable behavior judge, checking that it detects broken behavior,\nand distinguishing translation from architectural redesign. Apply those verification\nprinciples to UI journeys while using Marionette's installed contracts for the\nreplacement architecture.\n\n\n[Canonical source](/docs/markdown/docs/guides/framework-migration.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/guides/migration.md",
      "title": "Migrate from Marionette v4",
      "section": "Guides",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/guides/migration/",
      "markdownUrl": "https://marionettejs.com/docs/guides/migration.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/guides/migration.md",
      "sourceSha256": "5e0f72c9da11b024c6cbba37d676ebbcc05548ca53b8f4d12a0215c3f67da7a9",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "6b7c3cab3bd08d8323a445af2180bf35f69273e4f9fb7fd256240ed965c88db5",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 5e0f72c9da11b024c6cbba37d676ebbcc05548ca53b8f4d12a0215c3f67da7a9; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Migrate from v4 to v5\n\nUpgrade one application and its messaging participants together. Start from a working v4 application with checks for its important interactions, then change installation and integration setup before changing feature ownership. This guide covers common v4 application code; custom providers and low-level overrides should also be checked against their [reference contracts](/docs/api.md).\n\nFor an agent-assisted upgrade, give the agent this guide and the\n[agent entrypoint](/docs/agents.md), plus the application's entrypoint and existing\nbehavior checks. Have it inspect the installed package's docs, migrate one\nrepresentative feature, and run the checks in section 4 before repeating the\nchanges elsewhere. Keep data-layer replacement separate from the framework\nupgrade unless the application needs both.\n\n## 1. Replace installation and configure integrations\n\nReplace `backbone.marionette` with the matching `marionette` v5 release. Follow [package installation](/docs/quick-start.md#install-matching-packages) for the current package artifacts and companion versions. If you already use named imports, change their package path. Replace default namespace imports with named imports: `import { Application, View, MnObject, Radio } from 'marionette'`. The former namespace's `Object` alias becomes `MnObject`.\n\nCore supplies native DOM operations and accepts plain objects and static arrays. Backbone, jQuery, and Underscore are no longer required by core. Remove a dependency only when the application itself no longer uses it.\n\nConfigure the data sources and rendering your application actually uses in one setup module, imported before constructing consumers:\n\n- An existing Backbone application can retain its Models, Collections, and persistence operations. Import `BackboneApi` from `@mnjs/adapters/backbone`, then call `setDataApi(BackboneApi)`. Call `setStateApi(BackboneApi)` separately when owners use Backbone state. This connects existing data without changing Backbone objects or their native methods.\n- For new observable data, [@mnjs/data](/docs/packages/data.md) provides local Models and Collections. Use its `DataApi` and, when needed, `StateApi` as described in [setup](/docs/integrations/setup.md). Fetching and persistence remain separate concerns. Replacing Backbone's `save`, `fetch`, or server-side `destroy` requires a deliberate data-layer change.\n- The default renderer calls a template function with its data; it does not compile template selector strings. Preserve an application template compiler through `setRenderer` when needed. For Lit templates, configure `LitDomApi` from `@mnjs/adapters/dom/lit-html` with `setDomApi`.\n- Code requiring jQuery query or content methods can explicitly select `JQueryDomApi` from `@mnjs/adapters/dom/jquery`. This adapter does not create `$el` or restore jQuery event delegation. Its peer requirement is jQuery 4; verify application plugins before selecting it.\n\nSee [adapters](/docs/packages/adapters.md) for installation, provider behavior, and tested peers. Ordinary applications can use the default runtime setters; [runtime configuration](/docs/api/runtime.md) also supports class-specific setup and isolation.\n\nReplace every `backbone.radio` import with the selected runtime's Radio in the same upgrade, including publishers and requesters outside Marionette classes. The old and new buses have independent channels, so leaving either participant on the old bus disconnects communication. Default-runtime code can import `Radio` from `marionette`; isolated runtime code must use that runtime's `Radio`. Replace `Radio.DEBUG = true` with `Radio.setDebug()`. `Radio.log` and `Radio.debugLog` remain assignable logging hooks. See [Radio](/docs/packages/radio.md) for registry scope and request/reply methods.\n\n### Import and configure existing Backbone data\n\nThis upgrade retains Backbone persistence. Change every Radio participant together:\n\n```diff\n-import Mn from 'backbone.marionette';\n-import Radio from 'backbone.radio';\n+import { View, Radio, setDataApi } from 'marionette';\n+import BackboneApi from '@mnjs/adapters/backbone';\n+setDataApi(BackboneApi);\n\n-const Editor = Mn.View.extend({ modelEvents: { change: 'render' } });\n+const Editor = View.extend({ modelEvents: { change: 'render' } });\n```\n\n### Replace jQuery event assumptions\n\nNative delegated events require explicit cancellation. `getUI()` still returns a\ncollection, so select its element before using DOM properties:\n\n```diff\n onSave(event) {\n-  const title = this.getUI('title').val();\n+  event.preventDefault();\n+  const title = this.getUI('title')[0].value;\n   this.model.save({ title });\n-  return false;\n }\n```\n\nThis example assumes the Backbone provider above and a single named input. Add\n`event.stopPropagation()` when stopping propagation was part of the intended v4\nbehavior; cancelling a form submission alone does not require it.\n\n## 2. Update Views and composition\n\nThe root remains fixed for each View's lifetime. Resolve selector strings to actual elements before supplying `el`; unwrap an existing jQuery element with `[0]`. To use a different root, destroy the old View and construct a new one. Regions still accept selector strings as mount points.\n\n| Existing code or assumption | v5 change |\n| --- | --- |\n| `setElement(...)`, inherited `remove()` | Construct with the intended `el`; use `destroy()` for complete teardown. |\n| `$el`, jQuery methods on `ui.name`, `getUI(...)`, or `this.$(selector)` | Native UI queries return array-like collections. Use `this.getUI('name')[0]` for one element. With the jQuery DOM adapter, UI queries return jQuery collections; create `$(this.el)` explicitly if the application needs a root wrapper. |\n| jQuery delegated events, `return false`, event namespaces | Native handlers receive a DOM event. Use `event.delegateTarget` for a selector match and explicit `preventDefault()` / `stopPropagation()` when needed. Core does not inherit singular `delegate` / `undelegate` helpers. |\n| `children.findByModelCid(model.cid)` | Use `children.findByModel(model)`. For an explicit provider key, use `findByKey(key)`; keys come from the configured DataApi, not necessarily a Backbone `cid`. |\n| `viewComparator: false` to ignore collection reordering ([v4.1.3 example](https://github.com/marionettejs/backbone.marionette/blob/v4.1.3/docs/marionette.collectionview.md#defining-the-viewcomparator)) | Also set `sortWithCollection: false`; disabling the comparator alone does not disable v5 source reorder notifications. |\n| Collection-only templates reading `items` | Read `models`, the array of serialized model values. This change applies to a View's collection template data. |\n| `region.show(stringOrOptions)` or `showChildView(name, template)` | Construct the intended View explicitly and pass its instance. |\n| `getRegion`, `getRegions`, or `hasRegion` implicitly rendering a layout | These are inspection methods. Use `showChildView` for composition, or explicitly render before showing directly through a selector Region. |\n| View Region registration/removal events | Put setup alongside registration and observe the Region's own destruction when needed. The View's `add:region` / `remove:region` notifications are removed. |\n| Global `setEnabled` / `isEnabled` calls | Remove the registry. Configure `childViewEventPrefix` on the View and `preventDefault` / `stopPropagation` on individual trigger definitions. Move application settings to explicit configuration or state. |\n| Lifecycle hooks supplied as constructor options | Define hooks on the class or instance. `triggerMethod` resolves instance/prototype methods. |\n| `bind` / `unbind`, or space-separated framework event names | Use `on` / `off`. Each event or request name is literal; use maps or separate calls for multiple names. Backbone sources retain their own native event semantics. |\n| Root imports of target-first utility wrappers | Prefer the object's method, or use the receiver-based functions from [@mnjs/utils](/docs/packages/utils.md). |\n\nThe UI query and native DOM handler changes also apply to Behaviors; their element and delegated interactions belong to the host View. See [Behavior](/docs/api/behavior.md) for that contract.\n\nKeep root attributes distinct from template contents. `renderAttributes()` refreshes declared root attributes; `render()` refreshes contents. Native attribute removal requires `null`, and boolean HTML attributes should be present or absent rather than assigned `false`. Set live input values through DOM properties. See [View bindings](/docs/api/shared/view-bindings.md) for templates, attributes, UI, and events.\n\nFor CollectionView customizations, `attachHtml(els, container)` receives a native container. The child container supports iteration and its documented helpers; replace removed Underscore aliases or iteratee shorthand with explicit callbacks/native array operations. Sorting and filtering retain their public methods and callback forms; verify the [CollectionView reference](/docs/api/collection-view.md) when overriding them. After changing a Model attribute used by a comparator or filter, call `list.sort()` or `list.filter()` explicitly. This applies to both `@mnjs/data` and Backbone Models. Filtering still detaches rows without destroying them, and `children` still describes the presented set. These are presentation operations, not collection membership changes.\n\n## 3. Make feature readiness and ownership explicit\n\nIn v4, `Application.start()` fired notifications synchronously on every call and returned the Application. v5 adds `stop()`, `restart()`, and `isRunning()`. Await `start()` and `restart()`: they return `Promise<boolean>` and can reject. `stop()` and `destroy()` return synchronous booleans; remove Promise chaining and asynchronous teardown hooks. Starting an already-running Application does not repeat preparation. Handle failure at the boundary that requests the operation.\n\nMove work required before showing a feature from an async `onStart` or `onRender` into `prepareStart(options, { signal })`. Pass the signal to the request; return the ready result for `onStart(app, options, result)`. Notification hooks remain synchronous and their returned Promises are not awaited. The [Application reference](/docs/api/application.md#prepare-before-showing-ui) contains a complete readiness example and explains cancellation and failure.\n\nUse `onStart` to apply the ready result. Construct the shell and its connections once if it should survive restart; `viewEvents` observes root intent without rebinding on every start. When composing before attachment, call `setView(page)`, then the page's `showChildView(...)`, then `showView()`. The Application owns its selected root; stop destroys it, and a later start creates a new one. A Region built from constructor configuration is owned; a supplied Region instance is borrowed and remains reusable.\n\nRegister child Applications through `childApps` or `addChildApp` when the parent should own their lifetime. Registration does not start them: request their start explicitly and handle that Promise. Parent stop stops registered children; parent destruction destroys them. Keep local input/model edits in their View when they need no feature coordination; Application is useful when readiness, shared workflow, or lifetime requires an owner.\n\n`restart()` repeats preparation without stopping the active run. Keep the root and its child Views in `onStart` when preserving focus and input; see [retained restart](/docs/guides/retained-restart.md). Restart leaves registered children active, so restart a child explicitly when its readiness must change too. Use `app.stop(); await app.start(options)` for reconstruction or host relocation. Finish required saves before calling synchronous stop/destroy. Ordinary `listenTo` subscriptions to surviving sources remain bound across stop and restart.\n\n## 4. Verify the migrated application\n\nCheck the installation and actual entrypoint first, then exercise representative behavior. The [consumer-testing guide](/docs/guides/testing.md) supplies runnable checks for interaction, replacement, readiness and teardown:\n\n1. A successful start shows ready UI; a failed or superseded start does not commit obsolete UI. Verify that callers handle rejection.\n2. Local edits and collection membership/order changes update through the chosen data provider. Existing Backbone persistence still uses its intended API.\n3. Events and Radio requests reach every intended participant. Check event maps and former whitespace-separated names.\n4. Replacing a panel destroys the old View while surviving shared data remains usable. Stopping and starting a feature recreates its root; restart preserves the intended controls through loading, failure, and the chosen successful update.\n5. Successful owner destruction removes its UI and releases its subscriptions. A surviving listener receives the final `destroy` notification, then the destroyed Marionette source releases incoming listeners automatically. Extra destroy-to-`stopListening(source)` handlers are unnecessary for Marionette sources; external sources keep their own cleanup contracts.\n\nRemove manual root/registered-child destruction that duplicates Application ownership. Continue releasing application-owned timers, external subscriptions, and operations outside preparation according to their lifetime; framework cleanup cannot infer those resources. Use public behavior checks rather than private event registry assertions. See [event cleanup](/docs/api/shared/events.md#cleanup) and the class references when deciding who disposes a resource.\n\n\n[Canonical source](/docs/markdown/docs/guides/migration.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/guides/testing.md",
      "title": "Test an application",
      "section": "Guides",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/guides/testing/",
      "markdownUrl": "https://marionettejs.com/docs/guides/testing.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/guides/testing.md",
      "sourceSha256": "d0c956ff2ea1ccf292b3e406fd45d9d00380a20cd79624aa2f17240d23e8e482",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "152eafd28ab70b64eb2ad33d8272a00864552f0dd4e2f33701000eb79475dd96",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 d0c956ff2ea1ccf292b3e406fd45d9d00380a20cd79624aa2f17240d23e8e482; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Test a consumer application\n\nTest what a user or owning component can observe: rendered content, interaction, readiness, and disposal. A local editing View needs no Application. An Application test is useful when a feature must prepare before showing its screen.\n\nThis recipe uses Node's built-in test runner and JSDOM. Use a [supported Node LTS release](/docs/quick-start.md). First install `marionette`, `@mnjs/adapters`, `lit-html`, and `@mnjs/data` using the [package installation](/docs/quick-start.md) and [data setup](/docs/integrations/setup.md). Add the DOM implementation used here:\n\n```sh\nnpm install --save-dev --save-exact jsdom@30.1.0\n```\n\nCreate these four files in a `test` directory. The `.mjs` extension works without changing your application's module configuration. The example configures data and rendering on its own View classes to keep this recipe self-contained. Tests of your real classes should import your application setup module after the DOM preload and before those classes, as described in [integration setup](/docs/integrations/setup.md). `@mnjs/data` supplies optional observable attributes; API requests and persistence need a separate layer or another data solution.\n\n## `test/dom.mjs`\n\nInstall the DOM before importing Marionette and Lit. Both can capture their DOM environment during module initialization.\n\n```js\nimport { JSDOM } from 'jsdom';\n\nconst dom = new JSDOM('<!doctype html><html><body></body></html>', {\n  url: 'https://example.test/',\n});\nglobalThis.window = dom.window;\nglobalThis.document = dom.window.document;\nglobalThis.HTMLElement = dom.window.HTMLElement;\n```\n\n## `test/title-editor.mjs`\n\nThis local interaction changes only the View's own model. Lit retains the input across renders, and `live` compares the binding with its current DOM value.\n\n```js\nimport { View } from 'marionette';\nimport { DataApi } from '@mnjs/data';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\nimport { live } from 'lit-html/directives/live.js';\n\nexport const TitleEditor = View.extend({\n  template: ({ title }) => html`\n    <label>Title <input class=\"title\" .value=${live(title)}></label>\n    <p class=\"preview\">${title}</p>\n  `,\n  ui: { title: '.title' },\n  events: { 'input @ui.title': 'editTitle' },\n  modelEvents: { 'change:title': 'render' },\n  editTitle() {\n    this.model.set('title', this.getUI('title')[0].value);\n  },\n}).setDataApi(DataApi).setDomApi(LitDomApi);\n```\n\n## `test/summary-application.mjs`\n\nReadiness stays with the Application. The feature requests `/summary.json`, which returns an object with a string `title`. Tests replace `fetch` to hold, resolve, or reject this boundary without a network or arbitrary delay.\n\n```js\nimport { Application, View } from 'marionette';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\n\nconst SummaryView = View.extend({\n  template: ({ title }) => html`<h1>${title}</h1>`,\n}).setDomApi(LitDomApi);\n\nexport const SummaryApplication = Application.extend({\n  async prepareStart(_options, { signal }) {\n    const response = await fetch('/summary.json', { signal });\n    if (!response.ok) throw new Error('Could not load the summary.');\n    return response.json();\n  },\n  onStart(_app, _options, summary) {\n    this.showView(new SummaryView({ model: summary }));\n  },\n});\n```\n\nThe test runner restores its `fetch` mock after each test. Keep this recipe's tests sequential because they share a DOM and a global fetch boundary.\n\n## `test/app.test.mjs`\n\nEach test owns a mount and disposes the resources it creates. Assertions use public methods and DOM outcomes; they avoid listener tables, internal flags, and lifecycle implementation details. The replacement test spies on the public `render` method to detect a removed View reacting to a shared Model, even if rendering a destroyed View would make no visible change.\n\n```js\nimport assert from 'node:assert/strict';\nimport { test } from 'node:test';\nimport { Region, View } from 'marionette';\nimport { Model } from '@mnjs/data';\nimport { TitleEditor } from './title-editor.mjs';\nimport { SummaryApplication } from './summary-application.mjs';\n\ntest('editing updates the model and rendered title', t => {\n  const mount = document.body.appendChild(document.createElement('section'));\n  const region = new Region({ el: mount });\n  const model = new Model({ title: 'Untitled' });\n  t.after(() => { region.destroy(); model.destroy(); mount.remove(); });\n  const editor = new TitleEditor({ model });\n  region.show(editor);\n\n  const input = editor.getUI('title')[0];\n  input.value = 'Edited';\n  input.dispatchEvent(new window.Event('input', { bubbles: true }));\n  assert.equal(model.get('title'), 'Edited');\n  assert.equal(editor.el.querySelector('.preview').textContent, 'Edited');\n  assert.equal(editor.getUI('title')[0], input);\n  model.set('title', 'External change');\n  assert.equal(input.value, 'External change');\n});\n\ntest('replacing a Region destroys the old View and releases its subscriptions', t => {\n  const renders = t.mock.method(TitleEditor.prototype, 'render');\n  const mount = document.body.appendChild(document.createElement('section'));\n  const region = new Region({ el: mount });\n  const model = new Model({ title: 'Original' });\n  t.after(() => { region.destroy(); model.destroy(); mount.remove(); });\n  const editor = new TitleEditor({ model });\n  region.show(editor);\n  const input = editor.getUI('title')[0];\n  const oldRoot = editor.el;\n  const replacement = new View({ template: () => '<p>Replacement</p>' });\n  region.show(replacement);\n\n  assert.equal(editor.isDestroyed(), true);\n  assert.equal(oldRoot.isConnected, false);\n  assert.equal(region.currentView, replacement);\n  assert.equal(model.isDestroyed(), false);\n  const renderCount = renders.mock.callCount();\n  model.set('title', 'Still borrowed');\n  assert.equal(renders.mock.callCount(), renderCount);\n  assert.equal(oldRoot.querySelector('.preview').textContent, 'Original');\n  input.value = 'Removed control';\n  input.dispatchEvent(new window.Event('input', { bubbles: true }));\n  assert.equal(model.get('title'), 'Still borrowed');\n  assert.equal(mount.textContent, 'Replacement');\n});\n\ntest('readiness precedes activation and stop destroys the screen', async t => {\n  const mount = document.body.appendChild(document.createElement('section'));\n  const request = Promise.withResolvers();\n  t.mock.method(globalThis, 'fetch', () => request.promise);\n  const app = new SummaryApplication({ region: { el: mount } });\n  t.after(() => { app.destroy(); mount.remove(); });\n  const starting = app.start();\n  assert.equal(app.isRunning(), false);\n  assert.equal(mount.childElementCount, 0);\n  request.resolve(new Response(JSON.stringify({ title: 'Ready summary' })));\n  assert.equal(await starting, true);\n  assert.equal(app.isRunning(), true);\n  assert.equal(mount.querySelector('h1').textContent, 'Ready summary');\n  const screen = app.getView();\n\n  assert.equal(app.stop(), true);\n  assert.equal(app.isRunning(), false);\n  assert.equal(screen.isDestroyed(), true);\n  assert.equal(mount.childElementCount, 0);\n  const region = app.getRegion();\n  assert.equal(app.destroy(), true);\n  assert.equal(app.isDestroyed(), true);\n  assert.equal(region.isDestroyed(), true);\n});\n\ntest('failed readiness leaves an initially stopped feature without a screen', async t => {\n  const mount = document.body.appendChild(document.createElement('section'));\n  const failure = new Error('Unavailable');\n  t.mock.method(globalThis, 'fetch', async () => { throw failure; });\n  const app = new SummaryApplication({ region: { el: mount } });\n  t.after(() => { app.destroy(); mount.remove(); });\n  await assert.rejects(app.start(), error => error === failure);\n  assert.equal(app.isRunning(), false);\n  assert.equal(app.getView(), undefined);\n  assert.equal(mount.childElementCount, 0);\n});\n\ntest('stop cancels pending readiness and an obsolete result cannot show UI', async t => {\n  const mount = document.body.appendChild(document.createElement('section'));\n  const request = Promise.withResolvers();\n  let preparationSignal;\n  t.mock.method(globalThis, 'fetch', (_url, { signal }) => {\n    preparationSignal = signal;\n    return request.promise;\n  });\n  const app = new SummaryApplication({ region: { el: mount } });\n  t.after(() => { app.destroy(); mount.remove(); });\n  const starting = app.start();\n  app.stop();\n  assert.equal(preparationSignal.aborted, true);\n  request.resolve(new Response(JSON.stringify({ title: 'Obsolete summary' })));\n  assert.equal(await starting, false);\n  assert.equal(app.isRunning(), false);\n  assert.equal(mount.childElementCount, 0);\n});\n```\n\nThe render spy checks that a disposed editor no longer reacts to its borrowed Model. Unchanged DOM alone could miss a leaked callback because a destroyed View ignores rendering. For a View that updates through another public handler, observe that handler or its external effect instead.\n\nRun from the application root with the DOM preload:\n\n```sh\nnode --import ./test/dom.mjs --test --test-reporter=tap ./test/app.test.mjs\n```\n\nThese tests do not need an HTTP server, timers, or a complete application. The pending fetch mock deliberately ignores cancellation so the final test verifies that a superseded startup cannot activate the feature. Failed preparation is handled by the caller through the rejected `start()` Promise. Tests for an application's chosen error presentation belong alongside that application's UI.\n\n## Add browser checks where they matter\n\nJSDOM verifies DOM changes, delegated events, public lifecycle outcomes, and cleanup. It cannot establish real layout, focus and caret behavior while typing, browser navigation, or accessibility quality. Add browser tests for those user interactions and run them against your built consumer bundle. Test the behavior your application promises, including the chosen renderer and data provider.\n\nIn your application, import your application setup first, then the real View and Application modules and test their promised public behavior with these patterns. See [local editing](/docs/guides/local-editing.md), [retained restart](/docs/guides/retained-restart.md), and [tooling](/docs/tooling.md) for related contracts and checks.\n\n\n[Canonical source](/docs/markdown/docs/guides/testing.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/guides/typescript.md",
      "title": "Use TypeScript in an application",
      "section": "Guides",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/guides/typescript/",
      "markdownUrl": "https://marionettejs.com/docs/guides/typescript.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/guides/typescript.md",
      "sourceSha256": "baba4c8483115fd7a6bb16089f38e5666f9c0f632079b531a107ee48b1ed6285",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "78766b415b2b0bc2da727ca75f0a3659d5fecef6ed6b25e55f398525cd0ac359",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 baba4c8483115fd7a6bb16089f38e5666f9c0f632079b531a107ee48b1ed6285; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Practical TypeScript\n\nMarionette and the companion packages ship declarations with their public entrypoints. Use strict TypeScript checking and the DOM library for browser code. Your bundler's module-resolution settings still apply; see [consumer tooling](/docs/tooling.md) for a checked project setup.\n\n## Constructors, instances, options, and state\n\n`View` is a constructor value. A constructor created with `View.extend` keeps the options declared by its `initialize` method, custom methods, and the state returned by `createState`. Use `typeof` for the constructor and `InstanceType` for its instance. Broader public types such as `ViewInstance` are useful at boundaries that only need core methods; they do not describe your custom methods.\n\n```ts\nimport { View } from 'marionette';\n\ntype CounterOptions = { label: string };\nconst CounterView = View.extend({\n  tagName: 'button',\n  template: false,\n  initialize(options: CounterOptions) {\n    this.el.textContent = options.label;\n  },\n  createState() { return { count: 0 }; },\n  events: { click: 'increment' },\n  increment() { this.getState().count++; },\n  label() { return this.options.label; }\n});\n\ntype CounterConstructor = typeof CounterView;\ntype Counter = InstanceType<CounterConstructor>;\nconst counter: Counter = new CounterView({ label: 'Count' });\nconst label: string = counter.label();\nconst count: number = counter.getState().count;\n```\n\nHere `new CounterView()` and a numeric `label` are type errors. A typed `initialize` signature can declare the constructor options even when its body needs no setup, as in the later examples. Custom options remain in `this.options`; Marionette does not copy every option onto the instance. Read them there or with `getOption`. Each `createState` call creates this View's own state. Constructor-supplied `state` is borrowed and replaces the factory state; see [state ownership](/docs/api/shared/state.md).\n\nA native `class` can extend `CounterView` and inherit these types. Native class fields run after `super`, including Marionette initialization: avoid using them to replace configuration needed during construction or values assigned by `initialize`. Preserve parent lifecycle behavior when overriding methods. The [View reference](/docs/api/view.md#typescript) lists the public instance and constructor types.\n\n## Local DOM interactions\n\nDOM event targets and UI matches need runtime narrowing. With the native delegator, `delegateTarget` is the element matched by the selector; `target` can be a nested element. This example uses the native delegator; a custom delegator must provide the matched-element behavior this handler relies on. `getUI` can return `undefined`, and its default public query type is `ArrayLike<Element>`, so index it rather than assuming NodeList or jQuery methods.\n\nThis local editor owns a plain state object. It uses a class-scoped Lit adapter to insert text safely and a delegated DOM handler to update state. Lit updates the preview while retaining the input and its caret.\n\n```ts\nimport { View, type DelegatedEvent } from 'marionette';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\nimport { live } from 'lit-html/directives/live.js';\n\nconst EditorView = View.extend({\n  template: ({ title }: { title: string }) => html`\n    <label>Title <input class=\"title\" .value=${live(title)}></label>\n    <p class=\"preview\">${title}</p>\n  `,\n  templateContext() { return this.getState(); },\n  ui: { title: '.title' },\n  createState() { return { title: 'Untitled' }; },\n  events: { 'input @ui.title': 'editTitle' },\n  editTitle(event: DelegatedEvent) {\n    const input = event.delegateTarget;\n    if (!(input instanceof HTMLInputElement)) { return; }\n    this.getState().title = input.value;\n    this.render();\n  },\n  focusTitle() {\n    const input = this.getUI('title')?.[0];\n    if (input instanceof HTMLInputElement) { input.focus(); }\n  }\n});\nEditorView.setDomApi(LitDomApi);\nconst editor = new EditorView().render();\ndocument.body.append(editor.el);\neditor.focusTitle();\n```\n\nThe element checks establish what the code uses: `value` and `focus`. They also handle missing UI bindings. These types do not guarantee the selector exists in every template. Event maps use string names; TypeScript does not verify that a method annotation matches every event payload. Interaction tests verify that delivery. No Application is needed for this View's local interaction. Use [local editing](/docs/guides/local-editing.md) when a borrowed Model supplies the data.\n\n## Readiness results and lifecycle completion\n\nAn Application's `prepareStart` returns data required before activation. `onStart` receives that resolved result as its third argument. The public `start` and `restart` operations return `Promise<boolean>`; `stop` and `destroy` return synchronous booleans. The boolean reports lifecycle completion rather than preparation data. Handle rejected start/restart Promises and synchronous teardown errors at the calling boundary.\n\nTypeScript does not validate a server response. Treat parsed JSON as `unknown`, validate the fields your feature needs, and only then return a typed result. This example validates one title field; use your application's API schema validation for larger responses.\n\n```ts\nimport { Application, View, type LifecycleContext } from 'marionette';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\n\ntype Summary = { title: string };\nconst SummaryView = View.extend({\n  initialize(_options: Summary) {},\n  templateContext() { return { title: this.options.title }; },\n  template: ({ title }: Summary) => html`<h1>${title}</h1>`\n});\nSummaryView.setDomApi(LitDomApi);\n\nconst SummaryApplication = Application.extend({\n  async prepareStart(_options: unknown, { signal }: LifecycleContext): Promise<Summary> {\n    const response = await fetch('/summary.json', { signal });\n    if (!response.ok) { throw new Error('Could not load summary'); }\n    const value: unknown = await response.json();\n    if (typeof value !== 'object' || value === null ||\n        !('title' in value) || typeof value.title !== 'string') {\n      throw new Error('Invalid summary response');\n    }\n    return { title: value.title };\n  },\n  onStart(_application: unknown, _options: unknown, summary: Summary) {\n    this.setView(new SummaryView(summary));\n    this.showView();\n  }\n});\n\nconst mount = document.createElement('main');\ndocument.body.append(mount);\nconst app = new SummaryApplication({ region: { el: mount } });\nconst activation: Promise<boolean> = app.start();\nconst activated: boolean = await activation;\n```\n\nThe Application owns readiness and the displayed View. Pass the lifecycle signal to transport; stopping or destroying during pending preparation prevents that startup from activating and aborts its signal. An active restart prepares new data while retaining the current UI; commit its result in `onStart` and construct the shell once. See [retained restart](/docs/guides/retained-restart.md). Reuse the same `Summary` type in preparation and the explicitly annotated completion hook. Keep concrete application types when hooks or subclasses rely on an inherited preparation-result contract; the general `ApplicationInstance` type defaults that result to `unknown`.\n\n## Typed data and provider boundaries\n\nMarionette's `model` and `collection` properties are `unknown` at the general View boundary because data providers are replaceable. Registering `DataApi` does not narrow those properties. For a feature using native Models, declare the source in initializer options and access the typed option directly. The option and the View's `model` refer to the same borrowed source in this example.\n\n```ts\nimport { View } from 'marionette';\nimport { Model, DataApi } from '@mnjs/data';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\n\ntype TitleAttributes = { title: string };\ntype TitleOptions = { model: Model<TitleAttributes> };\nconst TitleView = View.extend({\n  initialize(_options: TitleOptions) {},\n  templateContext() {\n    return { title: this.options.model.get('title') ?? 'Untitled' };\n  },\n  template: ({ title }: { title: string }) => html`<h1>${title}</h1>`,\n  modelEvents: { 'change:title': 'render' }\n});\nTitleView.setDataApi(DataApi);\nTitleView.setDomApi(LitDomApi);\nconst model = new Model<TitleAttributes>({ title: 'Overview' });\nconst title = new TitleView({ model }).render();\nconst current: string | undefined = model.get('title');\n```\n\n`Model.get` can return `undefined` even with typed attributes: Models accept partial attributes and fields can be removed. A View borrows its Model; destroying the View releases its subscription without destroying that source.\n\n`@mnjs/data` provides local Models, Collections, and adapters, with no native `fetch`, `save`, or server synchronization. It may sit behind an API layer or be replaced with another data solution. Define and validate types at that solution's boundary; choose a compatible [data provider](/docs/api/providers/data.md) for Marionette. Type annotations establish shape, while providers and ownership establish runtime behavior.\n\n\n[Canonical source](/docs/markdown/docs/guides/typescript.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/guides/local-editing.md",
      "title": "Edit a View’s own model",
      "section": "Guides",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/guides/local-editing/",
      "markdownUrl": "https://marionettejs.com/docs/guides/local-editing.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/guides/local-editing.md",
      "sourceSha256": "50f53b24365d2ca886b7ca224b6f1298ccd105b75cc84cdd2eda171a28a511f6",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "1d83547675edbd11dc634b8f2405c99543e5e01f199e84cadea1a4e8c39ff5c7",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 50f53b24365d2ca886b7ca224b6f1298ccd105b75cc84cdd2eda171a28a511f6; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Edit a View's own model\n\nKeep an interaction local when it changes the data displayed by that View and needs no broader workflow. This example edits a title as the user types and also reflects changes made elsewhere to the same Model.\n\nStart with the [renderer and data setup](/docs/integrations/setup.md). `@mnjs/data` is optional and supplies observable attributes here. See that setup page for API access and persistence.\n\nAdd a mount to your page:\n\n```html\n<section id=\"editor\"></section>\n```\n\nIn the entry module:\n\n```js\nimport { Region, View, setDataApi, setDomApi } from 'marionette';\nimport { DataApi, Model } from '@mnjs/data';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\nimport { live } from 'lit-html/directives/live.js';\n\nsetDataApi(DataApi);\nsetDomApi(LitDomApi);\n\nconst TitleEditor = View.extend({\n  template: ({ title }) => html`\n    <label>Title <input class=\"title\" .value=${live(title)}></label>\n    <p class=\"preview\">${title}</p>\n  `,\n  ui: { title: '.title', preview: '.preview' },\n  events: { 'input @ui.title': 'editTitle' },\n  modelEvents: { 'change:title': 'render' },\n  editTitle() {\n    this.model.set('title', this.getUI('title')[0].value);\n  }\n});\n\nconst model = new Model({ title: 'Untitled' });\nconst region = new Region({ el: '#editor' });\nconst editor = new TitleEditor({ model });\nregion.show(editor);\n```\n\nThe input event changes the Model, whose observable change renders the View with Lit. Lit updates the existing nodes. Its `live` binding compares against the input's current DOM value, so typing keeps focus and selection while an external Model update changes the same input. Lit owns both the input binding and preview content; do not replace its interpolated content manually.\n\nThis is immediate local editing, with no separate draft or Save operation. If the selected data solution supplies a persistence method, a View can save its own model as part of a local interaction. `@mnjs/data` has no `save()` method; integrate an API layer or choose another data solution for persistence. Coordinate shared decisions, navigation, or readiness in an owner with the corresponding lifetime; see [architecture](/docs/architecture.md).\n\nWhen the panel closes, `region.empty()` destroys the editor and removes its model subscriptions. The supplied Model remains alive: the code that created or shared it decides when it should be destroyed. Destroy the Region when its owner finishes.\n\n## Keep a draft until Save succeeds\n\nFor an explicit Save interaction, keep input in View-owned state and update the supplied Model only after the API accepts it. The draft belongs to this editor's lifetime, so the View can own the request too. This independent example assumes `PATCH /api/titles/:id` accepts JSON `{ title }` and returns JSON `{ title }` containing the accepted value. The API function supplies persistence; optional `@mnjs/data` supplies observable attributes and has no `save()` method.\n\n```js\nimport { Region, View, setDataApi, setDomApi, setStateApi } from 'marionette';\nimport { DataApi, Model, StateApi } from '@mnjs/data';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\nimport { live } from 'lit-html/directives/live.js';\n\nsetDataApi(DataApi);\nsetDomApi(LitDomApi);\nsetStateApi(StateApi);\n\nasync function saveTitle(id, title, signal) {\n  const response = await fetch(`/api/titles/${encodeURIComponent(id)}`, {\n    method: 'PATCH', signal,\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify({ title })\n  });\n  if (!response.ok) throw new Error('Save failed');\n  return (await response.json()).title;\n}\n\nconst DraftEditor = View.extend({\n  createState() {\n    return new Model({\n      draftTitle: this.model.get('title'), saving: false, status: '', error: ''\n    });\n  },\n  stateEvents: { change: 'render' },\n  templateContext() { return this.getState().toObject(); },\n  template: ({ draftTitle, saving, status, error }) => html`\n    <form>\n      <label>Title <input class=\"title\" .value=${live(draftTitle)} ?readonly=${saving}></label>\n      <button type=\"submit\" aria-disabled=${saving ? 'true' : 'false'}>Save</button>\n      <p role=\"status\">${status}</p>\n      <p role=\"alert\">${error}</p>\n    </form>\n  `,\n  ui: { title: '.title' },\n  events: { 'input @ui.title': 'editDraft', 'submit form': 'save' },\n  editDraft() {\n    const state = this.getState();\n    if (state.get('saving')) return;\n    state.set({ draftTitle: this.getUI('title')[0].value, status: '' });\n  },\n  async save(event) {\n    event?.preventDefault();\n    const state = this.getState();\n    if (this.isDestroyed() || state.get('saving')) return false;\n    const request = new AbortController();\n    this.saveRequest = request;\n    state.set({ saving: true, status: 'Saving…', error: '' });\n    let title;\n    try {\n      title = await saveTitle(this.model.get('id'), state.get('draftTitle'), request.signal);\n    } catch {\n      if (this.saveRequest !== request || this.isDestroyed()) return false;\n      this.saveRequest = undefined;\n      state.set({ saving: false, status: '', error: 'Could not save. Your draft is still here; try again.' });\n      return false;\n    }\n    if (this.saveRequest !== request || this.isDestroyed()) return false;\n    this.saveRequest = undefined;\n    this.model.set('title', title);\n    state.set({ draftTitle: title, saving: false, status: 'Saved.' });\n    return true;\n  },\n  onBeforeDestroy() {\n    const request = this.saveRequest;\n    this.saveRequest = undefined;\n    request?.abort();\n  }\n});\n\nconst mount = document.createElement('section');\ndocument.body.append(mount);\nconst savedTitle = new Model({ id: 1, title: 'Original' });\nconst draftRegion = new Region({ el: mount });\nconst draftEditor = new DraftEditor({ model: savedTitle });\ndraftRegion.show(draftEditor);\n```\n\nTyping changes only the draft. During Save the input is read-only, and repeated submissions are ignored. The button stays focusable, with `aria-disabled` announcing its pending state. Failure preserves the draft, input nodes, and supplied Model so the user can retry. Success commits the API's accepted title and displays it in the input. External Model changes do not overwrite an open draft; this example starts a new draft when a new editor is created.\n\n`draftRegion.empty()` destroys the editor and its owned state while leaving `savedTitle` alive. Every asynchronous completion checks that it still belongs to the live editor, including transports that ignore abort. Cancellation prevents a late result from changing local state; it does not guarantee that the server undoes a save. Destroy the Region and remove the mount when their owner finishes.\n\n## Check the behavior\n\nType into the input and verify the preview updates without losing focus. Update the Model externally and verify both elements change. Empty the Region, change the Model again, and verify the removed editor no longer reacts. See [tooling](/docs/tooling.md) for package checks and debugging.\n\nFor the draft example, type and verify `savedTitle` stays unchanged until Save succeeds. Fail a request, then retry the same draft. Close the editor during Save and verify a late response cannot update the supplied Model or detached input.\n\n\n[Canonical source](/docs/markdown/docs/guides/local-editing.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/guides/retained-restart.md",
      "title": "Restart readiness while retaining UI",
      "section": "Guides",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/guides/retained-restart/",
      "markdownUrl": "https://marionettejs.com/docs/guides/retained-restart.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/guides/retained-restart.md",
      "sourceSha256": "c331277f256ab66f281c55a80a20c4829f815f26845d1efafac3818557f18190",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "550cac341f34c8275d9c9692c12391b6e83386e6d2efc8556259be8eac3bfca1",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 c331277f256ab66f281c55a80a20c4829f815f26845d1efafac3818557f18190; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Restart readiness while retaining UI\n\nUse `Application.restart()` to load readiness again while keeping the feature active. Pending preparation retains the root, child Applications, subscriptions, and state event delivery. Successful `onStart` code decides what changes on screen.\n\nThis dashboard reloads a summary while preserving its page and unfinished notes. `GET /summary.json` returns `{ \"openTasks\": number }`. API transport is separate from the optional `@mnjs/data` observable state. Install the packages in [setup](/docs/integrations/setup.md).\n\n## Construct the shell once\n\n```js\nimport { Application, View, setDataApi, setDomApi } from 'marionette';\nimport { Model, DataApi, StateApi } from '@mnjs/data';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\n\nsetDataApi(DataApi);\nsetDomApi(LitDomApi);\n\nasync function loadSummary(signal) {\n  const response = await fetch('/summary.json', { signal });\n  if (!response.ok) throw new Error('Could not load the summary.');\n  return response.json();\n}\n\nconst PageView = View.extend({\n  template: () => html`\n    <button type=\"button\" class=\"reload\">Reload summary</button>\n    <section class=\"summary\"></section><section class=\"notes\"></section>`,\n  regions: { summary: '.summary', notes: '.notes' },\n  triggers: { 'click .reload': 'reload' },\n});\nconst SummaryView = View.extend({\n  template: ({ openTasks, loading, error }) => html`\n    <p>Open tasks: ${openTasks}</p>\n    <p role=\"status\">${loading ? 'Loading…' : error}</p>`,\n  modelEvents: { change: 'render' },\n});\nconst NotesView = View.extend({\n  template: () => html`<label>Working notes <textarea></textarea></label>`,\n});\n\nconst DashboardApplication = Application.extend({\n  createState() { return new Model({ openTasks: 0, loading: false, error: '' }); },\n  viewEvents: { reload: 'reloadSummary' },\n  onBeforeStart() { this.getState().set({ loading: true, error: '' }); },\n  prepareStart(_options, { signal }) { return loadSummary(signal); },\n  onStart(_app, _options, summary) {\n    const state = this.getState();\n    state.set({ openTasks: summary.openTasks, loading: false, error: '' });\n    if (this.getView()) return;\n    const page = this.setView(new PageView());\n    page.showChildView('summary', new SummaryView({ model: state }));\n    page.showChildView('notes', new NotesView());\n    this.showView();\n  },\n  reloadSummary() {\n    return this.restart().catch(error => {\n      this.getState().set({ loading: false, error: error.message });\n    });\n  },\n}).setStateApi(StateApi);\n\nconst mount = document.createElement('main');\ndocument.body.append(mount);\nconst app = new DashboardApplication({ region: { el: mount } });\nawait app.start();\n```\n\nApplication owns the Model created by `createState`; SummaryView borrows it. Each successful result updates that Model. Only SummaryView renders again. PageView, NotesView, and the textarea retain their identity and unfinished input. `viewEvents` connects the page's intent once; restart does not install another listener.\n\n`reloadSummary` is the button's error boundary around `restart()`. It adds no request controller or concurrency layer. Initial `start()` failure rejects to its caller before the page exists. A failed reload leaves the running page and previous summary available and shows the error in its status area.\n\n## Let preparation discard obsolete results\n\nEach restart supersedes pending preparation, aborts its signal, and resolves the previous call `false`. Only the current successful result reaches `onStart`, even when a transport ignores abort. Applying data there prevents obsolete requests from changing the summary. The current failure rejects; the button's handler reports it. A cancelled call never reaches that catch handler.\n\nPass the preparation signal to the transport. After preparation completes, that signal is no longer a lifetime signal. Independent operations such as saving a draft need their own cancellation policy; they do not belong in readiness merely to acquire one.\n\n## End the run deliberately\n\n`stop()` synchronously cancels preparation and destroys the page and its child Views. A later `start()` loads again and builds a new page. `destroy()` also disposes registered children and owned state. An [external host](/docs/guides/existing-ui.md) must stop or destroy its feature when removing its mount; removing DOM alone does not end Application authority.\n\nRestart itself does not render or replace Views. Calling `setView(new PageView())` unconditionally in `onStart`, or rendering the existing PageView again, would replace its child UI and lose the notes. Preserve the shell and update the source or Region that changed. Use `app.stop(); await app.start(options)` when full reconstruction or a new host is intended.\n\nThe notes here are local input. If they must survive stopping or leaving the page, give the draft a longer-lived owner.\n\n[Application lifecycle](/docs/api/application.md) · [State ownership](/docs/api/shared/state.md) · [View rendering](/docs/api/view.md#rendering-and-status)\n\n\n[Canonical source](/docs/markdown/docs/guides/retained-restart.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/guides/existing-html.md",
      "title": "Add behavior to existing HTML",
      "section": "Guides",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/guides/existing-html/",
      "markdownUrl": "https://marionettejs.com/docs/guides/existing-html.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/guides/existing-html.md",
      "sourceSha256": "024ec76fab9e8a7d64153f35453aa4ae436d03d718a9669bb8ca9e518b1371e7",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "51e7d0d723d3c2478ddad5ea7fbbcbbac9ffe98a712ee8351305186b4bb71a60",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 024ec76fab9e8a7d64153f35453aa4ae436d03d718a9669bb8ca9e518b1371e7; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Add behavior to existing HTML\n\nA View can adopt server-rendered or static markup. Set `el` to the existing root and `template: false` to retain its contents. No renderer or data package is needed for this example.\n\nStart with this HTML:\n\n```html\n<section id=\"details\">\n  <button type=\"button\" aria-expanded=\"false\" aria-controls=\"details-body\">Details</button>\n  <div id=\"details-body\" hidden>Delivery takes two business days.</div>\n</section>\n```\n\nRun this module through your bundler after the markup is available. A native browser module script needs an import map to resolve the bare package import:\n\n```js\nimport { View } from 'marionette';\n\nconst DetailsView = View.extend({\n  template: false,\n  ui: { toggle: 'button', body: '#details-body' },\n  events: { 'click @ui.toggle': 'toggleDetails' },\n  toggleDetails() {\n    const body = this.getUI('body')[0];\n    body.hidden = !body.hidden;\n    this.getUI('toggle')[0].setAttribute('aria-expanded', String(!body.hidden));\n  }\n});\n\nconst details = new DetailsView({ el: document.querySelector('#details') });\n```\n\n`el` takes the actual DOM element. Construction binds the existing controls without replacing them. Because this root already has content and is in the document, `details.isRendered()` and `details.isAttached()` are true immediately. Construction does not emit render or attach events: perform any initial enhancement directly in `initialize`, rather than waiting for `onRender` or `onAttach`.\n\nThere is no `render()` call here. With `template: false`, calling it later also preserves the markup and emits no render event. The View can still own [named Regions](/docs/api/view.md#named-regions) and display managed children inside them without rendering the parent.\n\n## Own the adopted element\n\nAdoption gives the View responsibility for its root. `details.destroy()` removes the adopted section, cleans up its event bindings, and destroys any managed child Views. It does not leave the original markup behind. Use a root whose lifetime matches that responsibility.\n\nThis small example creates the View directly, so the code managing the page must destroy it when that page ends. For a larger feature, assign it to the appropriate Region or Application owner. An already attached View does not receive a new attach notification simply because a Region adopts it. See [Region ownership](/docs/api/region.md#showing-a-view) when moving existing Views between owners.\n\n## Check the behavior\n\nVerify the button is the same DOM node before and after construction, and that clicking toggles both visibility and `aria-expanded`. Calling `render()` should preserve those nodes and their current state. Destroying the View should remove the section and end its interaction handlers.\n\n\n[Canonical source](/docs/markdown/docs/guides/existing-html.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/guides/existing-ui.md",
      "title": "Integrate with existing UI",
      "section": "Guides",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/guides/existing-ui/",
      "markdownUrl": "https://marionettejs.com/docs/guides/existing-ui.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/guides/existing-ui.md",
      "sourceSha256": "ce14a28b781ed323f712790b605944af0de028decfdf536c1292570c3af52a4a",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "597ae8a995f846d4cec2911d7d763a1ab73a3ff2169dfaac57164a3732dc155e",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 ce14a28b781ed323f712790b605944af0de028decfdf536c1292570c3af52a4a; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Integrate with existing UI\n\nA page shell, custom element, or another UI framework can host a Marionette feature. Give the host responsibility for a stable mounting element and Marionette responsibility for the content inside it. The host must leave that content alone until the feature ends.\n\n## Mount a View in a host-owned element\n\nThis small feature needs local interaction and a lifetime, so a Region owns its View. No Application or data provider is required. Install the rendering packages from the [quick start](/docs/quick-start.md).\n\n```js\nimport { Region, View } from 'marionette';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\n\nconst CounterView = View.extend({\n  initialize() { this.count = 0; },\n  template: ({ count }) => html`<button type=\"button\">Count: ${count}</button>`,\n  templateContext() { return { count: this.count }; },\n  events: { 'click button': 'increment' },\n  increment() {\n    this.count++;\n    this.render();\n    this.triggerMethod('count:changed', this.count);\n  },\n}).setDomApi(LitDomApi);\n\nexport function mountCounter(el, onCountChanged) {\n  const region = new Region({ el });\n  const counter = new CounterView();\n  region.listenTo(counter, { 'count:changed': onCountChanged });\n  region.show(counter);\n  return {\n    destroy() { region.destroy(); },\n  };\n}\n```\n\nCall `mountCounter` when the host's empty element is available. The callback receives the new count; the feature keeps its local presentation state. Call the returned `destroy()` from the host's cleanup hook **before** removing or replacing that element. Region destruction destroys the View, releases subscriptions, and leaves the mount itself in place. Repeated cleanup is safe. Mounting again creates a new feature with fresh state.\n\nUse the host framework's mount/ref and cleanup hooks to perform these two operations. Keep the mounting element's identity stable across host updates. Give each mount its own Region; do not share a live View between Regions. If the host provides observable data, the View can borrow it through the configured [data provider](/docs/api/providers/data.md); destroying the View does not dispose borrowed data.\n\n## Host a feature with asynchronous readiness\n\nUse an [Application](/docs/api/application.md) for feature readiness or coordinated child Applications. Give it `region: { el }`; the host owns its `start()` and `destroy()` calls and handles their failures. Follow [startup and cancellation](/docs/api/application.md#preparation-cancellation-and-failure) and the executable [pending-start teardown test](/docs/guides/testing.md) for the lifecycle contract.\n\nKeep the Application reference available to host cleanup while startup is pending. Call synchronous `app.destroy()` in the host cleanup hook before reusing the mount. It cancels pending preparation and releases the feature UI. Finish any required asynchronous business work before invoking cleanup, according to the host’s lifecycle.\n\nRemoving DOM alone does not destroy a View or Application. Likewise, Marionette does not destroy the surrounding host. For markup whose root itself belongs to Marionette, see [adopting existing HTML](/docs/guides/existing-html.md); that View's destruction removes its root.\n\n## Check the boundary\n\nTest a click and callback, cleanup with a retained button reference, and a fresh mount. Confirm cleanup preserves the host element and prevents detached controls from producing callbacks. For asynchronous integrations, extend the consumer cancellation test with your actual host cleanup hook. Use [consumer testing](/docs/guides/testing.md) for lifecycle checks and a browser test for the real host's mount/cleanup behavior.\n\n\n[Canonical source](/docs/markdown/docs/guides/existing-ui.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/guides/routing.md",
      "title": "Connect navigation to feature ownership",
      "section": "Guides",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/guides/routing/",
      "markdownUrl": "https://marionettejs.com/docs/guides/routing.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/guides/routing.md",
      "sourceSha256": "e7ff6fe7c9554af81363ca24ae56743af885285b5f8a8fa0221acd32b05c9b2e",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "764bfa2140e322e02b2f11f510d87fa831c8ee438dd0e4c51d73e3fe59f7aae4",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 e7ff6fe7c9554af81363ca24ae56743af885285b5f8a8fa0221acd32b05c9b2e; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Connect navigation to feature ownership\n\nMarionette v5 supplies UI and Application lifecycles. Choose browser navigation or a separate router for URL matching and history. Connect route decisions to the owner that shows or starts the destination feature.\n\n## Keep a shell while changing its content\n\nThis small application uses fragment links for two synchronous pages. Its Application owns the shell and the browser subscription; the content Region owns the current page. No data provider is needed. The rendering packages are described in [setup](/docs/integrations/setup.md).\n\n```js\nimport { Application, View } from 'marionette';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\n\nconst PageView = View.extend({\n  template: () => html`\n    <nav aria-label=\"Pages\"><a href=\"#home\">Home</a> <a href=\"#about\">About</a></nav>\n    <main class=\"content\"></main>`,\n  regions: { content: '.content' },\n}).setDomApi(LitDomApi);\nconst HomeView = View.extend({\n  template: () => html`<h1 tabindex=\"-1\">Home</h1><p>Welcome.</p>`,\n}).setDomApi(LitDomApi);\nconst AboutView = View.extend({\n  template: () => html`<h1 tabindex=\"-1\">About</h1><p>About this application.</p>`,\n}).setDomApi(LitDomApi);\nconst NotFoundView = View.extend({\n  template: () => html`<h1 tabindex=\"-1\">Page not found</h1>`,\n}).setDomApi(LitDomApi);\n\nconst NavigationApplication = Application.extend({\n  onStart() {\n    if (!this.getView()) {\n      this.showView(new PageView());\n      this.onHashChange = () => this.showRoute();\n      window.addEventListener('hashchange', this.onHashChange);\n    }\n    this.showRoute({ focus: false });\n  },\n  showRoute({ focus = true } = {}) {\n    const route = window.location.hash || '#home';\n    if (route === this.currentRoute) return;\n    this.currentRoute = route;\n    const Destination = route === '#home' ? HomeView :\n      route === '#about' ? AboutView : NotFoundView;\n    const destination = new Destination();\n    this.getView().showChildView('content', destination);\n    const heading = destination.el.querySelector('h1');\n    document.title = heading.textContent;\n    if (focus) heading.focus();\n  },\n  onStop() {\n    window.removeEventListener('hashchange', this.onHashChange);\n    this.currentRoute = undefined;\n  },\n});\n\nconst mount = document.createElement('div');\ndocument.body.append(mount);\nconst app = new NavigationApplication({ region: { el: mount } });\nawait app.start();\n```\n\nStartup reads the current fragment explicitly, so a direct link to `#about` works. Following a link changes the URL; `hashchange` selects the destination. Browser Back/Forward uses the same path. The shell and its navigation remain mounted while Region replacement destroys the previous page. Repeated dispatch of the same route keeps the current page. Unknown fragments show a separate not-found View.\n\nEach destination updates the document title. Later navigation moves focus to its heading; startup leaves focus alone. Decide the focus policy for your actual navigation, especially when a route update merely filters retained content. A route parameter change need not replace the whole feature: update its owned state or use the destination Application’s [retained restart](/docs/guides/retained-restart.md) when appropriate.\n\nStopping destroys the shell and its children and removes the Window listener. Starting again reads the current URL and creates a fresh shell. Native `addEventListener` subscriptions need this explicit cleanup; Marionette's `listenTo` cleanup handles Marionette event sources, not Window subscriptions. Restart retains the shell and subscription; this example installs them only when no root exists. Route changes update the content Region directly.\n\n## Choose the URL owner\n\nFragment navigation is useful for a small standalone application. If an existing host already owns routing, let it select the feature and follow the [existing UI boundary](/docs/guides/existing-ui.md). Avoid starting a second global URL listener for an embedded feature.\n\nFor path-based routing, configure the server to serve the application entry for valid direct links and reloads. A History API implementation must handle `popstate` for traversal and explicitly dispatch its own `pushState`/`replaceState` transitions: those calls do not emit `popstate`, and changing a fragment through them does not emit `hashchange`. See the browser contracts for [pushState](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState) and [hashchange](https://developer.mozilla.org/en-US/docs/Web/API/Window/hashchange_event). Choose a routing library when matching, nested routes, redirects, or transition policies warrant it; Marionette ownership remains the same.\n\n## Route to asynchronous features\n\nWhen a destination needs readiness, let the navigation Application manage a child Application in the content Region. This independent example expects `GET /pages/home.json` and `GET /pages/about.json` to return `{ \"title\": string, \"body\": string }`. It keeps the shell while stopping the previous child run, then replaces the content with loading, the ready page, or an error. These Views share one Region, so only one is visible.\n\n```js\nimport { Application, View } from 'marionette';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\n\nconst ShellView = View.extend({\n  template: () => html`\n    <nav aria-label=\"Pages\"><a href=\"#home\">Home</a> <a href=\"#about\">About</a></nav>\n    <main class=\"content\"></main>`,\n  regions: { content: '.content' },\n}).setDomApi(LitDomApi);\nconst MessageView = View.extend({\n  template: ({ title, body }) => html`<h1>${title}</h1><p role=\"status\">${body}</p>`,\n}).setDomApi(LitDomApi);\nconst ContentView = View.extend({\n  template: ({ title, body }) => html`<h1>${title}</h1><p>${body}</p>`,\n}).setDomApi(LitDomApi);\nconst ErrorView = View.extend({\n  template: ({ message }) => html`\n    <h1>Could not load page</h1><p role=\"alert\">${message}</p>\n    <button type=\"button\" class=\"retry\">Retry</button>`,\n  triggers: { 'click .retry': 'retry' },\n}).setDomApi(LitDomApi);\n\nconst PageApplication = Application.extend({\n  async prepareStart({ route }, { signal }) {\n    const response = await fetch(`/pages/${route.slice(1)}.json`, { signal });\n    if (!response.ok) throw new Error('The page request failed.');\n    return response.json();\n  },\n  onStart(_app, _options, page) {\n    this.showView(new ContentView({ model: page }));\n    document.title = page.title;\n  },\n});\n\nconst NavigationApplication = Application.extend({\n  childApps: { page: PageApplication },\n  onStart() {\n    if (this.getView()) return;\n    this.showView(new ShellView());\n    this.onHashChange = () => {\n      this.navigationTask = this.showRoute();\n      this.navigationTask.catch(error => console.error(error));\n    };\n    window.addEventListener('hashchange', this.onHashChange);\n    this.onHashChange();\n  },\n  async showRoute() {\n    if (!this.isRunning()) return false;\n    const route = window.location.hash || '#home';\n    if (route === this.currentRoute) return false;\n    this.currentRoute = route;\n    const child = this.getChildApp('page');\n    child.stop();\n    const region = this.getView().getRegion('content');\n    if (route !== '#home' && route !== '#about') {\n      document.title = 'Page not found';\n      region.show(new MessageView({ model: {\n        title: 'Page not found', body: 'Choose Home or About.',\n      } }));\n      return true;\n    }\n    document.title = 'Loading page…';\n    region.show(new MessageView({ model: {\n      title: 'Loading page…', body: 'Please wait.',\n    } }));\n    try {\n      return await child.start({ region, route });\n    } catch (error) {\n      child.stop();\n      this.currentRoute = undefined;\n      document.title = 'Could not load page';\n      const errorView = new ErrorView({ model: { message: error.message } });\n      this.listenTo(errorView, { retry: this.onHashChange });\n      region.show(errorView);\n      return false;\n    }\n  },\n  onBeforeStop() {\n    this.currentRoute = undefined;\n    window.removeEventListener('hashchange', this.onHashChange);\n  },\n});\n\nconst mount = document.createElement('div');\ndocument.body.append(mount);\nconst app = new NavigationApplication({ region: { el: mount } });\nawait app.start();\n```\n\nThe URL selects the destination as soon as it changes. A failed request keeps that URL and shows an error View; Retry dispatches the current URL again. An unknown fragment shows a not-found View. Repeating a route that is loading or ready leaves it alone.\n\nThe owner stops the outgoing child before starting the next destination. Stopping the child cancels its pending start, which resolves `false`; obsolete failures do not reject that cancelled call. The next destination starts a new preparation. Stopping the outgoing child aborts its preparation signal; an obsolete result cannot activate even if the transport ignores abort. A rejected start is stopped before error presentation replaces its UI.\n\n`await app.start()` activates the shell; `navigationTask` tracks the separately started page transition. The child loads readiness data in `prepareStart` and renders it in `onStart`.\n\nStop is unconditional here: `onBeforeStop` removes the Window subscription before child teardown. Stop destroys the shell; a later start creates a new one and reads the current URL. Restart retains the shell, the Window listener, and the current child run. Destroy also disposes the registered child. See [Application composition](/docs/api/application.md#child-applications) and [consumer testing](/docs/guides/testing.md).\n\n## Check navigation\n\nTest direct links, link clicks, Back/Forward, unknown routes, and repeat selection. Verify shell identity survives page changes, outgoing pages are destroyed, and stop/start removes and reinstalls one URL subscription; restart retains that single subscription. Use a real browser for history and focus behavior.\n\n\n[Canonical source](/docs/markdown/docs/guides/routing.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/guides/lists.md",
      "title": "Show, sort, and filter a list",
      "section": "Guides",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/guides/lists/",
      "markdownUrl": "https://marionettejs.com/docs/guides/lists.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/guides/lists.md",
      "sourceSha256": "0733bd54d05d8c7979c720684aa8506b8737b19dbbb5100f0d2797ab0af39ae7",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "148524293e75ad81f3b12a2669df16cd0c970741ffee72f21d06ce5db360dfd8",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 0733bd54d05d8c7979c720684aa8506b8737b19dbbb5100f0d2797ab0af39ae7; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Show, sort, and filter a list\n\nUse CollectionView for repeated children that share one placement rule. A surrounding View can own the list's local controls and Region. Add an Application when the feature needs API readiness or broader coordination; sorting a displayed list does not require one.\n\nThis catalog uses the optional `@mnjs/data` Collection for observable membership. Fetching and persistence need an API layer or another data provider. Install the rendering and data packages from [setup](/docs/integrations/setup.md).\n\n## Own the controls and repeated rows\n\n```js\nimport { CollectionView, Region, View } from 'marionette';\nimport { Collection, DataApi } from '@mnjs/data';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\n\nconst ItemView = View.extend({\n  tagName: 'li',\n  template: ({ label }) => html`\n    <strong>${label}</strong>\n    <label>Notes for ${label} <input></label>`,\n  modelEvents: { change: 'render' },\n}).setDataApi(DataApi).setDomApi(LitDomApi);\nconst EmptyView = View.extend({\n  tagName: 'li',\n  template: () => html`No matching items.`,\n}).setDomApi(LitDomApi);\nconst ItemList = CollectionView.extend({\n  tagName: 'ul',\n  childView: ItemView,\n  emptyView: EmptyView,\n  viewComparator: 'label',\n}).setDataApi(DataApi);\nconst CatalogView = View.extend({\n  template: () => html`\n    <label><input type=\"checkbox\" class=\"available\"> Available only</label>\n    <button type=\"button\" class=\"reverse\">Reverse order</button>\n    <section class=\"items\" aria-label=\"Catalog\"></section>`,\n  regions: { items: '.items' },\n  ui: { available: '.available' },\n  events: { 'change @ui.available': 'filterItems', 'click .reverse': 'reverseItems' },\n  onRender() {\n    this.descending = false;\n    this.getUI('available')[0].checked = false;\n    this.list = new ItemList({ collection: this.options.items });\n    this.showChildView('items', this.list);\n  },\n  filterItems() {\n    this.list.setFilter(this.getUI('available')[0].checked ? { available: true } : null);\n  },\n  reverseItems() {\n    this.descending = !this.descending;\n    this.list.setComparator(this.descending ?\n      (left, right) => right.model.get('label').localeCompare(left.model.get('label')) : 'label');\n  },\n}).setDomApi(LitDomApi);\n\nconst items = new Collection([\n  { id: 'a', label: 'Apricot', available: true },\n  { id: 'b', label: 'Blueberry', available: false },\n]);\nconst catalog = new CatalogView({ items });\nconst mount = document.createElement('section');\ndocument.body.append(mount);\nconst region = new Region({ el: mount });\nregion.show(catalog);\n```\n\nThe outer Region owns CatalogView; its named Region owns ItemList; the list owns rows and its empty View. The collection is borrowed. Destroy the outer Region when this feature ends, then dispose data according to the lifetime of the code that created it.\n\nThe notes fields are temporary DOM input. Sorting moves the existing rows; filtering detaches excluded rows and retains their Views and input values. Returning a row preserves its nodes, but leaving the document can lose focus. When a filter hides the focused row, choose a focus destination such as the filter control. See [accessibility and rendering](/docs/guides/accessibility-rendering.md).\n\n## Update without rebuilding everything\n\n| Change | Operation | Effect |\n| --- | --- | --- |\n| Add or remove a member | `items.add(...)` / `items.remove(...)` | Creates/destroys affected rows and retains surviving rows. Removing membership does not destroy the Model. |\n| Change a displayed attribute | `model.set(...)` | This example's `modelEvents` renders that row. |\n| Change an attribute used by sorting/filtering | Then call `catalog.list.sort()` / `filter()` | Recomputes presentation; an `@mnjs/data` Model change does not automatically rerun the parent criteria. |\n| Show all rows | `catalog.list.removeFilter()` | Restores retained hidden rows. |\n| Replace the membership snapshot | `items.reset(...)` | Destroys and rebuilds rows, including rows for retained Models. |\n\nFor a group of additions or removals, use `items.add([...])` or `items.remove([...])` rather than calling the method in a loop. When membership changes, the `@mnjs/data` Collection emits one aggregate update per call, so CollectionView reconciles once per call instead of once per item while retaining surviving rows. Use `reset` for a whole replacement snapshot; its row destruction makes it unsuitable for preserving input or focus.\n\nAvoid full `list.render()` to apply a filter or sort: it rebuilds managed rows. Rendering CatalogView again also destroys its Region children; this example deliberately resets its local controls when rebuilding the list. If notes must survive those operations or navigation, put the draft in an appropriately owned data source.\n\nAn empty presentation can mean all rows are filtered out even when the collection has members. `emptyView` describes that presentation, rather than storing an empty record in the collection. Give it a root valid for the container, such as `li` inside `ul`.\n\n## Identity and scale\n\nThe configured DataApi determines keys and collection observation. With `@mnjs/data`, the key is Model `cid`; reusing a server `id` in a new Model does not reuse the old row. Other providers must supply stable unique keys, but a replacement model object still replaces its View.\n\n`list.children` describes the currently presented rows, excluding hidden rows and the empty View. Save a row reference before hiding it when checking identity. CollectionView is not a virtualized viewport: hidden rows remain alive. For large datasets, choose paging or a measured windowing solution based on the application's needs.\n\n## Check the behavior\n\nEnter notes, sort, hide and restore that row, and check the same input and value return. Add/remove members and verify surviving row identity and outgoing destruction. With Available only selected, call `items.at(0).set('available', false)` and `catalog.list.filter()` to filter every row out; verify empty presentation without changing collection length. Finish by destroying the Region and checking that no borrowed data was destroyed or continues rendering the old list. [CollectionView reference](/docs/api/collection-view.md) defines the full contract; [consumer testing](/docs/guides/testing.md) gives a test setup.\n\n\n[Canonical source](/docs/markdown/docs/guides/lists.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/guides/widgets.md",
      "title": "Integrate an imperative control",
      "section": "Guides",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/guides/widgets/",
      "markdownUrl": "https://marionettejs.com/docs/guides/widgets.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/guides/widgets.md",
      "sourceSha256": "cf8cc28d52bcac0c849d4a1e9e771beb987b5c834ed7cd94f44a77c0aedaa009",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "8ad9d2fb584e8174de7ca8b9a23ab27adc12c8d8a94c685cef90e95ff8edbc6f",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 cf8cc28d52bcac0c849d4a1e9e771beb987b5c834ed7cd94f44a77c0aedaa009; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Integrate an imperative control\n\nKeep a control's DOM and cleanup with the View that owns its element. A one-off control can stay in that View. Use a [Behavior](/docs/api/behavior.md) when multiple Views genuinely share the same integration.\n\nThis example uses the browser's native dialog API. It needs no renderer, data package, Application, or widget wrapper. Show the View through a Region before opening the dialog: [`showModal()` requires a connected element](https://html.spec.whatwg.org/multipage/interactive-elements.html#dom-dialog-showmodal).\n\n```js\nimport { Region, View } from 'marionette';\n\nconst HelpView = View.extend({\n  template: () => `\n    <button type=\"button\" class=\"open-help\">Help</button>\n    <dialog aria-label=\"Help\">\n      <h2>Help</h2>\n      <p>Choose a record to see its details.</p>\n      <form method=\"dialog\"><button autofocus>Close</button></form>\n    </dialog>\n  `,\n  ui: { open: '.open-help', dialog: 'dialog' },\n  events: { 'click @ui.open': 'openDialog' },\n  openDialog() {\n    this.getUI('dialog')[0].showModal();\n  },\n  closeDialog() {\n    const dialog = this.el.querySelector('dialog');\n    if (dialog && dialog.open) dialog.close();\n  },\n  onDomRemove() {\n    this.closeDialog();\n  },\n  onBeforeDestroy() {\n    this.closeDialog();\n  },\n});\n\nconst mount = document.body.appendChild(document.createElement('section'));\nconst region = new Region({ el: mount });\nconst help = new HelpView();\nregion.show(help);\n```\n\nThe native dialog owns modal display, focus handling, Escape dismissal, and its closing form. The View owns the interaction that opens it and closes it before its markup is removed. This is local presentation; no broader feature lifecycle is needed.\n\n## Match the control to the View lifecycle\n\nWith normal View monitoring, `onDomRemove` runs before an attached View re-renders or detaches. Closing there releases the modal while its element is still connected. `onBeforeDestroy` also covers terminal disposal, including a View already detached. Cleanup can run more than once; closing an already closed dialog does nothing.\n\nFor an external editor, chart, or other package, follow that package's actual API instead of treating the dialog as its adapter:\n\n- Create DOM-independent resources in `initialize`. Bind to freshly rendered elements in `onRender`.\n- Create or measure controls that require a connected element in `onAttach`, or `onDomRefresh` if they also need updating after an attached render. An adopted, already attached element gets no construction-time attach event; initialize that case explicitly.\n- Dispose or release bindings before the renderer replaces their elements. Suspend work on detachment if the View can return; re-establish it when attached again.\n- Release terminal resources in `onBeforeDestroy`, even when the View was never attached. Let the package's ownership rules determine whether disposal may be repeated.\n\nKeep the renderer and external control from both updating the same subtree. Use the package's documented change events to update local data or emit user intent, and release its subscriptions or global handlers when its owner ends. See the [View lifecycle reference](/docs/api/view.md#lifecycle-hooks-and-events) for hook arguments and ordering.\n\n## Reuse through a Behavior\n\nA Behavior receives its host's render, attach, detach, and destroy notifications, so the same integration hooks can be reused when their assumptions match each host. The host still owns its DOM.\n\nDirect `behavior.destroy()` emits no independent destroy notification. If an integration can be removed separately from its host, release its external resources in an override of `destroy` and delegate to `Behavior.prototype.destroy.call(this)`. Make that cleanup repeat-safe; relying only on forwarded `onBeforeDestroy` leaves direct removal uncovered. See [Behavior disposal](/docs/api/behavior.md#destruction-and-nested-behaviors) for the full contract.\n\n## Check the actual browser behavior\n\nOpen Help and verify focus enters the dialog. Close it with the form button and with Escape. Open it again before rendering, detaching, or destroying the View and verify it closes before removal. A detached View remains reusable: re-show it through the Region and verify Help opens again. `region.empty()` destroys the View; destroy the Region when its owner finishes.\n\nRun these modal checks in a browser. JSDOM can check the mounted markup and Marionette ownership transitions, but it does not supply the dialog's modal methods here. See [consumer testing](/docs/guides/testing.md) for testing boundaries.\n\n\n[Canonical source](/docs/markdown/docs/guides/widgets.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/guides/accessibility-rendering.md",
      "title": "Accessibility and rendering",
      "section": "Guides",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/guides/accessibility-rendering/",
      "markdownUrl": "https://marionettejs.com/docs/guides/accessibility-rendering.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/guides/accessibility-rendering.md",
      "sourceSha256": "e197de86f7c0905901a7bbebb45438f96e67de54929e11277d74fcf5e7f1a3ef",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "176380a4f946ee37ffa9ae4066741b6bdeeba144db083206139c08ce2f42eabd",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 e197de86f7c0905901a7bbebb45438f96e67de54929e11277d74fcf5e7f1a3ef; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Accessibility and rendering\n\nMarionette manages View lifetimes and placement. Your templates and interaction design determine accessible names, keyboard behavior, and where focus goes when content changes.\n\n## Start with semantic controls\n\nUse a native `button` for an action and a link with `href` for navigation. Label form fields visibly, keep document order meaningful, and preserve a visible focus indicator. A native button supplies keyboard activation, so a delegated `click` handler can serve pointer and keyboard users without duplicating Enter and Space handlers.\n\nFor a toggle button, keep its label stable and update `aria-pressed`. The [WAI button pattern](https://www.w3.org/WAI/ARIA/apg/patterns/button/) describes keyboard activation and focus behavior.\n\nThis View owns only local display state. Its class-scoped Lit adapter updates the same template's elements when the user toggles the setting.\n\n```js\nimport { Region, View } from 'marionette';\nimport LitDomApi from '@mnjs/adapters/dom/lit-html';\nimport { html } from 'lit-html';\n\nconst NotificationSettings = View.extend({\n  tagName: 'section',\n  createState() { return { title: 'Notifications', muted: false }; },\n  templateContext() { return this.getState(); },\n  template: ({ title, muted }) => html`\n    <h2 class=\"heading\" tabindex=\"-1\">${title}</h2>\n    <button type=\"button\" class=\"mute\" aria-pressed=${String(muted)}>\n      Mute notifications\n    </button>\n    <p>${muted ? 'Notifications are muted.' : 'Notifications are enabled.'}</p>\n  `,\n  ui: { heading: '.heading', mute: '.mute' },\n  events: { 'click @ui.mute': 'toggleMuted' },\n  toggleMuted() {\n    const state = this.getState();\n    state.muted = !state.muted;\n    this.render();\n  },\n  focusHeading() { this.getUI('heading')[0].focus(); }\n});\nNotificationSettings.setDomApi(LitDomApi);\n\nconst mount = document.createElement('main');\ndocument.body.append(mount);\nconst region = new Region({ el: mount });\nconst settings = new NotificationSettings();\nregion.show(settings);\n```\n\nThis is local state, with no persistence claim. When a server-backed setting belongs to a wider feature, give the save and failure workflow to its appropriate owner. The toggle's pressed state conveys the immediate local change; do not add announcements that repeat the control's own feedback without a reason.\n\n## Retain focus during updates; choose it during replacement\n\nThe toggle does not dismiss its context, so focus should remain on the button. Lit can retain the existing nodes when this View renders the same template again. Changing template branches, removing an element, or choosing an insertion provider that replaces descendants can still remove the focused node. Test the actual rendering behavior you use.\n\nShowing a different View in a [Region](/docs/api/region.md#showing-a-view) destroys the current View and removes its content. Marionette does not choose a focus destination. For a user-requested screen transition, show the new View, then focus its heading or an appropriate first control. For example, another `NotificationSettings` instance named `nextSettings` can use `region.show(nextSettings); nextSettings.focusHeading();` after the transition is accepted. The heading's `tabindex=\"-1\"` permits programmatic focus without adding an extra Tab stop.\n\nKeep this focus decision with the owner performing the transition. An unrelated background update should not move focus to a new heading. If a dialog closes, returning to its opener may be the appropriate policy instead. Follow the [WAI guidance on predictable focus](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_focus_discernable_predictable) and test the resulting keyboard sequence.\n\n## Keep text and raw HTML boundaries explicit\n\nMarionette's native DOM provider inserts template strings with `innerHTML`. It treats a string as HTML, so interpolating untrusted text into that string is unsafe. Use `textContent` for direct text updates or a template system that handles text interpolation.\n\nOrdinary string values in Lit child expressions, such as this example's title, become text. See [Lit expressions](https://lit.dev/docs/templates/expressions/#primitive-values). Raw HTML insertion, including Lit's [`unsafeHTML`](https://lit.dev/docs/templates/directives/#unsafehtml), requires trusted or sanitized HTML at the application's boundary. URL attributes also need the application's allowed-URL policy; text interpolation is not a complete security policy.\n\nChoose an integration whose output matches the [renderer and DOM provider](/docs/api/providers/dom.md) contract. Keep renderer-owned nodes under that renderer's control rather than overwriting their contents independently.\n\n## Verify the user-visible behavior\n\nUse browser interaction tests to Tab to the button, activate it with Enter and Space, and check both `aria-pressed` and visible feedback. Confirm the same button remains focused through the local update. Then replace the View through its Region, verify the old View is destroyed, and check that the transition owner moves focus to the intended new destination.\n\nInclude a text value containing HTML-like characters and verify it stays text. Test with keyboard navigation and assistive technology for your complete application; these focused checks do not establish accessibility conformance. See [consumer testing](/docs/guides/testing.md) for test setup and [retained restart](/docs/guides/retained-restart.md) for updates that preserve a larger page.\n\n\n[Canonical source](/docs/markdown/docs/guides/accessibility-rendering.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/guides/production.md",
      "title": "Build and deploy an application",
      "section": "Guides",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/guides/production/",
      "markdownUrl": "https://marionettejs.com/docs/guides/production.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/guides/production.md",
      "sourceSha256": "9e6e921f87c3ec2d2aa602911f2d20ac78e43e3c6df4b3c41806131d983ad715",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "c488fe9e57e11cb372f7c6dc92ab7f83c2b6c64d530398b7227433c643ee68fa",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 9e6e921f87c3ec2d2aa602911f2d20ac78e43e3c6df4b3c41806131d983ad715; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Build and deploy an application\n\nDeploy the application bundle with its configured providers and verify it through the server that will serve users. Marionette manages UI ownership and lifecycle; your bundler and server provide the build and delivery boundaries.\n\n## Keep installed packages coherent\n\nThese docs target **5.0.0**. Follow the [quick start](/docs/quick-start.md) to install matching package versions; keep the lockfile and use the documentation bundled with that installation. Verify your application against that exact installation before deployment.\n\nUse named ESM imports from `marionette` and the documented adapter subpaths. Build against installed packages rather than repository source aliases. Include the template engine required by the chosen adapter. Choose observable data and API access through [setup](/docs/integrations/setup.md).\n\nConfigure providers before constructing consumers. A shared setup module suits one class family; class setters such as `View.extend(...).setDomApi(LitDomApi)` suit a configured subclass. Configure CollectionView and its child View classes when both consume that adapter. Use an isolated runtime when independently configured features coexist. [Runtime configuration](/docs/api/runtime.md) explains these scopes; changing providers on live instances does not rebuild them.\n\n## Build the browser artifact\n\nIn the quick-start project, run `npm run build` and deploy the resulting `dist` directory. Preview that output locally with `npx vite preview`; Vite's preview server is for local verification. Configure the bundler's public base when serving from a subdirectory, and check the emitted asset URLs at that location. See Vite's [deployment guide](https://vite.dev/guide/static-deploy.html) and [public base configuration](https://vite.dev/guide/build.html#public-base-path).\n\nRun the application's lint and TypeScript checks separately from bundling. The [tooling guide](/docs/tooling.md) supplies installed-package configurations. A successful build does not establish readiness, cleanup, or browser interaction behavior; [consumer tests](/docs/guides/testing.md) exercise those boundaries.\n\n## Handle startup at its owner\n\nPut required asynchronous readiness in Application `prepareStart`, pass its signal to cancellable requests, and connect the ready UI in synchronous `onStart`. The caller of `start()` handles rejection and decides whether to show an error, offer retry, or end the feature. Retain the Application so the owner can call synchronous `stop()` for reuse or `destroy()` when its lifetime ends.\n\nSee the [Application failure contract](/docs/api/application.md#preparation-cancellation-and-failure) for cancellation, partial activation and lifecycle results.\n\nUse [retained restart](/docs/guides/retained-restart.md) to repeat preparation while preserving the active page. Create retained shells once and update only the source or child Region that changed. Embedded features follow the [existing UI ownership boundary](/docs/guides/existing-ui.md); their host must end the feature before removing its mounting content.\n\n## Serve direct links deliberately\n\nServe the application and API over HTTPS in production. Relative fetch URLs use the application's origin.\n\nFor path-based navigation, serve the application entry for recognized document routes, including direct visits and reloads. Keep asset and API handling separate: a missing JavaScript file or API resource must retain its appropriate error response rather than receiving application HTML. Test an unknown document route according to your chosen server/client not-found policy. Fragment routing does not require a separate server path for each fragment. The [navigation guide](/docs/guides/routing.md) covers URL ownership.\n\nPublish an entry document with the assets it references. Choose caching rules that allow clients to obtain a coherent build, and check an upgrade from a previously loaded version as well as a clean visit. Include the deployed base path and API origin in those checks.\n\n## Check the deployed application\n\nVerify a clean load, direct route reload, navigation, missing asset/API responses, failed readiness and retry, and feature removal while preparation is pending. Exercise keyboard interaction and focus in a real browser. Preserve errors with their stack and Marionette diagnostic code so the [installed lookup](/docs/tooling.md#look-up-a-diagnostic) matches the runtime.\n\nThe framework's browser test configuration runs Chromium, Firefox and WebKit through Playwright. Its browser transpilation query is `baseline widely available`. Those choices describe the repository's validation and transpilation profile; they do not establish behavior in every browser/device or supply missing browser APIs. Select and test your application's actual browser targets with its renderer, providers and deployed bundle.\n\n\n[Canonical source](/docs/markdown/docs/guides/production.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/records.md",
      "title": "Build a records feature",
      "section": "Guides",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/records/",
      "markdownUrl": "https://marionettejs.com/docs/records.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/records.md",
      "sourceSha256": "d28300ebf2c56c1819e4c890daa07c5e395934fc2f472984cdaf73af74144ffc",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "9fadc8ee813a1247a2691ee87705082f909b31e94eac42de5d88e8b44af3829c",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 d28300ebf2c56c1819e4c890daa07c5e395934fc2f472984cdaf73af74144ffc; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Build a records feature\n\nBuild a feature that loads records and shows the selected record beside its list. The [runnable example](/docs/source/examples/records/README.md) also reloads without replacing the layout, retries failures, and closes/reopens the feature. The excerpts below come from that example; follow the source links for the complete modules.\n\n## Run it\n\nThe source is included with these docs; the commands here use the repository checkout. For an application using installed packages, follow the [quick start](/docs/quick-start.md) and [setup reference](/docs/integrations/setup.md).\n\nThis repository example uses the pinned Node 24 contributor toolchain. Packaged applications follow the [consumer Node LTS policy](/docs/quick-start.md). From the framework repository root:\n\n```sh\nnpm ci --ignore-scripts\nnpm --prefix examples/records ci --ignore-scripts\nnpm --prefix examples/records run dev\n```\n\nOpen <http://127.0.0.1:5193>. Select a record, close the feature, then open it again. Each new start loads records and clears selection. The page's Open/Close controls remain mounted.\n\n## Attach to the page\n\n[index.html](/docs/source/examples/records/index.html) contains the page heading, controls, and empty content container. MainApplication's onStart attaches PageView to `#app` with `setView(new PageView({ el }))`. PageView uses `template: false`: its existing markup supplies the DOM, so no render or show call is needed. Its Regions and event triggers work normally.\n\nIn [page.js](/docs/source/examples/records/src/page.js):\n\n```js\nimport { View } from 'marionette';\n\nexport const PageView = View.extend({\n  template: false,\n  regions: { content: '.js-content' },\n  triggers: {\n    'click .js-open': 'open:records',\n    'click .js-close': 'close:records'\n  },\n  childViewTriggers: { retry: 'retry:records', reload: 'reload:records' }\n});\n```\n\nThe parent owns that View and the registered Records child. The page lasts for the document's lifetime; child stop/restart leaves it mounted. Stopping the parent destroys PageView and removes its element. Starting this parent again, or starting another parent, requires supplying the page markup again.\n\nInside [MainApplication](/docs/source/examples/records/src/main-application.js), `childApps`\nregisters the feature and `viewEvents` connects the page's intent to its lifecycle.\nThe following is an excerpt from the object passed to `Application.extend(...)`:\n\n```js\n  childApps: { records: RecordsApplication },\n  viewEvents: {\n    'open:records': 'openRecords',\n    'retry:records': 'restartRecords',\n    'reload:records': 'restartRecords',\n    'close:records': 'closeRecords'\n  },\n  onStart() {\n    if (this.getView()) { return; }\n    this.setView(new PageView({ el: this.getOption('el') }));\n    this.openRecords();\n  },\n  openRecords() {\n    return this.getChildApp('records').start({ region: this.getView().getRegion('content') })\n      .catch(error => this.showRecordsError(error));\n  },\n  restartRecords() {\n    return this.getChildApp('records').restart()\n      .catch(error => this.showRecordsError(error));\n  },\n  closeRecords() {\n    return this.getChildApp('records').stop();\n  }\n```\n\n`showRecordsError` is the failure handler described below. Notice that registration\nand startup are separate: Open starts the child in the page's content Region;\nClose stops that child while leaving the page available.\n\n## Prepare, then display\n\n[RecordsApplication](/docs/source/examples/records/src/records-application.js) follows three lifecycle steps:\n\n1. `onBeforeStart` marks loading. Initial startup resets selection and shows LoadingView; an active restart retains the current layout and selection.\n2. `prepareStart(options, { signal })` awaits the API, and returns a Collection built from the response.\n3. `onStart(app, options, collection)` uses that Collection directly. It creates RecordsLayout and its status View only when needed, then calls `showList` and `showDetail` to apply the prepared content. `showList` wires the new list’s intent listeners. `showView` mounts an initially prepared layout; showing the existing layout again leaves it intact.\n\nThe preparation and commit methods are part of the same Application definition.\n`recordsApi` comes from [records-api.js](/docs/source/examples/records/src/records-api.js);\n`Collection` comes from `@mnjs/data`, and the Views come from\n[records-views.js](/docs/source/examples/records/src/records-views.js).\n\nExcerpt from [RecordsApplication](/docs/source/examples/records/src/records-application.js),\ninside its `Application.extend(...)` definition:\n\n```js\n  async prepareStart(options, { signal }) {\n    const records = await recordsApi.list({ signal });\n    return new Collection(records);\n  },\n  onStart(app, options, collection) {\n    this.records = collection;\n    const state = this.getState();\n    if (!(this.getView() instanceof RecordsLayout)) {\n      const layout = this.setView(new RecordsLayout());\n      layout.showChildView('status', new RecordsStatus({ model: state }));\n    }\n    this.showList();\n    this.showDetail();\n    state.set({ count: collection.length, loading: false, error: '' });\n    this.showView();\n  }\n```\n\n`start()` remains pending until preparation completes. Closing during preparation cancels that start. Marionette prevents its obsolete result from reaching `onStart`, even when a service ignores cancellation. A superseded start resolves false rather than entering the error path. The Application needs no separate run flag or request controller for this initial load.\n\n`start()` opens the feature and is idempotent while running. Reload and Retry call `restart()` to repeat preparation. The page and ready records layout remain mounted during an active restart. Success replaces the list and detail Regions with the prepared records; it does not render the whole layout. Selection follows the same record ID; an absent record shows empty detail. The [retained-restart guide](/docs/guides/retained-restart.md) demonstrates updating an observable source while retaining child View and input identity too.\n\n[RecordsLayout](/docs/source/examples/records/src/records-views.js) defines the three mount\npoints used above. Replacing the list or detail leaves this shell in place:\n\n```js\nexport const RecordsLayout = View.extend({\n  className: 'records',\n  template: () => html`\n    <h2>Records</h2>\n    <div class=\"js-status\"></div>\n    <div class=\"records-columns\">\n      <div class=\"js-list\"></div>\n      <section class=\"js-detail\" aria-label=\"Record details\"></section>\n    </div>`,\n  childViewTriggers: { retry: 'retry', reload: 'reload' },\n  regions: {\n    status: '.js-status',\n    list: '.js-list',\n    detail: '.js-detail'\n  }\n});\n```\n\n## Follow one selection\n\nIn [records-views.js](/docs/source/examples/records/src/records-views.js), a row emits `select`\nand RecordsList forwards `select:record`. Each row receives the same selection state\nthrough `childViewOptions`:\n\n```js\nconst RecordRow = View.extend({\n  tagName: 'li',\n  modelEvents: { change: 'render' },\n  stateEvents: { 'change:selectedId': 'render' },\n  templateContext() {\n    return { selected: this.getState().get('selectedId') === this.model.id };\n  },\n  template: ({ title, selected }) => html`\n    <button type=\"button\" aria-pressed=${selected}>${title}</button>`,\n  triggers: { 'click button': 'select' }\n});\n\nexport const RecordsList = CollectionView.extend({\n  tagName: 'ul',\n  attributes: { 'aria-label': 'Records' },\n  childView: RecordRow,\n  childViewOptions() { return { state: this.getState() }; },\n  childViewTriggers: { select: 'select:record' }\n});\n```\n\nThe Application owns a `Model` with `selectedId`, `count`, `loading`, and `error`.\nIts `stateEvents: { 'change:selectedId': 'showDetail' }` connects a selection change\nto the detail Region. These methods connect the list's intent and choose the detail.\n\nAnother excerpt from [RecordsApplication](/docs/source/examples/records/src/records-application.js),\ninside its `Application.extend(...)` definition:\n\n```js\n  showList() {\n    const state = this.getState();\n    const list = this.getView().showChildView('list', new RecordsList({ collection: this.records, state }));\n    this.listenTo(list, { 'select:record': row => state.set('selectedId', row.model.id) });\n  },\n  showDetail() {\n    const model = this.records.get(this.getState().get('selectedId'));\n    const detail = model ? new DetailView({ model }) : new EmptyDetailView();\n    this.getView().showChildView('detail', detail);\n  }\n```\n\n```text\nRow button → select → list's select:record → selectedId changes\n                                             ├─ rows update selection (via shared state)\n                                             └─ detail Region shows the selected record\n```\n\nThe callback receives the emitting row, so it can read `row.model.id`. The Views\nneed no reference to the Application or to one another.\n\nThe Application chooses DetailView for a selected record or EmptyDetailView when selection is empty. Each View renders one presentation. The list never reaches into the detail markup. Selection keeps the page, list, and rows mounted.\n\n## Keep the boundaries small\n\n| Source | Responsibility |\n| --- | --- |\n| [main-application.js](/docs/source/examples/records/src/main-application.js) | Own the page and registered Records child; connect controls through `viewEvents` and handle loading failures. |\n| [records-application.js](/docs/source/examples/records/src/records-application.js) | Prepare records, own their collection and selection, coordinate the ready UI. |\n| [records-views.js](/docs/source/examples/records/src/records-views.js) | Render loading, error, list, and detail content. Emit intent. Regions and CollectionView manage their child Views. |\n| [records-api.js](/docs/source/examples/records/src/records-api.js) | Implement `list({ signal })`, returning `{ id, title, description }` objects. |\n| [page.js](/docs/source/examples/records/src/page.js) | Define the page Regions and Open/Close controls; forward Retry intent from the displayed error View. |\n| [main.js](/docs/source/examples/records/src/main.js) | Start MainApplication at the root element. |\n| [setup.js](/docs/source/examples/records/src/setup.js) | Configure the data/state integration and Lit renderer once. |\n\nMainApplication owns the page and registers RecordsApplication as a child. Its `viewEvents` connects page intent. `onStart` attaches the page once and starts the child in its content Region. Parent restart retains both without installing listeners or starting the child again. The parent is ready when its page is available; the child has its own data readiness. Stopping or destroying the parent also stops or destroys the registered child.\n\n`@mnjs/data` provides observable Models and Collections. See [data setup](/docs/integrations/setup.md#observable-data-and-api-access) for the API boundary. RecordsApplication imports recordsApi directly. There is no configurable service constructor option. The API module returns plain JSON records, and preparation adapts them to the feature-owned Collection. A service that already supplies the chosen observable collection can return it directly. Real transport and backend policies belong behind that boundary. Replacing the observable implementation also requires matching Marionette's DataApi/StateApi contracts.\n\n## Failure and cleanup\n\nMainApplication catches a rejected child start or restart and logs the original error. A failed initial start is stopped before ErrorView replaces LoadingView. A failed active restart keeps the records layout and data, with the error shown by its status View. Retry repeats preparation; cancelled calls resolve `false` without showing an error. LoadingView, initial ErrorView, and the ready layout share the page's content Region. Status View reload/retry intent travels through the layout and PageView to MainApplication, which calls the child's `restart()` once.\n\nClose calls synchronous `stop()` and empties the child's UI. The page controls remain available. Open after Close loads a new Collection, resets selection, and creates a new records layout.\n\nStop destroys the feature's Views; Marionette automatically removes the Application's listeners to the destroyed list. The Application keeps the prepared collection for selection lookup and passes it to the list. A successful start or restart replaces that reference. These local records have no independent resources requiring a stop hook. The Application and selection Model survive so the feature can reopen; final destruction disposes the owned state.\n\nLit interpolation renders record strings as text; no example-specific escaping helper is needed.\n\n## Check changes\n\nStop the preview server first; these checks start their own server from this checkout. From the framework repository root:\n\n```sh\nnpx playwright install chromium firefox webkit\nnpx playwright test --config examples/records/playwright.config.js --workers=3\nnpm --prefix examples/records run build\n```\n\nThe browser checks cover readiness, selection, retained restart and failure, retry, cancellation, close/reopen, and disposal. Review ownership as well as behavior. These checks use linked local package builds; installed candidate-package checks are recorded separately from these linked-source checks.\n\n\n[Canonical source](/docs/markdown/docs/records.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "docs/tooling.md",
      "title": "Check and debug an application",
      "section": "Development tools",
      "kind": "guide",
      "url": "https://marionettejs.com/docs/tooling/",
      "markdownUrl": "https://marionettejs.com/docs/tooling.md",
      "sourceUrl": "https://marionettejs.com/docs/markdown/docs/tooling.md",
      "sourceSha256": "f7c1217dd8cd3d45460d3c51797787d243a4b4bb34b0a338db4b5d9aea85abe7",
      "sourceRevision": "0f2284ad4bbfe8c82ce82714471697a68c2acaeb",
      "sha256": "44771021e17789cc6eb3f12a735ffa34dfba21a670bf998fdd28c74f792df8d8",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 f7c1217dd8cd3d45460d3c51797787d243a4b4bb34b0a338db4b5d9aea85abe7; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Check and debug an application\n\nUse these checks in the application created by the [quick start](/docs/quick-start.md). Marionette includes declarations, an ESLint plugin, and a version-matched diagnostic catalog. They check specific contracts; they do not decide where your application's workflows belong.\n\n## Lint JavaScript\n\nInstall the development tools in your application directory:\n\n```sh\nnpm install --ignore-scripts --save-dev --save-exact eslint@10.11.0 typescript@6.0.3\n```\n\nCreate `eslint.config.mjs`:\n\n```js\nimport marionette from 'marionette/eslint';\n\nexport default [\n  {\n    ...marionette.configs.recommended,\n    files: ['**/*.js', '**/*.mjs'],\n    ignores: ['dist/**', 'node_modules/**']\n  }\n];\n```\n\nThe recommended configuration enables `marionette/no-private-framework-members`. It reports recognized access to Marionette internals, such as `view._isRendered`, and directs you toward supported APIs such as `view.isRendered()`. It is a JavaScript analysis rule, not a complete type checker: indirect values or dynamic property names can prevent it from identifying a framework member. It does not prohibit your own private fields or determine whether a service call belongs in a View.\n\nFor example, this `interaction.js` uses public APIs and keeps a local interaction in its View:\n\n```js\nimport { View } from 'marionette';\n\nexport const ToggleView = View.extend({\n  events: { 'click button': 'toggle' },\n  toggle() {\n    this.trigger('toggle', this);\n  }\n});\n```\n\nRun the rule against your JavaScript:\n\n```sh\nnpx eslint . --max-warnings=0\n```\n\nAdd other ESLint rules according to your application's needs. TypeScript linting also needs a TypeScript parser and configuration; the configuration above covers JavaScript only.\n\n## Check TypeScript against the installed package\n\nFor a browser application built by Vite or another bundler, create `tsconfig.json`:\n\n```json\n{\n  \"compilerOptions\": {\n    \"target\": \"ES2024\",\n    \"lib\": [\"ES2024\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"strict\": true,\n    \"noEmit\": true,\n    \"skipLibCheck\": false,\n    \"types\": []\n  },\n  \"include\": [\"*.ts\"]\n}\n```\n\nAdjust `include` to match your source directories. Node applications need configuration suited to their module system. The package supplies its own declarations; do not install declarations for Marionette v4 or alias the package to repository source files.\n\nThis `screen.ts` checks a Region and View against the installed declarations:\n\n```ts\nimport type { RegionInstance, ViewInstance } from 'marionette';\n\nexport function showScreen(region: RegionInstance, view: ViewInstance): void {\n  region.show(view);\n}\n```\n\nUse instance types such as `RegionInstance` and `ViewInstance` in annotations; the `Region` and `View` exports are constructors. Run the compiler independently of the bundler:\n\n```sh\nnpx tsc -p tsconfig.json\n```\n\nFor example, passing a string to `region.show()` produces a type error because that method expects a View. A successful build may only mean that TypeScript was transformed into JavaScript; run the type check explicitly. Types do not prove that a selector exists, an event happens at the intended time, or a workflow has the right owner.\n\nFor typed initialization, DOM handlers, state and lifecycle results, follow [Use TypeScript](/docs/guides/typescript.md).\n\n## Look up a diagnostic\n\nWhen an error includes a code such as `MN0003`, use the lookup helper shipped with the same package:\n\n```sh\nnode node_modules/marionette/skills/marionette/scripts/docs.mjs --diagnostic MN0003\n```\n\nThe result includes the catalog explanation and any documented recovery guidance. Use the code from the actual error, preserve its stack trace, and read the associated API contract before changing the code. The [agent guide](/docs/agents.md#local-contract-lookup) explains lookup when a package lives in an external store.\n\nFor runnable interaction, replacement, readiness and teardown tests, follow [Test an application](/docs/guides/testing.md).\n\n## Debug the failing boundary\n\n1. Identify the installed version and configured renderer or data provider. A DOM, template, or persistence problem may belong to that integration.\n2. Reproduce the operation with the smallest relevant owner: a local edit in its View, a replacement in its Region, or readiness and shared coordination in its Application.\n3. Inspect public state such as `view.isRendered()`, `view.isAttached()`, and `view.isDestroyed()`. Observe lifecycle events instead of reading internal flags. For asynchronous operations, retain and inspect the returned Promise so a failure remains visible.\n4. Test the user-visible outcome and teardown. For a replaced panel, verify that the old panel is removed and its owned subscriptions stop reacting. For a failed start, verify the intended error UI and retry behavior.\n\nUse browser developer tools for the actual DOM, network, and event timing. Lint, declarations, and diagnostic lookup complement those checks. None measures architectural quality or proves that an agent understood the documentation; use the [ownership guide](/docs/architecture.md) and review observable behavior for that.\n\n## Agent installation\n\nThe installed package includes `skills/marionette`. The skill routes to that application's installed docs and includes an offline lookup helper. Reading `SKILL.md` directly also works.\n\nFor a Codex project, copy the complete folder to `.agents/skills/marionette` in your application and invoke `$marionette`. Keep the scripts with the entrypoint. For other clients, use their documented skill location and invocation support. See [Codex skill installation](https://learn.chatgpt.com/docs/build-skills).\n\nThe `marionette` plugin is distributed through repository marketplaces, separately from the npm package. Its version tracks the loader and connection, independently of the framework. The plugin locates the application's installed package and loads that package's skill; it does not bundle a newer copy of the API instructions. In a Codex client supporting local marketplaces, add a checkout with `codex plugin marketplace add /absolute/path/to/checkout`, then install Marionette using the client's plugin interface. See [OpenAI plugin installation](https://developers.openai.com/plugins/build/plugins). The repository also includes Claude Code and Cursor marketplace manifests. Verify installation in the client you use; a manifest alone does not establish a working installation or marketplace listing.\n\nThe loader recognizes `backbone.marionette` 4.x as a v4 installation and identifies older releases separately. Keep existing application work on its v4 contracts. For migration, choose the target v5 release and read that release's [migration guide](/docs/guides/migration.md); installing the plugin does not upgrade the application. When both packages are present, select guidance based on the feature's imports.\n\nChoose the copied package skill for local lookup without MCP. The plugin can also use the hosted connection, subject to the identity check below. A release without a packaged skill needs its own documentation or exact source revision.\n\n## Hosted documentation MCP\n\nThe plugin's connection is `https://mcp.marionettejs.com/mcp`. Before searching it, read the `marionette://catalog` resource. Compare both `provenance.packageVersion` and `provenance.sourceRevision` with the application's installed package and `docs-manifest.json`. A matching version alone does not establish the same contract, including when the hosted catalog serves a development candidate. Follow the catalog's `requestIdentity` field for required tool arguments. Pass the exact `version`; for a development candidate, also pass the matching `sourceRevision` on search and read calls, including `search_docs`, `search_sections`, and retrieval of their returned IDs. Do not use a latest-version alias.\n\nA reused prerelease version can contain different contracts. A manifest with `sourceDirty: true` includes changes beyond that revision, so its local docs remain authoritative. If either revision is unavailable, the identities differ, or the service is unavailable, use installed Markdown and the local helper. Hosted results do not override the installed artifact's contract. Copying the skill alone requires no hosted connection; disable the bundled server only through your client's supported settings if using the plugin without MCP.\n\n\n[Canonical source](/docs/markdown/docs/tooling.md) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0001",
      "title": "MN0001: view el must be dom element",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0001/",
      "markdownUrl": "https://marionettejs.com/errors/MN0001.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "79c8fed93a9cc9a4ed5b01653c9fc635fc6c42593136423efa9b4b8902e90398",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0001: view el must be dom element\n\nStatus: retired\nReported by: runtime\nObjects: CollectionView, View\nCategory: dom\nSeverity: error\n\n## Remediation\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n[CollectionView](/docs/api/collection-view/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0002",
      "title": "MN0002: region el type invalid",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0002/",
      "markdownUrl": "https://marionettejs.com/errors/MN0002.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "b26b183f6b7beb9f31c59a62bf0acc9cdbb24c4b1daa9c6e068d77cef48367e5",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0002: region el type invalid\n\nStatus: retired\nReported by: runtime\nObjects: Region\nCategory: dom\nSeverity: error\n\n## Remediation\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n[Region](/docs/api/region/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0003",
      "title": "MN0003: view already owned",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0003/",
      "markdownUrl": "https://marionettejs.com/errors/MN0003.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "39127beb33558f73a682a86205cd332afd2cb89a701946cad57afda0395e1d4f",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0003: view already owned\n\nStatus: active\nReported by: runtime\nObjects: Application, CollectionView, Region, View\nCategory: ownership\nSeverity: error\n\n## Remediation\n\nUse the owning Application to display its prepared root. Detach a displayed view from its Region or CollectionView before adopting it elsewhere, or create a new view instance.\n\n[Application](/docs/api/application/) · [CollectionView](/docs/api/collection-view/) · [Region](/docs/api/region/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0004",
      "title": "MN0004: region el required",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0004/",
      "markdownUrl": "https://marionettejs.com/errors/MN0004.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "5c8156532d9fd68d9609a9e71e7de67002ed5764e934e8fb448ffb9d1d0033d6",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0004: region el required\n\nStatus: active\nReported by: runtime\nObjects: Region\nCategory: dom\nSeverity: error\n\n## Remediation\n\nConfigure the Region with an el selector or DOM element before using it.\n\n[Region](/docs/api/region/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0005",
      "title": "MN0005: region el not found",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0005/",
      "markdownUrl": "https://marionettejs.com/errors/MN0005.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "341171172adadb724d25080182575e82c79f610ee5e9f513c5525167b104677d",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0005: region el not found\n\nStatus: active\nReported by: runtime\nObjects: Region\nCategory: dom\nSeverity: error\n\n## Remediation\n\nRender the parent View before direct selector-backed Region operations, ensure the selector resolves within its parent element, or explicitly allow a missing element where supported.\n\n[Region](/docs/api/region/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0006",
      "title": "MN0006: region view required",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0006/",
      "markdownUrl": "https://marionettejs.com/errors/MN0006.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "6500a2b9380e2dc20ffea91b7a22d9583a03326671a4040ea2ca2cec6a87706c",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0006: region view required\n\nStatus: retired\nReported by: runtime\nObjects: Region\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n[Region](/docs/api/region/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0007",
      "title": "MN0007: region view destroyed",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0007/",
      "markdownUrl": "https://marionettejs.com/errors/MN0007.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "9b959f917f2414d4fe9308d587b300fbe76a7307d8e4cb0335b5c0113ae6773c",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0007: region view destroyed\n\nStatus: active\nReported by: runtime\nObjects: Application, Region, View\nCategory: lifecycle\nSeverity: error\n\n## Remediation\n\nCreate a new View instance instead of attempting to show a destroyed view.\n\n[Application](/docs/api/application/) · [Region](/docs/api/region/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0008",
      "title": "MN0008: region definition invalid",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0008/",
      "markdownUrl": "https://marionettejs.com/errors/MN0008.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "bb69bcaf747c0eb94cbe811fb56d6b09d14a1b6b47bdb0fe4f6919e8a35652f5",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0008: region definition invalid\n\nStatus: retired\nReported by: runtime\nObjects: Application, Region, View\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n[Application](/docs/api/application/) · [Region](/docs/api/region/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0009",
      "title": "MN0009: event bindings invalid",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0009/",
      "markdownUrl": "https://marionettejs.com/errors/MN0009.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "a8600f8f3f2f2f48043be0d74883df3f937fe02e20fb94d6a316976c032e110d",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0009: event bindings invalid\n\nStatus: retired\nReported by: runtime\nObjects: Application, Behavior, CollectionView, MnObject, Region, View\nCategory: communication\nSeverity: error\n\n## Remediation\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n[Application](/docs/api/application/) · [Behavior](/docs/api/behavior/) · [CollectionView](/docs/api/collection-view/) · [MnObject](/docs/api/mnobject/) · [Region](/docs/api/region/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0010",
      "title": "MN0010: request bindings invalid",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0010/",
      "markdownUrl": "https://marionettejs.com/errors/MN0010.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "73354740eb6ee660b6e825d9e6e84e4f674e40564a9e14b0018631054b0905ca",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0010: request bindings invalid\n\nStatus: retired\nReported by: runtime\nObjects: Application, Behavior, CollectionView, MnObject, Region, View\nCategory: communication\nSeverity: error\n\n## Remediation\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n[Application](/docs/api/application/) · [Behavior](/docs/api/behavior/) · [CollectionView](/docs/api/collection-view/) · [MnObject](/docs/api/mnobject/) · [Region](/docs/api/region/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0011",
      "title": "MN0011: collection view child view required",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0011/",
      "markdownUrl": "https://marionettejs.com/errors/MN0011.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "30e535d95deb494c0efb99cccb1593620e1091a5fac24f08530b03ea2f74b6b2",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0011: collection view child view required\n\nStatus: active\nReported by: runtime\nObjects: CollectionView\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nConfigure childView with a View class or a function that returns a View class.\n\n[CollectionView](/docs/api/collection-view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0012",
      "title": "MN0012: collection view child view invalid",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0012/",
      "markdownUrl": "https://marionettejs.com/errors/MN0012.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "798b60fcdf0d197f47d2781d7a0d44d4bfcbb2607f317ba7278e02cc4a9df70f",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0012: collection view child view invalid\n\nStatus: retired\nReported by: runtime\nObjects: CollectionView\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n[CollectionView](/docs/api/collection-view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0013",
      "title": "MN0013: collection view container not found",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0013/",
      "markdownUrl": "https://marionettejs.com/errors/MN0013.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "22375f8092ca36ea080cd54b0e10cbbb6666ef9f58bc3af7357dd73f8d59677e",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0013: collection view container not found\n\nStatus: active\nReported by: runtime\nObjects: CollectionView\nCategory: dom\nSeverity: error\n\n## Remediation\n\nEnsure childViewContainer resolves to an element within the rendered CollectionView.\n\n[CollectionView](/docs/api/collection-view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0014",
      "title": "MN0014: collection view filter invalid",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0014/",
      "markdownUrl": "https://marionettejs.com/errors/MN0014.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "972f45f5e46ff4bbb5294648247c387d51092cf69b875d0ea10602b3ae3e02ab",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0014: collection view filter invalid\n\nStatus: retired\nReported by: runtime\nObjects: CollectionView\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n[CollectionView](/docs/api/collection-view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0015",
      "title": "MN0015: collection view swap non children",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0015/",
      "markdownUrl": "https://marionettejs.com/errors/MN0015.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "8266bb5f6af078470f64145c960a17389925763e5207ab2a35d2868df8656237",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0015: collection view swap non children\n\nStatus: active\nReported by: runtime\nObjects: CollectionView\nCategory: ownership\nSeverity: error\n\n## Remediation\n\nPass two views currently owned by the CollectionView to swapChildViews.\n\n[CollectionView](/docs/api/collection-view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0016",
      "title": "MN0016: behavior definition invalid",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0016/",
      "markdownUrl": "https://marionettejs.com/errors/MN0016.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "23b0919bba2428a35c3f6dab0c9fb716e1f3fc6cfd5127a3a208633a48085b16",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0016: behavior definition invalid\n\nStatus: retired\nReported by: runtime\nObjects: Behavior, CollectionView, View\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n[Behavior](/docs/api/behavior/) · [CollectionView](/docs/api/collection-view/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0017",
      "title": "MN0017: radio channel name required",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0017/",
      "markdownUrl": "https://marionettejs.com/errors/MN0017.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "b826cc7727ff2a703743af1edb2e664d5641ef36bc7d9c6ddffbed7afa4709f3",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0017: radio channel name required\n\nStatus: active\nReported by: runtime\nObjects: Radio\nCategory: communication\nSeverity: error\n\n## Remediation\n\nPass a non-empty channel name when creating or accessing a Radio channel.\n\n[@mnjs/radio: channels and requests](/docs/packages/radio/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0018",
      "title": "MN0018: ui reference invalid",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0018/",
      "markdownUrl": "https://marionettejs.com/errors/MN0018.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "41b188f5e187571be992ef5700178c05072358111e662e1317f6d79d79022298",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0018: ui reference invalid\n\nStatus: active\nReported by: runtime\nObjects: Behavior, CollectionView, View\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nUse @ui.<name> with a non-empty own key whose value is a string selector, or replace the reference with a literal selector.\n\n[Behavior](/docs/api/behavior/) · [CollectionView](/docs/api/collection-view/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0019",
      "title": "MN0019: handler not callable",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0019/",
      "markdownUrl": "https://marionettejs.com/errors/MN0019.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "b04e699657a33db3f82db42a7b9132b9129f4d90e7b4e9518ab761a86bbe8f04",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0019: handler not callable\n\nStatus: active\nReported by: runtime\nObjects: Application, Behavior, CollectionView, MnObject, Region, View\nCategory: communication\nSeverity: error\n\n## Remediation\n\nProvide a function or the string name of a callable method on the binding context.\n\n[Application](/docs/api/application/) · [Behavior](/docs/api/behavior/) · [CollectionView](/docs/api/collection-view/) · [MnObject](/docs/api/mnobject/) · [Region](/docs/api/region/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0020",
      "title": "MN0020: named region not found",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0020/",
      "markdownUrl": "https://marionettejs.com/errors/MN0020.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "cb1238d5195e75eaef50e5f235642d37b1795cf028ab39993b28a5e219159448",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0020: named region not found\n\nStatus: active\nReported by: runtime\nObjects: View\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nDefine the named Region before using child-View or Region-removal operations, or use getRegion or hasRegion for optional lookup.\n\n[View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0021",
      "title": "MN0021: radio channel not found",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0021/",
      "markdownUrl": "https://marionettejs.com/errors/MN0021.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "0a2b457201265d2613be2fc37e8610be265d1e20e8083c9512ec714907386f47",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0021: radio channel not found\n\nStatus: active\nReported by: runtime\nObjects: Radio\nCategory: communication\nSeverity: error\n\n## Remediation\n\nCreate the named channel with Radio.channel(name) before resetting it, or call Radio.reset() with no arguments to reset all existing channels.\n\n[@mnjs/radio: channels and requests](/docs/packages/radio/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0022",
      "title": "MN0022: collection view empty view invalid",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0022/",
      "markdownUrl": "https://marionettejs.com/errors/MN0022.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "542c77b5e697ad6d8dc26e1e67625af273fa3cf523228933190aa399b2356c7a",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0022: collection view empty view invalid\n\nStatus: retired\nReported by: runtime\nObjects: CollectionView\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n[CollectionView](/docs/api/collection-view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0023",
      "title": "MN0023: ui elements unavailable",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0023/",
      "markdownUrl": "https://marionettejs.com/errors/MN0023.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "c8b31aeae47ea33492a613a48b362294270cd212f19fc714f4534bad14b62043",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0023: ui elements unavailable\n\nStatus: active\nReported by: runtime\nObjects: Behavior, CollectionView, View\nCategory: lifecycle\nSeverity: error\n\n## Remediation\n\nDeclare a ui map, then render the View or explicitly bind its UI elements before calling getUI; bind them again before calling getUI after unbinding.\n\n[Behavior](/docs/api/behavior/) · [CollectionView](/docs/api/collection-view/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0024",
      "title": "MN0024: child container argument invalid",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0024/",
      "markdownUrl": "https://marionettejs.com/errors/MN0024.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "6894b53ff4f7d3bc7969e26aeeab4d42d727a39b83e54078087bc33a7a021023",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0024: child container argument invalid\n\nStatus: active\nReported by: runtime\nObjects: CollectionView\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nPass nonnegative integer counts. Reducing an empty child container requires an initial value.\n\n[CollectionView](/docs/api/collection-view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0025",
      "title": "MN0025: child container method not callable",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0025/",
      "markdownUrl": "https://marionettejs.com/errors/MN0025.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "39ddfa7071220abd1aaf06ced53d6b168aa0ceafbc6115248ce8c4d3adbcff44",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0025: child container method not callable\n\nStatus: retired\nReported by: runtime\nObjects: CollectionView\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n[CollectionView](/docs/api/collection-view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0026",
      "title": "MN0026: entity event name unsafe",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0026/",
      "markdownUrl": "https://marionettejs.com/errors/MN0026.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "1dffd6d2de838b8a8f66b473f7cd436ea25eca5a52b29a0182685dd4c77fade8",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0026: entity event name unsafe\n\nStatus: active\nReported by: runtime\nObjects: Application, Behavior, CollectionView, MnObject, Region, View\nCategory: communication\nSeverity: error\n\n## Remediation\n\nRename an own __proto__ entry in an entity-event map before binding or selectively unbinding it.\n\n[Application](/docs/api/application/) · [Behavior](/docs/api/behavior/) · [CollectionView](/docs/api/collection-view/) · [MnObject](/docs/api/mnobject/) · [Region](/docs/api/region/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0027",
      "title": "MN0027: feature name invalid",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0027/",
      "markdownUrl": "https://marionettejs.com/errors/MN0027.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "f8182f14f906496be0f64d1e72dd0086b6aecfb42e052c3487b9d220716f30b1",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0027: feature name invalid\n\nStatus: retired\nReported by: runtime\nObjects: Behavior, CollectionView, View\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nThe v5 feature registry is removed. Configure child event prefixes per View, trigger behavior per trigger, and application values through State or explicit configuration.\n\n[Behavior](/docs/api/behavior/) · [CollectionView](/docs/api/collection-view/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0028",
      "title": "MN0028: region destroyed operation",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0028/",
      "markdownUrl": "https://marionettejs.com/errors/MN0028.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "b42b6da866e55c8a14f2e82793a740badfd8aa8a4adaa753ccffbc2b155cdddb",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0028: region destroyed operation\n\nStatus: retired\nReported by: runtime\nObjects: Region\nCategory: lifecycle\nSeverity: error\n\n## Remediation\n\nCalls to show, empty, or reset after Region destruction are lifecycle-safe no-ops. Use a live Region when the operation must take effect.\n\n[Region](/docs/api/region/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0029",
      "title": "MN0029: view destroyed set element",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0029/",
      "markdownUrl": "https://marionettejs.com/errors/MN0029.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "b4b817dbe783ae01af98479b6a8145a5e6eeece12193896dcd61d26d006a30fb",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0029: view destroyed set element\n\nStatus: retired\nReported by: runtime\nObjects: CollectionView, View\nCategory: lifecycle\nSeverity: error\n\n## Remediation\n\nCalls to setElement after View or CollectionView destruction begins are lifecycle-safe no-ops. Use a live instance when element replacement must take effect.\n\n[CollectionView](/docs/api/collection-view/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0030",
      "title": "MN0030: region registration conflict",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0030/",
      "markdownUrl": "https://marionettejs.com/errors/MN0030.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "3c6d80514111fcb315418842a2fb203db40d5b3496048555451d785137f03f14",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0030: region registration conflict\n\nStatus: active\nReported by: runtime\nObjects: Region, View\nCategory: ownership\nSeverity: error\n\n## Remediation\n\nRegister a live, unowned Region under an unused name; remove an existing named Region before replacing it and use a fresh Region instance for a different owner.\n\n[Region](/docs/api/region/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0031",
      "title": "MN0031: application registration conflict",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0031/",
      "markdownUrl": "https://marionettejs.com/errors/MN0031.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "e097cbed10a3b7cec5091eddf9f8aebd057d2f8174842b5f3e2bdc2f147ee798",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0031: application registration conflict\n\nStatus: active\nReported by: runtime\nObjects: Application\nCategory: ownership\nSeverity: error\n\n## Remediation\n\nRegister a live, unowned Application instance under an unused non-empty string name; use hasChildApp before constructing a dynamic child when allocation must be avoided.\n\n[Application](/docs/api/application/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0032",
      "title": "MN0032: region name invalid",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0032/",
      "markdownUrl": "https://marionettejs.com/errors/MN0032.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "b4e03ba07025877db39c56937ae324eba19a80296176e3a90979a2c8c4f35f70",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0032: region name invalid\n\nStatus: active\nReported by: runtime\nObjects: View\nCategory: ownership\nSeverity: error\n\n## Remediation\n\nPass a non-empty string name to a named Region operation.\n\n[View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0033",
      "title": "MN0033: merge options keys invalid",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0033/",
      "markdownUrl": "https://marionettejs.com/errors/MN0033.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "b3d02c0ce0bba7cefd815d48847aeffa90c14cb0a7a9b6179fed11d92b79dd03",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0033: merge options keys invalid\n\nStatus: retired\nReported by: runtime\nObjects: Application, Behavior, CollectionView, MnObject, Region, View\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n[Application](/docs/api/application/) · [Behavior](/docs/api/behavior/) · [CollectionView](/docs/api/collection-view/) · [MnObject](/docs/api/mnobject/) · [Region](/docs/api/region/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0034",
      "title": "MN0034: state key invalid",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0034/",
      "markdownUrl": "https://marionettejs.com/errors/MN0034.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "88c396bd4e7307f0d08b809b16dc9fbe1925741fa7db9227e4f1602dd4d5e2a9",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0034: state key invalid\n\nStatus: retired\nReported by: runtime\nObjects: StateApi\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nThe concrete v5 alpha State key validation is removed. Use the selected source's native key contract.\n\n[Data and state providers](/docs/api/providers/data/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0035",
      "title": "MN0035: state ownership conflict",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0035/",
      "markdownUrl": "https://marionettejs.com/errors/MN0035.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "d587de033e6d702c51fc05ddfe3bda82b80f419d46ad4f28caad3c87c4641d85",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0035: state ownership conflict\n\nStatus: retired\nReported by: runtime\nObjects: Behavior, CollectionView, MnObject, View\nCategory: ownership\nSeverity: error\n\n## Remediation\n\nThe concrete v5 alpha State ownership rule is removed. Supplied sources are borrowed and may be shared by multiple owners; createState results are owned and disposed by their owner.\n\n[Behavior](/docs/api/behavior/) · [CollectionView](/docs/api/collection-view/) · [MnObject](/docs/api/mnobject/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0036",
      "title": "MN0036: event delegator contract invalid",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0036/",
      "markdownUrl": "https://marionettejs.com/errors/MN0036.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "80ca15d7a0063aaa1c46545e78632104e98bf702f4726b704c121ae480dfd23f",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0036: event delegator contract invalid\n\nStatus: retired\nReported by: runtime\nObjects: Behavior, CollectionView, View\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nUse the documented argument types. Marionette no longer emits a dedicated runtime diagnostic for this unsupported input shape.\n\n[Behavior](/docs/api/behavior/) · [CollectionView](/docs/api/collection-view/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0037",
      "title": "MN0037: adapter observation unsupported",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0037/",
      "markdownUrl": "https://marionettejs.com/errors/MN0037.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "520bbe7c18dfb9e96bc1c9c85dd817ab3750e4fd7a80fc7125bd206759a46ecd",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0037: adapter observation unsupported\n\nStatus: active\nReported by: runtime\nObjects: Application, Behavior, CollectionView, MnObject, View\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nConfigure a StateApi or DataApi that can observe the selected source, or remove the declarative event map.\n\n[Application](/docs/api/application/) · [Behavior](/docs/api/behavior/) · [CollectionView](/docs/api/collection-view/) · [MnObject](/docs/api/mnobject/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0038",
      "title": "MN0038: adapter cleanup invalid",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0038/",
      "markdownUrl": "https://marionettejs.com/errors/MN0038.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "186091b9b26e7d0f71c6914b3136d2e248070afc12975a176e1a924dda0440d8",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0038: adapter cleanup invalid\n\nStatus: retired\nReported by: runtime\nObjects: Application, Behavior, CollectionView, MnObject, View\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nDataApi and StateApi adapters must return cleanup functions. Core no longer wraps or validates cleanup on each registration.\n\n[Application](/docs/api/application/) · [Behavior](/docs/api/behavior/) · [CollectionView](/docs/api/collection-view/) · [MnObject](/docs/api/mnobject/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0039",
      "title": "MN0039: collection data contract invalid",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0039/",
      "markdownUrl": "https://marionettejs.com/errors/MN0039.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "4e5dd45eee28afa4c8fe5759eaaa3923acfbcdf39e4ee81a21a74a116700efa1",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0039: collection data contract invalid\n\nStatus: active\nReported by: runtime\nObjects: CollectionView\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nReturn an ordered array with unique stable keys and emit a valid reorder, reset, or update structural record.\n\n[CollectionView](/docs/api/collection-view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/MN0040",
      "title": "MN0040: private framework member access",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/MN0040/",
      "markdownUrl": "https://marionettejs.com/errors/MN0040.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "90ec148884e3dd4afc043db504a8e926624aed8c4e28c129818b2aefaf3a2985",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# MN0040: private framework member access\n\nStatus: active\nReported by: lint\nObjects: Application, Behavior, CollectionView, MnObject, Region, View\nCategory: configuration\nSeverity: error\n\n## Remediation\n\nUse the documented public Marionette API instead of reading or calling this private framework member.\n\n[Application](/docs/api/application/) · [Behavior](/docs/api/behavior/) · [CollectionView](/docs/api/collection-view/) · [MnObject](/docs/api/mnobject/) · [Region](/docs/api/region/) · [View](/docs/api/view/)\n\n[Check and debug an application](/docs/tooling/)\n\n[Diagnostic catalog](/errors/index.md) · [Source identity](/docs/manifest.json)\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    },
    {
      "id": "errors/index",
      "title": "Diagnostic codes",
      "section": "Diagnostics",
      "kind": "diagnostic",
      "url": "https://marionettejs.com/errors/",
      "markdownUrl": "https://marionettejs.com/errors/index.md",
      "sourceUrl": "https://marionettejs.com/docs/source/config/diagnostics/catalog.json",
      "sourceSha256": "89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4",
      "sha256": "0ecd58f2d9c1f40a93f08a98fb90093140446e19656c5458ff934dced2a0360b",
      "markdown": "<!-- Documentation snapshot: package 5.0.0; channel latest; archived channel latest; base revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; local changes false; original source SHA-256 89ca537fe5cacaef35d30f25aeb4d1ed4e1e8802c80c540f3672533c7b0145c4; reading source revision 0f2284ad4bbfe8c82ce82714471697a68c2acaeb; publication edits /docs/publication.json. -->\n\n# Diagnostic codes\n\n- [MN0001: view el must be dom element](/errors/MN0001.md): retired\n- [MN0002: region el type invalid](/errors/MN0002.md): retired\n- [MN0003: view already owned](/errors/MN0003.md): active\n- [MN0004: region el required](/errors/MN0004.md): active\n- [MN0005: region el not found](/errors/MN0005.md): active\n- [MN0006: region view required](/errors/MN0006.md): retired\n- [MN0007: region view destroyed](/errors/MN0007.md): active\n- [MN0008: region definition invalid](/errors/MN0008.md): retired\n- [MN0009: event bindings invalid](/errors/MN0009.md): retired\n- [MN0010: request bindings invalid](/errors/MN0010.md): retired\n- [MN0011: collection view child view required](/errors/MN0011.md): active\n- [MN0012: collection view child view invalid](/errors/MN0012.md): retired\n- [MN0013: collection view container not found](/errors/MN0013.md): active\n- [MN0014: collection view filter invalid](/errors/MN0014.md): retired\n- [MN0015: collection view swap non children](/errors/MN0015.md): active\n- [MN0016: behavior definition invalid](/errors/MN0016.md): retired\n- [MN0017: radio channel name required](/errors/MN0017.md): active\n- [MN0018: ui reference invalid](/errors/MN0018.md): active\n- [MN0019: handler not callable](/errors/MN0019.md): active\n- [MN0020: named region not found](/errors/MN0020.md): active\n- [MN0021: radio channel not found](/errors/MN0021.md): active\n- [MN0022: collection view empty view invalid](/errors/MN0022.md): retired\n- [MN0023: ui elements unavailable](/errors/MN0023.md): active\n- [MN0024: child container argument invalid](/errors/MN0024.md): active\n- [MN0025: child container method not callable](/errors/MN0025.md): retired\n- [MN0026: entity event name unsafe](/errors/MN0026.md): active\n- [MN0027: feature name invalid](/errors/MN0027.md): retired\n- [MN0028: region destroyed operation](/errors/MN0028.md): retired\n- [MN0029: view destroyed set element](/errors/MN0029.md): retired\n- [MN0030: region registration conflict](/errors/MN0030.md): active\n- [MN0031: application registration conflict](/errors/MN0031.md): active\n- [MN0032: region name invalid](/errors/MN0032.md): active\n- [MN0033: merge options keys invalid](/errors/MN0033.md): retired\n- [MN0034: state key invalid](/errors/MN0034.md): retired\n- [MN0035: state ownership conflict](/errors/MN0035.md): retired\n- [MN0036: event delegator contract invalid](/errors/MN0036.md): retired\n- [MN0037: adapter observation unsupported](/errors/MN0037.md): active\n- [MN0038: adapter cleanup invalid](/errors/MN0038.md): retired\n- [MN0039: collection data contract invalid](/errors/MN0039.md): active\n- [MN0040: private framework member access](/errors/MN0040.md): active\n\n\n[Canonical source](/docs/markdown/config/diagnostics/catalog.json) · [Source identity](/docs/manifest.json)\n"
    }
  ]
}
