@lgtm-hq/turbo-themes 0.12.16

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 (184) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +231 -0
  3. package/assets/css/adapters/bulma.css +26 -0
  4. package/assets/css/themes/bulma-dark.css +90 -0
  5. package/assets/css/themes/bulma-light.css +90 -0
  6. package/assets/css/themes/catppuccin-frappe.css +58 -0
  7. package/assets/css/themes/catppuccin-latte.css +58 -0
  8. package/assets/css/themes/catppuccin-macchiato.css +58 -0
  9. package/assets/css/themes/catppuccin-mocha.css +58 -0
  10. package/assets/css/themes/dracula.css +90 -0
  11. package/assets/css/themes/github-dark.css +58 -0
  12. package/assets/css/themes/github-light.css +58 -0
  13. package/assets/css/turbo-core.css +92 -0
  14. package/dist/adapters/bootstrap/_utilities.scss +178 -0
  15. package/dist/adapters/bootstrap/_variables.scss +99 -0
  16. package/dist/adapters/tailwind/colors.js +133 -0
  17. package/dist/adapters/tailwind/preset.js +136 -0
  18. package/dist/index.d.ts +12 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +14 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/themes/bulma.d.ts +31 -0
  23. package/dist/themes/bulma.d.ts.map +1 -0
  24. package/dist/themes/bulma.js +160 -0
  25. package/dist/themes/bulma.js.map +1 -0
  26. package/dist/themes/css.d.ts +4 -0
  27. package/dist/themes/css.d.ts.map +1 -0
  28. package/dist/themes/css.js +617 -0
  29. package/dist/themes/css.js.map +1 -0
  30. package/dist/themes/packs/bulma.d.ts +12 -0
  31. package/dist/themes/packs/bulma.d.ts.map +1 -0
  32. package/dist/themes/packs/bulma.js +285 -0
  33. package/dist/themes/packs/bulma.js.map +1 -0
  34. package/dist/themes/packs/catppuccin.synced.d.ts +3 -0
  35. package/dist/themes/packs/catppuccin.synced.d.ts.map +1 -0
  36. package/dist/themes/packs/catppuccin.synced.js +340 -0
  37. package/dist/themes/packs/catppuccin.synced.js.map +1 -0
  38. package/dist/themes/packs/dracula.d.ts +8 -0
  39. package/dist/themes/packs/dracula.d.ts.map +1 -0
  40. package/dist/themes/packs/dracula.js +145 -0
  41. package/dist/themes/packs/dracula.js.map +1 -0
  42. package/dist/themes/packs/github.synced.d.ts +10 -0
  43. package/dist/themes/packs/github.synced.d.ts.map +1 -0
  44. package/dist/themes/packs/github.synced.js +281 -0
  45. package/dist/themes/packs/github.synced.js.map +1 -0
  46. package/dist/themes/registry.d.ts +3 -0
  47. package/dist/themes/registry.d.ts.map +1 -0
  48. package/dist/themes/registry.js +16 -0
  49. package/dist/themes/registry.js.map +1 -0
  50. package/dist/themes/types.d.ts +172 -0
  51. package/dist/themes/types.d.ts.map +1 -0
  52. package/dist/themes/types.js +4 -0
  53. package/dist/themes/types.js.map +1 -0
  54. package/dist/tokens/index.d.ts +8 -0
  55. package/dist/tokens/index.d.ts.map +1 -0
  56. package/dist/tokens/index.js +9 -0
  57. package/dist/tokens/index.js.map +1 -0
  58. package/dist/tokens/style-dictionary/bulma-dark.json +410 -0
  59. package/dist/tokens/style-dictionary/bulma-light.json +410 -0
  60. package/dist/tokens/style-dictionary/catppuccin-frappe.json +264 -0
  61. package/dist/tokens/style-dictionary/catppuccin-latte.json +264 -0
  62. package/dist/tokens/style-dictionary/catppuccin-macchiato.json +264 -0
  63. package/dist/tokens/style-dictionary/catppuccin-mocha.json +264 -0
  64. package/dist/tokens/style-dictionary/dracula.json +409 -0
  65. package/dist/tokens/style-dictionary/github-dark.json +264 -0
  66. package/dist/tokens/style-dictionary/github-light.json +264 -0
  67. package/dist/tokens/style-dictionary/themes.json +2526 -0
  68. package/dist/tokens/style-dictionary/tokens.json +1050 -0
  69. package/dist/tokens/tokens-typed.json +218 -0
  70. package/package.json +180 -0
  71. package/packages/adapters/bulma/dist/bulma-adapter.css +153 -0
  72. package/packages/adapters/bulma/dist/index.d.ts +60 -0
  73. package/packages/adapters/bulma/dist/index.d.ts.map +1 -0
  74. package/packages/adapters/bulma/dist/index.js +343 -0
  75. package/packages/adapters/bulma/dist/index.js.map +1 -0
  76. package/packages/adapters/tailwind/dist/colors.d.ts +32 -0
  77. package/packages/adapters/tailwind/dist/colors.d.ts.map +1 -0
  78. package/packages/adapters/tailwind/dist/colors.js +133 -0
  79. package/packages/adapters/tailwind/dist/colors.js.map +1 -0
  80. package/packages/adapters/tailwind/dist/preset.d.ts +117 -0
  81. package/packages/adapters/tailwind/dist/preset.d.ts.map +1 -0
  82. package/packages/adapters/tailwind/dist/preset.js +136 -0
  83. package/packages/adapters/tailwind/dist/preset.js.map +1 -0
  84. package/packages/adapters/tailwind/dist/tsconfig.tsbuildinfo +1 -0
  85. package/packages/css/dist/base.d.ts +27 -0
  86. package/packages/css/dist/base.d.ts.map +1 -0
  87. package/packages/css/dist/base.js +277 -0
  88. package/packages/css/dist/base.js.map +1 -0
  89. package/packages/css/dist/components/buttons.css +141 -0
  90. package/packages/css/dist/components/cards.css +157 -0
  91. package/packages/css/dist/components/forms.css +109 -0
  92. package/packages/css/dist/components/navigation.css +175 -0
  93. package/packages/css/dist/components/notifications.css +192 -0
  94. package/packages/css/dist/components/progress.css +113 -0
  95. package/packages/css/dist/components/sidebar.css +537 -0
  96. package/packages/css/dist/components/tables.css +157 -0
  97. package/packages/css/dist/components/tabs.css +106 -0
  98. package/packages/css/dist/components/tags.css +121 -0
  99. package/packages/css/dist/generator.d.ts +60 -0
  100. package/packages/css/dist/generator.d.ts.map +1 -0
  101. package/packages/css/dist/generator.js +267 -0
  102. package/packages/css/dist/generator.js.map +1 -0
  103. package/packages/css/dist/index.d.ts +13 -0
  104. package/packages/css/dist/index.d.ts.map +1 -0
  105. package/packages/css/dist/index.js +16 -0
  106. package/packages/css/dist/index.js.map +1 -0
  107. package/packages/css/dist/syntax.d.ts +29 -0
  108. package/packages/css/dist/syntax.d.ts.map +1 -0
  109. package/packages/css/dist/syntax.js +341 -0
  110. package/packages/css/dist/syntax.js.map +1 -0
  111. package/packages/css/dist/themes/bulma-dark.css +86 -0
  112. package/packages/css/dist/themes/bulma-light.css +86 -0
  113. package/packages/css/dist/themes/catppuccin-frappe.css +61 -0
  114. package/packages/css/dist/themes/catppuccin-latte.css +61 -0
  115. package/packages/css/dist/themes/catppuccin-macchiato.css +61 -0
  116. package/packages/css/dist/themes/catppuccin-mocha.css +61 -0
  117. package/packages/css/dist/themes/dracula.css +85 -0
  118. package/packages/css/dist/themes/github-dark.css +61 -0
  119. package/packages/css/dist/themes/github-light.css +61 -0
  120. package/packages/css/dist/turbo-base.css +246 -0
  121. package/packages/css/dist/turbo-components.css +1833 -0
  122. package/packages/css/dist/turbo-core.css +92 -0
  123. package/packages/css/dist/turbo-syntax.css +242 -0
  124. package/packages/css/dist/turbo.css +727 -0
  125. package/packages/theme-selector/dist/accessibility.d.ts +8 -0
  126. package/packages/theme-selector/dist/accessibility.d.ts.map +1 -0
  127. package/packages/theme-selector/dist/accessibility.js +19 -0
  128. package/packages/theme-selector/dist/accessibility.js.map +1 -0
  129. package/packages/theme-selector/dist/apply-theme.d.ts +12 -0
  130. package/packages/theme-selector/dist/apply-theme.d.ts.map +1 -0
  131. package/packages/theme-selector/dist/apply-theme.js +60 -0
  132. package/packages/theme-selector/dist/apply-theme.js.map +1 -0
  133. package/packages/theme-selector/dist/constants.d.ts +28 -0
  134. package/packages/theme-selector/dist/constants.d.ts.map +1 -0
  135. package/packages/theme-selector/dist/constants.js +29 -0
  136. package/packages/theme-selector/dist/constants.js.map +1 -0
  137. package/packages/theme-selector/dist/dropdown/events.d.ts +9 -0
  138. package/packages/theme-selector/dist/dropdown/events.d.ts.map +1 -0
  139. package/packages/theme-selector/dist/dropdown/events.js +120 -0
  140. package/packages/theme-selector/dist/dropdown/events.js.map +1 -0
  141. package/packages/theme-selector/dist/dropdown/helpers.d.ts +12 -0
  142. package/packages/theme-selector/dist/dropdown/helpers.d.ts.map +1 -0
  143. package/packages/theme-selector/dist/dropdown/helpers.js +25 -0
  144. package/packages/theme-selector/dist/dropdown/helpers.js.map +1 -0
  145. package/packages/theme-selector/dist/dropdown/state.d.ts +26 -0
  146. package/packages/theme-selector/dist/dropdown/state.d.ts.map +1 -0
  147. package/packages/theme-selector/dist/dropdown/state.js +50 -0
  148. package/packages/theme-selector/dist/dropdown/state.js.map +1 -0
  149. package/packages/theme-selector/dist/dropdown/ui.d.ts +46 -0
  150. package/packages/theme-selector/dist/dropdown/ui.d.ts.map +1 -0
  151. package/packages/theme-selector/dist/dropdown/ui.js +179 -0
  152. package/packages/theme-selector/dist/dropdown/ui.js.map +1 -0
  153. package/packages/theme-selector/dist/errors.d.ts +59 -0
  154. package/packages/theme-selector/dist/errors.d.ts.map +1 -0
  155. package/packages/theme-selector/dist/errors.js +127 -0
  156. package/packages/theme-selector/dist/errors.js.map +1 -0
  157. package/packages/theme-selector/dist/index.d.ts +25 -0
  158. package/packages/theme-selector/dist/index.d.ts.map +1 -0
  159. package/packages/theme-selector/dist/index.js +114 -0
  160. package/packages/theme-selector/dist/index.js.map +1 -0
  161. package/packages/theme-selector/dist/navbar.d.ts +13 -0
  162. package/packages/theme-selector/dist/navbar.d.ts.map +1 -0
  163. package/packages/theme-selector/dist/navbar.js +75 -0
  164. package/packages/theme-selector/dist/navbar.js.map +1 -0
  165. package/packages/theme-selector/dist/storage.d.ts +32 -0
  166. package/packages/theme-selector/dist/storage.d.ts.map +1 -0
  167. package/packages/theme-selector/dist/storage.js +100 -0
  168. package/packages/theme-selector/dist/storage.js.map +1 -0
  169. package/packages/theme-selector/dist/theme-loader.d.ts +37 -0
  170. package/packages/theme-selector/dist/theme-loader.d.ts.map +1 -0
  171. package/packages/theme-selector/dist/theme-loader.js +142 -0
  172. package/packages/theme-selector/dist/theme-loader.js.map +1 -0
  173. package/packages/theme-selector/dist/theme-mapper.d.ts +25 -0
  174. package/packages/theme-selector/dist/theme-mapper.d.ts.map +1 -0
  175. package/packages/theme-selector/dist/theme-mapper.js +99 -0
  176. package/packages/theme-selector/dist/theme-mapper.js.map +1 -0
  177. package/packages/theme-selector/dist/theme-resolver.d.ts +50 -0
  178. package/packages/theme-selector/dist/theme-resolver.d.ts.map +1 -0
  179. package/packages/theme-selector/dist/theme-resolver.js +84 -0
  180. package/packages/theme-selector/dist/theme-resolver.js.map +1 -0
  181. package/packages/theme-selector/dist/types.d.ts +7 -0
  182. package/packages/theme-selector/dist/types.d.ts.map +1 -0
  183. package/packages/theme-selector/dist/types.js +6 -0
  184. package/packages/theme-selector/dist/types.js.map +1 -0
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Storage utilities for theme persistence
3
+ */
4
+ export { DEFAULT_THEME } from './constants.js';
5
+ /**
6
+ * Validates a theme ID against a set of valid IDs.
7
+ * Returns the theme ID if valid, otherwise returns the default theme.
8
+ */
9
+ export declare function validateThemeId(themeId: string | null, validIds: Set<string>): string;
10
+ /**
11
+ * Migrates legacy storage keys to the current format.
12
+ * Safely handles unavailable localStorage (e.g., private browsing).
13
+ */
14
+ export declare function migrateLegacyStorage(windowObj: Window): void;
15
+ /**
16
+ * Gets the saved theme from localStorage, or returns default.
17
+ * Optionally validates against a set of valid theme IDs.
18
+ * Safely handles unavailable localStorage (e.g., private browsing).
19
+ */
20
+ export declare function getSavedTheme(windowObj: Window, validIds?: Set<string>): string;
21
+ /**
22
+ * Saves a theme to localStorage.
23
+ * Optionally validates the theme ID against a set of valid IDs before saving.
24
+ * Safely handles unavailable localStorage (e.g., private browsing).
25
+ *
26
+ * @param windowObj - Window object with localStorage
27
+ * @param themeId - Theme ID to save
28
+ * @param validIds - Optional set of valid theme IDs for validation
29
+ * @returns true if saved successfully, false otherwise
30
+ */
31
+ export declare function saveTheme(windowObj: Window, themeId: string, validIds?: Set<string>): boolean;
32
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AACA;;GAEG;AAMH,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAyC/C;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAKrF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAQ5D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAM/E;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAM7F"}
@@ -0,0 +1,100 @@
1
+ // SPDX-License-Identifier: MIT
2
+ /**
3
+ * Storage utilities for theme persistence
4
+ */
5
+ import { STORAGE_KEY, LEGACY_STORAGE_KEYS, DEFAULT_THEME } from './constants.js';
6
+ import { ThemeErrors, logThemeError } from './errors.js';
7
+ // Re-export DEFAULT_THEME for convenience
8
+ export { DEFAULT_THEME } from './constants.js';
9
+ /**
10
+ * Safely get an item from localStorage.
11
+ * Returns null if storage is unavailable (e.g., private browsing mode).
12
+ */
13
+ function safeGetItem(windowObj, key) {
14
+ try {
15
+ return windowObj.localStorage.getItem(key);
16
+ }
17
+ catch (error) {
18
+ logThemeError(ThemeErrors.STORAGE_UNAVAILABLE('getItem', error));
19
+ return null;
20
+ }
21
+ }
22
+ /**
23
+ * Safely set an item in localStorage.
24
+ * Returns false if storage is unavailable.
25
+ */
26
+ function safeSetItem(windowObj, key, value) {
27
+ try {
28
+ windowObj.localStorage.setItem(key, value);
29
+ return true;
30
+ }
31
+ catch (error) {
32
+ logThemeError(ThemeErrors.STORAGE_UNAVAILABLE('setItem', error));
33
+ return false;
34
+ }
35
+ }
36
+ /**
37
+ * Safely remove an item from localStorage.
38
+ * Silently fails if storage is unavailable.
39
+ */
40
+ function safeRemoveItem(windowObj, key) {
41
+ try {
42
+ windowObj.localStorage.removeItem(key);
43
+ }
44
+ catch (error) {
45
+ logThemeError(ThemeErrors.STORAGE_UNAVAILABLE('removeItem', error));
46
+ }
47
+ }
48
+ /**
49
+ * Validates a theme ID against a set of valid IDs.
50
+ * Returns the theme ID if valid, otherwise returns the default theme.
51
+ */
52
+ export function validateThemeId(themeId, validIds) {
53
+ if (themeId && validIds.has(themeId)) {
54
+ return themeId;
55
+ }
56
+ return DEFAULT_THEME;
57
+ }
58
+ /**
59
+ * Migrates legacy storage keys to the current format.
60
+ * Safely handles unavailable localStorage (e.g., private browsing).
61
+ */
62
+ export function migrateLegacyStorage(windowObj) {
63
+ for (const legacyKey of LEGACY_STORAGE_KEYS) {
64
+ const legacy = safeGetItem(windowObj, legacyKey);
65
+ if (legacy && !safeGetItem(windowObj, STORAGE_KEY)) {
66
+ safeSetItem(windowObj, STORAGE_KEY, legacy);
67
+ safeRemoveItem(windowObj, legacyKey);
68
+ }
69
+ }
70
+ }
71
+ /**
72
+ * Gets the saved theme from localStorage, or returns default.
73
+ * Optionally validates against a set of valid theme IDs.
74
+ * Safely handles unavailable localStorage (e.g., private browsing).
75
+ */
76
+ export function getSavedTheme(windowObj, validIds) {
77
+ const stored = safeGetItem(windowObj, STORAGE_KEY);
78
+ if (validIds) {
79
+ return validateThemeId(stored, validIds);
80
+ }
81
+ return stored || DEFAULT_THEME;
82
+ }
83
+ /**
84
+ * Saves a theme to localStorage.
85
+ * Optionally validates the theme ID against a set of valid IDs before saving.
86
+ * Safely handles unavailable localStorage (e.g., private browsing).
87
+ *
88
+ * @param windowObj - Window object with localStorage
89
+ * @param themeId - Theme ID to save
90
+ * @param validIds - Optional set of valid theme IDs for validation
91
+ * @returns true if saved successfully, false otherwise
92
+ */
93
+ export function saveTheme(windowObj, themeId, validIds) {
94
+ if (validIds && !validIds.has(themeId)) {
95
+ logThemeError(ThemeErrors.INVALID_THEME_ID(themeId));
96
+ return false;
97
+ }
98
+ return safeSetItem(windowObj, STORAGE_KEY, themeId);
99
+ }
100
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Theme CSS loading utilities
3
+ */
4
+ export interface ThemeInfo {
5
+ id: string;
6
+ cssFile: string;
7
+ icon?: string | undefined;
8
+ }
9
+ /**
10
+ * Resolves an asset path relative to the site's base URL.
11
+ */
12
+ export declare function resolveAssetPath(assetPath: string, baseUrl: string): string;
13
+ /**
14
+ * Gets the base URL from the document's data-baseurl attribute.
15
+ * Validates the URL to prevent injection attacks:
16
+ * - Rejects protocol-relative URLs (//example.com)
17
+ * - Rejects non-HTTPS absolute URLs (except localhost)
18
+ * - Only allows same-origin or relative paths
19
+ */
20
+ export declare function getBaseUrl(doc: Document): string;
21
+ /**
22
+ * Loads a CSS file with a timeout, returning a promise that resolves when loaded.
23
+ */
24
+ export declare function loadCSSWithTimeout(link: HTMLLinkElement, themeId: string, timeoutMs?: number): Promise<void>;
25
+ /**
26
+ * Gets the current theme from document element classes
27
+ */
28
+ export declare function getCurrentThemeFromClasses(element: HTMLElement): string | null;
29
+ /**
30
+ * Applies theme class to document element
31
+ */
32
+ export declare function applyThemeClass(doc: Document, themeId: string): void;
33
+ /**
34
+ * Loads theme CSS file if not already loaded
35
+ */
36
+ export declare function loadThemeCSS(doc: Document, theme: ThemeInfo, baseUrl: string): Promise<void>;
37
+ //# sourceMappingURL=theme-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-loader.d.ts","sourceRoot":"","sources":["../src/theme-loader.ts"],"names":[],"mappings":"AACA;;GAEG;AAKH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAK3E;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAkChD;AAUD;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,MAAM,EACf,SAAS,SAAQ,GAChB,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAQ9E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAWpE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAmCf"}
@@ -0,0 +1,142 @@
1
+ // SPDX-License-Identifier: MIT
2
+ /**
3
+ * Theme CSS loading utilities
4
+ */
5
+ import { DOM_SELECTORS } from './constants.js';
6
+ import { ThemeErrors, logThemeError } from './errors.js';
7
+ /**
8
+ * Resolves an asset path relative to the site's base URL.
9
+ */
10
+ export function resolveAssetPath(assetPath, baseUrl) {
11
+ // Normalize baseUrl - remove trailing slash if present, then add one
12
+ const normalizedBase = baseUrl.replace(/\/$/, '');
13
+ const base = normalizedBase ? `${window.location.origin}${normalizedBase}/` : `${window.location.origin}/`;
14
+ return new URL(assetPath, base).pathname;
15
+ }
16
+ /**
17
+ * Gets the base URL from the document's data-baseurl attribute.
18
+ * Validates the URL to prevent injection attacks:
19
+ * - Rejects protocol-relative URLs (//example.com)
20
+ * - Rejects non-HTTPS absolute URLs (except localhost)
21
+ * - Only allows same-origin or relative paths
22
+ */
23
+ export function getBaseUrl(doc) {
24
+ const baseElement = doc.documentElement;
25
+ const raw = baseElement?.getAttribute('data-baseurl') || '';
26
+ // Empty base URL is valid (use site root)
27
+ if (!raw)
28
+ return '';
29
+ // Reject protocol-relative URLs (security risk)
30
+ if (raw.startsWith('//')) {
31
+ logThemeError(ThemeErrors.PROTOCOL_REJECTED());
32
+ return '';
33
+ }
34
+ // Reject non-HTTPS absolute URLs (except localhost for development)
35
+ if (raw.startsWith('http://') && !raw.startsWith('http://localhost')) {
36
+ logThemeError(ThemeErrors.INSECURE_HTTP_REJECTED());
37
+ return '';
38
+ }
39
+ try {
40
+ // Parse relative to current origin to validate
41
+ const currentOrigin = typeof window !== 'undefined' ? window.location.origin : 'http://localhost';
42
+ const u = new URL(raw, currentOrigin);
43
+ // Only allow same-origin URLs or relative paths
44
+ if (u.origin !== currentOrigin) {
45
+ logThemeError(ThemeErrors.CROSS_ORIGIN_REJECTED(u.origin));
46
+ return '';
47
+ }
48
+ return u.pathname.replace(/\/$/, '');
49
+ }
50
+ catch {
51
+ return '';
52
+ }
53
+ }
54
+ /**
55
+ * Clears onload/onerror handlers from a link element to prevent memory leaks.
56
+ */
57
+ function clearLinkHandlers(link) {
58
+ link.onload = null;
59
+ link.onerror = null;
60
+ }
61
+ /**
62
+ * Loads a CSS file with a timeout, returning a promise that resolves when loaded.
63
+ */
64
+ export function loadCSSWithTimeout(link, themeId, timeoutMs = 10000) {
65
+ return new Promise((resolve, reject) => {
66
+ const timeoutId = setTimeout(() => {
67
+ clearLinkHandlers(link);
68
+ reject(new Error(`Theme ${themeId} load timeout`));
69
+ }, timeoutMs);
70
+ link.onload = () => {
71
+ clearTimeout(timeoutId);
72
+ clearLinkHandlers(link);
73
+ resolve();
74
+ };
75
+ link.onerror = () => {
76
+ clearTimeout(timeoutId);
77
+ clearLinkHandlers(link);
78
+ reject(new Error(`Failed to load theme ${themeId}`));
79
+ };
80
+ });
81
+ }
82
+ /**
83
+ * Gets the current theme from document element classes
84
+ */
85
+ export function getCurrentThemeFromClasses(element) {
86
+ const classList = Array.from(element.classList);
87
+ for (const className of classList) {
88
+ if (className.startsWith('theme-')) {
89
+ return className.substring(6); // Remove 'theme-' prefix
90
+ }
91
+ }
92
+ return null;
93
+ }
94
+ /**
95
+ * Applies theme class to document element
96
+ */
97
+ export function applyThemeClass(doc, themeId) {
98
+ // Remove existing theme classes in a single batch operation
99
+ const themeClasses = Array.from(doc.documentElement.classList).filter((className) => className.startsWith('theme-'));
100
+ if (themeClasses.length > 0) {
101
+ doc.documentElement.classList.remove(...themeClasses);
102
+ }
103
+ // Add the new theme class
104
+ doc.documentElement.classList.add(`theme-${themeId}`);
105
+ }
106
+ /**
107
+ * Loads theme CSS file if not already loaded
108
+ */
109
+ export async function loadThemeCSS(doc, theme, baseUrl) {
110
+ const themeLinkId = `theme-${theme.id}-css`;
111
+ let themeLink = doc.getElementById(themeLinkId);
112
+ if (!themeLink) {
113
+ themeLink = doc.createElement('link');
114
+ themeLink.id = themeLinkId;
115
+ themeLink.rel = 'stylesheet';
116
+ themeLink.type = 'text/css';
117
+ themeLink.setAttribute('data-theme-id', theme.id);
118
+ try {
119
+ themeLink.href = resolveAssetPath(theme.cssFile, baseUrl);
120
+ }
121
+ catch {
122
+ logThemeError(ThemeErrors.INVALID_CSS_PATH(theme.id));
123
+ return;
124
+ }
125
+ doc.head.appendChild(themeLink);
126
+ // Wait for CSS to load (but don't fail if it doesn't load)
127
+ try {
128
+ await loadCSSWithTimeout(themeLink, theme.id);
129
+ }
130
+ catch (error) {
131
+ logThemeError(ThemeErrors.CSS_LOAD_FAILED(theme.id, error));
132
+ }
133
+ }
134
+ // Clean up old theme CSS links (keep current and base themes)
135
+ doc.querySelectorAll(DOM_SELECTORS.THEME_CSS_LINKS).forEach((link) => {
136
+ const linkThemeId = link.id.replace('theme-', '').replace('-css', '');
137
+ if (linkThemeId !== theme.id && linkThemeId !== 'base') {
138
+ link.remove();
139
+ }
140
+ });
141
+ }
142
+ //# sourceMappingURL=theme-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-loader.js","sourceRoot":"","sources":["../src/theme-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Maps core theme flavors to UI-specific format
3
+ */
4
+ import type { ThemeFlavor as CanonicalThemeFlavor } from '@lgtm-hq/turbo-themes-core';
5
+ import type { ThemeFamily } from './types.js';
6
+ export interface ThemeColors {
7
+ bg: string;
8
+ surface: string;
9
+ accent: string;
10
+ text: string;
11
+ }
12
+ export interface ThemeFlavor extends Pick<CanonicalThemeFlavor, 'id' | 'appearance' | 'vendor'> {
13
+ id: string;
14
+ name: string;
15
+ description: string;
16
+ cssFile: string;
17
+ icon?: string | undefined;
18
+ family: ThemeFamily;
19
+ colors: ThemeColors;
20
+ }
21
+ /**
22
+ * Maps a canonical theme flavor to UI-specific format
23
+ */
24
+ export declare function mapFlavorToUI(flavor: CanonicalThemeFlavor): ThemeFlavor;
25
+ //# sourceMappingURL=theme-mapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-mapper.d.ts","sourceRoot":"","sources":["../src/theme-mapper.ts"],"names":[],"mappings":"AACA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,IAAI,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACtF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,oBAAoB,EAAE,IAAI,GAAG,YAAY,GAAG,QAAQ,CAAC;IAC7F,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,WAAW,CAAC;CACrB;AAmGD;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,oBAAoB,GAAG,WAAW,CAavE"}
@@ -0,0 +1,99 @@
1
+ // SPDX-License-Identifier: MIT
2
+ /**
3
+ * Maps core theme flavors to UI-specific format
4
+ */
5
+ // ============================================================================
6
+ // Lookup Tables
7
+ // ============================================================================
8
+ /** Vendor to family mapping */
9
+ const VENDOR_FAMILY_MAP = {
10
+ bulma: 'bulma',
11
+ catppuccin: 'catppuccin',
12
+ github: 'github',
13
+ dracula: 'dracula',
14
+ };
15
+ const DEFAULT_FAMILY = 'bulma';
16
+ const VENDOR_ICON_MAP = {
17
+ bulma: 'assets/img/turbo-themes-logo.png',
18
+ catppuccin: {
19
+ light: 'assets/img/catppuccin-logo-latte.png',
20
+ dark: 'assets/img/catppuccin-logo-macchiato.png',
21
+ },
22
+ github: {
23
+ light: 'assets/img/github-logo-light.png',
24
+ dark: 'assets/img/github-logo-dark.png',
25
+ },
26
+ dracula: 'assets/img/dracula-logo.png',
27
+ };
28
+ /** Predefined flavor descriptions */
29
+ const FLAVOR_DESCRIPTIONS = {
30
+ 'bulma-light': 'Classic Bulma look with a bright, neutral palette.',
31
+ 'bulma-dark': 'Dark Bulma theme tuned for low-light reading.',
32
+ 'catppuccin-latte': 'Light, soft Catppuccin palette for daytime use.',
33
+ 'catppuccin-frappe': 'Balanced dark Catppuccin theme for focused work.',
34
+ 'catppuccin-macchiato': 'Deep, atmospheric Catppuccin variant with rich contrast.',
35
+ 'catppuccin-mocha': 'Cozy, high-contrast Catppuccin theme for late-night sessions.',
36
+ dracula: 'Iconic Dracula dark theme with vibrant accents.',
37
+ 'github-light': 'GitHub-inspired light theme suited for documentation and UI heavy pages.',
38
+ 'github-dark': 'GitHub dark theme optimized for code-heavy views.',
39
+ };
40
+ // ============================================================================
41
+ // Helper Functions
42
+ // ============================================================================
43
+ /**
44
+ * Gets the theme family from vendor name
45
+ */
46
+ function getFamily(vendor) {
47
+ return VENDOR_FAMILY_MAP[vendor] ?? DEFAULT_FAMILY;
48
+ }
49
+ /**
50
+ * Gets icon path for a vendor
51
+ */
52
+ function getIconForVendor(vendor, appearance) {
53
+ const iconConfig = VENDOR_ICON_MAP[vendor];
54
+ if (!iconConfig) {
55
+ return undefined;
56
+ }
57
+ if (typeof iconConfig === 'string') {
58
+ return iconConfig;
59
+ }
60
+ return iconConfig[appearance];
61
+ }
62
+ /**
63
+ * Gets description for a flavor
64
+ */
65
+ function getDescriptionForFlavor(id, label) {
66
+ return FLAVOR_DESCRIPTIONS[id] ?? `${label} theme`;
67
+ }
68
+ /**
69
+ * Extracts preview colors from theme tokens
70
+ */
71
+ function extractPreviewColors(tokens) {
72
+ return {
73
+ bg: tokens.background.base,
74
+ surface: tokens.background.surface,
75
+ accent: tokens.brand.primary,
76
+ text: tokens.text.primary,
77
+ };
78
+ }
79
+ // ============================================================================
80
+ // Public API
81
+ // ============================================================================
82
+ /**
83
+ * Maps a canonical theme flavor to UI-specific format
84
+ */
85
+ export function mapFlavorToUI(flavor) {
86
+ const family = getFamily(flavor.vendor);
87
+ return {
88
+ id: flavor.id,
89
+ name: flavor.label,
90
+ description: getDescriptionForFlavor(flavor.id, flavor.label),
91
+ cssFile: `packages/css/dist/themes/${flavor.id}.css`,
92
+ icon: getIconForVendor(flavor.vendor, flavor.appearance),
93
+ family,
94
+ vendor: flavor.vendor,
95
+ appearance: flavor.appearance,
96
+ colors: extractPreviewColors(flavor.tokens),
97
+ };
98
+ }
99
+ //# sourceMappingURL=theme-mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-mapper.js","sourceRoot":"","sources":["../src/theme-mapper.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B;;GAEG;AAsBH,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAE/E,+BAA+B;AAC/B,MAAM,iBAAiB,GAAgC;IACrD,KAAK,EAAE,OAAO;IACd,UAAU,EAAE,YAAY;IACxB,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;CACnB,CAAC;AAEF,MAAM,cAAc,GAAgB,OAAO,CAAC;AAQ5C,MAAM,eAAe,GAA6C;IAChE,KAAK,EAAE,kCAAkC;IACzC,UAAU,EAAE;QACV,KAAK,EAAE,sCAAsC;QAC7C,IAAI,EAAE,0CAA0C;KACjD;IACD,MAAM,EAAE;QACN,KAAK,EAAE,kCAAkC;QACzC,IAAI,EAAE,iCAAiC;KACxC;IACD,OAAO,EAAE,6BAA6B;CACvC,CAAC;AAEF,qCAAqC;AACrC,MAAM,mBAAmB,GAA2B;IAClD,aAAa,EAAE,oDAAoD;IACnE,YAAY,EAAE,+CAA+C;IAC7D,kBAAkB,EAAE,iDAAiD;IACrE,mBAAmB,EAAE,kDAAkD;IACvE,sBAAsB,EAAE,0DAA0D;IAClF,kBAAkB,EAAE,+DAA+D;IACnF,OAAO,EAAE,iDAAiD;IAC1D,cAAc,EAAE,0EAA0E;IAC1F,aAAa,EAAE,mDAAmD;CACnE,CAAC;AAEF,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;GAEG;AACH,SAAS,SAAS,CAAC,MAAc;IAC/B,OAAO,iBAAiB,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,MAAc,EAAE,UAA4B;IACpE,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAE3C,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QACnC,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,OAAO,UAAU,CAAC,UAAU,CAAC,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAAC,EAAU,EAAE,KAAa;IACxD,OAAO,mBAAmB,CAAC,EAAE,CAAC,IAAI,GAAG,KAAK,QAAQ,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,MAAsC;IAClE,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI;QAC1B,OAAO,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO;QAClC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO;QAC5B,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO;KAC1B,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,aAAa;AACb,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,MAA4B;IACxD,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACxC,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,IAAI,EAAE,MAAM,CAAC,KAAK;QAClB,WAAW,EAAE,uBAAuB,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC;QAC7D,OAAO,EAAE,4BAA4B,MAAM,CAAC,EAAE,MAAM;QACpD,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC;QACxD,MAAM;QACN,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,MAAM,EAAE,oBAAoB,CAAC,MAAM,CAAC,MAAM,CAAC;KAC5C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Theme resolution utilities - centralized theme lookup and validation.
3
+ *
4
+ * Provides cached access to theme data and validation to avoid
5
+ * repeated mapping and set creation across the codebase.
6
+ */
7
+ import { type ThemeFlavor } from './theme-mapper.js';
8
+ /**
9
+ * Gets all themes mapped to UI format.
10
+ * Results are cached for performance.
11
+ */
12
+ export declare function getThemes(): ThemeFlavor[];
13
+ /**
14
+ * Gets a Set of all valid theme IDs.
15
+ * Results are cached for performance.
16
+ */
17
+ export declare function getValidThemeIds(): Set<string>;
18
+ /**
19
+ * Resolves a theme by ID, falling back to default if not found.
20
+ *
21
+ * @param themeId - The theme ID to resolve
22
+ * @returns The matching theme, default theme, or first available theme
23
+ */
24
+ export declare function resolveTheme(themeId: string): ThemeFlavor | undefined;
25
+ /**
26
+ * Validates a theme ID for safety and format correctness.
27
+ *
28
+ * Accepts only alphanumeric characters, hyphens, and underscores.
29
+ * Rejects special characters, unicode, and excessively long IDs.
30
+ *
31
+ * @param id - The value to validate as a theme ID
32
+ * @returns True if the ID is valid, false otherwise
33
+ */
34
+ export declare function isValidThemeId(id: unknown): boolean;
35
+ /**
36
+ * Sanitizes a theme ID by removing unsafe characters.
37
+ *
38
+ * Removes any characters that could cause DOM/CSS/XSS issues.
39
+ * Used as a fallback when displaying potentially untrusted input.
40
+ *
41
+ * @param id - The theme ID to sanitize
42
+ * @returns The sanitized ID containing only safe characters
43
+ */
44
+ export declare function sanitizeThemeId(id: string): string;
45
+ /**
46
+ * Resets the cached themes. Used for testing.
47
+ * @internal
48
+ */
49
+ export declare function _resetThemeCache(): void;
50
+ //# sourceMappingURL=theme-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-resolver.d.ts","sourceRoot":"","sources":["../src/theme-resolver.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAGH,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAOpE;;;GAGG;AACH,wBAAgB,SAAS,IAAI,WAAW,EAAE,CAKzC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,GAAG,CAAC,MAAM,CAAC,CAK9C;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAOrE;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAKnD;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAGvC"}
@@ -0,0 +1,84 @@
1
+ // SPDX-License-Identifier: MIT
2
+ /**
3
+ * Theme resolution utilities - centralized theme lookup and validation.
4
+ *
5
+ * Provides cached access to theme data and validation to avoid
6
+ * repeated mapping and set creation across the codebase.
7
+ */
8
+ import { flavors } from '@lgtm-hq/turbo-themes-core';
9
+ import { mapFlavorToUI } from './theme-mapper.js';
10
+ import { DEFAULT_THEME } from './constants.js';
11
+ // Cache mapped themes and valid IDs
12
+ let mappedThemes = null;
13
+ let validThemeIds = null;
14
+ /**
15
+ * Gets all themes mapped to UI format.
16
+ * Results are cached for performance.
17
+ */
18
+ export function getThemes() {
19
+ if (!mappedThemes) {
20
+ mappedThemes = flavors.map(mapFlavorToUI);
21
+ }
22
+ return mappedThemes || [];
23
+ }
24
+ /**
25
+ * Gets a Set of all valid theme IDs.
26
+ * Results are cached for performance.
27
+ */
28
+ export function getValidThemeIds() {
29
+ if (!validThemeIds) {
30
+ validThemeIds = new Set(flavors.map((f) => f.id));
31
+ }
32
+ return validThemeIds;
33
+ }
34
+ /**
35
+ * Resolves a theme by ID, falling back to default if not found.
36
+ *
37
+ * @param themeId - The theme ID to resolve
38
+ * @returns The matching theme, default theme, or first available theme
39
+ */
40
+ export function resolveTheme(themeId) {
41
+ const themes = getThemes();
42
+ return (themes.find((t) => t.id === themeId) ||
43
+ themes.find((t) => t.id === DEFAULT_THEME) ||
44
+ themes[0]);
45
+ }
46
+ /**
47
+ * Validates a theme ID for safety and format correctness.
48
+ *
49
+ * Accepts only alphanumeric characters, hyphens, and underscores.
50
+ * Rejects special characters, unicode, and excessively long IDs.
51
+ *
52
+ * @param id - The value to validate as a theme ID
53
+ * @returns True if the ID is valid, false otherwise
54
+ */
55
+ export function isValidThemeId(id) {
56
+ if (typeof id !== 'string')
57
+ return false;
58
+ if (id.length === 0)
59
+ return false;
60
+ if (id.length > 100)
61
+ return false;
62
+ return /^[a-zA-Z0-9_-]+$/.test(id);
63
+ }
64
+ /**
65
+ * Sanitizes a theme ID by removing unsafe characters.
66
+ *
67
+ * Removes any characters that could cause DOM/CSS/XSS issues.
68
+ * Used as a fallback when displaying potentially untrusted input.
69
+ *
70
+ * @param id - The theme ID to sanitize
71
+ * @returns The sanitized ID containing only safe characters
72
+ */
73
+ export function sanitizeThemeId(id) {
74
+ return id.replace(/[^a-zA-Z0-9_-]/g, '');
75
+ }
76
+ /**
77
+ * Resets the cached themes. Used for testing.
78
+ * @internal
79
+ */
80
+ export function _resetThemeCache() {
81
+ mappedThemes = null;
82
+ validThemeIds = null;
83
+ }
84
+ //# sourceMappingURL=theme-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-resolver.js","sourceRoot":"","sources":["../src/theme-resolver.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACrD,OAAO,EAAE,aAAa,EAAoB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,oCAAoC;AACpC,IAAI,YAAY,GAAyB,IAAI,CAAC;AAC9C,IAAI,aAAa,GAAuB,IAAI,CAAC;AAE7C;;;GAGG;AACH,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,YAAY,IAAI,EAAE,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,aAAa,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,OAAO,CACL,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC;QACpC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,aAAa,CAAC;QAC1C,MAAM,CAAC,CAAC,CAAC,CACV,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,EAAW;IACxC,IAAI,OAAO,EAAE,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACzC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAClC,IAAI,EAAE,CAAC,MAAM,GAAG,GAAG;QAAE,OAAO,KAAK,CAAC;IAClC,OAAO,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,EAAU;IACxC,OAAO,EAAE,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,YAAY,GAAG,IAAI,CAAC;IACpB,aAAa,GAAG,IAAI,CAAC;AACvB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Public types for theme selector
3
+ */
4
+ export type ThemeMode = 'theme';
5
+ export type ThemeAppearance = 'light' | 'dark';
6
+ export type ThemeFamily = 'bulma' | 'catppuccin' | 'github' | 'dracula';
7
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA;;GAEG;AAEH,MAAM,MAAM,SAAS,GAAG,OAAO,CAAC;AAChC,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,CAAC;AAC/C,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,YAAY,GAAG,QAAQ,GAAG,SAAS,CAAC"}
@@ -0,0 +1,6 @@
1
+ // SPDX-License-Identifier: MIT
2
+ /**
3
+ * Public types for theme selector
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B;;GAEG"}