@kubed.io/cdn 0.0.0-stage โ 0.0.1
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/LICENSE +21 -0
- package/README.md +77 -2
- package/dist/kd/define.d.ts +13 -0
- package/dist/kd/index.d.ts +2 -0
- package/dist/kd/theme.d.ts +23 -0
- package/dist/kd.css +138 -0
- package/dist/kd.js +64 -0
- package/dist/kd.js.map +1 -0
- package/package.json +36 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 kubed.io
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,78 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ๐ฆ cdn
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**A theme layer and web components for Grafana panels.** Shared CSS and ES modules that dashboards load by URL instead of carrying copies: the npm package [`@kubed.io/cdn`](https://www.npmjs.com/package/@kubed.io/cdn), served by [jsDelivr](https://www.jsdelivr.com/). ๐จ
|
|
4
|
+
|
|
5
|
+
[](https://github.com/kubed-io/cdn/actions/workflows/test.yml)
|
|
6
|
+
[](https://github.com/kubed-io/cdn/actions/workflows/quality.yml)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## ๐๏ธ What is here
|
|
11
|
+
|
|
12
|
+
| File | What it is |
|
|
13
|
+
|---|---|
|
|
14
|
+
| `dist/kd.js` | the core: `applyTheme`, `followTheme` and `define` |
|
|
15
|
+
| `dist/kd.css` | text, links, tables, badges, code and cards for `.kd` markup, styled only from the theme |
|
|
16
|
+
|
|
17
|
+
The source is TypeScript under `src/`, one folder per entry. `dist/` is built by CI and exists only in the published package.
|
|
18
|
+
|
|
19
|
+
## ๐ The URL
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
https://cdn.jsdelivr.net/npm/@kubed.io/cdn@X.Y.Z/dist/<file>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
An exact version is cached for a year and can never change underneath a dashboard. **Never a range like `@0` in a dashboard**: it is stale for up to a week and moves without notice.
|
|
26
|
+
|
|
27
|
+
Each dashboard holds the base URL once, in a hidden constant variable named `assets`:
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
- kind: ConstantVariable
|
|
31
|
+
spec:
|
|
32
|
+
name: assets
|
|
33
|
+
query: https://cdn.jsdelivr.net/npm/@kubed.io/cdn@X.Y.Z/dist
|
|
34
|
+
hide: hideVariable
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
A release is then a one-line change per dashboard. Move every dashboard together: panels share one page, and the first version of a custom element loaded owns its tag until a full reload.
|
|
38
|
+
|
|
39
|
+
## ๐จ The theme
|
|
40
|
+
|
|
41
|
+
`applyTheme` sets these on the panel root, plus `data-theme="dark"` or `"light"`. The names are the public API and follow semver.
|
|
42
|
+
|
|
43
|
+
| Property | From `GrafanaTheme2` |
|
|
44
|
+
|---|---|
|
|
45
|
+
| `--kd-bg`, `--kd-bg-2`, `--kd-canvas` | `colors.background.primary`, `.secondary`, `.canvas` |
|
|
46
|
+
| `--kd-text`, `--kd-text-2`, `--kd-text-dim` | `colors.text.primary`, `.secondary`, `.disabled` |
|
|
47
|
+
| `--kd-link` | `colors.text.link` |
|
|
48
|
+
| `--kd-border`, `--kd-border-strong` | `colors.border.weak`, `.medium` |
|
|
49
|
+
| `--kd-primary`, `--kd-success`, `--kd-warning`, `--kd-error`, `--kd-info` | `colors.<name>.main` |
|
|
50
|
+
| `--kd-font`, `--kd-font-mono` | `typography.fontFamily`, `.fontFamilyMonospace` |
|
|
51
|
+
| `--kd-radius` | `shape.radius.default` |
|
|
52
|
+
| `--kd-space` | `spacing(1)` |
|
|
53
|
+
|
|
54
|
+
**Everything is scoped under `.kd`.** Business Text loads stylesheets into the whole page, so no rule here touches an element, `*` or `:root` outside a `.kd` root.
|
|
55
|
+
|
|
56
|
+
## ๐งฉ In a Business Text panel
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
externalStyles: ["${assets}/kd.css"]
|
|
60
|
+
content: <div class="kd"> ... </div>
|
|
61
|
+
afterRender: import(context.grafana.replaceVariables("${assets}") + "/kd.js")
|
|
62
|
+
.then(m => m.applyTheme(context.element, context.grafana.theme))
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`afterRender` runs on every re-render and `applyTheme` is idempotent, so switching Grafana's theme restyles the panel. Code with no `context.grafana.theme` calls `followTheme(element)` instead: it reads the live theme from Grafana's runtime and follows a theme switch.
|
|
66
|
+
|
|
67
|
+
Every panel imports what it needs itself. The browser loads a URL once per page however many panels import it.
|
|
68
|
+
|
|
69
|
+
## ๐ ๏ธ Develop
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npm ci
|
|
73
|
+
npm run typecheck
|
|
74
|
+
npm test
|
|
75
|
+
npm run build
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Unreleased code is tried in Grafana by publishing a pre-release (a `pre*` bump in the ๐งฌ Publish Version workflow), which goes to npm under the `next` tag.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** This build's package version. */
|
|
2
|
+
export declare const VERSION: string;
|
|
3
|
+
/**
|
|
4
|
+
* Registers a custom element unless the name is taken, and says so when it is.
|
|
5
|
+
*
|
|
6
|
+
* Every panel on a page shares one registry, and a definition outlives SPA
|
|
7
|
+
* navigation, so the first version of a tag loaded owns it until a full page
|
|
8
|
+
* reload. A second define would throw; this keeps the first and warns when the
|
|
9
|
+
* two builds differ.
|
|
10
|
+
*
|
|
11
|
+
* @returns whether this call defined the element
|
|
12
|
+
*/
|
|
13
|
+
export declare function define(name: string, element: CustomElementConstructor, registry?: CustomElementRegistry): boolean;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** The parts of a GrafanaTheme2 the theme layer reads. Any of them may be missing. */
|
|
2
|
+
export interface ThemeLike {
|
|
3
|
+
isDark?: boolean;
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Sets the `--kd-*` properties and `data-theme` ("dark" or "light") on
|
|
8
|
+
* `element` from a GrafanaTheme2. Idempotent, so it is safe in Business Text's
|
|
9
|
+
* `afterRender`, which runs on every re-render.
|
|
10
|
+
*
|
|
11
|
+
* @param element the panel's own root, never `:root`
|
|
12
|
+
* @param theme a GrafanaTheme2, e.g. `context.grafana.theme`
|
|
13
|
+
*/
|
|
14
|
+
export declare function applyTheme(element: HTMLElement | null | undefined, theme: ThemeLike | null | undefined): void;
|
|
15
|
+
/**
|
|
16
|
+
* Themes `element` from Grafana's live theme without being handed one, and
|
|
17
|
+
* keeps it themed across a live theme switch. For code that has no
|
|
18
|
+
* `context.grafana.theme`. The `<body>` theme class is never used: it goes
|
|
19
|
+
* stale on a live switch.
|
|
20
|
+
*
|
|
21
|
+
* @returns a function that stops following; a no-op outside Grafana
|
|
22
|
+
*/
|
|
23
|
+
export declare function followTheme(element: HTMLElement): Promise<() => void>;
|
package/dist/kd.css
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Base styles for markup inside a `.kd` root, built only on the --kd-* properties
|
|
3
|
+
* the theme layer sets. Business Text loads stylesheets into the whole page, so
|
|
4
|
+
* every rule is scoped under .kd.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
.kd {
|
|
8
|
+
color: var(--kd-text);
|
|
9
|
+
font-family: var(--kd-font);
|
|
10
|
+
line-height: 1.5;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.kd a {
|
|
14
|
+
color: var(--kd-link);
|
|
15
|
+
text-decoration: none;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.kd a:hover {
|
|
19
|
+
text-decoration: underline;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.kd .dim {
|
|
23
|
+
color: var(--kd-text-dim);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.kd .muted {
|
|
27
|
+
color: var(--kd-text-2);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* Tables */
|
|
31
|
+
|
|
32
|
+
.kd table {
|
|
33
|
+
width: 100%;
|
|
34
|
+
border-collapse: collapse;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.kd th,
|
|
38
|
+
.kd td {
|
|
39
|
+
padding: calc(var(--kd-space) / 2) var(--kd-space);
|
|
40
|
+
border-bottom: 1px solid var(--kd-border);
|
|
41
|
+
text-align: left;
|
|
42
|
+
vertical-align: top;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.kd th {
|
|
46
|
+
color: var(--kd-text-2);
|
|
47
|
+
font-weight: 500;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.kd tbody tr:hover {
|
|
51
|
+
background: var(--kd-bg-2);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Badges */
|
|
55
|
+
|
|
56
|
+
.kd .badge {
|
|
57
|
+
display: inline-block;
|
|
58
|
+
padding: 0 calc(var(--kd-space) * 0.75);
|
|
59
|
+
border: 1px solid var(--kd-border-strong);
|
|
60
|
+
border-radius: var(--kd-radius);
|
|
61
|
+
color: var(--kd-text-2);
|
|
62
|
+
font-size: 0.85em;
|
|
63
|
+
line-height: 1.6;
|
|
64
|
+
white-space: nowrap;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.kd .badge.primary {
|
|
68
|
+
border-color: var(--kd-primary);
|
|
69
|
+
color: var(--kd-primary);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.kd .badge.success {
|
|
73
|
+
border-color: var(--kd-success);
|
|
74
|
+
color: var(--kd-success);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.kd .badge.warning {
|
|
78
|
+
border-color: var(--kd-warning);
|
|
79
|
+
color: var(--kd-warning);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.kd .badge.error {
|
|
83
|
+
border-color: var(--kd-error);
|
|
84
|
+
color: var(--kd-error);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.kd .badge.info {
|
|
88
|
+
border-color: var(--kd-info);
|
|
89
|
+
color: var(--kd-info);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* Code */
|
|
93
|
+
|
|
94
|
+
.kd code,
|
|
95
|
+
.kd pre {
|
|
96
|
+
font-family: var(--kd-font-mono);
|
|
97
|
+
font-size: 0.9em;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.kd code {
|
|
101
|
+
padding: 0 calc(var(--kd-space) / 2);
|
|
102
|
+
border-radius: var(--kd-radius);
|
|
103
|
+
background: var(--kd-bg-2);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.kd pre {
|
|
107
|
+
padding: var(--kd-space);
|
|
108
|
+
border: 1px solid var(--kd-border);
|
|
109
|
+
border-radius: var(--kd-radius);
|
|
110
|
+
background: var(--kd-canvas);
|
|
111
|
+
overflow: auto;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.kd pre code {
|
|
115
|
+
padding: 0;
|
|
116
|
+
background: transparent;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/* Cards */
|
|
120
|
+
|
|
121
|
+
.kd .card {
|
|
122
|
+
padding: calc(var(--kd-space) * 2);
|
|
123
|
+
border: 1px solid var(--kd-border);
|
|
124
|
+
border-radius: var(--kd-radius);
|
|
125
|
+
background: var(--kd-bg-2);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.kd .card + .card {
|
|
129
|
+
margin-top: var(--kd-space);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.kd .card > :first-child {
|
|
133
|
+
margin-top: 0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.kd .card > :last-child {
|
|
137
|
+
margin-bottom: 0;
|
|
138
|
+
}
|
package/dist/kd.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
//#region src/kd/theme.ts
|
|
2
|
+
var e = [
|
|
3
|
+
["--kd-bg", (e) => e.colors.background.primary],
|
|
4
|
+
["--kd-bg-2", (e) => e.colors.background.secondary],
|
|
5
|
+
["--kd-canvas", (e) => e.colors.background.canvas],
|
|
6
|
+
["--kd-text", (e) => e.colors.text.primary],
|
|
7
|
+
["--kd-text-2", (e) => e.colors.text.secondary],
|
|
8
|
+
["--kd-text-dim", (e) => e.colors.text.disabled],
|
|
9
|
+
["--kd-link", (e) => e.colors.text.link],
|
|
10
|
+
["--kd-border", (e) => e.colors.border.weak],
|
|
11
|
+
["--kd-border-strong", (e) => e.colors.border.medium],
|
|
12
|
+
["--kd-primary", (e) => e.colors.primary.main],
|
|
13
|
+
["--kd-success", (e) => e.colors.success.main],
|
|
14
|
+
["--kd-warning", (e) => e.colors.warning.main],
|
|
15
|
+
["--kd-error", (e) => e.colors.error.main],
|
|
16
|
+
["--kd-info", (e) => e.colors.info.main],
|
|
17
|
+
["--kd-font", (e) => e.typography.fontFamily],
|
|
18
|
+
["--kd-font-mono", (e) => e.typography.fontFamilyMonospace],
|
|
19
|
+
["--kd-radius", (e) => e.shape.radius.default],
|
|
20
|
+
["--kd-space", (e) => e.spacing(1)]
|
|
21
|
+
];
|
|
22
|
+
function t(e, t) {
|
|
23
|
+
try {
|
|
24
|
+
let n = t(e);
|
|
25
|
+
return typeof n == "string" || typeof n == "number" ? String(n) : void 0;
|
|
26
|
+
} catch {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function n(n, r) {
|
|
31
|
+
if (n && r) {
|
|
32
|
+
for (let [i, a] of e) {
|
|
33
|
+
let e = t(r, a);
|
|
34
|
+
e !== void 0 && n.style.setProperty(i, e);
|
|
35
|
+
}
|
|
36
|
+
typeof r.isDark == "boolean" && n.setAttribute("data-theme", r.isDark ? "dark" : "light");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
var r = /* @__PURE__ */ new WeakMap();
|
|
40
|
+
function i(e) {
|
|
41
|
+
let t = r.get(e);
|
|
42
|
+
return t || (t = Promise.resolve().then(() => e.System?.import?.("@grafana/runtime")).then((e) => {
|
|
43
|
+
let t = e;
|
|
44
|
+
return t?.config?.theme2 && t.getAppEvents && t.ThemeChangedEvent ? t : null;
|
|
45
|
+
}).catch(() => null), r.set(e, t)), t;
|
|
46
|
+
}
|
|
47
|
+
async function a(e) {
|
|
48
|
+
let t = e.ownerDocument?.defaultView, r = t ? await i(t) : null;
|
|
49
|
+
if (!r) return () => {};
|
|
50
|
+
n(e, r.config.theme2);
|
|
51
|
+
let a = r.getAppEvents().subscribe(r.ThemeChangedEvent, (t) => n(e, t?.payload ?? r.config.theme2));
|
|
52
|
+
return () => a.unsubscribe();
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/kd/define.ts
|
|
56
|
+
var o = "0.0.1";
|
|
57
|
+
function s(e, t, n = customElements) {
|
|
58
|
+
let r = n.get(e);
|
|
59
|
+
return r ? (r !== t && r.kdVersion !== "0.0.1" && console.warn(`@kubed.io/cdn ${o}: <${e}> is already defined by ${r.kdVersion ? `@kubed.io/cdn ${r.kdVersion}` : "another script"}; that definition stays until the page is reloaded.`), !1) : (Object.defineProperty(t, "kdVersion", { value: o }), n.define(e, t), !0);
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
export { o as VERSION, n as applyTheme, s as define, a as followTheme };
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=kd.js.map
|
package/dist/kd.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kd.js","names":["PROPERTIES","t","read","value","get","theme","applyTheme","element","name","runtimes","runtime","found","win","rt","r","followTheme","subscription","event","VERSION","define","existing","registry"],"sources":["../src/kd/theme.ts","../src/kd/define.ts"],"sourcesContent":["// The theme layer: Grafana's live theme as `--kd-*` custom properties.\n// The property names are this package's public API and follow semver.\n\n/** The parts of a GrafanaTheme2 the theme layer reads. Any of them may be missing. */\nexport interface ThemeLike {\n isDark?: boolean;\n [key: string]: unknown;\n}\n\ntype Read = (theme: any) => unknown;\n\nconst PROPERTIES: [string, Read][] = [\n ['--kd-bg', (t) => t.colors.background.primary],\n ['--kd-bg-2', (t) => t.colors.background.secondary],\n ['--kd-canvas', (t) => t.colors.background.canvas],\n ['--kd-text', (t) => t.colors.text.primary],\n ['--kd-text-2', (t) => t.colors.text.secondary],\n ['--kd-text-dim', (t) => t.colors.text.disabled],\n ['--kd-link', (t) => t.colors.text.link],\n ['--kd-border', (t) => t.colors.border.weak],\n ['--kd-border-strong', (t) => t.colors.border.medium],\n ['--kd-primary', (t) => t.colors.primary.main],\n ['--kd-success', (t) => t.colors.success.main],\n ['--kd-warning', (t) => t.colors.warning.main],\n ['--kd-error', (t) => t.colors.error.main],\n ['--kd-info', (t) => t.colors.info.main],\n ['--kd-font', (t) => t.typography.fontFamily],\n ['--kd-font-mono', (t) => t.typography.fontFamilyMonospace],\n ['--kd-radius', (t) => t.shape.radius.default],\n ['--kd-space', (t) => t.spacing(1)],\n];\n\n// A theme from an older or newer Grafana may lack a field; that property is\n// skipped so the rest still apply, and CSS falls back to its own default.\nfunction read(theme: ThemeLike, get: Read): string | undefined {\n try {\n const value = get(theme);\n return typeof value === 'string' || typeof value === 'number' ? String(value) : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Sets the `--kd-*` properties and `data-theme` (\"dark\" or \"light\") on\n * `element` from a GrafanaTheme2. Idempotent, so it is safe in Business Text's\n * `afterRender`, which runs on every re-render.\n *\n * @param element the panel's own root, never `:root`\n * @param theme a GrafanaTheme2, e.g. `context.grafana.theme`\n */\nexport function applyTheme(element: HTMLElement | null | undefined, theme: ThemeLike | null | undefined): void {\n if (!element || !theme) return;\n for (const [name, get] of PROPERTIES) {\n const value = read(theme, get);\n if (value !== undefined) element.style.setProperty(name, value);\n }\n if (typeof theme.isDark === 'boolean') {\n element.setAttribute('data-theme', theme.isDark ? 'dark' : 'light');\n }\n}\n\n/** The parts of `@grafana/runtime` that following the theme needs. */\ninterface Runtime {\n config: { theme2: ThemeLike };\n getAppEvents(): {\n subscribe(event: unknown, handler: (event: { payload?: ThemeLike }) => void): { unsubscribe(): void };\n };\n ThemeChangedEvent: unknown;\n}\n\ntype GrafanaWindow = Window & { System?: { import?(id: string): Promise<unknown> } };\n\nconst runtimes = new WeakMap<Window, Promise<Runtime | null>>();\n\n// Grafana loads plugins through SystemJS and shares its own packages there, so\n// the page's live config and event bus are one import away. Outside Grafana\n// there is no System and this resolves to null.\nfunction runtime(win: GrafanaWindow): Promise<Runtime | null> {\n let found = runtimes.get(win);\n if (!found) {\n found = Promise.resolve()\n .then(() => win.System?.import?.('@grafana/runtime'))\n .then((r) => {\n const rt = r as Partial<Runtime> | undefined;\n return rt?.config?.theme2 && rt.getAppEvents && rt.ThemeChangedEvent ? (rt as Runtime) : null;\n })\n .catch(() => null);\n runtimes.set(win, found);\n }\n return found;\n}\n\n/**\n * Themes `element` from Grafana's live theme without being handed one, and\n * keeps it themed across a live theme switch. For code that has no\n * `context.grafana.theme`. The `<body>` theme class is never used: it goes\n * stale on a live switch.\n *\n * @returns a function that stops following; a no-op outside Grafana\n */\nexport async function followTheme(element: HTMLElement): Promise<() => void> {\n const win = element.ownerDocument?.defaultView as GrafanaWindow | null;\n const rt = win ? await runtime(win) : null;\n if (!rt) return () => {};\n applyTheme(element, rt.config.theme2);\n const subscription = rt\n .getAppEvents()\n .subscribe(rt.ThemeChangedEvent, (event) => applyTheme(element, event?.payload ?? rt.config.theme2));\n return () => subscription.unsubscribe();\n}\n","/** This build's package version. */\nexport const VERSION: string = __KD_VERSION__;\n\n/**\n * Registers a custom element unless the name is taken, and says so when it is.\n *\n * Every panel on a page shares one registry, and a definition outlives SPA\n * navigation, so the first version of a tag loaded owns it until a full page\n * reload. A second define would throw; this keeps the first and warns when the\n * two builds differ.\n *\n * @returns whether this call defined the element\n */\nexport function define(\n name: string,\n element: CustomElementConstructor,\n registry: CustomElementRegistry = customElements,\n): boolean {\n const existing = registry.get(name) as (CustomElementConstructor & { kdVersion?: string }) | undefined;\n if (existing) {\n if (existing !== element && existing.kdVersion !== VERSION) {\n console.warn(\n `@kubed.io/cdn ${VERSION}: <${name}> is already defined by ${existing.kdVersion ? `@kubed.io/cdn ${existing.kdVersion}` : 'another script'}; ` +\n 'that definition stays until the page is reloaded.',\n );\n }\n return false;\n }\n Object.defineProperty(element, 'kdVersion', { value: VERSION });\n registry.define(name, element);\n return true;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubed.io/cdn",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "A theme layer and web components for Grafana panels, loaded by URL from jsDelivr.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/kubed-io/cdn.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/kubed-io/cdn#readme",
|
|
12
|
+
"bugs": "https://github.com/kubed-io/cdn/issues",
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"exports": {
|
|
17
|
+
"./kd.js": {
|
|
18
|
+
"types": "./dist/kd/index.d.ts",
|
|
19
|
+
"default": "./dist/kd.js"
|
|
20
|
+
},
|
|
21
|
+
"./kd.css": "./dist/kd.css"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "vite build && tsc -p tsconfig.build.json",
|
|
25
|
+
"typecheck": "tsc --noEmit",
|
|
26
|
+
"test": "vitest run",
|
|
27
|
+
"prepublishOnly": "npm run typecheck && npm test && npm run build"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"happy-dom": "^20.14.5",
|
|
34
|
+
"typescript": "^7.0.2",
|
|
35
|
+
"vite": "^8.3.3",
|
|
36
|
+
"vitest": "^5.0.3"
|
|
37
|
+
}
|
|
38
|
+
}
|