diff --git a/.github/actions/setup-monorepo/action.yml b/.github/actions/setup-monorepo/action.yml
index 16dfb1f..0264b95 100644
--- a/.github/actions/setup-monorepo/action.yml
+++ b/.github/actions/setup-monorepo/action.yml
@@ -7,7 +7,7 @@ runs:
with:
node-version: "24.13.0"
- - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
+ - uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
with:
version: 10
diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml
index df073c9..6949d97 100644
--- a/.github/workflows/deploy-docs.yml
+++ b/.github/workflows/deploy-docs.yml
@@ -61,7 +61,7 @@ jobs:
key: size-baseline-${{ runner.os }}-${{ github.sha }}
- name: Deploy to Cloudflare Pages
- uses: cloudflare/wrangler-action@v3
+ uses: cloudflare/wrangler-action@v4
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
diff --git a/.github/workflows/deploy-wrenfield.yml b/.github/workflows/deploy-wrenfield.yml
new file mode 100644
index 0000000..514a100
--- /dev/null
+++ b/.github/workflows/deploy-wrenfield.yml
@@ -0,0 +1,42 @@
+# Manual redeploy of wrenfield.excom.dev from `main`. Pushes to `main` deploy
+# through the Release workflow (publish.yml), after the version bump, so the
+# page always pins a Kit version that is on npm. Run this from `main` only:
+# another ref can carry a Kit version that was never published.
+#
+# CLOUDFLARE_API_TOKEN needs Workers Scripts:Edit (account), plus Workers
+# Routes:Edit and DNS:Edit on the excom.dev zone for the custom domain
+# declared in packages/wrenfield/wrangler.jsonc.
+name: Deploy Wrenfield
+
+on:
+ workflow_dispatch:
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ timeout-minutes: 15
+ permissions:
+ contents: read
+ steps:
+ - uses: actions/checkout@v6
+
+ # No dependencies to install: staging copies files and reads the Kit
+ # version from packages/nucleus-kit/package.json.
+ - uses: actions/setup-node@v6
+ with:
+ node-version: "24.13.0"
+ - run: node packages/wrenfield/scripts/stage.mjs
+
+ # From the repo root like the docs deploy: the action installs wrangler
+ # with npm where it runs, which cannot read the package's `workspace:`
+ # dependencies. Config paths resolve relative to the config file.
+ - name: Deploy to Cloudflare Workers
+ uses: cloudflare/wrangler-action@v4
+ with:
+ apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
+ accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
+ command: deploy --config packages/wrenfield/wrangler.jsonc
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index 51dace3..dca2c20 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -69,7 +69,7 @@ jobs:
- uses: actions/setup-node@v6
with:
node-version: "24.13.0"
- - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
+ - uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
with:
version: 10
@@ -82,14 +82,14 @@ jobs:
run: pnpm dlx @cyclonedx/cdxgen -t pnpm --no-install-deps --no-babel --spec-version 1.6 -o bom.json
- name: Upload SBOM as Artifact
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
with:
name: sbom-cyclonedx.json
path: bom.json
- name: Grype Dependency Scanner (Report)
id: scan-package
- uses: anchore/scan-action@40a61b52209e9d50e87917c5b901783d546b12d0
+ uses: anchore/scan-action@27805bf3b4e84b4a5c980df22ed233c00390a439 # v7.4.2
with:
sbom: bom.json
fail-build: false
@@ -97,7 +97,7 @@ jobs:
timeout-minutes: 10
- name: Upload Grype SARIF Results
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
with:
name: grype-scan-results.sarif
path: ${{ steps.scan-package.outputs.sarif }}
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 644c53d..9c02dd3 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -8,14 +8,15 @@
# 2. Build everything from the bumped tree, so package metas, CDN
# snippets, npm READMEs and the docs site carry the new versions.
# 3. Publish to npm (and the VS Code extension).
-# 4. Deploy the docs site, on every push: a docs-only change has nothing
-# to publish but still needs a deploy.
+# 4. Deploy the docs site and Wrenfield, on every push: a docs-only change
+# has nothing to publish but still needs a deploy. Wrenfield pins the Kit
+# version just bumped, so it runs after the publish.
# 5. Push the bump commit last, so `main` only records versions that
# reached npm.
# Why one pipeline: a site deployed in parallel is built from the pre-bump
# commit and shows the old versions, and the bump commit never starts a run
# to correct it (`[skip ci]`; GITHUB_TOKEN pushes start no workflows).
-# deploy-docs.yml is for manual redeploys only.
+# deploy-docs.yml and deploy-wrenfield.yml are for manual redeploys only.
name: Release
on:
@@ -136,11 +137,23 @@ jobs:
path: size-baseline
key: size-baseline-${{ runner.os }}-${{ github.sha }}
- name: Deploy to Cloudflare Pages
- uses: cloudflare/wrangler-action@v3
+ uses: cloudflare/wrangler-action@v4
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy packages/docs-site/dist --project-name=excom-docs
+ # Wrenfield (wrenfield.excom.dev), a Worker with static assets. The token
+ # also needs Workers Scripts:Edit (account), plus Workers Routes:Edit and
+ # DNS:Edit on the excom.dev zone for the custom domain. The stage step
+ # reads the bumped Kit version, which the publish above put on npm.
+ - name: Stage Wrenfield
+ run: node packages/wrenfield/scripts/stage.mjs
+ - name: Deploy Wrenfield to Cloudflare Workers
+ uses: cloudflare/wrangler-action@v4
+ with:
+ apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
+ accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
+ command: deploy --config packages/wrenfield/wrangler.jsonc
# 5. Push the bump, if one was committed (HEAD moved off the checked-out
# commit). Runs whenever npm publish succeeded, even if the extension or
diff --git a/README.md b/README.md
index 091252c..b07ee3b 100644
--- a/README.md
+++ b/README.md
@@ -18,22 +18,22 @@ Your HTML __*is*__ the app! Drop-in custom elements that each have a single resp
## How it's different from existing UI solutions
-- **Back to the future** Welcome back to building static HTML5 apps. A break from complex JavaScript apps that compile to HTML.
-- **Little to no JavaScript** You no longer need to write JS for the vast majority of UI cases. You may still call-out to your own pure functions for complex cases.
-- **Native++** It's real HTML. With a separate, synergistic guest: Quark.
-- **No magic** No special frameworks, build processes, rendering wizardry, or "HTML-in-my-JS" / "JS-in-my-HTML" DSLs.
-- **Progressively enhanced** Drop into existing static/server-side-rendered sites. Neutron and Quark can also be used independently.
-- **Fully composable** Templates, templating, behavior, and custom logic are all decoupled & robust.
-- **Reactive State Machine** A simple, reliable, declarative syntax for your business logic - Quark.
-- **No reconciliation tax** No large memory copies of state/DOM to be rebuilt, diffed against the DOM, recompiled with every state change.
-- **Lightweight** All Nucleus Kit elements + Quark + Neutron have a smaller footprint (just over ~50kb compressed) than some UI framework cores alone.
+- **Back to the future** — Welcome back to building static HTML5 apps. A break from complex JavaScript apps that compile to HTML.
+- **Little to no JavaScript** — You no longer need to write JS for the vast majority of UI cases. You may still call-out to your own pure functions for complex cases.
+- **Native++** — It's real HTML. With a separate, synergistic guest: Quark.
+- **No magic** — No special frameworks, build processes, rendering wizardry, or "HTML-in-my-JS" / "JS-in-my-HTML" DSLs.
+- **Progressively enhanced** — Drop into existing static/server-side-rendered sites. Nucleus elements and Quark can also be used independently.
+- **Fully composable** — Templates, templating, behavior, and custom logic are all decoupled & robust.
+- **Reactive State Machine** — A simple, reliable, declarative syntax for your business logic - Quark.
+- **No reconciliation tax** — No large memory copies of state/DOM to be rebuilt, diffed against the DOM, recompiled with every state change.
+- **Lightweight** — All Nucleus elements + Quark + Neutron have a smaller footprint (just over ~50kb compressed) than some UI framework cores alone.
## What's in the stack
-- **Nucleus Kit elements** A growing catalog of drop-in custom elements, including: drawers, tabs, tables, lazy views, forms, routing, passkeys, data fetching, and more.
-- **Quark** Like CSS, for document mutation. Select elements, bind data, stamp lists, wire events, and drive state transitions with simple rules instead of imperative code.
-- **Valence.css** Semantic, classless CSS that caters to both native and custom elements, with themes, light/dark schemes, and design tokens. Designed for easy drop-in. Optional.
-- **Neutron** The small JS factory used to author the elements above. Reach for it only when the Nucleus Kit catalog lacks what you need. Optional.
+- **Nucleus Kit elements** — A growing catalog of drop-in custom elements, including: drawers, tabs, tables, lazy views, forms, routing, passkeys, data fetching, and more.
+- **Quark** — Like CSS, for document mutation. Select elements, bind data, stamp lists, wire events, and drive state transitions with simple rules instead of imperative code.
+- **Valence.css** — Semantic, classless CSS that caters to both native and custom elements, with themes, light/dark schemes, and design tokens. Designed for easy drop-in. Optional.
+- **Neutron** — The small JS factory used to author the elements above. Reach for it only when the Nucleus Kit catalog lacks what you need. Optional.
Every piece stands alone. Use one element on an existing site, or compose the whole stack into a full single-page app. `nucleus-kit` bundles it all behind one import; if you find you only use a handful of elements, install those packages à la carte instead (`@excom/content-drawer`, `@excom/quark-sheet`, …) and skip the rest.
@@ -49,19 +49,25 @@ Then `import "@excom/nucleus-kit"` and `@import "@excom/nucleus-kit/basic.css"`.
## Why teams pick it
-- **Significantly less app code** This is possible for two primary reasons. First, because Nucleus Kit elements are fully composable, configurable, and controllable, they will likely be compatible with the desired experience of most applications that use them; there is a low likelihood you will need to build your own. Secondly, Quark enables the majority of customization without needing to invite JavaScript.
-- **No components** There is no "component" concept in this architecture. This allows application pieces to be maximally reusable and composable, as there is no home to entrap logic with a tightly coupled view.
-- **One source of truth** Live markup _is_ the primary application state, so an entire family of bugs ("the UI disagrees with the model") cannot exist.
-- **Fully inspectable** Open devtools and the entire application is in front of you: every value, every binding, and every transition. The state is the document/DOM, so all is plainly transparent to see, alter, and debug in your inspector.
-- **Accessible by default** Declarative & ARIA state is the state... not a mirror someone forgot to update.
-- **Human and machine friendly** Inspect [the docs site](https://excom.dev/nucleus) to see its declarativeness. No more `
` soups bound to untraceable JavaScript. Custom elements make for a beautifully declarative document. A page that is legible, addressable, and serializable is an ideal target for code generation, AI-assisted editing, and confident human auditing. Tools reason about the screen's exact state instead of inferring a component tree. Likewise, writing and debugging UI code by hand has never felt simpler.
-- **Declarative business behavior** The vast majority of your proprietary behaviors exist as simple configurations, rather than buried inside imperative spaghetti code.
+- **Significantly less app code** — This is possible for two primary reasons. First, because Nucleus Kit elements are fully composable, configurable, and controllable, they will likely be compatible with the desired experience of most applications that use them; there is a low likelihood you will need to build your own. Secondly, Quark enables the majority of customization without needing to invite JavaScript.
+- **No components** — There is no "component" concept in this architecture. This allows application pieces to be maximally reusable and composable, as there is no home to entrap logic with a tightly coupled view.
+- **One source of truth** — Live markup _is_ the primary application state, so an entire family of bugs ("the UI disagrees with the model") cannot exist.
+- **Fully inspectable** — Open devtools and the entire application is in front of you: every value, every binding, and every transition. The state is the document/DOM, so all is plainly transparent to see, alter, and debug in your inspector.
+- **Accessible by default** — Declarative & ARIA state is the state... not a mirror someone forgot to update.
+- **Human and machine friendly** — Inspect [the docs site](https://excom.dev/nucleus) to see its declarativeness. No more `
` soups bound to untraceable JavaScript. Custom elements make for a beautifully declarative document. A page that is legible, addressable, and serializable is an ideal target for code generation, AI-assisted editing, and confident human auditing. Tools reason about the screen's exact state instead of inferring a component tree. Likewise, writing and debugging UI code by hand has never felt simpler.
+- **Declarative business behavior** — The vast majority of your proprietary behaviors exist as simple configurations, rather than buried inside imperative spaghetti code.
## Where it shines
Content-rich sites, complex data-driven business rules, progressive enhancement of static/server-rendered pages, embedded user experiences. See [Limitations](https://excom.dev/nucleus/docs/limitations) for the edges.
-The Nucleus Stack also opens up new possibilities that were not easily served by any UI technology before: zero-build-tool UIs (e.g. on-the-fly generation), declarative & auditable target for LLM UI building, plain text assembly to rich UX (like a CMS), incremental upgrading of static/legacy SSR sites, resource-constrained web UIs (especially where scripting needs to be validated or limited, like an ATM), embedded UX (such as upgrading markdown with embedded functionality).
+The Nucleus Stack also opens up new possibilities that were not easily served by any UI technology before:
+- zero-build-tool UIs (e.g. on-the-fly generation)
+- declarative & auditable target for LLM UI building
+- programmatic assembly of rich UX (like a CMS)
+- incremental upgrading of static/legacy SSR sites
+- resource-constrained, secure, or sandboxed web UIs (especially where scripting needs to be validated or limited, like an ATM)
+- embedded UX (such as upgrading markdown with embedded functionality)
## Dogfood is nutritious
diff --git a/common/changes/@excom/abortable-element/test-rig_2026-10-01-tests.json b/common/changes/@excom/abortable-element/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..2d15109
--- /dev/null
+++ b/common/changes/@excom/abortable-element/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/abortable-element",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/abortable-element"
+}
diff --git a/common/changes/@excom/content-carousel/test-rig_2026-09-30-track.json b/common/changes/@excom/content-carousel/test-rig_2026-09-30-track.json
new file mode 100644
index 0000000..4b61aec
--- /dev/null
+++ b/common/changes/@excom/content-carousel/test-rig_2026-09-30-track.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/content-carousel",
+ "comment": "Track mode hides every slide beyond the active slide's neighbours and no longer animates the first slide into place",
+ "type": "patch"
+ }
+ ],
+ "packageName": "@excom/content-carousel"
+}
diff --git a/common/changes/@excom/content-drawer/test-rig_2026-10-01-tests.json b/common/changes/@excom/content-drawer/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..9468931
--- /dev/null
+++ b/common/changes/@excom/content-drawer/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/content-drawer",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/content-drawer"
+}
diff --git a/common/changes/@excom/content-tabs/test-rig_2026-10-01-tests.json b/common/changes/@excom/content-tabs/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..26149e1
--- /dev/null
+++ b/common/changes/@excom/content-tabs/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/content-tabs",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/content-tabs"
+}
diff --git a/common/changes/@excom/data-table/test-rig_2026-10-01-tests.json b/common/changes/@excom/data-table/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..e09758b
--- /dev/null
+++ b/common/changes/@excom/data-table/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/data-table",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/data-table"
+}
diff --git a/common/changes/@excom/detect-browser/test-rig_2026-10-01-tests.json b/common/changes/@excom/detect-browser/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..90fa959
--- /dev/null
+++ b/common/changes/@excom/detect-browser/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/detect-browser",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/detect-browser"
+}
diff --git a/common/changes/@excom/detect-features/test-rig_2026-10-01-tests.json b/common/changes/@excom/detect-features/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..20889d8
--- /dev/null
+++ b/common/changes/@excom/detect-features/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/detect-features",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/detect-features"
+}
diff --git a/common/changes/@excom/detect-media/test-rig_2026-10-01-tests.json b/common/changes/@excom/detect-media/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..e3fc105
--- /dev/null
+++ b/common/changes/@excom/detect-media/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/detect-media",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/detect-media"
+}
diff --git a/common/changes/@excom/dialog-anchor/test-rig_2026-10-01-tests.json b/common/changes/@excom/dialog-anchor/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..7a4e3ef
--- /dev/null
+++ b/common/changes/@excom/dialog-anchor/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/dialog-anchor",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/dialog-anchor"
+}
diff --git a/common/changes/@excom/dismiss-watcher/test-rig_2026-10-01-tests.json b/common/changes/@excom/dismiss-watcher/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..734c111
--- /dev/null
+++ b/common/changes/@excom/dismiss-watcher/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/dismiss-watcher",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/dismiss-watcher"
+}
diff --git a/common/changes/@excom/docs-site/test-rig_2026-10-01-test-fixes.json b/common/changes/@excom/docs-site/test-rig_2026-10-01-test-fixes.json
new file mode 100644
index 0000000..b0de029
--- /dev/null
+++ b/common/changes/@excom/docs-site/test-rig_2026-10-01-test-fixes.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/docs-site",
+ "comment": "Fix happy-dom iframe throw in live-app test and correct nav order assertion in site-nav test",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/docs-site"
+}
diff --git a/common/changes/@excom/dom-observer/test-rig_2026-10-01-tests.json b/common/changes/@excom/dom-observer/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..9cc39f8
--- /dev/null
+++ b/common/changes/@excom/dom-observer/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/dom-observer",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/dom-observer"
+}
diff --git a/common/changes/@excom/event-handler/test-rig_2026-10-01-tests.json b/common/changes/@excom/event-handler/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..8603005
--- /dev/null
+++ b/common/changes/@excom/event-handler/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/event-handler",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/event-handler"
+}
diff --git a/common/changes/@excom/fetchable-element/test-rig_2026-10-01-tests.json b/common/changes/@excom/fetchable-element/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..c54d3be
--- /dev/null
+++ b/common/changes/@excom/fetchable-element/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/fetchable-element",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/fetchable-element"
+}
diff --git a/common/changes/@excom/gesture-handler/test-rig_2026-09-30-axis-lock.json b/common/changes/@excom/gesture-handler/test-rig_2026-09-30-axis-lock.json
new file mode 100644
index 0000000..56a9906
--- /dev/null
+++ b/common/changes/@excom/gesture-handler/test-rig_2026-09-30-axis-lock.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/gesture-handler",
+ "comment": "Pan handlers cancel the page's cross-axis scroll on the first touch move",
+ "type": "patch"
+ }
+ ],
+ "packageName": "@excom/gesture-handler"
+}
diff --git a/common/changes/@excom/hash-object/test-rig_2026-10-01-tests.json b/common/changes/@excom/hash-object/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..5562f12
--- /dev/null
+++ b/common/changes/@excom/hash-object/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/hash-object",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/hash-object"
+}
diff --git a/common/changes/@excom/heft-rig/test-rig_2026-09-30-nav-group.json b/common/changes/@excom/heft-rig/test-rig_2026-09-30-nav-group.json
new file mode 100644
index 0000000..d17bf10
--- /dev/null
+++ b/common/changes/@excom/heft-rig/test-rig_2026-09-30-nav-group.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/heft-rig",
+ "comment": "Add the optional `excom.navGroup` package.json key (only `\"libraries\"` is accepted by `format-package-json`), carried into the docs-site `index.json` catalog so a package can move from its type's sidebar list into a named group",
+ "type": "minor"
+ }
+ ],
+ "packageName": "@excom/heft-rig"
+}
diff --git a/common/changes/@excom/heft-rig/test-rig_2026-09-30-release-notes.json b/common/changes/@excom/heft-rig/test-rig_2026-09-30-release-notes.json
new file mode 100644
index 0000000..99921ad
--- /dev/null
+++ b/common/changes/@excom/heft-rig/test-rig_2026-09-30-release-notes.json
@@ -0,0 +1,20 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/heft-rig",
+ "comment": "Add release notes: `build-package-metas.mjs` appends the `CHANGELOG.json` notes (minus dependency and `none` comments) to the README HTML as a closing ``, and `build-docs.mjs` adds the three newest releases as `## Release notes` to the primary element's Markdown, so they reach the site and the LLM docs",
+ "type": "minor"
+ },
+ {
+ "packageName": "@excom/heft-rig",
+ "comment": "Fix the library build's type declarations, which pointed at a folder outside the tarball; `verify-publish-outputs.mjs` now fails a publish when a declaration path dangles",
+ "type": "patch"
+ },
+ {
+ "packageName": "@excom/heft-rig",
+ "comment": "Add `excom.umd: false` to skip the UMD bundle of a Node-only library (no CDN script in its install snippet), the `app` package type and unscoped names in `format-package-json`, and the test layer moved to `@excom/nucleus-dom` and `@excom/nucleus-test`",
+ "type": "minor"
+ }
+ ],
+ "packageName": "@excom/heft-rig"
+}
diff --git a/common/changes/@excom/heft-rig/test-rig_2026-10-01-app-vite-dev.json b/common/changes/@excom/heft-rig/test-rig_2026-10-01-app-vite-dev.json
new file mode 100644
index 0000000..fda76f8
--- /dev/null
+++ b/common/changes/@excom/heft-rig/test-rig_2026-10-01-app-vite-dev.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/heft-rig",
+ "comment": "Support `app` packageType in vite-dev so app packages use the shared Vite dev server",
+ "type": "patch"
+ }
+ ],
+ "packageName": "@excom/heft-rig"
+}
diff --git a/common/changes/@excom/include-content/test-rig_2026-10-01-tests.json b/common/changes/@excom/include-content/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..2f3ebf7
--- /dev/null
+++ b/common/changes/@excom/include-content/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/include-content",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/include-content"
+}
diff --git a/common/changes/@excom/kit-devtools/test-rig_2026-09-30-declarations.json b/common/changes/@excom/kit-devtools/test-rig_2026-09-30-declarations.json
new file mode 100644
index 0000000..7c23c58
--- /dev/null
+++ b/common/changes/@excom/kit-devtools/test-rig_2026-09-30-declarations.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/kit-devtools",
+ "comment": "Fix the published type declarations: `index.d.ts` pointed at a folder that is not in the tarball, so consumers got `any` for named re-exports and missing-member errors for `export *` instead of the real types",
+ "type": "patch"
+ }
+ ],
+ "packageName": "@excom/kit-devtools"
+}
diff --git a/common/changes/@excom/kit-logger/test-rig_2026-10-01-tests.json b/common/changes/@excom/kit-logger/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..022ae3a
--- /dev/null
+++ b/common/changes/@excom/kit-logger/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/kit-logger",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/kit-logger"
+}
diff --git a/common/changes/@excom/kit-router/test-rig_2026-10-01-tests.json b/common/changes/@excom/kit-router/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..11d5d2d
--- /dev/null
+++ b/common/changes/@excom/kit-router/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/kit-router",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/kit-router"
+}
diff --git a/common/changes/@excom/kit-scroller/test-rig_2026-10-01-tests.json b/common/changes/@excom/kit-scroller/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..189083f
--- /dev/null
+++ b/common/changes/@excom/kit-scroller/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/kit-scroller",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/kit-scroller"
+}
diff --git a/common/changes/@excom/kit-shims/test-rig_2026-10-01-tests.json b/common/changes/@excom/kit-shims/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..b2da1a7
--- /dev/null
+++ b/common/changes/@excom/kit-shims/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/kit-shims",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/kit-shims"
+}
diff --git a/common/changes/@excom/kit-utils/test-rig_2026-10-01-tests.json b/common/changes/@excom/kit-utils/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..b85d50c
--- /dev/null
+++ b/common/changes/@excom/kit-utils/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/kit-utils",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/kit-utils"
+}
diff --git a/common/changes/@excom/listenable-element/test-rig_2026-10-01-tests.json b/common/changes/@excom/listenable-element/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..9259123
--- /dev/null
+++ b/common/changes/@excom/listenable-element/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/listenable-element",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/listenable-element"
+}
diff --git a/common/changes/@excom/loadable-element/test-rig_2026-10-01-tests.json b/common/changes/@excom/loadable-element/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..a4d13f7
--- /dev/null
+++ b/common/changes/@excom/loadable-element/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/loadable-element",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/loadable-element"
+}
diff --git a/common/changes/@excom/mapbox-view/test-rig_2026-10-01-tests.json b/common/changes/@excom/mapbox-view/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..9bc9d14
--- /dev/null
+++ b/common/changes/@excom/mapbox-view/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/mapbox-view",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/mapbox-view"
+}
diff --git a/common/changes/@excom/network-status/test-rig_2026-10-01-tests.json b/common/changes/@excom/network-status/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..69ddb43
--- /dev/null
+++ b/common/changes/@excom/network-status/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/network-status",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/network-status"
+}
diff --git a/common/changes/@excom/neutron/test-rig_2026-09-30-declarations.json b/common/changes/@excom/neutron/test-rig_2026-09-30-declarations.json
new file mode 100644
index 0000000..39832d1
--- /dev/null
+++ b/common/changes/@excom/neutron/test-rig_2026-09-30-declarations.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/neutron",
+ "comment": "Fix the published type declarations: `index.d.ts` pointed at a folder that is not in the tarball, so consumers got `any` for named re-exports and missing-member errors for `export *` instead of the real types",
+ "type": "patch"
+ }
+ ],
+ "packageName": "@excom/neutron"
+}
diff --git a/common/changes/@excom/nucleus-devtools/test-rig_2026-10-01-settle-ticks.json b/common/changes/@excom/nucleus-devtools/test-rig_2026-10-01-settle-ticks.json
new file mode 100644
index 0000000..d2307c6
--- /dev/null
+++ b/common/changes/@excom/nucleus-devtools/test-rig_2026-10-01-settle-ticks.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/nucleus-devtools",
+ "comment": "Increase settle ticks in element view test to avoid CI timer race",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/nucleus-devtools"
+}
diff --git a/common/changes/@excom/nucleus-dom/test-rig_2026-09-30-initial.json b/common/changes/@excom/nucleus-dom/test-rig_2026-09-30-initial.json
new file mode 100644
index 0000000..6293379
--- /dev/null
+++ b/common/changes/@excom/nucleus-dom/test-rig_2026-09-30-initial.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/nucleus-dom",
+ "comment": "Initial release of `@excom/nucleus-dom`: happy-dom pinned exactly, the browser-parity shims (document-wide queries with `:scope`, MutationObserver pin, the Command API, `checkVisibility`, `ServiceWorkerContainer`) and `createDom()`",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/nucleus-dom"
+}
diff --git a/common/changes/@excom/nucleus-dom/test-rig_2026-09-30-nav-group.json b/common/changes/@excom/nucleus-dom/test-rig_2026-09-30-nav-group.json
new file mode 100644
index 0000000..42fd32f
--- /dev/null
+++ b/common/changes/@excom/nucleus-dom/test-rig_2026-09-30-nav-group.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/nucleus-dom",
+ "comment": "Set `excom.navGroup: \"libraries\"` so the docs site lists the package in its Libraries group",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/nucleus-dom"
+}
diff --git a/common/changes/@excom/nucleus-kit/test-rig_2026-09-30-fix-batch.json b/common/changes/@excom/nucleus-kit/test-rig_2026-09-30-fix-batch.json
new file mode 100644
index 0000000..a407716
--- /dev/null
+++ b/common/changes/@excom/nucleus-kit/test-rig_2026-09-30-fix-batch.json
@@ -0,0 +1,40 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/nucleus-kit",
+ "comment": "Add `Quark.meter`, the engine's work counters (`counts`, `reset()`, `scopeSelectors()`), always on, for complexity snapshots with `@excom/nucleus-test`",
+ "type": "minor"
+ },
+ {
+ "packageName": "@excom/nucleus-kit",
+ "comment": "Add a warning when a `spa-manager` update settles by `render-timeout` while a route is still pending, so an empty first paint has a cause in the console at log level 2",
+ "type": "minor"
+ },
+ {
+ "packageName": "@excom/nucleus-kit",
+ "comment": "Update `content-carousel` in `slide-animation=\"track\"` to render only the active slide and its two DOM neighbours (a wrap with three or more slides cuts instead of sliding), and to animate nothing before the first move, so an initial `is-active` appears in place",
+ "type": "minor"
+ },
+ {
+ "packageName": "@excom/nucleus-kit",
+ "comment": "Update `gesture-handler` `pan-x` / `pan-y` handlers to hold the page still for the rest of a touch whose first 3 px run along the handler's axis, through a non-passive `touchmove` listener; `touch-action` is unchanged, a touch that starts across the axis scrolls as before, and a same-axis scroller under the finger keeps scrolling",
+ "type": "minor"
+ },
+ {
+ "packageName": "@excom/nucleus-kit",
+ "comment": "Fix `web-authn` after a failed ceremony or options request: `is-loading` is cleared, `is-error` is set with the message in `provision`, and a retry clears `is-error`",
+ "type": "patch"
+ },
+ {
+ "packageName": "@excom/nucleus-kit",
+ "comment": "Fix an issue where an `is-fallback` route stayed off after leaving a nested route for a URL no route matches: the fallback now checks which routes match the path, so its position among its siblings no longer matters, a page without a `spa-manager` gets a working fallback, and a fallback inside a layout can activate on the layout's unmatched child paths",
+ "type": "patch"
+ },
+ {
+ "packageName": "@excom/nucleus-kit",
+ "comment": "Fix the published type declarations of `neutron`, `quark`, `quark-parser`, `quark-formatter` and `kit-devtools`, which pointed at a folder outside their tarballs, so the Kit's re-exported types resolve instead of `any`",
+ "type": "patch"
+ }
+ ],
+ "packageName": "@excom/nucleus-kit"
+}
diff --git a/common/changes/@excom/nucleus-test/test-rig_2026-09-30-complexity.json b/common/changes/@excom/nucleus-test/test-rig_2026-09-30-complexity.json
new file mode 100644
index 0000000..9b3245b
--- /dev/null
+++ b/common/changes/@excom/nucleus-test/test-rig_2026-09-30-complexity.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/nucleus-test",
+ "comment": "measureComplexity, expectComplexity and trackComplexity snapshot Quark and DOM work per test",
+ "type": "minor"
+ }
+ ],
+ "packageName": "@excom/nucleus-test"
+}
diff --git a/common/changes/@excom/nucleus-test/test-rig_2026-09-30-initial.json b/common/changes/@excom/nucleus-test/test-rig_2026-09-30-initial.json
new file mode 100644
index 0000000..e37af19
--- /dev/null
+++ b/common/changes/@excom/nucleus-test/test-rig_2026-09-30-initial.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/nucleus-test",
+ "comment": "Initial release of `@excom/nucleus-test`: the vitest setup (shims, listener registry, `equalTag`, `toMatchListeners`, `toContainListeners`, the HTML snapshot serializer, the console node guard) and the test utilities (`fixture`, `click`, `wait`, `waitForEvent`, `spyFetch`)",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/nucleus-test"
+}
diff --git a/common/changes/@excom/provider-fetch/test-rig_2026-10-01-tests.json b/common/changes/@excom/provider-fetch/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..3c5b2e7
--- /dev/null
+++ b/common/changes/@excom/provider-fetch/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/provider-fetch",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/provider-fetch"
+}
diff --git a/common/changes/@excom/provider-geolocation/test-rig_2026-10-01-tests.json b/common/changes/@excom/provider-geolocation/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..b7d8843
--- /dev/null
+++ b/common/changes/@excom/provider-geolocation/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/provider-geolocation",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/provider-geolocation"
+}
diff --git a/common/changes/@excom/provider-orientation/test-rig_2026-10-01-tests.json b/common/changes/@excom/provider-orientation/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..2c60019
--- /dev/null
+++ b/common/changes/@excom/provider-orientation/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/provider-orientation",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/provider-orientation"
+}
diff --git a/common/changes/@excom/provider-storage/test-rig_2026-10-01-tests.json b/common/changes/@excom/provider-storage/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..e1a91fc
--- /dev/null
+++ b/common/changes/@excom/provider-storage/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/provider-storage",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/provider-storage"
+}
diff --git a/common/changes/@excom/quark-formatter/test-rig_2026-09-30-declarations.json b/common/changes/@excom/quark-formatter/test-rig_2026-09-30-declarations.json
new file mode 100644
index 0000000..65bacd4
--- /dev/null
+++ b/common/changes/@excom/quark-formatter/test-rig_2026-09-30-declarations.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/quark-formatter",
+ "comment": "Fix the published type declarations: `index.d.ts` pointed at a folder that is not in the tarball, so consumers got `any` for named re-exports and missing-member errors for `export *` instead of the real types",
+ "type": "patch"
+ }
+ ],
+ "packageName": "@excom/quark-formatter"
+}
diff --git a/common/changes/@excom/quark-formatter/test-rig_2026-09-30-nav-group.json b/common/changes/@excom/quark-formatter/test-rig_2026-09-30-nav-group.json
new file mode 100644
index 0000000..34ff0df
--- /dev/null
+++ b/common/changes/@excom/quark-formatter/test-rig_2026-09-30-nav-group.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/quark-formatter",
+ "comment": "Set `excom.navGroup: \"libraries\"` so the docs site lists the package in its Libraries group",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/quark-formatter"
+}
diff --git a/common/changes/@excom/quark-parser/test-rig_2026-09-30-declarations.json b/common/changes/@excom/quark-parser/test-rig_2026-09-30-declarations.json
new file mode 100644
index 0000000..9ffa3ed
--- /dev/null
+++ b/common/changes/@excom/quark-parser/test-rig_2026-09-30-declarations.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/quark-parser",
+ "comment": "Fix the published type declarations: `index.d.ts` pointed at a folder that is not in the tarball, so consumers got `any` for named re-exports and missing-member errors for `export *` instead of the real types",
+ "type": "patch"
+ }
+ ],
+ "packageName": "@excom/quark-parser"
+}
diff --git a/common/changes/@excom/quark-sheet/test-rig_2026-10-01-tests.json b/common/changes/@excom/quark-sheet/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..2dff11b
--- /dev/null
+++ b/common/changes/@excom/quark-sheet/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/quark-sheet",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/quark-sheet"
+}
diff --git a/common/changes/@excom/quark/test-rig_2026-09-30-declarations.json b/common/changes/@excom/quark/test-rig_2026-09-30-declarations.json
new file mode 100644
index 0000000..069c532
--- /dev/null
+++ b/common/changes/@excom/quark/test-rig_2026-09-30-declarations.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/quark",
+ "comment": "Fix the published type declarations: `index.d.ts` pointed at a folder that is not in the tarball, so consumers got `any` for named re-exports and missing-member errors for `export *` instead of the real types",
+ "type": "patch"
+ }
+ ],
+ "packageName": "@excom/quark"
+}
diff --git a/common/changes/@excom/quark/test-rig_2026-09-30-meter.json b/common/changes/@excom/quark/test-rig_2026-09-30-meter.json
new file mode 100644
index 0000000..ff1c9e7
--- /dev/null
+++ b/common/changes/@excom/quark/test-rig_2026-09-30-meter.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/quark",
+ "comment": "Quark.meter exposes the engine's work counters for complexity snapshots",
+ "type": "minor"
+ }
+ ],
+ "packageName": "@excom/quark"
+}
diff --git a/common/changes/@excom/renderable-element/test-rig_2026-10-01-tests.json b/common/changes/@excom/renderable-element/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..9874e76
--- /dev/null
+++ b/common/changes/@excom/renderable-element/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/renderable-element",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/renderable-element"
+}
diff --git a/common/changes/@excom/routable-element/test-rig_2026-10-01-tests.json b/common/changes/@excom/routable-element/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..0cabefe
--- /dev/null
+++ b/common/changes/@excom/routable-element/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/routable-element",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/routable-element"
+}
diff --git a/common/changes/@excom/scroll-into-view/test-rig_2026-10-01-tests.json b/common/changes/@excom/scroll-into-view/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..22a65eb
--- /dev/null
+++ b/common/changes/@excom/scroll-into-view/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/scroll-into-view",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/scroll-into-view"
+}
diff --git a/common/changes/@excom/service-worker/test-rig_2026-10-01-tests.json b/common/changes/@excom/service-worker/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..be07caa
--- /dev/null
+++ b/common/changes/@excom/service-worker/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/service-worker",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/service-worker"
+}
diff --git a/common/changes/@excom/spa-route/test-rig_2026-09-30-fallback.json b/common/changes/@excom/spa-route/test-rig_2026-09-30-fallback.json
new file mode 100644
index 0000000..b84bfe9
--- /dev/null
+++ b/common/changes/@excom/spa-route/test-rig_2026-09-30-fallback.json
@@ -0,0 +1,20 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/spa-route",
+ "comment": "Fix an issue where an `is-fallback` route stayed off after leaving a nested route for a URL no route matches: the fallback now checks which routes match the path instead of reading their `is-active` state, so its position among its siblings no longer matters while navigating, a page without a `spa-manager` gets a working fallback, a fallback inside a layout can activate on the layout's unmatched child paths, and other fallbacks never hold it off",
+ "type": "patch"
+ },
+ {
+ "packageName": "@excom/spa-route",
+ "comment": "Add a warning when a `spa-manager` update settles by `render-timeout` while a route is still pending, so an empty first paint has a cause in the console at log level 2",
+ "type": "patch"
+ },
+ {
+ "packageName": "@excom/spa-route",
+ "comment": "Add `@excom/spa-route/testing`, the router helpers for Vitest on happy-dom: `resetRouter()`, `navigate()`, `popstate()`, `installViewTransition()` and `trackUnhandledRejections()`",
+ "type": "minor"
+ }
+ ],
+ "packageName": "@excom/spa-route"
+}
diff --git a/common/changes/@excom/super-form/test-rig_2026-10-01-tests.json b/common/changes/@excom/super-form/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..572edfa
--- /dev/null
+++ b/common/changes/@excom/super-form/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/super-form",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/super-form"
+}
diff --git a/common/changes/@excom/super-img/test-rig_2026-10-01-tests.json b/common/changes/@excom/super-img/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..7275799
--- /dev/null
+++ b/common/changes/@excom/super-img/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/super-img",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/super-img"
+}
diff --git a/common/changes/@excom/super-input/test-rig_2026-10-01-tests.json b/common/changes/@excom/super-input/test-rig_2026-10-01-tests.json
new file mode 100644
index 0000000..1196b91
--- /dev/null
+++ b/common/changes/@excom/super-input/test-rig_2026-10-01-tests.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/super-input",
+ "comment": "Add `@excom/nucleus-test` and update test imports",
+ "type": "none"
+ }
+ ],
+ "packageName": "@excom/super-input"
+}
diff --git a/common/changes/@excom/web-authn/test-rig_2026-09-30-error-state.json b/common/changes/@excom/web-authn/test-rig_2026-09-30-error-state.json
new file mode 100644
index 0000000..95f4c6d
--- /dev/null
+++ b/common/changes/@excom/web-authn/test-rig_2026-09-30-error-state.json
@@ -0,0 +1,10 @@
+{
+ "changes": [
+ {
+ "packageName": "@excom/web-authn",
+ "comment": "A failed ceremony or options request now clears is-loading and sets is-error with the message in provision",
+ "type": "patch"
+ }
+ ],
+ "packageName": "@excom/web-authn"
+}
diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml
index bbb8c5a..c9ef66c 100644
--- a/common/config/rush/pnpm-lock.yaml
+++ b/common/config/rush/pnpm-lock.yaml
@@ -22,6 +22,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/content-carousel:
dependencies:
@@ -35,6 +38,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/content-drawer:
dependencies:
@@ -51,6 +57,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/content-tabs:
dependencies:
@@ -64,6 +73,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/data-table:
dependencies:
@@ -80,6 +92,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/detect-browser:
dependencies:
@@ -90,6 +105,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/detect-features:
dependencies:
@@ -100,6 +118,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/detect-media:
dependencies:
@@ -113,6 +134,9 @@ importers:
'@excom/include-content':
specifier: workspace:^
version: link:../include-content
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
'@excom/quark':
specifier: workspace:^
version: link:../quark
@@ -135,6 +159,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/dismiss-watcher:
dependencies:
@@ -157,6 +184,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
'@excom/quark':
specifier: workspace:^
version: link:../quark
@@ -314,6 +344,12 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-dom':
+ specifier: workspace:^
+ version: link:../nucleus-dom
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
'@excom/quark-formatter':
specifier: workspace:^
version: link:../quark-formatter
@@ -330,6 +366,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/event-handler:
dependencies:
@@ -346,6 +385,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/fetchable-element:
dependencies:
@@ -368,6 +410,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/gesture-handler:
dependencies:
@@ -390,6 +435,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
'@excom/quark':
specifier: workspace:^
version: link:../quark
@@ -402,15 +450,15 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/heft-rig:
dependencies:
'@microsoft/api-extractor':
specifier: ^7.55.5
version: 7.55.5(@types/node@20.19.27)
- '@open-wc/semantic-dom-diff':
- specifier: ^0.20.1
- version: 0.20.1
'@rushstack/heft':
specifier: ^1.1.7
version: 1.1.7(@types/node@20.19.27)
@@ -505,6 +553,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/kit-devtools:
dependencies:
@@ -518,12 +569,18 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/kit-logger:
devDependencies:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/kit-router:
dependencies:
@@ -537,18 +594,27 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/kit-scroller:
devDependencies:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/kit-shims:
devDependencies:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/kit-utils:
dependencies:
@@ -559,6 +625,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/listenable-element:
dependencies:
@@ -575,6 +644,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/loadable-element:
dependencies:
@@ -585,6 +657,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/mapbox-view:
dependencies:
@@ -601,6 +676,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/network-status:
dependencies:
@@ -611,6 +689,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/neutron:
dependencies:
@@ -627,6 +708,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/nucleus-devtools:
dependencies:
@@ -652,6 +736,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
typescript:
specifier: ^5.9.2
version: 5.9.3
@@ -659,6 +746,16 @@ importers:
specifier: ^0.20.5
version: 0.20.27(@types/node@20.19.27)(eslint@9.39.2(jiti@2.7.0))(jiti@2.7.0)(rolldown@1.2.8)
+ ../../packages/nucleus-dom:
+ dependencies:
+ happy-dom:
+ specifier: 20.8.3
+ version: 20.8.3
+ devDependencies:
+ '@excom/heft-rig':
+ specifier: workspace:^
+ version: link:../heft-rig
+
../../packages/nucleus-kit:
dependencies:
'@excom/content-carousel':
@@ -752,6 +849,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/nucleus-quark-highlighter:
devDependencies:
@@ -768,6 +868,22 @@ importers:
specifier: ^0.28.2
version: 0.28.2
+ ../../packages/nucleus-test:
+ dependencies:
+ '@excom/nucleus-dom':
+ specifier: workspace:^
+ version: link:../nucleus-dom
+ '@open-wc/semantic-dom-diff':
+ specifier: ^0.20.1
+ version: 0.20.1
+ devDependencies:
+ '@excom/heft-rig':
+ specifier: workspace:^
+ version: link:../heft-rig
+ vitest:
+ specifier: ^4.1.11
+ version: 4.1.11(@types/node@20.19.27)(@vitest/coverage-v8@4.1.11)(happy-dom@20.8.3)(vite@8.3.0(@types/node@20.19.27)(esbuild@0.28.2)(jiti@2.7.0))
+
../../packages/provider-fetch:
dependencies:
'@excom/fetchable-element':
@@ -783,6 +899,9 @@ importers:
'@excom/kit-logger':
specifier: workspace:^
version: link:../kit-logger
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/provider-geolocation:
dependencies:
@@ -793,6 +912,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/provider-orientation:
dependencies:
@@ -803,6 +925,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/provider-storage:
dependencies:
@@ -816,6 +941,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/quark:
dependencies:
@@ -838,6 +966,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
'@excom/provider-fetch':
specifier: workspace:^
version: link:../provider-fetch
@@ -850,6 +981,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
'@excom/quark-parser':
specifier: workspace:^
version: link:../quark-parser
@@ -859,6 +993,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/quark-sheet:
dependencies:
@@ -881,6 +1018,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/renderable-element:
dependencies:
@@ -903,6 +1043,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/routable-element:
dependencies:
@@ -916,6 +1059,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/scroll-into-view:
dependencies:
@@ -935,6 +1081,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/service-worker:
dependencies:
@@ -948,6 +1097,9 @@ importers:
'@excom/kit-utils':
specifier: workspace:^
version: link:../kit-utils
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/spa-route:
dependencies:
@@ -976,6 +1128,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/super-form:
dependencies:
@@ -992,6 +1147,9 @@ importers:
'@excom/kit-logger':
specifier: workspace:^
version: link:../kit-logger
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
'@excom/quark':
specifier: workspace:^
version: link:../quark
@@ -1008,6 +1166,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/super-input:
dependencies:
@@ -1024,6 +1185,9 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
../../packages/valence:
devDependencies:
@@ -1046,6 +1210,25 @@ importers:
'@excom/heft-rig':
specifier: workspace:^
version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
+
+ ../../packages/wrenfield:
+ dependencies:
+ '@excom/nucleus-kit':
+ specifier: workspace:^
+ version: link:../nucleus-kit
+ devDependencies:
+ '@excom/heft-rig':
+ specifier: workspace:^
+ version: link:../heft-rig
+ '@excom/nucleus-test':
+ specifier: workspace:^
+ version: link:../nucleus-test
+ '@excom/spa-route':
+ specifier: workspace:^
+ version: link:../spa-route
packages:
@@ -6691,7 +6874,7 @@ snapshots:
istanbul-reports: 3.2.0
log-update: 4.0.0
nanocolors: 0.2.13
- nanoid: 3.3.11
+ nanoid: 3.3.19
open: 8.4.2
picomatch: 2.3.1
source-map: 0.7.6
diff --git a/packages/abortable-element/package.json b/packages/abortable-element/package.json
index 92093e7..faeb978 100644
--- a/packages/abortable-element/package.json
+++ b/packages/abortable-element/package.json
@@ -26,7 +26,8 @@
},
"peerDependencies": {},
"devDependencies": {
- "@excom/heft-rig": "workspace:^"
+ "@excom/heft-rig": "workspace:^",
+ "@excom/nucleus-test": "workspace:^"
},
"repository": {
"url": "excom-dev/nucleus",
@@ -44,4 +45,4 @@
"excom": {
"packageType": "element-base"
}
-}
+}
\ No newline at end of file
diff --git a/packages/abortable-element/support/tests/abortable-element.test.ts b/packages/abortable-element/support/tests/abortable-element.test.ts
index 3f14fef..17bb466 100644
--- a/packages/abortable-element/support/tests/abortable-element.test.ts
+++ b/packages/abortable-element/support/tests/abortable-element.test.ts
@@ -5,7 +5,7 @@ import {
expect,
fixture,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+} from "@excom/nucleus-test";
const TAG = "abortable-element-test";
if (!customElements.get(TAG)) {
diff --git a/packages/content-carousel/content-carousel.ts b/packages/content-carousel/content-carousel.ts
index 245e196..05f9079 100644
--- a/packages/content-carousel/content-carousel.ts
+++ b/packages/content-carousel/content-carousel.ts
@@ -67,7 +67,7 @@ export const ContentCarousel = Neutron({
/**
* @option
* Transition used when the active slide changes.
- * @values slide | fade
+ * @values slide | fade | track
* @default slide
*/
slideAnimation: String,
@@ -75,7 +75,8 @@ export const ContentCarousel = Neutron({
* @state
* Direction of the most recent slide change — drives the CSS
* animation direction. `is-active` moved from one slide to another
- * counts as `forward` / `back` by position.
+ * counts as `forward` / `back` by position. Unset until the first move,
+ * so the initial slide appears without animating in.
* @values forward | back
*/
lastMove: String,
diff --git a/packages/content-carousel/package.json b/packages/content-carousel/package.json
index 177f38a..a7a283e 100644
--- a/packages/content-carousel/package.json
+++ b/packages/content-carousel/package.json
@@ -27,7 +27,8 @@
},
"peerDependencies": {},
"devDependencies": {
- "@excom/heft-rig": "workspace:^"
+ "@excom/heft-rig": "workspace:^",
+ "@excom/nucleus-test": "workspace:^"
},
"repository": {
"url": "excom-dev/nucleus",
@@ -43,4 +44,4 @@
"excom": {
"packageType": "kit-element"
}
-}
+}
\ No newline at end of file
diff --git a/packages/content-carousel/src/content-carousel.css b/packages/content-carousel/src/content-carousel.css
index 8782251..e1bd5fc 100644
--- a/packages/content-carousel/src/content-carousel.css
+++ b/packages/content-carousel/src/content-carousel.css
@@ -180,8 +180,6 @@
100%
)
);
- transition: transform var(--content-carousel-slide-animation-duration)
- var(--content-carousel-transition-ease);
&:--content-carousel-slide--is-active {
--content-carousel-slot: 0;
z-index: 2;
@@ -189,12 +187,21 @@
&:has(~ :--content-carousel-slide--is-active) {
--content-carousel-slot: -1;
}
- &:is(&:--content-carousel-slide--is-active + & + &),
- &:has(+ & + &:--content-carousel-slide--is-active) {
- /* hide slides that are two slides away */
+ /* Neighbours are DOM siblings; a slide further out would share their
+ ±100% slot and paint over them. Tests assert this sibling contract. */
+ &:not(
+ :--content-carousel-slide--is-active,
+ :--content-carousel-slide--is-active + *,
+ :has(+ :--content-carousel-slide--is-active)
+ ) {
display: none !important;
}
}
+ /* Only after a move: the initial `is-active` lands without sliding in */
+ &:--content-carousel--last-move :--content-carousel-slide {
+ transition: transform var(--content-carousel-slide-animation-duration)
+ var(--content-carousel-transition-ease);
+ }
&:--content-carousel--is-scrubbing {
--content-carousel-progress: var(--gesture-progress, 0);
:--content-carousel-slide {
diff --git a/packages/content-carousel/support/docs/README.md b/packages/content-carousel/support/docs/README.md
index cb98b44..bb96652 100644
--- a/packages/content-carousel/support/docs/README.md
+++ b/packages/content-carousel/support/docs/README.md
@@ -8,7 +8,7 @@ Rotate slides on autopilot or on click — galleries, hero banners, walkthroughs
- **Auto-play** Rotate on a timer via `auto-play`
- **Manual nav** `--back` / `--next` commands from plain buttons; `rel="prev"` / `rel="next"` positions them
-- **Slide or fade** Choose the transition with `slide-animation`
+- **Slide or fade** Choose the transition with `slide-animation`: `slide` / `fade` / `track`
- **Swipeable** `slide-animation="track"` wrapped in [`gesture-handler`](/nucleus/packages/gesture-handler): drag and flick between slides
- **Pauses itself** Manual navigation stops auto-play automatically
- **Bindable position** `.provision` is `{ index, count, lastMove }` — a
@@ -41,6 +41,8 @@ content-carousel {
}
```
+Nothing animates until the first move: `last-move` is unset until then, so an initial `is-active`, in markup or written by the app, appears in place. `slide-animation="track"` renders only the active slide and its two DOM neighbours, so slides must be siblings (a `display: contents` wrapper around them is fine) and, with three or more slides, a wrap — `--next` from the last, `--back` from the first — cuts to the new slide instead of sliding; put it inside [`gesture-handler`](/nucleus/packages/gesture-handler) to drag it.
+
### API Reference
diff --git a/packages/content-carousel/support/tests/content-carousel.test.ts b/packages/content-carousel/support/tests/content-carousel.test.ts
index f57b8c0..7cb54dd 100644
--- a/packages/content-carousel/support/tests/content-carousel.test.ts
+++ b/packages/content-carousel/support/tests/content-carousel.test.ts
@@ -6,7 +6,7 @@ import {
it,
vi,
wait,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+} from "@excom/nucleus-test";
import "../../index";
import { invokeCommand } from "@excom/neutron";
@@ -487,6 +487,52 @@ describe("content-carousel (changes from outside)", () => {
});
});
+describe("content-carousel (track mode)", () => {
+ afterEach(() => {
+ document.body.innerHTML = "";
+ vi.restoreAllMocks();
+ });
+
+ // happy-dom applies no stylesheet (and misreads combinators inside `:not()`):
+ // the sibling facts content-carousel.css shows slides by, one at a time
+ const slot = (slide: Element) =>
+ slide.matches("[is-active]")
+ ? 0
+ : slide.matches("[is-active] + *")
+ ? 1
+ : slide.matches(":has(+ [is-active])")
+ ? -1
+ : "hidden";
+
+ const build = (active = "is-active") =>
+ fixture(
+ `
+
+ ${"".repeat(4)}
+ `,
+ );
+
+ it("renders only the active slide and its neighbours", async () => {
+ const carousel = build();
+ const slides = [...carousel.querySelectorAll("content-carousel-slide")];
+ expect(slides.map(slot)).toEqual([0, 1, "hidden", "hidden", "hidden"]);
+ await command(carousel, "--next");
+ expect(slides.map(slot)).toEqual([-1, 0, 1, "hidden", "hidden"]);
+ });
+
+ it("sets last-move on the first move, not on connect or the initial is-active", async () => {
+ const carousel = build("");
+ const slides = carousel.querySelectorAll("content-carousel-slide");
+ expect(carousel.hasAttribute("last-move")).toBe(false);
+ slides[0].setAttribute("is-active", "");
+ await wait(0);
+ expect(carousel.provision).toEqual({ index: 0, count: 5, lastMove: null });
+ expect(carousel.hasAttribute("last-move")).toBe(false);
+ await command(carousel, "--next");
+ expect(carousel.getAttribute("last-move")).toBe("forward");
+ });
+});
+
describe("content-carousel (auto-play lifecycle)", () => {
afterEach(() => {
document.body.innerHTML = "";
diff --git a/packages/content-carousel/support/tests/fade.view.test.ts b/packages/content-carousel/support/tests/fade.view.test.ts
index 5f10297..000f4dd 100644
--- a/packages/content-carousel/support/tests/fade.view.test.ts
+++ b/packages/content-carousel/support/tests/fade.view.test.ts
@@ -4,8 +4,9 @@ import {
describe,
expect,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
-import { mountView, readDemo } from "@excom/quark/support/tests/view-helpers";
+ readDemo,
+} from "@excom/nucleus-test";
+import { mountView } from "@excom/quark/support/tests/view-helpers";
describe("fade view", () => {
afterEach(() => {
diff --git a/packages/content-carousel/support/tests/manual.view.test.ts b/packages/content-carousel/support/tests/manual.view.test.ts
index b7a5b96..814f67a 100644
--- a/packages/content-carousel/support/tests/manual.view.test.ts
+++ b/packages/content-carousel/support/tests/manual.view.test.ts
@@ -5,12 +5,12 @@ import {
describe,
expect,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+ readDemo,
+} from "@excom/nucleus-test";
import {
click,
flush,
mountView,
- readDemo,
} from "@excom/quark/support/tests/view-helpers";
describe("manual view", () => {
diff --git a/packages/content-carousel/support/tests/simple.view.test.ts b/packages/content-carousel/support/tests/simple.view.test.ts
index 74deb65..76f25db 100644
--- a/packages/content-carousel/support/tests/simple.view.test.ts
+++ b/packages/content-carousel/support/tests/simple.view.test.ts
@@ -4,9 +4,10 @@ import {
describe,
expect,
it,
+ readDemo,
wait,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
-import { mountView, readDemo } from "@excom/quark/support/tests/view-helpers";
+} from "@excom/nucleus-test";
+import { mountView } from "@excom/quark/support/tests/view-helpers";
describe("simple view", () => {
afterEach(() => {
diff --git a/packages/content-drawer/package.json b/packages/content-drawer/package.json
index dac2fbe..3202848 100644
--- a/packages/content-drawer/package.json
+++ b/packages/content-drawer/package.json
@@ -28,7 +28,8 @@
},
"peerDependencies": {},
"devDependencies": {
- "@excom/heft-rig": "workspace:^"
+ "@excom/heft-rig": "workspace:^",
+ "@excom/nucleus-test": "workspace:^"
},
"repository": {
"url": "excom-dev/nucleus",
@@ -44,4 +45,4 @@
"excom": {
"packageType": "kit-element"
}
-}
+}
\ No newline at end of file
diff --git a/packages/content-drawer/support/tests/content-drawer.test.ts b/packages/content-drawer/support/tests/content-drawer.test.ts
index 54b2f8a..efdafda 100644
--- a/packages/content-drawer/support/tests/content-drawer.test.ts
+++ b/packages/content-drawer/support/tests/content-drawer.test.ts
@@ -6,7 +6,7 @@ import {
it,
vi,
wait,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+} from "@excom/nucleus-test";
import "../../index";
import { propsFromSource } from "../../content-drawer";
import { invokeCommand } from "@excom/neutron";
diff --git a/packages/content-drawer/support/tests/disappear.view.test.ts b/packages/content-drawer/support/tests/disappear.view.test.ts
index 33b3985..57f1fe0 100644
--- a/packages/content-drawer/support/tests/disappear.view.test.ts
+++ b/packages/content-drawer/support/tests/disappear.view.test.ts
@@ -5,13 +5,13 @@ import {
describe,
expect,
it,
+ readDemo,
wait,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+} from "@excom/nucleus-test";
import {
click,
flush,
mountView,
- readDemo,
} from "@excom/quark/support/tests/view-helpers";
describe("disappear view", () => {
diff --git a/packages/content-drawer/support/tests/dismiss.view.test.ts b/packages/content-drawer/support/tests/dismiss.view.test.ts
index 1c3aed1..dd3a66a 100644
--- a/packages/content-drawer/support/tests/dismiss.view.test.ts
+++ b/packages/content-drawer/support/tests/dismiss.view.test.ts
@@ -7,12 +7,12 @@ import {
describe,
expect,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+ readDemo,
+} from "@excom/nucleus-test";
import {
click,
flush,
mountView,
- readDemo,
} from "@excom/quark/support/tests/view-helpers";
const outsideMouseup = (target: EventTarget) =>
diff --git a/packages/content-drawer/support/tests/from-side.view.test.ts b/packages/content-drawer/support/tests/from-side.view.test.ts
index 626d83b..bb5c3e1 100644
--- a/packages/content-drawer/support/tests/from-side.view.test.ts
+++ b/packages/content-drawer/support/tests/from-side.view.test.ts
@@ -5,12 +5,12 @@ import {
describe,
expect,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+ readDemo,
+} from "@excom/nucleus-test";
import {
click,
flush,
mountView,
- readDemo,
} from "@excom/quark/support/tests/view-helpers";
describe("from-side view", () => {
diff --git a/packages/content-drawer/support/tests/simple.view.test.ts b/packages/content-drawer/support/tests/simple.view.test.ts
index ea72778..a838833 100644
--- a/packages/content-drawer/support/tests/simple.view.test.ts
+++ b/packages/content-drawer/support/tests/simple.view.test.ts
@@ -5,12 +5,12 @@ import {
describe,
expect,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+ readDemo,
+} from "@excom/nucleus-test";
import {
click,
flush,
mountView,
- readDemo,
} from "@excom/quark/support/tests/view-helpers";
describe("simple view", () => {
diff --git a/packages/content-drawer/support/tests/singleton.view.test.ts b/packages/content-drawer/support/tests/singleton.view.test.ts
index d1b1cde..b4256a8 100644
--- a/packages/content-drawer/support/tests/singleton.view.test.ts
+++ b/packages/content-drawer/support/tests/singleton.view.test.ts
@@ -5,12 +5,12 @@ import {
describe,
expect,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+ readDemo,
+} from "@excom/nucleus-test";
import {
click,
flush,
mountView,
- readDemo,
} from "@excom/quark/support/tests/view-helpers";
describe("singleton view", () => {
diff --git a/packages/content-drawer/support/tests/stages.view.test.ts b/packages/content-drawer/support/tests/stages.view.test.ts
index e08305f..a83cacd 100644
--- a/packages/content-drawer/support/tests/stages.view.test.ts
+++ b/packages/content-drawer/support/tests/stages.view.test.ts
@@ -5,12 +5,12 @@ import {
describe,
expect,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+ readDemo,
+} from "@excom/nucleus-test";
import {
click,
flush,
mountView,
- readDemo,
} from "@excom/quark/support/tests/view-helpers";
describe("stages view", () => {
diff --git a/packages/content-tabs/package.json b/packages/content-tabs/package.json
index dde60ea..c8ae391 100644
--- a/packages/content-tabs/package.json
+++ b/packages/content-tabs/package.json
@@ -27,7 +27,8 @@
},
"peerDependencies": {},
"devDependencies": {
- "@excom/heft-rig": "workspace:^"
+ "@excom/heft-rig": "workspace:^",
+ "@excom/nucleus-test": "workspace:^"
},
"repository": {
"url": "excom-dev/nucleus",
@@ -43,4 +44,4 @@
"excom": {
"packageType": "kit-element"
}
-}
+}
\ No newline at end of file
diff --git a/packages/content-tabs/support/tests/content-tabs.test.ts b/packages/content-tabs/support/tests/content-tabs.test.ts
index be1b246..c9fccdc 100644
--- a/packages/content-tabs/support/tests/content-tabs.test.ts
+++ b/packages/content-tabs/support/tests/content-tabs.test.ts
@@ -6,7 +6,7 @@ import {
it,
vi,
wait,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+} from "@excom/nucleus-test";
import "../../index";
/*
diff --git a/packages/content-tabs/support/tests/file-tabs.view.test.ts b/packages/content-tabs/support/tests/file-tabs.view.test.ts
index 30bc924..e6283e8 100644
--- a/packages/content-tabs/support/tests/file-tabs.view.test.ts
+++ b/packages/content-tabs/support/tests/file-tabs.view.test.ts
@@ -4,9 +4,10 @@ import {
describe,
expect,
it,
+ readDemo,
wait,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
-import { mountView, readDemo } from "@excom/quark/support/tests/view-helpers";
+} from "@excom/nucleus-test";
+import { mountView } from "@excom/quark/support/tests/view-helpers";
describe("file-tabs view", () => {
afterEach(() => {
diff --git a/packages/content-tabs/support/tests/multi.view.test.ts b/packages/content-tabs/support/tests/multi.view.test.ts
index 85c0880..0438d6c 100644
--- a/packages/content-tabs/support/tests/multi.view.test.ts
+++ b/packages/content-tabs/support/tests/multi.view.test.ts
@@ -4,9 +4,10 @@ import {
describe,
expect,
it,
+ readDemo,
wait,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
-import { mountView, readDemo } from "@excom/quark/support/tests/view-helpers";
+} from "@excom/nucleus-test";
+import { mountView } from "@excom/quark/support/tests/view-helpers";
describe("multi view", () => {
afterEach(() => {
diff --git a/packages/content-tabs/support/tests/named.view.test.ts b/packages/content-tabs/support/tests/named.view.test.ts
index 99774c1..c560f1a 100644
--- a/packages/content-tabs/support/tests/named.view.test.ts
+++ b/packages/content-tabs/support/tests/named.view.test.ts
@@ -4,9 +4,10 @@ import {
describe,
expect,
it,
+ readDemo,
wait,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
-import { mountView, readDemo } from "@excom/quark/support/tests/view-helpers";
+} from "@excom/nucleus-test";
+import { mountView } from "@excom/quark/support/tests/view-helpers";
describe("named view", () => {
afterEach(() => {
diff --git a/packages/content-tabs/support/tests/simple.view.test.ts b/packages/content-tabs/support/tests/simple.view.test.ts
index 9bb1eb3..4de6d96 100644
--- a/packages/content-tabs/support/tests/simple.view.test.ts
+++ b/packages/content-tabs/support/tests/simple.view.test.ts
@@ -4,9 +4,10 @@ import {
describe,
expect,
it,
+ readDemo,
wait,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
-import { mountView, readDemo } from "@excom/quark/support/tests/view-helpers";
+} from "@excom/nucleus-test";
+import { mountView } from "@excom/quark/support/tests/view-helpers";
describe("simple view", () => {
afterEach(() => {
diff --git a/packages/data-table/package.json b/packages/data-table/package.json
index d396cfa..b3e0338 100644
--- a/packages/data-table/package.json
+++ b/packages/data-table/package.json
@@ -28,7 +28,8 @@
},
"peerDependencies": {},
"devDependencies": {
- "@excom/heft-rig": "workspace:^"
+ "@excom/heft-rig": "workspace:^",
+ "@excom/nucleus-test": "workspace:^"
},
"repository": {
"url": "excom-dev/nucleus",
@@ -44,4 +45,4 @@
"excom": {
"packageType": "kit-element"
}
-}
+}
\ No newline at end of file
diff --git a/packages/data-table/support/tests/data-table.test.ts b/packages/data-table/support/tests/data-table.test.ts
index dce1eba..cc7383d 100644
--- a/packages/data-table/support/tests/data-table.test.ts
+++ b/packages/data-table/support/tests/data-table.test.ts
@@ -7,7 +7,7 @@ import {
vi,
wait,
waitForEvent,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+} from "@excom/nucleus-test";
import "../../index";
import type { DataTableSortDetail } from "../../data-table";
import { invokeCommand } from "@excom/neutron";
diff --git a/packages/data-table/support/tests/filter.view.test.ts b/packages/data-table/support/tests/filter.view.test.ts
index 072ffda..0984138 100644
--- a/packages/data-table/support/tests/filter.view.test.ts
+++ b/packages/data-table/support/tests/filter.view.test.ts
@@ -5,8 +5,9 @@ import {
describe,
expect,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
-import { flush, mountView, readDemo } from "@excom/quark/support/tests/view-helpers";
+ readDemo,
+} from "@excom/nucleus-test";
+import { flush, mountView } from "@excom/quark/support/tests/view-helpers";
const isFilteredOut = (tr: HTMLElement) =>
tr.style.getPropertyValue("--data-tr-display") === "none";
diff --git a/packages/data-table/support/tests/simple.view.test.ts b/packages/data-table/support/tests/simple.view.test.ts
index ff04d8c..30475d7 100644
--- a/packages/data-table/support/tests/simple.view.test.ts
+++ b/packages/data-table/support/tests/simple.view.test.ts
@@ -4,9 +4,10 @@ import {
describe,
expect,
it,
+ readDemo,
wait,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
-import { click, flush, mountView, readDemo } from "@excom/quark/support/tests/view-helpers";
+} from "@excom/nucleus-test";
+import { click, flush, mountView } from "@excom/quark/support/tests/view-helpers";
const rowOrder = (tr: HTMLElement) =>
parseInt(tr.style.getPropertyValue("--data-tr-order") || "0", 10);
diff --git a/packages/detect-browser/package.json b/packages/detect-browser/package.json
index ed57a44..d283c7b 100644
--- a/packages/detect-browser/package.json
+++ b/packages/detect-browser/package.json
@@ -26,7 +26,8 @@
},
"peerDependencies": {},
"devDependencies": {
- "@excom/heft-rig": "workspace:^"
+ "@excom/heft-rig": "workspace:^",
+ "@excom/nucleus-test": "workspace:^"
},
"repository": {
"url": "excom-dev/nucleus",
@@ -42,4 +43,4 @@
"excom": {
"packageType": "kit-element"
}
-}
+}
\ No newline at end of file
diff --git a/packages/detect-browser/support/tests/detect-browser.test.ts b/packages/detect-browser/support/tests/detect-browser.test.ts
index 65acd5b..d7ce8ae 100644
--- a/packages/detect-browser/support/tests/detect-browser.test.ts
+++ b/packages/detect-browser/support/tests/detect-browser.test.ts
@@ -6,7 +6,7 @@ import {
it,
vi,
wait,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+} from "@excom/nucleus-test";
import "../../index";
const UA = {
diff --git a/packages/detect-browser/support/tests/language.view.test.ts b/packages/detect-browser/support/tests/language.view.test.ts
index 44d2313..8dc4ec3 100644
--- a/packages/detect-browser/support/tests/language.view.test.ts
+++ b/packages/detect-browser/support/tests/language.view.test.ts
@@ -4,8 +4,9 @@ import {
describe,
expect,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
-import { mountView, readDemo } from "@excom/quark/support/tests/view-helpers";
+ readDemo,
+} from "@excom/nucleus-test";
+import { mountView } from "@excom/quark/support/tests/view-helpers";
describe("language view", () => {
afterEach(() => {
diff --git a/packages/detect-browser/support/tests/safari.view.test.ts b/packages/detect-browser/support/tests/safari.view.test.ts
index c2ac8d4..e21d693 100644
--- a/packages/detect-browser/support/tests/safari.view.test.ts
+++ b/packages/detect-browser/support/tests/safari.view.test.ts
@@ -6,9 +6,10 @@ import {
describe,
expect,
it,
+ readDemo,
vi,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
-import { mountView, readDemo } from "@excom/quark/support/tests/view-helpers";
+} from "@excom/nucleus-test";
+import { mountView } from "@excom/quark/support/tests/view-helpers";
const IOS_SAFARI =
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1";
diff --git a/packages/detect-browser/support/tests/simple.view.test.ts b/packages/detect-browser/support/tests/simple.view.test.ts
index 1fe7d95..9912f66 100644
--- a/packages/detect-browser/support/tests/simple.view.test.ts
+++ b/packages/detect-browser/support/tests/simple.view.test.ts
@@ -4,8 +4,9 @@ import {
describe,
expect,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
-import { mountView, readDemo } from "@excom/quark/support/tests/view-helpers";
+ readDemo,
+} from "@excom/nucleus-test";
+import { mountView } from "@excom/quark/support/tests/view-helpers";
describe("simple view", () => {
afterEach(() => {
diff --git a/packages/detect-features/package.json b/packages/detect-features/package.json
index b987dba..5666510 100644
--- a/packages/detect-features/package.json
+++ b/packages/detect-features/package.json
@@ -26,7 +26,8 @@
},
"peerDependencies": {},
"devDependencies": {
- "@excom/heft-rig": "workspace:^"
+ "@excom/heft-rig": "workspace:^",
+ "@excom/nucleus-test": "workspace:^"
},
"repository": {
"url": "excom-dev/nucleus",
@@ -42,4 +43,4 @@
"excom": {
"packageType": "kit-element"
}
-}
+}
\ No newline at end of file
diff --git a/packages/detect-features/support/tests/detect-features.test.ts b/packages/detect-features/support/tests/detect-features.test.ts
index 7280e1c..5209055 100644
--- a/packages/detect-features/support/tests/detect-features.test.ts
+++ b/packages/detect-features/support/tests/detect-features.test.ts
@@ -5,7 +5,7 @@ import {
expect,
it,
} from "@excom/heft-rig/node_modules/vitest";
-import { fixture } from "@excom/heft-rig/profiles/default/config/test-utils";
+import { fixture } from "@excom/nucleus-test";
const FEATURES = [
"geolocation",
diff --git a/packages/detect-features/support/tests/share.view.test.ts b/packages/detect-features/support/tests/share.view.test.ts
index f25a8fc..7bcbe2b 100644
--- a/packages/detect-features/support/tests/share.view.test.ts
+++ b/packages/detect-features/support/tests/share.view.test.ts
@@ -4,8 +4,9 @@ import {
describe,
expect,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
-import { mountView, readDemo } from "@excom/quark/support/tests/view-helpers";
+ readDemo,
+} from "@excom/nucleus-test";
+import { mountView } from "@excom/quark/support/tests/view-helpers";
describe("share view", () => {
afterEach(() => {
diff --git a/packages/detect-features/support/tests/simple.view.test.ts b/packages/detect-features/support/tests/simple.view.test.ts
index 0c43613..82fce7f 100644
--- a/packages/detect-features/support/tests/simple.view.test.ts
+++ b/packages/detect-features/support/tests/simple.view.test.ts
@@ -4,8 +4,9 @@ import {
describe,
expect,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
-import { mountView, readDemo } from "@excom/quark/support/tests/view-helpers";
+ readDemo,
+} from "@excom/nucleus-test";
+import { mountView } from "@excom/quark/support/tests/view-helpers";
describe("simple view", () => {
afterEach(() => {
diff --git a/packages/detect-media/package.json b/packages/detect-media/package.json
index 5eb6c63..32e7ac1 100644
--- a/packages/detect-media/package.json
+++ b/packages/detect-media/package.json
@@ -28,6 +28,7 @@
"devDependencies": {
"@excom/heft-rig": "workspace:^",
"@excom/include-content": "workspace:^",
+ "@excom/nucleus-test": "workspace:^",
"@excom/quark": "workspace:^",
"@excom/quark-sheet": "workspace:^"
},
@@ -45,4 +46,4 @@
"excom": {
"packageType": "kit-element"
}
-}
+}
\ No newline at end of file
diff --git a/packages/detect-media/support/tests/detect-media.test.ts b/packages/detect-media/support/tests/detect-media.test.ts
index 6467cfe..6ea080c 100644
--- a/packages/detect-media/support/tests/detect-media.test.ts
+++ b/packages/detect-media/support/tests/detect-media.test.ts
@@ -6,7 +6,7 @@ import {
it,
vi,
wait,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+} from "@excom/nucleus-test";
import "../../index";
import { lastFake, resetFakes, stubMatchMedia } from "./fake-match-media";
diff --git a/packages/detect-media/support/tests/fake-match-media.ts b/packages/detect-media/support/tests/fake-match-media.ts
index 43d5b1d..22bba50 100644
--- a/packages/detect-media/support/tests/fake-match-media.ts
+++ b/packages/detect-media/support/tests/fake-match-media.ts
@@ -1,4 +1,4 @@
-import { vi } from "@excom/heft-rig/profiles/default/config/test-utils";
+import { vi } from "@excom/nucleus-test";
export type FakeMediaQueryList = {
media: string;
diff --git a/packages/detect-media/support/tests/pointer.view.test.ts b/packages/detect-media/support/tests/pointer.view.test.ts
index ec0fce4..fd77950 100644
--- a/packages/detect-media/support/tests/pointer.view.test.ts
+++ b/packages/detect-media/support/tests/pointer.view.test.ts
@@ -6,9 +6,10 @@ import {
describe,
expect,
it,
+ readDemo,
vi,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
-import { flush, mountView, readDemo } from "@excom/quark/support/tests/view-helpers";
+} from "@excom/nucleus-test";
+import { flush, mountView } from "@excom/quark/support/tests/view-helpers";
import { lastFake, resetFakes, stubMatchMedia } from "./fake-match-media";
const COARSE = "(pointer: coarse)";
diff --git a/packages/detect-media/support/tests/simple.view.test.ts b/packages/detect-media/support/tests/simple.view.test.ts
index 11cba88..c2464a7 100644
--- a/packages/detect-media/support/tests/simple.view.test.ts
+++ b/packages/detect-media/support/tests/simple.view.test.ts
@@ -4,9 +4,10 @@ import {
describe,
expect,
it,
+ readDemo,
vi,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
-import { flush, mountView, readDemo } from "@excom/quark/support/tests/view-helpers";
+} from "@excom/nucleus-test";
+import { flush, mountView } from "@excom/quark/support/tests/view-helpers";
import { lastFake, resetFakes, stubMatchMedia } from "./fake-match-media";
const DARK = "(prefers-color-scheme: dark)";
diff --git a/packages/dialog-anchor/package.json b/packages/dialog-anchor/package.json
index cc54d29..ee67666 100644
--- a/packages/dialog-anchor/package.json
+++ b/packages/dialog-anchor/package.json
@@ -28,7 +28,8 @@
},
"peerDependencies": {},
"devDependencies": {
- "@excom/heft-rig": "workspace:^"
+ "@excom/heft-rig": "workspace:^",
+ "@excom/nucleus-test": "workspace:^"
},
"repository": {
"url": "excom-dev/nucleus",
@@ -44,4 +45,4 @@
"excom": {
"packageType": "kit-element"
}
-}
+}
\ No newline at end of file
diff --git a/packages/dialog-anchor/support/tests/auto-close.view.test.ts b/packages/dialog-anchor/support/tests/auto-close.view.test.ts
index d7a97eb..e277169 100644
--- a/packages/dialog-anchor/support/tests/auto-close.view.test.ts
+++ b/packages/dialog-anchor/support/tests/auto-close.view.test.ts
@@ -5,12 +5,12 @@ import {
describe,
expect,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+ readDemo,
+} from "@excom/nucleus-test";
import {
click,
flush,
mountView,
- readDemo,
} from "@excom/quark/support/tests/view-helpers";
describe("auto-close view", () => {
diff --git a/packages/dialog-anchor/support/tests/dialog-anchor.test.ts b/packages/dialog-anchor/support/tests/dialog-anchor.test.ts
index 8f17e37..6342695 100644
--- a/packages/dialog-anchor/support/tests/dialog-anchor.test.ts
+++ b/packages/dialog-anchor/support/tests/dialog-anchor.test.ts
@@ -5,7 +5,7 @@ import {
fixture,
it,
vi,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+} from "@excom/nucleus-test";
import "../../index";
describe("dialog-anchor", () => {
diff --git a/packages/dialog-anchor/support/tests/is-modal.view.test.ts b/packages/dialog-anchor/support/tests/is-modal.view.test.ts
index 21cd602..39a4f9e 100644
--- a/packages/dialog-anchor/support/tests/is-modal.view.test.ts
+++ b/packages/dialog-anchor/support/tests/is-modal.view.test.ts
@@ -4,12 +4,12 @@ import {
describe,
expect,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+ readDemo,
+} from "@excom/nucleus-test";
import {
click,
flush,
mountView,
- readDemo,
} from "@excom/quark/support/tests/view-helpers";
describe("is-modal view", () => {
diff --git a/packages/dialog-anchor/support/tests/simple.view.test.ts b/packages/dialog-anchor/support/tests/simple.view.test.ts
index 24af1c0..2b29c3b 100644
--- a/packages/dialog-anchor/support/tests/simple.view.test.ts
+++ b/packages/dialog-anchor/support/tests/simple.view.test.ts
@@ -4,12 +4,12 @@ import {
describe,
expect,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+ readDemo,
+} from "@excom/nucleus-test";
import {
click,
flush,
mountView,
- readDemo,
} from "@excom/quark/support/tests/view-helpers";
describe("simple view", () => {
diff --git a/packages/dismiss-watcher/dismiss-watcher.ts b/packages/dismiss-watcher/dismiss-watcher.ts
index 420d09d..2cb582d 100644
--- a/packages/dismiss-watcher/dismiss-watcher.ts
+++ b/packages/dismiss-watcher/dismiss-watcher.ts
@@ -1,11 +1,6 @@
import { CloseWatcher } from "@excom/kit-shims";
import { selectOne } from "@excom/kit-utils";
-import {
- ConstructorType,
- Neutron,
- TEvent,
- TokenList,
-} from "@excom/neutron";
+import { ConstructorType, Neutron, TEvent, TokenList } from "@excom/neutron";
export type DismissWatcherReason = "escape" | "outside-click";
diff --git a/packages/dismiss-watcher/package.json b/packages/dismiss-watcher/package.json
index 2cad47d..ee54ad2 100644
--- a/packages/dismiss-watcher/package.json
+++ b/packages/dismiss-watcher/package.json
@@ -31,6 +31,7 @@
"@excom/content-drawer": "workspace:^",
"@excom/event-handler": "workspace:^",
"@excom/heft-rig": "workspace:^",
+ "@excom/nucleus-test": "workspace:^",
"@excom/quark": "workspace:^",
"@excom/quark-sheet": "workspace:^"
},
@@ -48,4 +49,4 @@
"excom": {
"packageType": "kit-element"
}
-}
+}
\ No newline at end of file
diff --git a/packages/dismiss-watcher/support/tests/dismiss-watcher.test.ts b/packages/dismiss-watcher/support/tests/dismiss-watcher.test.ts
index 81e2b70..e67679f 100644
--- a/packages/dismiss-watcher/support/tests/dismiss-watcher.test.ts
+++ b/packages/dismiss-watcher/support/tests/dismiss-watcher.test.ts
@@ -6,7 +6,7 @@ import {
it,
vi,
wait,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+} from "@excom/nucleus-test";
import "../../index";
const outsideMouseup = (target: EventTarget = document.body) =>
diff --git a/packages/dismiss-watcher/support/tests/drawer.view.test.ts b/packages/dismiss-watcher/support/tests/drawer.view.test.ts
index cd451fa..0a549eb 100644
--- a/packages/dismiss-watcher/support/tests/drawer.view.test.ts
+++ b/packages/dismiss-watcher/support/tests/drawer.view.test.ts
@@ -8,11 +8,11 @@ import {
describe,
expect,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+ readDemo,
+} from "@excom/nucleus-test";
import {
flush,
mountView,
- readDemo,
} from "@excom/quark/support/tests/view-helpers";
const outsideMouseup = (target: EventTarget) =>
diff --git a/packages/dismiss-watcher/support/tests/simple.view.test.ts b/packages/dismiss-watcher/support/tests/simple.view.test.ts
index 87ae538..12db0c5 100644
--- a/packages/dismiss-watcher/support/tests/simple.view.test.ts
+++ b/packages/dismiss-watcher/support/tests/simple.view.test.ts
@@ -6,12 +6,12 @@ import {
describe,
expect,
it,
-} from "@excom/heft-rig/profiles/default/config/test-utils";
+ readDemo,
+} from "@excom/nucleus-test";
import {
click,
flush,
mountView,
- readDemo,
} from "@excom/quark/support/tests/view-helpers";
const outsideMouseup = (target: EventTarget) =>
diff --git a/packages/docs-site/index.html b/packages/docs-site/index.html
index 5c38d22..5536ba7 100644
--- a/packages/docs-site/index.html
+++ b/packages/docs-site/index.html
@@ -108,6 +108,7 @@
@use "/shell" as *;
+ @use "quark:list" as list;
#release-notice {
/* opens once: sheet re-runs restart a delay, so gate it on the fact it writes */
@@ -123,19 +124,24 @@
provider-fetch[api-url*="package-metas/index.json"][is-success] {
$package-indices: prop("provision").body;
+ /* `excom.navGroup` moves a package out of its type's list, into that group */
+ $ungrouped: list.reject($package-indices.packages, "navGroup");
.package-links {
[bind-elements] ul:not(ul ul) {
- content: iterate(getPackagesByType($package-indices, "kit-element"));
+ content: iterate(getPackagesByType($ungrouped, "kit-element"));
}
[bind-element-bases] ul:not(ul ul) {
- content: iterate(getPackagesByType($package-indices, "element-base"));
+ content: iterate(getPackagesByType($ungrouped, "element-base"));
}
[bind-tools] ul:not(ul ul) {
- content: iterate(getPackagesByType($package-indices, "tool"));
+ content: iterate(getPackagesByType($ungrouped, "tool"));
}
/* the standalone libraries: same rows, rendered flat (shell.css) */
[bind-libraries] ul:not(ul ul) {
- content: iterate(getPackagesByType($package-indices, "library"));
+ content: iterate(getPackagesByType($ungrouped, "library"));
+ }
+ [bind-library-group] ul:not(ul ul) {
+ content: iterate(list.filter($package-indices.packages, "navGroup", "libraries"));
}
ul:not(ul ul) > li {
$pkg: item.shortName;
@@ -364,6 +370,7 @@