@cobdfamily/clf-core 7.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.
Files changed (44) hide show
  1. package/README.md +250 -0
  2. package/dist/_variables.scss +973 -0
  3. package/dist/components/cobd-embed.d.ts +4 -0
  4. package/dist/components/cobd-embed.js +163 -0
  5. package/dist/components/cobd-nav.d.ts +1 -0
  6. package/dist/components/cobd-nav.js +383 -0
  7. package/dist/components/cobd-support.d.ts +26 -0
  8. package/dist/components/cobd-support.js +296 -0
  9. package/dist/components/font-scale-toggle.d.ts +9 -0
  10. package/dist/components/font-scale-toggle.js +159 -0
  11. package/dist/components/forms/checkbox.d.ts +1 -0
  12. package/dist/components/forms/checkbox.js +118 -0
  13. package/dist/components/forms/common.d.ts +17 -0
  14. package/dist/components/forms/common.js +137 -0
  15. package/dist/components/forms/index.d.ts +5 -0
  16. package/dist/components/forms/index.js +13 -0
  17. package/dist/components/forms/select.d.ts +1 -0
  18. package/dist/components/forms/select.js +132 -0
  19. package/dist/components/forms/submit.d.ts +1 -0
  20. package/dist/components/forms/submit.js +78 -0
  21. package/dist/components/forms/textarea.d.ts +1 -0
  22. package/dist/components/forms/textarea.js +95 -0
  23. package/dist/components/forms/textfield.d.ts +1 -0
  24. package/dist/components/forms/textfield.js +125 -0
  25. package/dist/components/index.d.ts +7 -0
  26. package/dist/components/index.js +33 -0
  27. package/dist/components/theme-toggle.d.ts +10 -0
  28. package/dist/components/theme-toggle.js +130 -0
  29. package/dist/i18n/chrome.json +94 -0
  30. package/dist/navs/cobd.ca.json +83 -0
  31. package/dist/navs/more-cobd.json +60 -0
  32. package/dist/navs.d.ts +27 -0
  33. package/dist/navs.js +193 -0
  34. package/dist/theming/font-scale-paint.d.ts +0 -0
  35. package/dist/theming/font-scale-paint.js +32 -0
  36. package/dist/theming/init.d.ts +1 -0
  37. package/dist/theming/init.js +19 -0
  38. package/dist/theming/runtime.d.ts +22 -0
  39. package/dist/theming/runtime.js +333 -0
  40. package/dist/tokens.css +972 -0
  41. package/dist/tokens.json +97 -0
  42. package/dist/tokens.scss +95 -0
  43. package/package.json +123 -0
  44. package/src/navs/schema.json +64 -0
@@ -0,0 +1,130 @@
1
+ // <cobd-theme-toggle> — vanilla custom element that cycles
2
+ // light -> dark -> auto and calls setTheme() from the
3
+ // runtime module. Picks up CLF tokens for its own styling.
4
+ import { setTheme, getThemePreference, onThemeChange, } from "../theming/runtime.js";
5
+ const ORDER = [
6
+ "light", "dark", "hc-light", "hc-dark", "auto",
7
+ ];
8
+ const LABEL = {
9
+ "light": "Light theme",
10
+ "dark": "Dark theme",
11
+ "hc-light": "High-contrast light theme",
12
+ "hc-dark": "High-contrast dark theme",
13
+ "auto": "Follow system theme",
14
+ };
15
+ const ICON = {
16
+ "light": "M12 4V2m0 20v-2m8-8h2M2 12h2m13.66 6.66l1.41 1.41"
17
+ + "M4.93 4.93l1.41 1.41m11.32 0l1.41-1.41M4.93 19.07"
18
+ + "l1.41-1.41M12 7a5 5 0 1 0 0 10 5 5 0 0 0 0-10z",
19
+ "dark": "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z",
20
+ "hc-light": "M12 2v20M4 12h16M2 12a10 10 0 0 1 20 0Z",
21
+ "hc-dark": "M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20zm0 0v20",
22
+ "auto": "M12 2a10 10 0 1 0 10 10A10 10 0 0 0 12 2zm0 18V4"
23
+ + "a8 8 0 0 1 0 16z",
24
+ };
25
+ const STYLE = `
26
+ :host {
27
+ display: inline-block;
28
+ --_size: 2.5rem;
29
+ }
30
+ button {
31
+ display: inline-flex;
32
+ align-items: center;
33
+ justify-content: center;
34
+ width: var(--_size);
35
+ height: var(--_size);
36
+ padding: 0;
37
+ border: 1px solid var(--cobd-color-medium, currentColor);
38
+ border-radius: var(--cobd-radius-md, 8px);
39
+ background: transparent;
40
+ color: var(--cobd-color-foreground, currentColor);
41
+ cursor: pointer;
42
+ font: inherit;
43
+ line-height: 0;
44
+ transition:
45
+ background-color var(--cobd-motion-duration-fast, 120ms)
46
+ var(--cobd-motion-easing-standard, ease),
47
+ color var(--cobd-motion-duration-fast, 120ms)
48
+ var(--cobd-motion-easing-standard, ease);
49
+ }
50
+ button:hover {
51
+ background: var(--cobd-color-light, rgba(0,0,0,0.05));
52
+ }
53
+ button:focus-visible {
54
+ outline: 2px solid var(--cobd-color-primary, currentColor);
55
+ outline-offset: 2px;
56
+ }
57
+ @media (prefers-reduced-motion: reduce) {
58
+ button { transition: none; }
59
+ }
60
+ svg {
61
+ width: 1.25rem;
62
+ height: 1.25rem;
63
+ fill: none;
64
+ stroke: currentColor;
65
+ stroke-width: 2;
66
+ stroke-linecap: round;
67
+ stroke-linejoin: round;
68
+ }
69
+ ::slotted(*) {
70
+ width: 1.25rem;
71
+ height: 1.25rem;
72
+ }
73
+ `;
74
+ export class CobdThemeToggle extends HTMLElement {
75
+ constructor() {
76
+ super(...arguments);
77
+ this.cleanup = null;
78
+ }
79
+ connectedCallback() {
80
+ if (!this.shadowRoot) {
81
+ const root = this.attachShadow({ mode: "open" });
82
+ const style = document.createElement("style");
83
+ style.textContent = STYLE;
84
+ this.button = document.createElement("button");
85
+ this.button.type = "button";
86
+ const svgNS = "http://www.w3.org/2000/svg";
87
+ const svg = document.createElementNS(svgNS, "svg");
88
+ svg.setAttribute("viewBox", "0 0 24 24");
89
+ svg.setAttribute("aria-hidden", "true");
90
+ this.path = document.createElementNS(svgNS, "path");
91
+ svg.appendChild(this.path);
92
+ this.slotEl = document.createElement("slot");
93
+ this.button.appendChild(svg);
94
+ this.button.appendChild(this.slotEl);
95
+ root.appendChild(style);
96
+ root.appendChild(this.button);
97
+ this.button.addEventListener("click", () => this.cycle());
98
+ }
99
+ this.render();
100
+ this.cleanup = onThemeChange(() => this.render());
101
+ }
102
+ disconnectedCallback() {
103
+ this.cleanup?.();
104
+ this.cleanup = null;
105
+ }
106
+ cycle() {
107
+ const current = getThemePreference();
108
+ const i = ORDER.indexOf(current);
109
+ const next = ORDER[(i + 1) % ORDER.length];
110
+ setTheme(next);
111
+ }
112
+ render() {
113
+ const pref = getThemePreference();
114
+ this.button.setAttribute("aria-label", LABEL[pref]);
115
+ this.button.title = LABEL[pref];
116
+ this.path.setAttribute("d", ICON[pref]);
117
+ // Hide built-in SVG when caller supplied a slotted icon.
118
+ const slottedIcon = this.querySelector(`[slot="icon-${pref}"]`);
119
+ const svg = this.button.querySelector("svg");
120
+ if (svg) {
121
+ svg.style.display =
122
+ slottedIcon ? "none" : "";
123
+ }
124
+ this.slotEl.name = `icon-${pref}`;
125
+ }
126
+ }
127
+ if (typeof customElements !== "undefined"
128
+ && !customElements.get("cobd-theme-toggle")) {
129
+ customElements.define("cobd-theme-toggle", CobdThemeToggle);
130
+ }
@@ -0,0 +1,94 @@
1
+ {
2
+ "$comment": "CLF chrome i18n strings. Every label here belongs to a CLF-shipped UI surface (menu, skip links, theme toggle, text-size segment, Accessibility Settings accordion, error page, searchbar). They live in clf so the package that owns the chrome also owns its translations. clf-factory's build-i18n reads this file and emits engine-native i18n files (Hugo YAML, KC properties, WP gettext, Moodle PHP) for the consuming theme.",
3
+ "locales": ["en", "fr"],
4
+ "strings": [
5
+ {
6
+ "id": "i18n.menu",
7
+ "hugo": "menu",
8
+ "kc": "menu",
9
+ "moodle": "menu",
10
+ "en": "Menu",
11
+ "fr": "Menu"
12
+ },
13
+ {
14
+ "id": "i18n.done",
15
+ "hugo": "done",
16
+ "kc": "done",
17
+ "moodle": "done",
18
+ "en": "Done",
19
+ "fr": "Terminé"
20
+ },
21
+ {
22
+ "id": "i18n.skip_to_main",
23
+ "hugo": "skip_to_main",
24
+ "kc": "skipToMain",
25
+ "moodle": "skiptomain",
26
+ "en": "Skip to main content",
27
+ "fr": "Passer au contenu principal"
28
+ },
29
+ {
30
+ "id": "i18n.skip_to_search",
31
+ "hugo": "skip_to_search",
32
+ "kc": "skipToSearch",
33
+ "moodle": "skiptosearch",
34
+ "en": "Skip to search",
35
+ "fr": "Passer à la recherche"
36
+ },
37
+ {
38
+ "id": "i18n.primary_nav",
39
+ "hugo": "primary_nav",
40
+ "kc": "primaryNav",
41
+ "moodle": "primary_nav",
42
+ "en": "Primary",
43
+ "fr": "Principal"
44
+ },
45
+ {
46
+ "id": "i18n.search_placeholder",
47
+ "hugo": "search_placeholder",
48
+ "kc": "searchPlaceholder",
49
+ "moodle": "search_placeholder",
50
+ "en": "Search",
51
+ "fr": "Rechercher"
52
+ },
53
+ {
54
+ "id": "i18n.return_home",
55
+ "hugo": "return_home",
56
+ "kc": "returnHome",
57
+ "moodle": "return_home",
58
+ "en": "Return home",
59
+ "fr": "Retour à l'accueil"
60
+ },
61
+ {
62
+ "id": "i18n.theme",
63
+ "hugo": "theme",
64
+ "kc": "theme",
65
+ "moodle": "theme",
66
+ "en": "Theme",
67
+ "fr": "Thème"
68
+ },
69
+ {
70
+ "id": "i18n.text_size",
71
+ "hugo": "text_size",
72
+ "kc": "textSize",
73
+ "moodle": "textsize",
74
+ "en": "Text size",
75
+ "fr": "Taille du texte"
76
+ },
77
+ {
78
+ "id": "i18n.accessibility_settings",
79
+ "hugo": "accessibility_settings",
80
+ "kc": "accessibilitySettings",
81
+ "moodle": "accessibilitysettings",
82
+ "en": "Accessibility Settings",
83
+ "fr": "Paramètres d'accessibilité"
84
+ },
85
+ {
86
+ "id": "i18n.submit",
87
+ "hugo": "submit",
88
+ "kc": "submit",
89
+ "moodle": "submit",
90
+ "en": "Submit",
91
+ "fr": "Soumettre"
92
+ }
93
+ ]
94
+ }
@@ -0,0 +1,83 @@
1
+ {
2
+ "$schema": "https://clf.cobd.ca/schemas/nav.json",
3
+ "slug": "cobd.ca",
4
+ "label": "COBD",
5
+ "label_i18n": {
6
+ "fr": "COBD"
7
+ },
8
+ "items": [
9
+ {
10
+ "id": "home",
11
+ "label": "COBD Home",
12
+ "label_i18n": {
13
+ "fr": "Accueil COBD"
14
+ },
15
+ "href": "/",
16
+ "icon": "home-outline"
17
+ },
18
+ {
19
+ "id": "training",
20
+ "label": "Training",
21
+ "label_i18n": {
22
+ "fr": "Formation"
23
+ },
24
+ "href": "/programs/training/",
25
+ "icon": "school-outline"
26
+ },
27
+ {
28
+ "id": "camps",
29
+ "label": "Camps",
30
+ "label_i18n": {
31
+ "fr": "Camps"
32
+ },
33
+ "href": "https://campbowen.ca/",
34
+ "icon": "bonfire-outline",
35
+ "rel": "external"
36
+ },
37
+ {
38
+ "id": "programs",
39
+ "label": "All Programs",
40
+ "label_i18n": {
41
+ "fr": "Tous les programmes"
42
+ },
43
+ "href": "/programs/",
44
+ "icon": "apps-outline"
45
+ },
46
+ {
47
+ "id": "events",
48
+ "label": "Upcoming Events",
49
+ "label_i18n": {
50
+ "fr": "Évènements à venir"
51
+ },
52
+ "href": "/events/",
53
+ "icon": "calendar-outline"
54
+ },
55
+ {
56
+ "id": "blog",
57
+ "label": "Blog",
58
+ "label_i18n": {
59
+ "fr": "Blogue"
60
+ },
61
+ "href": "/blog/",
62
+ "icon": "newspaper-outline"
63
+ },
64
+ {
65
+ "id": "donate",
66
+ "label": "Donate",
67
+ "label_i18n": {
68
+ "fr": "Faire un don"
69
+ },
70
+ "href": "/donate/",
71
+ "icon": "heart-outline"
72
+ },
73
+ {
74
+ "id": "contact",
75
+ "label": "Contact Us",
76
+ "label_i18n": {
77
+ "fr": "Nous joindre"
78
+ },
79
+ "href": "/contact/",
80
+ "icon": "mail-outline"
81
+ }
82
+ ]
83
+ }
@@ -0,0 +1,60 @@
1
+ {
2
+ "$schema": "https://clf.cobd.ca/schemas/nav.json",
3
+ "slug": "more-cobd",
4
+ "label": "More COBD",
5
+ "label_i18n": {
6
+ "fr": "Famille COBD"
7
+ },
8
+ "items": [
9
+ {
10
+ "id": "about",
11
+ "label": "About COBD",
12
+ "label_i18n": {
13
+ "fr": "À propos de COBD"
14
+ },
15
+ "href": "https://cobd.ca/",
16
+ "icon": "information-circle",
17
+ "rel": "external"
18
+ },
19
+ {
20
+ "id": "programs",
21
+ "label": "More Programs and Services",
22
+ "label_i18n": {
23
+ "fr": "Plus de programmes et services"
24
+ },
25
+ "href": "https://cobd.ca/programs/",
26
+ "icon": "apps",
27
+ "rel": "external"
28
+ },
29
+ {
30
+ "id": "accessibility",
31
+ "label": "Accessibility Statement",
32
+ "label_i18n": {
33
+ "fr": "Déclaration d'accessibilité"
34
+ },
35
+ "href": "https://cobd.ca/accessibility/",
36
+ "icon": "accessibility",
37
+ "rel": "external"
38
+ },
39
+ {
40
+ "id": "privacy",
41
+ "label": "Privacy Policy",
42
+ "label_i18n": {
43
+ "fr": "Politique de confidentialité"
44
+ },
45
+ "href": "https://cobd.ca/privacy/",
46
+ "icon": "shield-checkmark",
47
+ "rel": "external"
48
+ },
49
+ {
50
+ "id": "contact",
51
+ "label": "Contact COBD",
52
+ "label_i18n": {
53
+ "fr": "Contacter COBD"
54
+ },
55
+ "href": "https://cobd.ca/contact/",
56
+ "icon": "mail",
57
+ "rel": "external"
58
+ }
59
+ ]
60
+ }
package/dist/navs.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ // Generated by build-navs.mjs — do not edit.
2
+
3
+ export interface NavItem {
4
+ id: string;
5
+ label: string;
6
+ href?: string;
7
+ rel?: "external";
8
+ icon?: string;
9
+ items?: NavItem[];
10
+ requiresAuth?: boolean;
11
+ description?: string;
12
+ }
13
+
14
+ export interface Nav {
15
+ slug: string;
16
+ label: string;
17
+ items: NavItem[];
18
+ }
19
+
20
+ export function listNavs(): string[];
21
+ // Pass a BCP-47 locale to apply label_i18n overrides;
22
+ // labels without a match for that locale stay as-is.
23
+ export function getNav(slug: string, locale?: string): Nav;
24
+ export function getNavRemote(
25
+ slug: string,
26
+ opts?: { base?: string; locale?: string },
27
+ ): Promise<Nav>;
package/dist/navs.js ADDED
@@ -0,0 +1,193 @@
1
+ // Generated by build-navs.mjs — do not edit.
2
+
3
+ const NAVS = {
4
+ "cobd.ca": {
5
+ "$schema": "https://clf.cobd.ca/schemas/nav.json",
6
+ "slug": "cobd.ca",
7
+ "label": "COBD",
8
+ "label_i18n": {
9
+ "fr": "COBD"
10
+ },
11
+ "items": [
12
+ {
13
+ "id": "home",
14
+ "label": "COBD Home",
15
+ "label_i18n": {
16
+ "fr": "Accueil COBD"
17
+ },
18
+ "href": "/",
19
+ "icon": "home-outline"
20
+ },
21
+ {
22
+ "id": "training",
23
+ "label": "Training",
24
+ "label_i18n": {
25
+ "fr": "Formation"
26
+ },
27
+ "href": "/programs/training/",
28
+ "icon": "school-outline"
29
+ },
30
+ {
31
+ "id": "camps",
32
+ "label": "Camps",
33
+ "label_i18n": {
34
+ "fr": "Camps"
35
+ },
36
+ "href": "https://campbowen.ca/",
37
+ "icon": "bonfire-outline",
38
+ "rel": "external"
39
+ },
40
+ {
41
+ "id": "programs",
42
+ "label": "All Programs",
43
+ "label_i18n": {
44
+ "fr": "Tous les programmes"
45
+ },
46
+ "href": "/programs/",
47
+ "icon": "apps-outline"
48
+ },
49
+ {
50
+ "id": "events",
51
+ "label": "Upcoming Events",
52
+ "label_i18n": {
53
+ "fr": "Évènements à venir"
54
+ },
55
+ "href": "/events/",
56
+ "icon": "calendar-outline"
57
+ },
58
+ {
59
+ "id": "blog",
60
+ "label": "Blog",
61
+ "label_i18n": {
62
+ "fr": "Blogue"
63
+ },
64
+ "href": "/blog/",
65
+ "icon": "newspaper-outline"
66
+ },
67
+ {
68
+ "id": "donate",
69
+ "label": "Donate",
70
+ "label_i18n": {
71
+ "fr": "Faire un don"
72
+ },
73
+ "href": "/donate/",
74
+ "icon": "heart-outline"
75
+ },
76
+ {
77
+ "id": "contact",
78
+ "label": "Contact Us",
79
+ "label_i18n": {
80
+ "fr": "Nous joindre"
81
+ },
82
+ "href": "/contact/",
83
+ "icon": "mail-outline"
84
+ }
85
+ ]
86
+ },
87
+ "more-cobd": {
88
+ "$schema": "https://clf.cobd.ca/schemas/nav.json",
89
+ "slug": "more-cobd",
90
+ "label": "More COBD",
91
+ "label_i18n": {
92
+ "fr": "Famille COBD"
93
+ },
94
+ "items": [
95
+ {
96
+ "id": "about",
97
+ "label": "About COBD",
98
+ "label_i18n": {
99
+ "fr": "À propos de COBD"
100
+ },
101
+ "href": "https://cobd.ca/",
102
+ "icon": "information-circle",
103
+ "rel": "external"
104
+ },
105
+ {
106
+ "id": "programs",
107
+ "label": "More Programs and Services",
108
+ "label_i18n": {
109
+ "fr": "Plus de programmes et services"
110
+ },
111
+ "href": "https://cobd.ca/programs/",
112
+ "icon": "apps",
113
+ "rel": "external"
114
+ },
115
+ {
116
+ "id": "accessibility",
117
+ "label": "Accessibility Statement",
118
+ "label_i18n": {
119
+ "fr": "Déclaration d'accessibilité"
120
+ },
121
+ "href": "https://cobd.ca/accessibility/",
122
+ "icon": "accessibility",
123
+ "rel": "external"
124
+ },
125
+ {
126
+ "id": "privacy",
127
+ "label": "Privacy Policy",
128
+ "label_i18n": {
129
+ "fr": "Politique de confidentialité"
130
+ },
131
+ "href": "https://cobd.ca/privacy/",
132
+ "icon": "shield-checkmark",
133
+ "rel": "external"
134
+ },
135
+ {
136
+ "id": "contact",
137
+ "label": "Contact COBD",
138
+ "label_i18n": {
139
+ "fr": "Contacter COBD"
140
+ },
141
+ "href": "https://cobd.ca/contact/",
142
+ "icon": "mail",
143
+ "rel": "external"
144
+ }
145
+ ]
146
+ }
147
+ };
148
+
149
+ function applyLocale(obj, locale) {
150
+ if (locale && obj.label_i18n && obj.label_i18n[locale]) {
151
+ obj.label = obj.label_i18n[locale];
152
+ }
153
+ if (obj.items) {
154
+ for (const child of obj.items) applyLocale(child, locale);
155
+ }
156
+ delete obj.label_i18n;
157
+ return obj;
158
+ }
159
+
160
+ export function listNavs() {
161
+ return Object.keys(NAVS).sort();
162
+ }
163
+
164
+ // getNav(slug) -> default labels
165
+ // getNav(slug, 'fr') -> French labels (fallback
166
+ // to default when missing)
167
+ export function getNav(slug, locale) {
168
+ const nav = NAVS[slug];
169
+ if (!nav) {
170
+ throw new Error(
171
+ "@cobdfamily/clf-core: unknown nav slug '" + slug + "'. "
172
+ + "Known: " + Object.keys(NAVS).join(", "),
173
+ );
174
+ }
175
+ // Defensive deep-copy, then localize in place.
176
+ return applyLocale(
177
+ JSON.parse(JSON.stringify(nav)), locale);
178
+ }
179
+
180
+ export async function getNavRemote(slug, opts) {
181
+ const base = (opts && opts.base) || "https://nav.cobd.ca";
182
+ const locale = opts && opts.locale;
183
+ const url = base.replace(/\/+$/, "") + "/" + slug + ".json";
184
+ try {
185
+ const res = await fetch(url, { cache: "no-cache" });
186
+ if (!res.ok) throw new Error("http " + res.status);
187
+ const nav = await res.json();
188
+ return applyLocale(nav, locale);
189
+ } catch (err) {
190
+ // Fall back to bundled.
191
+ return getNav(slug, locale);
192
+ }
193
+ }
File without changes
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ /* clf font-scale-paint.ts -- runs synchronously in
3
+ * <head> before first paint so users who picked
4
+ * Small or Large text-size don't see a flash of
5
+ * Medium-sized content while the rest of the
6
+ * page loads.
7
+ *
8
+ * Classic script (NOT a module). The file is
9
+ * compiled with no imports / exports so tsc
10
+ * emits it script-shape; loaded via
11
+ * <script src="..."> (no type="module") in
12
+ * <head>. Module scripts defer execution past
13
+ * first paint, which would cause a flash for
14
+ * users on Large/Small.
15
+ *
16
+ * This is a deliberately minimal duplicate of
17
+ * the runtime's font-scale logic -- the runtime
18
+ * module loads as a module and can't be relied
19
+ * on to execute pre-paint. Keep the SCALES map
20
+ * + cookie name in sync with runtime.ts.
21
+ */
22
+ (() => {
23
+ const SCALES = {
24
+ sm: 0.9, md: 1.0, lg: 1.15,
25
+ };
26
+ const m = /(?:^|; )cobd-font-scale=([^;]+)/
27
+ .exec(document.cookie);
28
+ const v = m && (m[1] in SCALES) ? m[1] : "md";
29
+ const root = document.documentElement;
30
+ root.style.setProperty("--cobd-font-scale", String(SCALES[v]));
31
+ root.setAttribute("data-cobd-font-scale", v);
32
+ })();
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ // Side-effect module: imports the theming runtime
2
+ // and calls initTheming() at load time. Exists so
3
+ // consumers can replace the inline
4
+ //
5
+ // <script type="module">
6
+ // import { initTheming } from ".../runtime.js";
7
+ // initTheming();
8
+ // </script>
9
+ //
10
+ // in their static HTML with an external module
11
+ // script reference. That keeps the compiled output
12
+ // CSP-strict-clean -- no inline blocks (other than
13
+ // JSON-LD, which strict CSP whitelists separately).
14
+ //
15
+ // Loaded as a module script, so the import is
16
+ // resolved + initTheming() fires once when the
17
+ // browser parses the module.
18
+ import { initTheming } from "./runtime.js";
19
+ initTheming();
@@ -0,0 +1,22 @@
1
+ export type ThemePref = "light" | "dark" | "hc-light" | "hc-dark" | "auto";
2
+ export type Resolved = "light" | "dark" | "hc-light" | "hc-dark";
3
+ export interface ThemingOptions {
4
+ storage?: "local" | "cookie";
5
+ cookieDomain?: string;
6
+ cookieName?: string;
7
+ cookieMaxAgeDays?: number;
8
+ }
9
+ type Listener = (t: Resolved) => void;
10
+ export declare function getThemes(): ThemePref[];
11
+ export declare function getThemePreference(): ThemePref;
12
+ export declare function getActiveTheme(): Resolved;
13
+ export declare function setTheme(pref: ThemePref): void;
14
+ export declare function onThemeChange(cb: Listener): () => void;
15
+ export declare function initTheming(opts?: ThemingOptions): void;
16
+ export type FontScalePref = "sm" | "md" | "lg";
17
+ type FontScaleListener = (p: FontScalePref) => void;
18
+ export declare function getFontScales(): FontScalePref[];
19
+ export declare function getFontScalePreference(): FontScalePref;
20
+ export declare function setFontScale(pref: FontScalePref): void;
21
+ export declare function onFontScaleChange(cb: FontScaleListener): () => void;
22
+ export {};