@excom/nucleus-kit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.rush/temp/chunked-rush-logs/nucleus-kit.apply-exports.chunks.jsonl +1 -0
- package/.rush/temp/chunked-rush-logs/nucleus-kit.build_docs.chunks.jsonl +1 -0
- package/.rush/temp/chunked-rush-logs/nucleus-kit.build_package-metas.chunks.jsonl +1 -0
- package/.rush/temp/operation/apply-exports/all.log +1 -0
- package/.rush/temp/operation/apply-exports/log-chunks.jsonl +1 -0
- package/.rush/temp/operation/apply-exports/state.json +3 -0
- package/.rush/temp/operation/build_docs/all.log +1 -0
- package/.rush/temp/operation/build_docs/log-chunks.jsonl +1 -0
- package/.rush/temp/operation/build_docs/state.json +3 -0
- package/.rush/temp/operation/build_package-metas/all.log +1 -0
- package/.rush/temp/operation/build_package-metas/log-chunks.jsonl +1 -0
- package/.rush/temp/operation/build_package-metas/state.json +3 -0
- package/.rush/temp/shrinkwrap-deps.json +3 -0
- package/basic.css +2 -0
- package/config/rig.json +6 -0
- package/custom-elements.css +18 -0
- package/index.ts +27 -0
- package/nucleus-kit.progressive.ts +107 -0
- package/package.json +68 -0
- package/rush-logs/nucleus-kit.apply-exports.cache.log +1 -0
- package/rush-logs/nucleus-kit.apply-exports.log +1 -0
- package/rush-logs/nucleus-kit.build_docs.cache.log +1 -0
- package/rush-logs/nucleus-kit.build_docs.log +1 -0
- package/rush-logs/nucleus-kit.build_package-metas.cache.log +1 -0
- package/rush-logs/nucleus-kit.build_package-metas.log +1 -0
- package/support/dist-docs/docs/breaking_changes.md +2 -0
- package/support/dist-docs/docs/readme.md +119 -0
- package/support/docs/BREAKING_CHANGES.md +2 -0
- package/support/docs/README.md +119 -0
- package/support/package-meta.json +36 -0
- package/support/tests/loop-guard.test.ts +92 -0
- package/support/tests/nucleus-kit.test.ts +19 -0
- package/support/tests/progressive.test.ts +129 -0
- package/tsconfig.json +5 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: cd \"$RUSH_PROJECT_FOLDER\" && node ../heft-rig/scripts/apply-exports.mjs \n"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: node node_modules/@excom/heft-rig/scripts/build-docs.mjs \n"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: node node_modules/@excom/heft-rig/scripts/build-package-metas.mjs \n"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: cd "$RUSH_PROJECT_FOLDER" && node ../heft-rig/scripts/apply-exports.mjs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: cd \"$RUSH_PROJECT_FOLDER\" && node ../heft-rig/scripts/apply-exports.mjs \n"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: node node_modules/@excom/heft-rig/scripts/build-docs.mjs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: node node_modules/@excom/heft-rig/scripts/build-docs.mjs \n"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: node node_modules/@excom/heft-rig/scripts/build-package-metas.mjs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: node node_modules/@excom/heft-rig/scripts/build-package-metas.mjs \n"}
|
package/basic.css
ADDED
package/config/rig.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/* Nucleus Kit element CSS. */
|
|
2
|
+
@import "@excom/content-carousel/index.css";
|
|
3
|
+
@import "@excom/content-drawer/index.css";
|
|
4
|
+
@import "@excom/content-tabs/index.css";
|
|
5
|
+
/* @import "@excom/provider-fetch/index.css"; */
|
|
6
|
+
@import "@excom/data-table/index.css";
|
|
7
|
+
@import "@excom/dialog-anchor/index.css";
|
|
8
|
+
@import "@excom/event-handler/index.css";
|
|
9
|
+
@import "@excom/gesture-handler/index.css";
|
|
10
|
+
@import "@excom/include-content/index.css";
|
|
11
|
+
/* @import "@excom/mapbox-view/index.css"; */
|
|
12
|
+
@import "@excom/quark-sheet/index.css";
|
|
13
|
+
@import "@excom/scroll-into-view/index.css";
|
|
14
|
+
@import "@excom/spa-route/index.css";
|
|
15
|
+
/* @import "@excom/super-form/index.css"; */
|
|
16
|
+
/* @import "@excom/super-img/index.css"; */
|
|
17
|
+
@import "@excom/super-input/index.css";
|
|
18
|
+
/* @import "@excom/detect-features/index.css"; */
|
package/index.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export * from "@excom/content-carousel";
|
|
2
|
+
export * from "@excom/content-drawer";
|
|
3
|
+
export * from "@excom/content-tabs";
|
|
4
|
+
export * from "@excom/data-table";
|
|
5
|
+
export * from "@excom/detect-browser";
|
|
6
|
+
export * from "@excom/detect-features";
|
|
7
|
+
export * from "@excom/detect-media";
|
|
8
|
+
export * from "@excom/dialog-anchor";
|
|
9
|
+
export * from "@excom/dismiss-watcher";
|
|
10
|
+
export * from "@excom/dom-observer";
|
|
11
|
+
export * from "@excom/event-handler";
|
|
12
|
+
export * from "@excom/gesture-handler";
|
|
13
|
+
export * from "@excom/include-content";
|
|
14
|
+
export * from "@excom/network-status";
|
|
15
|
+
export * from "@excom/neutron";
|
|
16
|
+
export * from "@excom/provider-fetch";
|
|
17
|
+
export * from "@excom/provider-geolocation";
|
|
18
|
+
export * from "@excom/provider-orientation";
|
|
19
|
+
export * from "@excom/provider-storage";
|
|
20
|
+
export * from "@excom/quark";
|
|
21
|
+
export * from "@excom/quark-sheet";
|
|
22
|
+
export * from "@excom/scroll-into-view";
|
|
23
|
+
export * from "@excom/service-worker";
|
|
24
|
+
export * from "@excom/spa-route";
|
|
25
|
+
export * from "@excom/super-form";
|
|
26
|
+
export * from "@excom/super-input";
|
|
27
|
+
export * from "@excom/web-authn";
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `nucleus-kit.progressive.min.js`: lazy Nucleus Kit. Watches for Nucleus Kit
|
|
3
|
+
* element tags (initial scan + `MutationObserver`) and imports that package on
|
|
4
|
+
* first sight. Shared chunks (`neutron`, `kit-utils`, `quark`, bases) live
|
|
5
|
+
* under `dist/progressive/` and load once.
|
|
6
|
+
*
|
|
7
|
+
* Vs the all-in `index.umd.min.js`: one extra round-trip before upgrade
|
|
8
|
+
* (style the pre-upgrade state yourself), and ESM only.
|
|
9
|
+
*/
|
|
10
|
+
type Loader = () => Promise<unknown>;
|
|
11
|
+
|
|
12
|
+
const contentCarousel: Loader = () => import("@excom/content-carousel");
|
|
13
|
+
const contentDrawer: Loader = () => import("@excom/content-drawer");
|
|
14
|
+
const contentTabs: Loader = () => import("@excom/content-tabs");
|
|
15
|
+
const dataTable: Loader = () => import("@excom/data-table");
|
|
16
|
+
const spaRoute: Loader = () => import("@excom/spa-route");
|
|
17
|
+
|
|
18
|
+
/** Element tag → the package that defines it. */
|
|
19
|
+
export const PROGRESSIVE_LOADERS: Readonly<Record<string, Loader>> = {
|
|
20
|
+
"content-carousel": contentCarousel,
|
|
21
|
+
"content-carousel-slide": contentCarousel,
|
|
22
|
+
"content-drawer": contentDrawer,
|
|
23
|
+
"content-tabs": contentTabs,
|
|
24
|
+
"content-tabs-body": contentTabs,
|
|
25
|
+
"content-tabs-header": contentTabs,
|
|
26
|
+
"data-table": dataTable,
|
|
27
|
+
"data-th": dataTable,
|
|
28
|
+
"detect-browser": () => import("@excom/detect-browser"),
|
|
29
|
+
"detect-features": () => import("@excom/detect-features"),
|
|
30
|
+
"detect-media": () => import("@excom/detect-media"),
|
|
31
|
+
"dialog-anchor": () => import("@excom/dialog-anchor"),
|
|
32
|
+
"dismiss-watcher": () => import("@excom/dismiss-watcher"),
|
|
33
|
+
"dom-observer": () => import("@excom/dom-observer"),
|
|
34
|
+
"event-handler": () => import("@excom/event-handler"),
|
|
35
|
+
"gesture-handler": () => import("@excom/gesture-handler"),
|
|
36
|
+
"include-content": () => import("@excom/include-content"),
|
|
37
|
+
"network-status": () => import("@excom/network-status"),
|
|
38
|
+
"provider-fetch": () => import("@excom/provider-fetch"),
|
|
39
|
+
"provider-geolocation": () => import("@excom/provider-geolocation"),
|
|
40
|
+
"provider-orientation": () => import("@excom/provider-orientation"),
|
|
41
|
+
"provider-storage": () => import("@excom/provider-storage"),
|
|
42
|
+
"quark-sheet": () => import("@excom/quark-sheet"),
|
|
43
|
+
"scroll-into-view": () => import("@excom/scroll-into-view"),
|
|
44
|
+
"service-worker": () => import("@excom/service-worker"),
|
|
45
|
+
"spa-a": spaRoute,
|
|
46
|
+
"spa-manager": spaRoute,
|
|
47
|
+
"spa-route": spaRoute,
|
|
48
|
+
"super-form": () => import("@excom/super-form"),
|
|
49
|
+
"super-input": () => import("@excom/super-input"),
|
|
50
|
+
"web-authn": () => import("@excom/web-authn"),
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/** Every tag the progressive entry can load. */
|
|
54
|
+
export const PROGRESSIVE_TAGS: readonly string[] =
|
|
55
|
+
Object.keys(PROGRESSIVE_LOADERS);
|
|
56
|
+
|
|
57
|
+
const SELECTOR = PROGRESSIVE_TAGS.join(",");
|
|
58
|
+
const pending = new Map<Loader, Promise<unknown>>();
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Load (once) the package defining `tag`. Resolves when its module has
|
|
62
|
+
* evaluated, i.e. the element is defined; `undefined` for tags Nucleus Kit
|
|
63
|
+
* does not know. A failed import is logged and retried on the next call.
|
|
64
|
+
*/
|
|
65
|
+
export const loadElement = (tag: string): Promise<unknown> | undefined => {
|
|
66
|
+
const loader = PROGRESSIVE_LOADERS[tag];
|
|
67
|
+
if (!loader) return undefined;
|
|
68
|
+
let promise = pending.get(loader);
|
|
69
|
+
if (!promise) {
|
|
70
|
+
promise = loader().catch((error) => {
|
|
71
|
+
pending.delete(loader);
|
|
72
|
+
console.error(`[nucleus-kit] failed to load <${tag}>`, error);
|
|
73
|
+
throw error;
|
|
74
|
+
});
|
|
75
|
+
pending.set(loader, promise);
|
|
76
|
+
}
|
|
77
|
+
return promise;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const scan = (node: Node) => {
|
|
81
|
+
if (node instanceof Element && node.localName in PROGRESSIVE_LOADERS) {
|
|
82
|
+
loadElement(node.localName);
|
|
83
|
+
}
|
|
84
|
+
if ("querySelectorAll" in node) {
|
|
85
|
+
(node as ParentNode)
|
|
86
|
+
.querySelectorAll(SELECTOR)
|
|
87
|
+
.forEach((el) => loadElement(el.localName));
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Load the Nucleus Kit elements as their tags appear under `root` (an initial
|
|
93
|
+
* scan, then every inserted subtree). Returns a disposer. The entry calls this
|
|
94
|
+
* on `document` at import time; call it yourself for a shadow root.
|
|
95
|
+
*/
|
|
96
|
+
export const observeElements = (
|
|
97
|
+
root: Document | Element | ShadowRoot
|
|
98
|
+
): (() => void) => {
|
|
99
|
+
scan(root);
|
|
100
|
+
const observer = new MutationObserver((records) => {
|
|
101
|
+
for (const record of records) record.addedNodes.forEach(scan);
|
|
102
|
+
});
|
|
103
|
+
observer.observe(root, { childList: true, subtree: true });
|
|
104
|
+
return () => observer.disconnect();
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
observeElements(document);
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@excom/nucleus-kit",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "The whole Nucleus Stack in one package — elements, Quark, Valence.css",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=24.13.0"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@excom/content-carousel": "^0.1.0",
|
|
12
|
+
"@excom/content-drawer": "^0.1.0",
|
|
13
|
+
"@excom/content-tabs": "^0.1.0",
|
|
14
|
+
"@excom/data-table": "^0.1.0",
|
|
15
|
+
"@excom/detect-browser": "^0.1.0",
|
|
16
|
+
"@excom/detect-features": "^0.1.0",
|
|
17
|
+
"@excom/detect-media": "^0.1.0",
|
|
18
|
+
"@excom/dismiss-watcher": "^0.1.0",
|
|
19
|
+
"@excom/dom-observer": "^0.1.0",
|
|
20
|
+
"@excom/event-handler": "^0.1.0",
|
|
21
|
+
"@excom/include-content": "^0.1.0",
|
|
22
|
+
"@excom/gesture-handler": "^0.1.0",
|
|
23
|
+
"@excom/dialog-anchor": "^0.1.0",
|
|
24
|
+
"@excom/network-status": "^0.1.0",
|
|
25
|
+
"@excom/neutron": "^0.1.0",
|
|
26
|
+
"@excom/provider-fetch": "^0.1.0",
|
|
27
|
+
"@excom/provider-orientation": "^0.1.0",
|
|
28
|
+
"@excom/provider-geolocation": "^0.1.0",
|
|
29
|
+
"@excom/provider-storage": "^0.1.0",
|
|
30
|
+
"@excom/quark": "^0.1.0",
|
|
31
|
+
"@excom/quark-sheet": "^0.1.0",
|
|
32
|
+
"@excom/scroll-into-view": "^0.1.0",
|
|
33
|
+
"@excom/service-worker": "^0.1.0",
|
|
34
|
+
"@excom/spa-route": "^0.1.0",
|
|
35
|
+
"@excom/super-form": "^0.1.0",
|
|
36
|
+
"@excom/super-input": "^0.1.0",
|
|
37
|
+
"@excom/valence": "^0.1.0",
|
|
38
|
+
"@excom/web-authn": "^0.1.0"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@excom/heft-rig": "^0.1.0"
|
|
43
|
+
},
|
|
44
|
+
"repository": {
|
|
45
|
+
"url": "excom-dev/nucleus",
|
|
46
|
+
"directory": "packages/nucleus-kit"
|
|
47
|
+
},
|
|
48
|
+
"homepage": "https://github.com/excom-dev/nucleus/tree/main/packages/nucleus-kit/support/docs/README.md",
|
|
49
|
+
"bugs": "https://github.com/excom-dev/nucleus/issues",
|
|
50
|
+
"keywords": [
|
|
51
|
+
"nucleus-kit"
|
|
52
|
+
],
|
|
53
|
+
"excom": {
|
|
54
|
+
"packageType": "library",
|
|
55
|
+
"sideEffectImport": true
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "node node_modules/@excom/heft-rig/scripts/vite-build.mjs",
|
|
59
|
+
"build:watch": "node node_modules/@excom/heft-rig/scripts/vite-build-watch.mjs",
|
|
60
|
+
"format": "node node_modules/@excom/heft-rig/scripts/format.mjs",
|
|
61
|
+
"test": "node node_modules/@excom/heft-rig/scripts/vitest.mjs",
|
|
62
|
+
"coverage": "node node_modules/@excom/heft-rig/scripts/coverage.mjs",
|
|
63
|
+
"dev": "node node_modules/@excom/heft-rig/scripts/vite-dev.mjs",
|
|
64
|
+
"preview": "node node_modules/@excom/heft-rig/scripts/vite-preview.mjs",
|
|
65
|
+
"build:package-metas": "node node_modules/@excom/heft-rig/scripts/build-package-metas.mjs",
|
|
66
|
+
"build:docs": "node node_modules/@excom/heft-rig/scripts/build-docs.mjs"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Caching has been disabled for this project's "apply-exports" command.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: cd "$RUSH_PROJECT_FOLDER" && node ../heft-rig/scripts/apply-exports.mjs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This project does not define the caching behavior of the "build:docs" command, so caching has been disabled.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: node node_modules/@excom/heft-rig/scripts/build-docs.mjs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This project does not define the caching behavior of the "build:package-metas" command, so caching has been disabled.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: node node_modules/@excom/heft-rig/scripts/build-package-metas.mjs
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
- Renamed web-authn attrs
|
|
2
|
+
- Command-style events became native commands (2026-09-13): `provider-fetch-trigger` → `--fetch`; `super-form-trigger` / `web-authn-trigger` → `--submit`; `content-drawer-open` / `-close` / `-toggle` → `--open` / `--close` / `--toggle` (per-open props from the invoker's `data-*`, not `detail`); `content-carousel-next` / `-back` → `--next` / `--back`; `include-content-reload` / `spa-route-reload` / `quark-sheet-reload` → `--reload`; `provider-geolocation-request` / `provider-orientation-request` → `--request`; `data-table-export` → `--export` (options as `data-file-type` / `data-file-name` / `data-full` on the invoker); `data-table-filter` removed — write `filter-value` / `filter-casing`. Invoke with `<button command="--verb" commandfor="id">`, `<event-handler command-name="--verb" target-ref="…">`, `<dismiss-watcher command-name="--close">`, or `new CommandEvent()`.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Nucleus Kit
|
|
2
|
+
|
|
3
|
+
The whole Nucleus Stack in one package — every element, provider, Quark, and Valence.css behind a single import.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **One JS import** Registers every Nucleus Kit element
|
|
8
|
+
- **One CSS import** Valence.css theme + shared element styles (`basic.css`)
|
|
9
|
+
- **App-ready** Routing, sheets, forms, drawers, providers, and more
|
|
10
|
+
- **À la carte** Every package is published on its own; if you only use a few elements, install just those
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
<include-content is-active template-ref="/views/install-section/install-section.html"></include-content>
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
import "@excom/nucleus-kit";
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```css
|
|
23
|
+
@import "@excom/nucleus-kit/basic.css";
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
That loads Valence.css (`basic` theme) plus element CSS and registers the
|
|
27
|
+
packages below.
|
|
28
|
+
|
|
29
|
+
### Progressive bundle (experimental)
|
|
30
|
+
|
|
31
|
+
`nucleus-kit.progressive.min.js` registers nothing up front. It watches the
|
|
32
|
+
document for Nucleus Kit element tags and imports each element's package the
|
|
33
|
+
first time its tag appears (initial scan, then every inserted subtree), so a
|
|
34
|
+
page pays only for the elements it uses. Packages shared by several elements
|
|
35
|
+
(`neutron`, `kit-utils`, `quark`, the element bases) are separate chunks
|
|
36
|
+
under `dist/progressive/`, fetched once. The entry is 3 kB; a page using
|
|
37
|
+
`quark-sheet` and `content-drawer` loads ~55 kB gzip less than the all-in
|
|
38
|
+
build.
|
|
39
|
+
|
|
40
|
+
```html
|
|
41
|
+
<script type="module" src="/node_modules/@excom/nucleus-kit/nucleus-kit.progressive.min.js"></script>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Trade-offs: elements upgrade one network round-trip later (style the
|
|
45
|
+
pre-upgrade state with `:not(:defined)`), it is ES modules only, and elements
|
|
46
|
+
inside a shadow root need `observeElements(shadowRoot)` from the same module.
|
|
47
|
+
The all-in `index.umd.min.js` and the ESM `index.js` are unchanged.
|
|
48
|
+
|
|
49
|
+
### À la carte
|
|
50
|
+
|
|
51
|
+
Nucleus Kit is a convenience, not a requirement. If you find you are not using
|
|
52
|
+
most of its elements, install the packages you do use individually and drop it:
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
npm install @excom/quark-sheet @excom/provider-fetch @excom/content-drawer
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
import "@excom/quark-sheet";
|
|
60
|
+
import "@excom/provider-fetch";
|
|
61
|
+
import "@excom/content-drawer";
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Each package is self-contained — same elements, same versions, same CSS hooks —
|
|
65
|
+
and its README documents the slim install. Valence.css is `@excom/valence`.
|
|
66
|
+
|
|
67
|
+
### What's included
|
|
68
|
+
|
|
69
|
+
**Core**
|
|
70
|
+
|
|
71
|
+
- [`neutron`](/nucleus/packages/neutron) — custom element factory
|
|
72
|
+
- [`quark`](/nucleus/packages/quark) / [`quark-sheet`](/nucleus/packages/quark-sheet) — DOM
|
|
73
|
+
orchestration
|
|
74
|
+
- [`valence`](/nucleus/packages/valence) — Valence.css, semantic CSS (via `basic.css`)
|
|
75
|
+
|
|
76
|
+
**Layout / chrome**
|
|
77
|
+
|
|
78
|
+
- [`content-carousel`](/nucleus/packages/content-carousel)
|
|
79
|
+
- [`content-drawer`](/nucleus/packages/content-drawer)
|
|
80
|
+
- [`content-tabs`](/nucleus/packages/content-tabs)
|
|
81
|
+
- [`dialog-anchor`](/nucleus/packages/dialog-anchor)
|
|
82
|
+
- [`dismiss-watcher`](/nucleus/packages/dismiss-watcher)
|
|
83
|
+
- [`data-table`](/nucleus/packages/data-table)
|
|
84
|
+
|
|
85
|
+
**Content / routing**
|
|
86
|
+
|
|
87
|
+
- [`include-content`](/nucleus/packages/include-content)
|
|
88
|
+
- [`spa-route`](/nucleus/packages/spa-route)
|
|
89
|
+
- [`scroll-into-view`](/nucleus/packages/scroll-into-view)
|
|
90
|
+
|
|
91
|
+
**Forms / auth**
|
|
92
|
+
|
|
93
|
+
- [`super-form`](/nucleus/packages/super-form)
|
|
94
|
+
- [`super-input`](/nucleus/packages/super-input)
|
|
95
|
+
- [`web-authn`](/nucleus/packages/web-authn)
|
|
96
|
+
|
|
97
|
+
**Providers**
|
|
98
|
+
|
|
99
|
+
- [`provider-fetch`](/nucleus/packages/provider-fetch)
|
|
100
|
+
- [`provider-geolocation`](/nucleus/packages/provider-geolocation)
|
|
101
|
+
- [`provider-orientation`](/nucleus/packages/provider-orientation)
|
|
102
|
+
- [`provider-storage`](/nucleus/packages/provider-storage)
|
|
103
|
+
|
|
104
|
+
**Platform**
|
|
105
|
+
|
|
106
|
+
- [`detect-browser`](/nucleus/packages/detect-browser)
|
|
107
|
+
- [`detect-features`](/nucleus/packages/detect-features)
|
|
108
|
+
- [`detect-media`](/nucleus/packages/detect-media)
|
|
109
|
+
- [`dom-observer`](/nucleus/packages/dom-observer)
|
|
110
|
+
- [`event-handler`](/nucleus/packages/event-handler)
|
|
111
|
+
- [`gesture-handler`](/nucleus/packages/gesture-handler)
|
|
112
|
+
- [`network-status`](/nucleus/packages/network-status)
|
|
113
|
+
- [`service-worker`](/nucleus/packages/service-worker)
|
|
114
|
+
|
|
115
|
+
### Not in Nucleus Kit
|
|
116
|
+
|
|
117
|
+
Install separately when needed: `mapbox-view`, `super-img`, element bases
|
|
118
|
+
(`abortable-element`, `fetchable-element`, …), and editor tooling such as
|
|
119
|
+
[`nucleus-quark-highlighter`](/nucleus/packages/nucleus-quark-highlighter).
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
- Renamed web-authn attrs
|
|
2
|
+
- Command-style events became native commands (2026-09-13): `provider-fetch-trigger` → `--fetch`; `super-form-trigger` / `web-authn-trigger` → `--submit`; `content-drawer-open` / `-close` / `-toggle` → `--open` / `--close` / `--toggle` (per-open props from the invoker's `data-*`, not `detail`); `content-carousel-next` / `-back` → `--next` / `--back`; `include-content-reload` / `spa-route-reload` / `quark-sheet-reload` → `--reload`; `provider-geolocation-request` / `provider-orientation-request` → `--request`; `data-table-export` → `--export` (options as `data-file-type` / `data-file-name` / `data-full` on the invoker); `data-table-filter` removed — write `filter-value` / `filter-casing`. Invoke with `<button command="--verb" commandfor="id">`, `<event-handler command-name="--verb" target-ref="…">`, `<dismiss-watcher command-name="--close">`, or `new CommandEvent()`.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Nucleus Kit
|
|
2
|
+
|
|
3
|
+
The whole Nucleus Stack in one package — every element, provider, Quark, and Valence.css behind a single import.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **One JS import** Registers every Nucleus Kit element
|
|
8
|
+
- **One CSS import** Valence.css theme + shared element styles (`basic.css`)
|
|
9
|
+
- **App-ready** Routing, sheets, forms, drawers, providers, and more
|
|
10
|
+
- **À la carte** Every package is published on its own; if you only use a few elements, install just those
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
<include-content is-active template-ref="/views/install-section/install-section.html"></include-content>
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
import "@excom/nucleus-kit";
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```css
|
|
23
|
+
@import "@excom/nucleus-kit/basic.css";
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
That loads Valence.css (`basic` theme) plus element CSS and registers the
|
|
27
|
+
packages below.
|
|
28
|
+
|
|
29
|
+
### Progressive bundle (experimental)
|
|
30
|
+
|
|
31
|
+
`nucleus-kit.progressive.min.js` registers nothing up front. It watches the
|
|
32
|
+
document for Nucleus Kit element tags and imports each element's package the
|
|
33
|
+
first time its tag appears (initial scan, then every inserted subtree), so a
|
|
34
|
+
page pays only for the elements it uses. Packages shared by several elements
|
|
35
|
+
(`neutron`, `kit-utils`, `quark`, the element bases) are separate chunks
|
|
36
|
+
under `dist/progressive/`, fetched once. The entry is 3 kB; a page using
|
|
37
|
+
`quark-sheet` and `content-drawer` loads ~55 kB gzip less than the all-in
|
|
38
|
+
build.
|
|
39
|
+
|
|
40
|
+
```html
|
|
41
|
+
<script type="module" src="/node_modules/@excom/nucleus-kit/nucleus-kit.progressive.min.js"></script>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Trade-offs: elements upgrade one network round-trip later (style the
|
|
45
|
+
pre-upgrade state with `:not(:defined)`), it is ES modules only, and elements
|
|
46
|
+
inside a shadow root need `observeElements(shadowRoot)` from the same module.
|
|
47
|
+
The all-in `index.umd.min.js` and the ESM `index.js` are unchanged.
|
|
48
|
+
|
|
49
|
+
### À la carte
|
|
50
|
+
|
|
51
|
+
Nucleus Kit is a convenience, not a requirement. If you find you are not using
|
|
52
|
+
most of its elements, install the packages you do use individually and drop it:
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
npm install @excom/quark-sheet @excom/provider-fetch @excom/content-drawer
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
import "@excom/quark-sheet";
|
|
60
|
+
import "@excom/provider-fetch";
|
|
61
|
+
import "@excom/content-drawer";
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Each package is self-contained — same elements, same versions, same CSS hooks —
|
|
65
|
+
and its README documents the slim install. Valence.css is `@excom/valence`.
|
|
66
|
+
|
|
67
|
+
### What's included
|
|
68
|
+
|
|
69
|
+
**Core**
|
|
70
|
+
|
|
71
|
+
- [`neutron`](/nucleus/packages/neutron) — custom element factory
|
|
72
|
+
- [`quark`](/nucleus/packages/quark) / [`quark-sheet`](/nucleus/packages/quark-sheet) — DOM
|
|
73
|
+
orchestration
|
|
74
|
+
- [`valence`](/nucleus/packages/valence) — Valence.css, semantic CSS (via `basic.css`)
|
|
75
|
+
|
|
76
|
+
**Layout / chrome**
|
|
77
|
+
|
|
78
|
+
- [`content-carousel`](/nucleus/packages/content-carousel)
|
|
79
|
+
- [`content-drawer`](/nucleus/packages/content-drawer)
|
|
80
|
+
- [`content-tabs`](/nucleus/packages/content-tabs)
|
|
81
|
+
- [`dialog-anchor`](/nucleus/packages/dialog-anchor)
|
|
82
|
+
- [`dismiss-watcher`](/nucleus/packages/dismiss-watcher)
|
|
83
|
+
- [`data-table`](/nucleus/packages/data-table)
|
|
84
|
+
|
|
85
|
+
**Content / routing**
|
|
86
|
+
|
|
87
|
+
- [`include-content`](/nucleus/packages/include-content)
|
|
88
|
+
- [`spa-route`](/nucleus/packages/spa-route)
|
|
89
|
+
- [`scroll-into-view`](/nucleus/packages/scroll-into-view)
|
|
90
|
+
|
|
91
|
+
**Forms / auth**
|
|
92
|
+
|
|
93
|
+
- [`super-form`](/nucleus/packages/super-form)
|
|
94
|
+
- [`super-input`](/nucleus/packages/super-input)
|
|
95
|
+
- [`web-authn`](/nucleus/packages/web-authn)
|
|
96
|
+
|
|
97
|
+
**Providers**
|
|
98
|
+
|
|
99
|
+
- [`provider-fetch`](/nucleus/packages/provider-fetch)
|
|
100
|
+
- [`provider-geolocation`](/nucleus/packages/provider-geolocation)
|
|
101
|
+
- [`provider-orientation`](/nucleus/packages/provider-orientation)
|
|
102
|
+
- [`provider-storage`](/nucleus/packages/provider-storage)
|
|
103
|
+
|
|
104
|
+
**Platform**
|
|
105
|
+
|
|
106
|
+
- [`detect-browser`](/nucleus/packages/detect-browser)
|
|
107
|
+
- [`detect-features`](/nucleus/packages/detect-features)
|
|
108
|
+
- [`detect-media`](/nucleus/packages/detect-media)
|
|
109
|
+
- [`dom-observer`](/nucleus/packages/dom-observer)
|
|
110
|
+
- [`event-handler`](/nucleus/packages/event-handler)
|
|
111
|
+
- [`gesture-handler`](/nucleus/packages/gesture-handler)
|
|
112
|
+
- [`network-status`](/nucleus/packages/network-status)
|
|
113
|
+
- [`service-worker`](/nucleus/packages/service-worker)
|
|
114
|
+
|
|
115
|
+
### Not in Nucleus Kit
|
|
116
|
+
|
|
117
|
+
Install separately when needed: `mapbox-view`, `super-img`, element bases
|
|
118
|
+
(`abortable-element`, `fetchable-element`, …), and editor tooling such as
|
|
119
|
+
[`nucleus-quark-highlighter`](/nucleus/packages/nucleus-quark-highlighter).
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"shortName": "nucleus-kit",
|
|
3
|
+
"package": {
|
|
4
|
+
"name": "@excom/nucleus-kit",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"description": "The whole Nucleus Stack in one package — elements, Quark, Valence.css",
|
|
7
|
+
"peerDependencies": {},
|
|
8
|
+
"excom": {
|
|
9
|
+
"packageType": "library",
|
|
10
|
+
"sideEffectImport": true
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"demos": {},
|
|
14
|
+
"readme": "<h1 id=\"md-nucleus-kit\">Nucleus Kit</h1>\n<p>The whole Nucleus Stack in one package — every element, provider, Quark, and Valence.css behind a single import.</p>\n<h2 id=\"md-features\">Features</h2>\n<ul>\n<li><strong>One JS import</strong> Registers every Nucleus Kit element</li>\n<li><strong>One CSS import</strong> Valence.css theme + shared element styles (<code>basic.css</code>)</li>\n<li><strong>App-ready</strong> Routing, sheets, forms, drawers, providers, and more</li>\n<li><strong>À la carte</strong> Every package is published on its own; if you only use a few elements, install just those</li>\n</ul>\n<h2 id=\"md-installation\">Installation</h2>\n<p><include-content is-active template-ref=\"/views/install-section/install-section.html\"></include-content></p>\n<h2 id=\"md-usage\">Usage</h2>\n<include-content data-language=\"js\"><template>import \"@excom/nucleus-kit\";</template></include-content>\n<include-content data-language=\"css\"><template>@import \"@excom/nucleus-kit/basic.css\";</template></include-content>\n<p>That loads Valence.css (<code>basic</code> theme) plus element CSS and registers the\npackages below.</p>\n<h3 id=\"md-progressive-bundle-experimental\">Progressive bundle (experimental)</h3>\n<p><code>nucleus-kit.progressive.min.js</code> registers nothing up front. It watches the\ndocument for Nucleus Kit element tags and imports each element's package the\nfirst time its tag appears (initial scan, then every inserted subtree), so a\npage pays only for the elements it uses. Packages shared by several elements\n(<code>neutron</code>, <code>kit-utils</code>, <code>quark</code>, the element bases) are separate chunks\nunder <code>dist/progressive/</code>, fetched once. The entry is 3 kB; a page using\n<code>quark-sheet</code> and <code>content-drawer</code> loads ~55 kB gzip less than the all-in\nbuild.</p>\n<include-content data-language=\"html\"><template><script type=\"module\" src=\"/node_modules/@excom/nucleus-kit/nucleus-kit.progressive.min.js\"></script></template></include-content>\n<p>Trade-offs: elements upgrade one network round-trip later (style the\npre-upgrade state with <code>:not(:defined)</code>), it is ES modules only, and elements\ninside a shadow root need <code>observeElements(shadowRoot)</code> from the same module.\nThe all-in <code>index.umd.min.js</code> and the ESM <code>index.js</code> are unchanged.</p>\n<h3 id=\"md-la-carte\">À la carte</h3>\n<p>Nucleus Kit is a convenience, not a requirement. If you find you are not using\nmost of its elements, install the packages you do use individually and drop it:</p>\n<include-content data-language=\"sh\"><template>npm install @excom/quark-sheet @excom/provider-fetch @excom/content-drawer</template></include-content>\n<include-content data-language=\"js\"><template>import \"@excom/quark-sheet\";\nimport \"@excom/provider-fetch\";\nimport \"@excom/content-drawer\";</template></include-content>\n<p>Each package is self-contained — same elements, same versions, same CSS hooks —\nand its README documents the slim install. Valence.css is <code>@excom/valence</code>.</p>\n<h3 id=\"md-what-39-s-included\">What's included</h3>\n<p><strong>Core</strong></p>\n<ul>\n<li><spa-a route-href=\"/nucleus/packages/neutron\" role=\"link\"><code>neutron</code></spa-a> — custom element factory</li>\n<li><spa-a route-href=\"/nucleus/packages/quark\" role=\"link\"><code>quark</code></spa-a> / <spa-a route-href=\"/nucleus/packages/quark-sheet\" role=\"link\"><code>quark-sheet</code></spa-a> — DOM\norchestration</li>\n<li><spa-a route-href=\"/nucleus/packages/valence\" role=\"link\"><code>valence</code></spa-a> — Valence.css, semantic CSS (via <code>basic.css</code>)</li>\n</ul>\n<p><strong>Layout / chrome</strong></p>\n<ul>\n<li><spa-a route-href=\"/nucleus/packages/content-carousel\" role=\"link\"><code>content-carousel</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/content-drawer\" role=\"link\"><code>content-drawer</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/content-tabs\" role=\"link\"><code>content-tabs</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/dialog-anchor\" role=\"link\"><code>dialog-anchor</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/dismiss-watcher\" role=\"link\"><code>dismiss-watcher</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/data-table\" role=\"link\"><code>data-table</code></spa-a></li>\n</ul>\n<p><strong>Content / routing</strong></p>\n<ul>\n<li><spa-a route-href=\"/nucleus/packages/include-content\" role=\"link\"><code>include-content</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/spa-route\" role=\"link\"><code>spa-route</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/scroll-into-view\" role=\"link\"><code>scroll-into-view</code></spa-a></li>\n</ul>\n<p><strong>Forms / auth</strong></p>\n<ul>\n<li><spa-a route-href=\"/nucleus/packages/super-form\" role=\"link\"><code>super-form</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/super-input\" role=\"link\"><code>super-input</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/web-authn\" role=\"link\"><code>web-authn</code></spa-a></li>\n</ul>\n<p><strong>Providers</strong></p>\n<ul>\n<li><spa-a route-href=\"/nucleus/packages/provider-fetch\" role=\"link\"><code>provider-fetch</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/provider-geolocation\" role=\"link\"><code>provider-geolocation</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/provider-orientation\" role=\"link\"><code>provider-orientation</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/provider-storage\" role=\"link\"><code>provider-storage</code></spa-a></li>\n</ul>\n<p><strong>Platform</strong></p>\n<ul>\n<li><spa-a route-href=\"/nucleus/packages/detect-browser\" role=\"link\"><code>detect-browser</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/detect-features\" role=\"link\"><code>detect-features</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/detect-media\" role=\"link\"><code>detect-media</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/dom-observer\" role=\"link\"><code>dom-observer</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/event-handler\" role=\"link\"><code>event-handler</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/gesture-handler\" role=\"link\"><code>gesture-handler</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/network-status\" role=\"link\"><code>network-status</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/service-worker\" role=\"link\"><code>service-worker</code></spa-a></li>\n</ul>\n<h3 id=\"md-not-in-nucleus-kit\">Not in Nucleus Kit</h3>\n<p>Install separately when needed: <code>mapbox-view</code>, <code>super-img</code>, element bases\n(<code>abortable-element</code>, <code>fetchable-element</code>, …), and editor tooling such as\n<spa-a route-href=\"/nucleus/packages/nucleus-quark-highlighter\" role=\"link\"><code>nucleus-quark-highlighter</code></spa-a>.</p>\n",
|
|
15
|
+
"docs": {
|
|
16
|
+
"breaking_changes": "<ul>\n<li>Renamed web-authn attrs</li>\n<li>Command-style events became native commands (2026-09-13): <code>provider-fetch-trigger</code> → <code>--fetch</code>; <code>super-form-trigger</code> / <code>web-authn-trigger</code> → <code>--submit</code>; <code>content-drawer-open</code> / <code>-close</code> / <code>-toggle</code> → <code>--open</code> / <code>--close</code> / <code>--toggle</code> (per-open props from the invoker's <code>data-*</code>, not <code>detail</code>); <code>content-carousel-next</code> / <code>-back</code> → <code>--next</code> / <code>--back</code>; <code>include-content-reload</code> / <code>spa-route-reload</code> / <code>quark-sheet-reload</code> → <code>--reload</code>; <code>provider-geolocation-request</code> / <code>provider-orientation-request</code> → <code>--request</code>; <code>data-table-export</code> → <code>--export</code> (options as <code>data-file-type</code> / <code>data-file-name</code> / <code>data-full</code> on the invoker); <code>data-table-filter</code> removed — write <code>filter-value</code> / <code>filter-casing</code>. Invoke with <code><button command="--verb" commandfor="id"></code>, <code><event-handler command-name="--verb" target-ref="…"></code>, <code><dismiss-watcher command-name="--close"></code>, or <code>new CommandEvent()</code>.</li>\n</ul>\n",
|
|
17
|
+
"readme": "<h1 id=\"md-nucleus-kit\">Nucleus Kit</h1>\n<p>The whole Nucleus Stack in one package — every element, provider, Quark, and Valence.css behind a single import.</p>\n<h2 id=\"md-features\">Features</h2>\n<ul>\n<li><strong>One JS import</strong> Registers every Nucleus Kit element</li>\n<li><strong>One CSS import</strong> Valence.css theme + shared element styles (<code>basic.css</code>)</li>\n<li><strong>App-ready</strong> Routing, sheets, forms, drawers, providers, and more</li>\n<li><strong>À la carte</strong> Every package is published on its own; if you only use a few elements, install just those</li>\n</ul>\n<h2 id=\"md-installation\">Installation</h2>\n<p><include-content is-active template-ref=\"/views/install-section/install-section.html\"></include-content></p>\n<h2 id=\"md-usage\">Usage</h2>\n<include-content data-language=\"js\"><template>import \"@excom/nucleus-kit\";</template></include-content>\n<include-content data-language=\"css\"><template>@import \"@excom/nucleus-kit/basic.css\";</template></include-content>\n<p>That loads Valence.css (<code>basic</code> theme) plus element CSS and registers the\npackages below.</p>\n<h3 id=\"md-progressive-bundle-experimental\">Progressive bundle (experimental)</h3>\n<p><code>nucleus-kit.progressive.min.js</code> registers nothing up front. It watches the\ndocument for Nucleus Kit element tags and imports each element's package the\nfirst time its tag appears (initial scan, then every inserted subtree), so a\npage pays only for the elements it uses. Packages shared by several elements\n(<code>neutron</code>, <code>kit-utils</code>, <code>quark</code>, the element bases) are separate chunks\nunder <code>dist/progressive/</code>, fetched once. The entry is 3 kB; a page using\n<code>quark-sheet</code> and <code>content-drawer</code> loads ~55 kB gzip less than the all-in\nbuild.</p>\n<include-content data-language=\"html\"><template><script type=\"module\" src=\"/node_modules/@excom/nucleus-kit/nucleus-kit.progressive.min.js\"></script></template></include-content>\n<p>Trade-offs: elements upgrade one network round-trip later (style the\npre-upgrade state with <code>:not(:defined)</code>), it is ES modules only, and elements\ninside a shadow root need <code>observeElements(shadowRoot)</code> from the same module.\nThe all-in <code>index.umd.min.js</code> and the ESM <code>index.js</code> are unchanged.</p>\n<h3 id=\"md-la-carte\">À la carte</h3>\n<p>Nucleus Kit is a convenience, not a requirement. If you find you are not using\nmost of its elements, install the packages you do use individually and drop it:</p>\n<include-content data-language=\"sh\"><template>npm install @excom/quark-sheet @excom/provider-fetch @excom/content-drawer</template></include-content>\n<include-content data-language=\"js\"><template>import \"@excom/quark-sheet\";\nimport \"@excom/provider-fetch\";\nimport \"@excom/content-drawer\";</template></include-content>\n<p>Each package is self-contained — same elements, same versions, same CSS hooks —\nand its README documents the slim install. Valence.css is <code>@excom/valence</code>.</p>\n<h3 id=\"md-what-39-s-included\">What's included</h3>\n<p><strong>Core</strong></p>\n<ul>\n<li><spa-a route-href=\"/nucleus/packages/neutron\" role=\"link\"><code>neutron</code></spa-a> — custom element factory</li>\n<li><spa-a route-href=\"/nucleus/packages/quark\" role=\"link\"><code>quark</code></spa-a> / <spa-a route-href=\"/nucleus/packages/quark-sheet\" role=\"link\"><code>quark-sheet</code></spa-a> — DOM\norchestration</li>\n<li><spa-a route-href=\"/nucleus/packages/valence\" role=\"link\"><code>valence</code></spa-a> — Valence.css, semantic CSS (via <code>basic.css</code>)</li>\n</ul>\n<p><strong>Layout / chrome</strong></p>\n<ul>\n<li><spa-a route-href=\"/nucleus/packages/content-carousel\" role=\"link\"><code>content-carousel</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/content-drawer\" role=\"link\"><code>content-drawer</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/content-tabs\" role=\"link\"><code>content-tabs</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/dialog-anchor\" role=\"link\"><code>dialog-anchor</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/dismiss-watcher\" role=\"link\"><code>dismiss-watcher</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/data-table\" role=\"link\"><code>data-table</code></spa-a></li>\n</ul>\n<p><strong>Content / routing</strong></p>\n<ul>\n<li><spa-a route-href=\"/nucleus/packages/include-content\" role=\"link\"><code>include-content</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/spa-route\" role=\"link\"><code>spa-route</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/scroll-into-view\" role=\"link\"><code>scroll-into-view</code></spa-a></li>\n</ul>\n<p><strong>Forms / auth</strong></p>\n<ul>\n<li><spa-a route-href=\"/nucleus/packages/super-form\" role=\"link\"><code>super-form</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/super-input\" role=\"link\"><code>super-input</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/web-authn\" role=\"link\"><code>web-authn</code></spa-a></li>\n</ul>\n<p><strong>Providers</strong></p>\n<ul>\n<li><spa-a route-href=\"/nucleus/packages/provider-fetch\" role=\"link\"><code>provider-fetch</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/provider-geolocation\" role=\"link\"><code>provider-geolocation</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/provider-orientation\" role=\"link\"><code>provider-orientation</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/provider-storage\" role=\"link\"><code>provider-storage</code></spa-a></li>\n</ul>\n<p><strong>Platform</strong></p>\n<ul>\n<li><spa-a route-href=\"/nucleus/packages/detect-browser\" role=\"link\"><code>detect-browser</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/detect-features\" role=\"link\"><code>detect-features</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/detect-media\" role=\"link\"><code>detect-media</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/dom-observer\" role=\"link\"><code>dom-observer</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/event-handler\" role=\"link\"><code>event-handler</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/gesture-handler\" role=\"link\"><code>gesture-handler</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/network-status\" role=\"link\"><code>network-status</code></spa-a></li>\n<li><spa-a route-href=\"/nucleus/packages/service-worker\" role=\"link\"><code>service-worker</code></spa-a></li>\n</ul>\n<h3 id=\"md-not-in-nucleus-kit\">Not in Nucleus Kit</h3>\n<p>Install separately when needed: <code>mapbox-view</code>, <code>super-img</code>, element bases\n(<code>abortable-element</code>, <code>fetchable-element</code>, …), and editor tooling such as\n<spa-a route-href=\"/nucleus/packages/nucleus-quark-highlighter\" role=\"link\"><code>nucleus-quark-highlighter</code></spa-a>.</p>\n"
|
|
18
|
+
},
|
|
19
|
+
"installation": {
|
|
20
|
+
"name": "@excom/nucleus-kit",
|
|
21
|
+
"shortName": "nucleus-kit",
|
|
22
|
+
"version": "0.1.0",
|
|
23
|
+
"description": "The whole Nucleus Stack in one package — elements, Quark, Valence.css",
|
|
24
|
+
"packageType": "library",
|
|
25
|
+
"install": {
|
|
26
|
+
"npm": "npm install @excom/nucleus-kit"
|
|
27
|
+
},
|
|
28
|
+
"imports": {
|
|
29
|
+
"js": "import \"@excom/nucleus-kit\";",
|
|
30
|
+
"css": "@import \"@excom/nucleus-kit/basic.css\";"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": []
|
|
33
|
+
},
|
|
34
|
+
"elementApis": [],
|
|
35
|
+
"exportedFiles": {}
|
|
36
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-package loop: an event-emitting Adapter (`dom-observer`) and a Quark
|
|
3
|
+
* `@on` block that writes the attribute the Adapter observes. Every hop is
|
|
4
|
+
* asynchronous (MutationObserver → event → deferred paint), so only the
|
|
5
|
+
* shared loop guard's address-carried depth can see it as one chain.
|
|
6
|
+
*/
|
|
7
|
+
import "../../index";
|
|
8
|
+
import {
|
|
9
|
+
afterEach,
|
|
10
|
+
beforeEach,
|
|
11
|
+
describe,
|
|
12
|
+
expect,
|
|
13
|
+
fixture,
|
|
14
|
+
it,
|
|
15
|
+
wait,
|
|
16
|
+
} from "@excom/heft-rig/profiles/default/config/test-utils";
|
|
17
|
+
import { LoopGuard, type LoopGuardTrip } from "@excom/kit-utils";
|
|
18
|
+
|
|
19
|
+
describe("nucleus-kit: loop guard across elements and Quark", () => {
|
|
20
|
+
let trips: LoopGuardTrip[];
|
|
21
|
+
let off: () => void;
|
|
22
|
+
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
LoopGuard.reset();
|
|
25
|
+
LoopGuard.configure({ limit: 6, log: () => {} });
|
|
26
|
+
trips = [];
|
|
27
|
+
off = LoopGuard.onTrip((trip) => trips.push(trip));
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
afterEach(() => {
|
|
31
|
+
off();
|
|
32
|
+
LoopGuard.reset();
|
|
33
|
+
document.body.innerHTML = "";
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const settle = async (done: () => boolean, ticks = 400) => {
|
|
37
|
+
for (let i = 0; i < ticks && !done(); i++) await wait(0);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
it("cuts an attribute → event → @on block → attribute cycle", async () => {
|
|
41
|
+
const root = fixture<HTMLElement>(
|
|
42
|
+
`<section>
|
|
43
|
+
<quark-sheet>
|
|
44
|
+
dom-observer {
|
|
45
|
+
@on dom-observer-change {
|
|
46
|
+
#box { data-n: attr("data-n") + "x"; }
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
</quark-sheet>
|
|
50
|
+
<dom-observer target-ref="#box"><div id="box" data-n=""></div></dom-observer>
|
|
51
|
+
</section>`
|
|
52
|
+
);
|
|
53
|
+
const box = root.querySelector("#box")!;
|
|
54
|
+
await wait(0);
|
|
55
|
+
await wait(0);
|
|
56
|
+
// kick the cycle from outside: one mutation → change event → block
|
|
57
|
+
// writes `data-n` → another mutation → …
|
|
58
|
+
box.setAttribute("data-n", "start");
|
|
59
|
+
await settle(() => trips.length > 0);
|
|
60
|
+
expect(trips.length).toBeGreaterThanOrEqual(1);
|
|
61
|
+
expect(trips[0]).toMatchObject({ kind: "depth", target: box, name: "data-n" });
|
|
62
|
+
const value = box.getAttribute("data-n")!;
|
|
63
|
+
expect(value.length).toBeLessThanOrEqual("start".length + LoopGuard.limit);
|
|
64
|
+
// dead: nothing changes any more
|
|
65
|
+
for (let i = 0; i < 10; i++) await wait(0);
|
|
66
|
+
expect(box.getAttribute("data-n")).toBe(value);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("does not trip when each change is an external one", async () => {
|
|
70
|
+
const root = fixture<HTMLElement>(
|
|
71
|
+
`<section>
|
|
72
|
+
<quark-sheet>
|
|
73
|
+
dom-observer {
|
|
74
|
+
@on dom-observer-change {
|
|
75
|
+
#box { data-seen: attr("data-n"); }
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
</quark-sheet>
|
|
79
|
+
<dom-observer target-ref="#box"><div id="box" data-n=""></div></dom-observer>
|
|
80
|
+
</section>`
|
|
81
|
+
);
|
|
82
|
+
const box = root.querySelector("#box")!;
|
|
83
|
+
await wait(0);
|
|
84
|
+
await wait(0);
|
|
85
|
+
for (let i = 1; i <= 10; i++) {
|
|
86
|
+
box.setAttribute("data-n", String(i));
|
|
87
|
+
await settle(() => box.getAttribute("data-seen") === String(i), 40);
|
|
88
|
+
}
|
|
89
|
+
expect(box.getAttribute("data-seen")).toBe("10");
|
|
90
|
+
expect(trips).toEqual([]);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import "../../index";
|
|
2
|
+
import {
|
|
3
|
+
afterEach,
|
|
4
|
+
describe,
|
|
5
|
+
expect,
|
|
6
|
+
it,
|
|
7
|
+
} from "@excom/heft-rig/node_modules/vitest";
|
|
8
|
+
|
|
9
|
+
describe("nucleus-kit", () => {
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
document.body.innerHTML = "";
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("registers a few shared elements", () => {
|
|
15
|
+
expect(customElements.get("content-drawer")).toBeTruthy();
|
|
16
|
+
expect(customElements.get("detect-browser")).toBeTruthy();
|
|
17
|
+
expect(customElements.get("dom-observer")).toBeTruthy();
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The progressive entry: nothing registered up front, each package imported
|
|
3
|
+
* the first time one of its tags appears in the document.
|
|
4
|
+
*/
|
|
5
|
+
import {
|
|
6
|
+
loadElement,
|
|
7
|
+
observeElements,
|
|
8
|
+
PROGRESSIVE_LOADERS,
|
|
9
|
+
PROGRESSIVE_TAGS,
|
|
10
|
+
} from "../../nucleus-kit.progressive";
|
|
11
|
+
import {
|
|
12
|
+
afterEach,
|
|
13
|
+
describe,
|
|
14
|
+
expect,
|
|
15
|
+
it,
|
|
16
|
+
vi,
|
|
17
|
+
wait,
|
|
18
|
+
} from "@excom/heft-rig/profiles/default/config/test-utils";
|
|
19
|
+
|
|
20
|
+
const settle = async () => {
|
|
21
|
+
await wait(0);
|
|
22
|
+
await wait(0);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
describe("nucleus-kit progressive entry", () => {
|
|
26
|
+
afterEach(() => {
|
|
27
|
+
document.body.innerHTML = "";
|
|
28
|
+
vi.restoreAllMocks();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("covers every tag Nucleus Kit defines", () => {
|
|
32
|
+
expect([...PROGRESSIVE_TAGS].sort()).toEqual(
|
|
33
|
+
[
|
|
34
|
+
"content-carousel",
|
|
35
|
+
"content-carousel-slide",
|
|
36
|
+
"content-drawer",
|
|
37
|
+
"content-tabs",
|
|
38
|
+
"content-tabs-body",
|
|
39
|
+
"content-tabs-header",
|
|
40
|
+
"data-table",
|
|
41
|
+
"data-th",
|
|
42
|
+
"detect-browser",
|
|
43
|
+
"detect-features",
|
|
44
|
+
"detect-media",
|
|
45
|
+
"dialog-anchor",
|
|
46
|
+
"dismiss-watcher",
|
|
47
|
+
"dom-observer",
|
|
48
|
+
"event-handler",
|
|
49
|
+
"gesture-handler",
|
|
50
|
+
"include-content",
|
|
51
|
+
"network-status",
|
|
52
|
+
"provider-fetch",
|
|
53
|
+
"provider-geolocation",
|
|
54
|
+
"provider-orientation",
|
|
55
|
+
"provider-storage",
|
|
56
|
+
"quark-sheet",
|
|
57
|
+
"scroll-into-view",
|
|
58
|
+
"service-worker",
|
|
59
|
+
"spa-a",
|
|
60
|
+
"spa-manager",
|
|
61
|
+
"spa-route",
|
|
62
|
+
"super-form",
|
|
63
|
+
"super-input",
|
|
64
|
+
"web-authn",
|
|
65
|
+
].sort()
|
|
66
|
+
);
|
|
67
|
+
// sub-adapters share their parent's loader so a family is one import
|
|
68
|
+
expect(PROGRESSIVE_LOADERS["content-tabs-header"]).toBe(PROGRESSIVE_LOADERS["content-tabs"]);
|
|
69
|
+
expect(PROGRESSIVE_LOADERS["spa-a"]).toBe(PROGRESSIVE_LOADERS["spa-route"]);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("defines every tag it maps", async () => {
|
|
73
|
+
await Promise.all(PROGRESSIVE_TAGS.map((tag) => loadElement(tag)));
|
|
74
|
+
for (const tag of PROGRESSIVE_TAGS) {
|
|
75
|
+
expect(customElements.get(tag), tag).toBeDefined();
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("loads a package once on demand and defines its elements", async () => {
|
|
80
|
+
const first = loadElement("content-drawer");
|
|
81
|
+
expect(loadElement("content-drawer")).toBe(first);
|
|
82
|
+
await first;
|
|
83
|
+
expect(customElements.get("content-drawer")).toBeDefined();
|
|
84
|
+
expect(loadElement("not-a-kit-tag")).toBeUndefined();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("loads elements inserted into the document, including nested ones", async () => {
|
|
88
|
+
document.body.innerHTML = `<div>text <section><super-form></super-form></section></div>`;
|
|
89
|
+
document.body.appendChild(document.createTextNode("loose text"));
|
|
90
|
+
await settle();
|
|
91
|
+
await loadElement("super-form");
|
|
92
|
+
expect(customElements.get("super-form")).toBeDefined();
|
|
93
|
+
|
|
94
|
+
const el = document.createElement("dialog-anchor");
|
|
95
|
+
document.body.appendChild(el);
|
|
96
|
+
await settle();
|
|
97
|
+
await loadElement("dialog-anchor");
|
|
98
|
+
expect(customElements.get("dialog-anchor")).toBeDefined();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("observes a shadow root on request and stops when disposed", async () => {
|
|
102
|
+
const host = document.createElement("div");
|
|
103
|
+
const shadow = host.attachShadow({ mode: "open" });
|
|
104
|
+
shadow.innerHTML = `<network-status></network-status>`;
|
|
105
|
+
document.body.appendChild(host);
|
|
106
|
+
const stop = observeElements(shadow);
|
|
107
|
+
await loadElement("network-status");
|
|
108
|
+
expect(customElements.get("network-status")).toBeDefined();
|
|
109
|
+
stop();
|
|
110
|
+
const spy = vi.spyOn(PROGRESSIVE_LOADERS as Record<string, () => Promise<unknown>>, "scroll-into-view");
|
|
111
|
+
shadow.appendChild(document.createElement("scroll-into-view"));
|
|
112
|
+
await settle();
|
|
113
|
+
expect(spy).not.toHaveBeenCalled();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("logs a failed import and retries on the next call", async () => {
|
|
117
|
+
const error = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
118
|
+
let attempts = 0;
|
|
119
|
+
(PROGRESSIVE_LOADERS as Record<string, () => Promise<unknown>>)["x-broken"] = () => {
|
|
120
|
+
attempts++;
|
|
121
|
+
return attempts === 1 ? Promise.reject(new Error("nope")) : Promise.resolve("ok");
|
|
122
|
+
};
|
|
123
|
+
await expect(loadElement("x-broken")).rejects.toThrow("nope");
|
|
124
|
+
expect(error).toHaveBeenCalledWith("[nucleus-kit] failed to load <x-broken>", expect.any(Error));
|
|
125
|
+
await expect(loadElement("x-broken")).resolves.toBe("ok");
|
|
126
|
+
expect(attempts).toBe(2);
|
|
127
|
+
delete (PROGRESSIVE_LOADERS as Record<string, unknown>)["x-broken"];
|
|
128
|
+
});
|
|
129
|
+
});
|