@screenly/edge-apps 0.0.1 → 0.0.3

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 (143) hide show
  1. package/dist/assets/fonts/Inter-Medium.woff2 +0 -0
  2. package/dist/assets/fonts/Inter-Regular.woff2 +0 -0
  3. package/dist/assets/fonts/Inter-SemiBold.woff2 +0 -0
  4. package/dist/assets/images/icons/chancesleet.svg +4 -0
  5. package/dist/assets/images/icons/clear-night.svg +5 -0
  6. package/dist/assets/images/icons/clear.svg +11 -0
  7. package/dist/assets/images/icons/cloudy.svg +4 -0
  8. package/dist/assets/images/icons/drizzle.svg +5 -0
  9. package/dist/assets/images/icons/fewdrops.svg +4 -0
  10. package/dist/assets/images/icons/fog.svg +6 -0
  11. package/dist/assets/images/icons/haze.svg +6 -0
  12. package/dist/assets/images/icons/mostly-cloudy-night.svg +7 -0
  13. package/dist/assets/images/icons/mostly-cloudy.svg +13 -0
  14. package/dist/assets/images/icons/partially-cloudy-night.svg +6 -0
  15. package/dist/assets/images/icons/partially-cloudy.svg +12 -0
  16. package/dist/assets/images/icons/partlysunny.svg +6 -0
  17. package/dist/assets/images/icons/rain-night.svg +8 -0
  18. package/dist/assets/images/icons/rainy.svg +6 -0
  19. package/dist/assets/images/icons/sleet-night.svg +14 -0
  20. package/dist/assets/images/icons/sleet.svg +4 -0
  21. package/dist/assets/images/icons/snow.svg +19 -0
  22. package/dist/assets/images/icons/thunderstorm-night.svg +9 -0
  23. package/dist/assets/images/icons/thunderstorm.svg +7 -0
  24. package/dist/assets/images/icons/windy.svg +6 -0
  25. package/dist/assets/images/screenly.svg +10 -0
  26. package/dist/components/app-header/app-header.d.ts +43 -0
  27. package/dist/components/app-header/app-header.d.ts.map +1 -0
  28. package/dist/components/app-header/app-header.js +244 -0
  29. package/dist/components/auto-scaler/auto-scaler.d.ts +65 -0
  30. package/dist/components/auto-scaler/auto-scaler.d.ts.map +1 -0
  31. package/dist/components/auto-scaler/auto-scaler.js +304 -0
  32. package/dist/components/brand-logo/brand-logo.d.ts +42 -0
  33. package/dist/components/brand-logo/brand-logo.d.ts.map +1 -0
  34. package/dist/components/brand-logo/brand-logo.js +209 -0
  35. package/dist/components/calendar-views/calendar-view-utils.d.ts +5 -0
  36. package/dist/components/calendar-views/calendar-view-utils.d.ts.map +1 -0
  37. package/dist/components/calendar-views/calendar-view-utils.js +73 -0
  38. package/dist/components/calendar-views/calendar-window-utils.d.ts +9 -0
  39. package/dist/components/calendar-views/calendar-window-utils.d.ts.map +1 -0
  40. package/dist/components/calendar-views/calendar-window-utils.js +57 -0
  41. package/dist/components/calendar-views/daily-calendar-view/daily-calendar-view-styles.d.ts +2 -0
  42. package/dist/components/calendar-views/daily-calendar-view/daily-calendar-view-styles.d.ts.map +1 -0
  43. package/dist/components/calendar-views/daily-calendar-view/daily-calendar-view-styles.js +175 -0
  44. package/dist/components/calendar-views/daily-calendar-view/daily-calendar-view.d.ts +21 -0
  45. package/dist/components/calendar-views/daily-calendar-view/daily-calendar-view.d.ts.map +1 -0
  46. package/dist/components/calendar-views/daily-calendar-view/daily-calendar-view.js +130 -0
  47. package/dist/components/calendar-views/daily-calendar-view/index.d.ts +2 -0
  48. package/dist/components/calendar-views/daily-calendar-view/index.d.ts.map +1 -0
  49. package/dist/components/calendar-views/daily-calendar-view/index.js +1 -0
  50. package/dist/components/calendar-views/event-layout.d.ts +18 -0
  51. package/dist/components/calendar-views/event-layout.d.ts.map +1 -0
  52. package/dist/components/calendar-views/event-layout.js +139 -0
  53. package/dist/components/calendar-views/schedule-calendar-view/index.d.ts +2 -0
  54. package/dist/components/calendar-views/schedule-calendar-view/index.d.ts.map +1 -0
  55. package/dist/components/calendar-views/schedule-calendar-view/index.js +1 -0
  56. package/dist/components/calendar-views/schedule-calendar-view/schedule-calendar-view-styles.d.ts +2 -0
  57. package/dist/components/calendar-views/schedule-calendar-view/schedule-calendar-view-styles.d.ts.map +1 -0
  58. package/dist/components/calendar-views/schedule-calendar-view/schedule-calendar-view-styles.js +118 -0
  59. package/dist/components/calendar-views/schedule-calendar-view/schedule-calendar-view.d.ts +23 -0
  60. package/dist/components/calendar-views/schedule-calendar-view/schedule-calendar-view.d.ts.map +1 -0
  61. package/dist/components/calendar-views/schedule-calendar-view/schedule-calendar-view.js +167 -0
  62. package/dist/components/calendar-views/weekly-calendar-view/index.d.ts +3 -0
  63. package/dist/components/calendar-views/weekly-calendar-view/index.d.ts.map +1 -0
  64. package/dist/components/calendar-views/weekly-calendar-view/index.js +1 -0
  65. package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view-styles.d.ts +2 -0
  66. package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view-styles.d.ts.map +1 -0
  67. package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view-styles.js +234 -0
  68. package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view-utils.d.ts +16 -0
  69. package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view-utils.d.ts.map +1 -0
  70. package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view-utils.js +83 -0
  71. package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view.d.ts +26 -0
  72. package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view.d.ts.map +1 -0
  73. package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view.js +220 -0
  74. package/dist/components/dev-tools/dev-tools.d.ts +48 -0
  75. package/dist/components/dev-tools/dev-tools.d.ts.map +1 -0
  76. package/dist/components/dev-tools/dev-tools.js +186 -0
  77. package/dist/components/index.d.ts +14 -0
  78. package/dist/components/index.d.ts.map +1 -0
  79. package/dist/components/index.js +13 -0
  80. package/dist/components/register.d.ts +12 -0
  81. package/dist/components/register.d.ts.map +1 -0
  82. package/dist/components/register.js +11 -0
  83. package/dist/core/index.d.ts +30 -0
  84. package/dist/core/index.d.ts.map +1 -0
  85. package/dist/core/index.js +77 -0
  86. package/dist/index.d.ts +5 -0
  87. package/dist/index.d.ts.map +1 -0
  88. package/dist/index.js +8 -0
  89. package/dist/test/index.d.ts +3 -0
  90. package/dist/test/index.d.ts.map +1 -0
  91. package/dist/test/index.js +2 -0
  92. package/dist/test/mock.d.ts +23 -0
  93. package/dist/test/mock.d.ts.map +1 -0
  94. package/dist/test/mock.js +49 -0
  95. package/dist/test/screenshots.d.ts +120 -0
  96. package/dist/test/screenshots.d.ts.map +1 -0
  97. package/dist/test/screenshots.js +127 -0
  98. package/dist/test/setup.d.ts +2 -0
  99. package/dist/test/setup.d.ts.map +1 -0
  100. package/dist/test/setup.js +13 -0
  101. package/dist/types/index.d.ts +138 -0
  102. package/dist/types/index.d.ts.map +1 -0
  103. package/dist/types/index.js +15 -0
  104. package/dist/utils/calendar.d.ts +28 -0
  105. package/dist/utils/calendar.d.ts.map +1 -0
  106. package/dist/utils/calendar.js +77 -0
  107. package/dist/utils/error-handling.d.ts +6 -0
  108. package/dist/utils/error-handling.d.ts.map +1 -0
  109. package/dist/utils/error-handling.js +16 -0
  110. package/dist/utils/html.d.ts +7 -0
  111. package/dist/utils/html.d.ts.map +1 -0
  112. package/dist/utils/html.js +13 -0
  113. package/dist/utils/index.d.ts +13 -0
  114. package/dist/utils/index.d.ts.map +1 -0
  115. package/dist/utils/index.js +12 -0
  116. package/dist/utils/locale.d.ts +68 -0
  117. package/dist/utils/locale.d.ts.map +1 -0
  118. package/dist/utils/locale.js +318 -0
  119. package/dist/utils/metadata.d.ts +39 -0
  120. package/dist/utils/metadata.d.ts.map +1 -0
  121. package/dist/utils/metadata.js +66 -0
  122. package/dist/utils/oauth.d.ts +16 -0
  123. package/dist/utils/oauth.d.ts.map +1 -0
  124. package/dist/utils/oauth.js +42 -0
  125. package/dist/utils/screen.d.ts +26 -0
  126. package/dist/utils/screen.d.ts.map +1 -0
  127. package/dist/utils/screen.js +44 -0
  128. package/dist/utils/settings.d.ts +38 -0
  129. package/dist/utils/settings.d.ts.map +1 -0
  130. package/dist/utils/settings.js +89 -0
  131. package/dist/utils/template.d.ts +2 -0
  132. package/dist/utils/template.d.ts.map +1 -0
  133. package/dist/utils/template.js +6 -0
  134. package/dist/utils/theme.d.ts +47 -0
  135. package/dist/utils/theme.d.ts.map +1 -0
  136. package/dist/utils/theme.js +183 -0
  137. package/dist/utils/utm.d.ts +23 -0
  138. package/dist/utils/utm.d.ts.map +1 -0
  139. package/dist/utils/utm.js +30 -0
  140. package/dist/utils/weather.d.ts +84 -0
  141. package/dist/utils/weather.d.ts.map +1 -0
  142. package/dist/utils/weather.js +272 -0
  143. package/package.json +8 -7
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Screen Utilities
3
+ * Utilities for screen orientation, dimensions, and other screen-related functions
4
+ */
5
+ /**
6
+ * Check if the current screen orientation is portrait
7
+ * @returns true if portrait, false if landscape
8
+ */
9
+ export function isPortrait() {
10
+ if (typeof window === 'undefined') {
11
+ return false;
12
+ }
13
+ return window.matchMedia('(orientation: portrait)').matches;
14
+ }
15
+ /**
16
+ * Check if the current screen orientation is landscape
17
+ * @returns true if landscape, false if portrait
18
+ */
19
+ export function isLandscape() {
20
+ if (typeof window === 'undefined') {
21
+ return true; // Default to landscape for SSR
22
+ }
23
+ return window.matchMedia('(orientation: landscape)').matches;
24
+ }
25
+ /**
26
+ * Get the current screen orientation
27
+ * @returns 'portrait' | 'landscape'
28
+ */
29
+ export function getOrientation() {
30
+ return isPortrait() ? 'portrait' : 'landscape';
31
+ }
32
+ /**
33
+ * Center the auto-scaler element vertically within the viewport.
34
+ * Useful for apps that restrict display to a single orientation (portrait or
35
+ * landscape), where the auto-scaler may not fill the full viewport height.
36
+ */
37
+ export function centerAutoScalerVertically() {
38
+ const scaler = document.querySelector('auto-scaler');
39
+ if (!scaler)
40
+ return;
41
+ const scaledHeight = scaler.getBoundingClientRect().height;
42
+ const offsetY = Math.max(0, (window.innerHeight - scaledHeight) / 2);
43
+ scaler.style.top = `${offsetY}px`;
44
+ }
@@ -0,0 +1,38 @@
1
+ import type { ScreenlySettings } from '../types/index.js';
2
+ /**
3
+ * Get all Screenly settings
4
+ */
5
+ export declare function getSettings(): ScreenlySettings;
6
+ /**
7
+ * Get a specific setting value
8
+ */
9
+ export declare function getSetting<T = unknown>(key: string): T | undefined;
10
+ /**
11
+ * Get a setting with a default value
12
+ */
13
+ export declare function getSettingWithDefault<T>(key: string, defaultValue: T): T;
14
+ /**
15
+ * Check if a setting exists
16
+ */
17
+ export declare function hasSetting(key: string): boolean;
18
+ /**
19
+ * Get the theme mode
20
+ */
21
+ export declare function getTheme(): 'light' | 'dark' | undefined;
22
+ /**
23
+ * Get the CORS proxy URL
24
+ */
25
+ export declare function getCorsProxyUrl(): string;
26
+ /**
27
+ * Signal that the app is ready for rendering
28
+ * This should be called when your app has finished loading and is ready to be displayed
29
+ */
30
+ export declare function signalReady(): void;
31
+ export type MeasurementUnit = 'metric' | 'imperial';
32
+ /**
33
+ * Resolve measurement unit from settings with auto-detection fallback
34
+ * @param countryCode - Two-character ISO country code for auto-detection
35
+ * @returns Resolved measurement unit ('metric' or 'imperial')
36
+ */
37
+ export declare function resolveMeasurementUnit(countryCode: string): MeasurementUnit;
38
+ //# sourceMappingURL=settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/utils/settings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAGzD;;GAEG;AACH,wBAAgB,WAAW,IAAI,gBAAgB,CAE9C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAElE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC,CA0BxE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE/C;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,OAAO,GAAG,MAAM,GAAG,SAAS,CAEvD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAGD,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,UAAU,CAAA;AAEnD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,CAa3E"}
@@ -0,0 +1,89 @@
1
+ import { getMeasurementUnitByCountry } from './locale.js';
2
+ /**
3
+ * Get all Screenly settings
4
+ */
5
+ export function getSettings() {
6
+ return screenly.settings;
7
+ }
8
+ /**
9
+ * Get a specific setting value
10
+ */
11
+ export function getSetting(key) {
12
+ return screenly.settings[key];
13
+ }
14
+ /**
15
+ * Get a setting with a default value
16
+ */
17
+ export function getSettingWithDefault(key, defaultValue) {
18
+ const value = screenly.settings[key];
19
+ if (value === undefined)
20
+ return defaultValue;
21
+ if (typeof value === 'string' && value === '') {
22
+ return defaultValue;
23
+ }
24
+ // If the value is a string and the default is a number, try to parse it
25
+ if (typeof value === 'string' && typeof defaultValue === 'number') {
26
+ const trimmed = value.trim();
27
+ if (trimmed === '')
28
+ return defaultValue;
29
+ const parsed = Number(trimmed);
30
+ if (!isNaN(parsed))
31
+ return parsed;
32
+ return defaultValue;
33
+ }
34
+ // If the value is a string and the default is a boolean, try to parse it
35
+ if (typeof value === 'string' && typeof defaultValue === 'boolean') {
36
+ const lowerValue = value.toLowerCase();
37
+ if (lowerValue === 'true')
38
+ return true;
39
+ if (lowerValue === 'false')
40
+ return false;
41
+ return defaultValue;
42
+ }
43
+ return value;
44
+ }
45
+ /**
46
+ * Check if a setting exists
47
+ */
48
+ export function hasSetting(key) {
49
+ return key in screenly.settings;
50
+ }
51
+ /**
52
+ * Get the theme mode
53
+ */
54
+ export function getTheme() {
55
+ return screenly.settings.theme;
56
+ }
57
+ /**
58
+ * Get the CORS proxy URL
59
+ */
60
+ export function getCorsProxyUrl() {
61
+ return screenly.cors_proxy_url;
62
+ }
63
+ /**
64
+ * Signal that the app is ready for rendering
65
+ * This should be called when your app has finished loading and is ready to be displayed
66
+ */
67
+ export function signalReady() {
68
+ screenly.signalReadyForRendering();
69
+ }
70
+ /**
71
+ * Resolve measurement unit from settings with auto-detection fallback
72
+ * @param countryCode - Two-character ISO country code for auto-detection
73
+ * @returns Resolved measurement unit ('metric' or 'imperial')
74
+ */
75
+ export function resolveMeasurementUnit(countryCode) {
76
+ const unitSetting = getSettingWithDefault('unit', 'auto');
77
+ if (unitSetting === 'auto') {
78
+ // Auto-detect based on country when setting is explicitly 'auto'
79
+ return getMeasurementUnitByCountry(countryCode);
80
+ }
81
+ else if (unitSetting === 'metric' || unitSetting === 'imperial') {
82
+ // Only accept known valid units
83
+ return unitSetting;
84
+ }
85
+ else {
86
+ // Fallback for invalid/corrupted settings: auto-detect based on country
87
+ return getMeasurementUnitByCountry(countryCode);
88
+ }
89
+ }
@@ -0,0 +1,2 @@
1
+ export declare function getTemplate(id: string): HTMLTemplateElement;
2
+ //# sourceMappingURL=template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/utils/template.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,mBAAmB,CAI3D"}
@@ -0,0 +1,6 @@
1
+ export function getTemplate(id) {
2
+ const template = document.getElementById(id);
3
+ if (!template)
4
+ throw new Error(`Template ${id} not found`);
5
+ return template;
6
+ }
@@ -0,0 +1,47 @@
1
+ import type { ThemeColors, BrandingConfig } from '../types/index.js';
2
+ /**
3
+ * Default theme colors used by Screenly
4
+ */
5
+ export declare const DEFAULT_THEME_COLORS: ThemeColors;
6
+ /**
7
+ * Get the primary theme color from settings or use default
8
+ */
9
+ export declare function getPrimaryColor(accentColor?: string): string;
10
+ /**
11
+ * Get the secondary theme color based on theme mode
12
+ */
13
+ export declare function getSecondaryColor(theme: 'light' | 'dark' | undefined, lightColor?: string, darkColor?: string): string;
14
+ /**
15
+ * Setup theme colors from Screenly settings
16
+ * This function reads from the global screenly object and returns theme colors
17
+ */
18
+ export declare function getThemeColors(): ThemeColors;
19
+ /**
20
+ * Apply theme colors to CSS custom properties
21
+ */
22
+ export declare function applyThemeColors(colors: ThemeColors): void;
23
+ /**
24
+ * Setup theme by reading from Screenly settings and applying to CSS
25
+ */
26
+ export declare function setupTheme(): ThemeColors;
27
+ /**
28
+ * Fetch and process a logo image from a URL
29
+ * Handles SVG, PNG, and JPEG formats
30
+ */
31
+ export declare function fetchLogoImage(fileUrl: string): Promise<string>;
32
+ /**
33
+ * Setup branding logo from Screenly settings.
34
+ *
35
+ * Attempts to fetch the logo image using a CORS proxy URL based on the current theme.
36
+ * Falls back to a direct URL if the proxy fetch fails, and returns the default logo if no logo is configured or all fetch attempts fail.
37
+ *
38
+ * @returns {Promise<string>} The processed logo URL:
39
+ * - Returns a data URI for SVG images, or the original URL for PNG/JPEG images, if successfully fetched via the CORS proxy or fallback URL.
40
+ * - Returns the default logo URL if no logo is configured or all fetch attempts fail.
41
+ */
42
+ export declare function setupBrandingLogo(): Promise<string>;
43
+ /**
44
+ * Setup complete branding (theme colors and logo)
45
+ */
46
+ export declare function setupBranding(): Promise<BrandingConfig>;
47
+ //# sourceMappingURL=theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/utils/theme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAGpE;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAKlC,CAAA;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAK5D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,EACnC,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAgBR;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAgB5C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAiB1D;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,WAAW,CAIxC;AAaD;;;GAGG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkDrE;AAED;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAyCzD;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,cAAc,CAAC,CAQ7D"}
@@ -0,0 +1,183 @@
1
+ import defaultLogoUrl from '../assets/images/screenly.svg';
2
+ /**
3
+ * Default theme colors used by Screenly
4
+ */
5
+ export const DEFAULT_THEME_COLORS = {
6
+ primary: '#972EFF',
7
+ secondary: '#454BD2',
8
+ tertiary: '#FFFFFF',
9
+ background: '#C9CDD0',
10
+ };
11
+ /**
12
+ * Get the primary theme color from settings or use default
13
+ */
14
+ export function getPrimaryColor(accentColor) {
15
+ if (!accentColor || accentColor.toLowerCase() === '#ffffff') {
16
+ return DEFAULT_THEME_COLORS.primary;
17
+ }
18
+ return accentColor;
19
+ }
20
+ /**
21
+ * Get the secondary theme color based on theme mode
22
+ */
23
+ export function getSecondaryColor(theme, lightColor, darkColor) {
24
+ const defaultSecondary = '#adafbe';
25
+ if (theme === 'light') {
26
+ return !lightColor || lightColor.toLowerCase() === '#ffffff'
27
+ ? defaultSecondary
28
+ : lightColor;
29
+ }
30
+ if (theme === 'dark') {
31
+ return !darkColor || darkColor.toLowerCase() === '#ffffff'
32
+ ? defaultSecondary
33
+ : darkColor;
34
+ }
35
+ return DEFAULT_THEME_COLORS.secondary;
36
+ }
37
+ /**
38
+ * Setup theme colors from Screenly settings
39
+ * This function reads from the global screenly object and returns theme colors
40
+ */
41
+ export function getThemeColors() {
42
+ const settings = screenly.settings;
43
+ const primary = getPrimaryColor(settings.screenly_color_accent);
44
+ const secondary = getSecondaryColor(settings.theme, settings.screenly_color_light, settings.screenly_color_dark);
45
+ return {
46
+ primary,
47
+ secondary,
48
+ tertiary: DEFAULT_THEME_COLORS.tertiary,
49
+ background: DEFAULT_THEME_COLORS.background,
50
+ };
51
+ }
52
+ /**
53
+ * Apply theme colors to CSS custom properties
54
+ */
55
+ export function applyThemeColors(colors) {
56
+ document.documentElement.style.setProperty('--theme-color-primary', colors.primary);
57
+ document.documentElement.style.setProperty('--theme-color-secondary', colors.secondary);
58
+ document.documentElement.style.setProperty('--theme-color-tertiary', colors.tertiary);
59
+ document.documentElement.style.setProperty('--theme-color-background', colors.background);
60
+ }
61
+ /**
62
+ * Setup theme by reading from Screenly settings and applying to CSS
63
+ */
64
+ export function setupTheme() {
65
+ const colors = getThemeColors();
66
+ applyThemeColors(colors);
67
+ return colors;
68
+ }
69
+ /**
70
+ * Convert Uint8Array to base64 string
71
+ */
72
+ function uint8ToBase64(bytes) {
73
+ let binary = '';
74
+ for (let i = 0; i < bytes.length; i++) {
75
+ binary += String.fromCharCode(bytes[i]);
76
+ }
77
+ return btoa(binary);
78
+ }
79
+ /**
80
+ * Fetch and process a logo image from a URL
81
+ * Handles SVG, PNG, and JPEG formats
82
+ */
83
+ export async function fetchLogoImage(fileUrl) {
84
+ const response = await fetch(fileUrl);
85
+ if (!response.ok) {
86
+ throw new Error(`Failed to fetch image from ${fileUrl}, status: ${response.status}`);
87
+ }
88
+ const blob = await response.blob();
89
+ const buffer = await blob.arrayBuffer();
90
+ const uintArray = new Uint8Array(buffer);
91
+ // Get the first 8 bytes for magic number detection (sufficient for PNG and JPEG)
92
+ const hex = Array.from(uintArray.slice(0, 8))
93
+ .map((b) => b.toString(16).padStart(2, '0'))
94
+ .join('')
95
+ .toUpperCase();
96
+ // Convert the first few bytes to ASCII for text-based formats like SVG
97
+ const ascii = String.fromCharCode(...Array.from(uintArray.slice(0, 100)));
98
+ const pngMagicNumber = '89504E470D0A1A0A';
99
+ const jpegMagicNumber = 'FFD8FF';
100
+ // Determine file type based on magic number or ASCII text
101
+ if (ascii.startsWith('<?xml') || ascii.startsWith('<svg')) {
102
+ // Convert SVG to Base64
103
+ return new Promise((resolve, reject) => {
104
+ const svgReader = new FileReader();
105
+ svgReader.readAsText(blob);
106
+ svgReader.onloadend = function () {
107
+ try {
108
+ const svgText = svgReader.result;
109
+ const encoder = new TextEncoder();
110
+ const uint8Array = encoder.encode(svgText);
111
+ const base64 = uint8ToBase64(uint8Array);
112
+ resolve('data:image/svg+xml;base64,' + base64);
113
+ }
114
+ catch (error) {
115
+ reject(error);
116
+ }
117
+ };
118
+ svgReader.onerror = () => reject(new Error('Failed to read SVG file'));
119
+ });
120
+ }
121
+ if (hex.startsWith(pngMagicNumber) || hex.startsWith(jpegMagicNumber)) {
122
+ // Return URL for PNG or JPEG
123
+ return fileUrl;
124
+ }
125
+ throw new Error('Unknown image type');
126
+ }
127
+ /**
128
+ * Setup branding logo from Screenly settings.
129
+ *
130
+ * Attempts to fetch the logo image using a CORS proxy URL based on the current theme.
131
+ * Falls back to a direct URL if the proxy fetch fails, and returns the default logo if no logo is configured or all fetch attempts fail.
132
+ *
133
+ * @returns {Promise<string>} The processed logo URL:
134
+ * - Returns a data URI for SVG images, or the original URL for PNG/JPEG images, if successfully fetched via the CORS proxy or fallback URL.
135
+ * - Returns the default logo URL if no logo is configured or all fetch attempts fail.
136
+ */
137
+ export async function setupBrandingLogo() {
138
+ const settings = screenly.settings;
139
+ const theme = settings.theme || 'light';
140
+ const lightLogo = settings.screenly_logo_light ?? '';
141
+ const darkLogo = settings.screenly_logo_dark ?? '';
142
+ // Determine which logo to use based on theme
143
+ let logoUrl = '';
144
+ let fallbackUrl = '';
145
+ const isDark = theme === 'dark';
146
+ const primaryLogo = isDark ? darkLogo : lightLogo;
147
+ const secondaryLogo = isDark ? lightLogo : darkLogo;
148
+ const resolvedLogo = primaryLogo || secondaryLogo;
149
+ if (resolvedLogo) {
150
+ logoUrl = `${screenly.cors_proxy_url}/${resolvedLogo}`;
151
+ fallbackUrl = resolvedLogo;
152
+ }
153
+ // Return default logo if no logo is configured
154
+ if (!fallbackUrl)
155
+ return defaultLogoUrl;
156
+ // Try to fetch the image using the CORS proxy URL
157
+ try {
158
+ return await fetchLogoImage(logoUrl);
159
+ }
160
+ catch (err) {
161
+ console.warn('Failed to fetch logo image from primary URL:', logoUrl, err);
162
+ }
163
+ // If CORS fails, try the fallback URL
164
+ try {
165
+ return await fetchLogoImage(fallbackUrl);
166
+ }
167
+ catch (err) {
168
+ console.warn('Failed to fetch logo image from fallback URL:', fallbackUrl, err);
169
+ }
170
+ // Return default logo if all fetches fail
171
+ return defaultLogoUrl;
172
+ }
173
+ /**
174
+ * Setup complete branding (theme colors and logo)
175
+ */
176
+ export async function setupBranding() {
177
+ const colors = setupTheme();
178
+ const logoUrl = await setupBrandingLogo();
179
+ return {
180
+ colors,
181
+ logoUrl,
182
+ };
183
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * UTM parameters for tracking
3
+ */
4
+ export interface UTMParams {
5
+ utm_source: string;
6
+ utm_medium: string;
7
+ utm_location: string;
8
+ utm_placement: string;
9
+ [key: string]: string;
10
+ }
11
+ /**
12
+ * Get default UTM parameters from Screenly metadata
13
+ */
14
+ export declare function getDefaultUTMParams(): UTMParams;
15
+ /**
16
+ * Add UTM parameters to a URL
17
+ */
18
+ export declare function addUTMParams(url: string, params?: Partial<UTMParams>): string;
19
+ /**
20
+ * Conditionally add UTM parameters to a URL
21
+ */
22
+ export declare function addUTMParamsIf(url: string, enabled: boolean, params?: Partial<UTMParams>): string;
23
+ //# sourceMappingURL=utm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utm.d.ts","sourceRoot":"","sources":["../../src/utils/utm.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CACtB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,SAAS,CAS/C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,CAU7E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAC1B,MAAM,CAER"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Get default UTM parameters from Screenly metadata
3
+ */
4
+ export function getDefaultUTMParams() {
5
+ const { location, hostname } = screenly.metadata;
6
+ return {
7
+ utm_source: 'screenly',
8
+ utm_medium: 'digital-signage',
9
+ utm_location: location,
10
+ utm_placement: hostname,
11
+ };
12
+ }
13
+ /**
14
+ * Add UTM parameters to a URL
15
+ */
16
+ export function addUTMParams(url, params) {
17
+ const utmParams = { ...getDefaultUTMParams(), ...params };
18
+ const queryString = Object.entries(utmParams)
19
+ .filter(([, value]) => value !== undefined)
20
+ .map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
21
+ .join('&');
22
+ const separator = url.includes('?') ? '&' : '?';
23
+ return `${url}${separator}${queryString}`;
24
+ }
25
+ /**
26
+ * Conditionally add UTM parameters to a URL
27
+ */
28
+ export function addUTMParamsIf(url, enabled, params) {
29
+ return enabled ? addUTMParams(url, params) : url;
30
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Weather Utilities
3
+ * Functions for weather icon mapping and related utilities
4
+ */
5
+ import { type MeasurementUnit } from './settings.js';
6
+ export declare const WEATHER_ICONS: Record<string, string>;
7
+ /**
8
+ * Check if a given timestamp is during nighttime (8 PM - 5 AM) in the specified timezone
9
+ */
10
+ export declare function isNightForTimestamp(dt: number, timeZone: string): boolean;
11
+ /**
12
+ * Get weather icon key based on OpenWeatherMap weather condition ID and time of day
13
+ * @param id - OpenWeatherMap weather condition ID (e.g., 800 for clear sky)
14
+ * @param dt - Unix timestamp in seconds
15
+ * @param timeZone - IANA timezone string (e.g., 'America/New_York')
16
+ * @returns Icon key string (e.g., 'clear', 'clear-night', 'rain', etc.)
17
+ */
18
+ export declare function getWeatherIconKey(id: number, dt: number, timeZone: string): string;
19
+ /**
20
+ * Get the full URL path for a weather icon
21
+ * @param iconKey - Icon key from getWeatherIconKey (e.g., 'clear', 'rain-night')
22
+ * @param iconBase - Base path for weather icons (default: '/assets/images/icons')
23
+ * @returns Full URL path to the icon SVG file
24
+ */
25
+ export declare function getWeatherIconUrl(iconKey: string, iconBase?: string): string;
26
+ /**
27
+ * Get weather icon source (imported SVG) based on weather condition ID and time
28
+ * @param weatherId - OpenWeatherMap weather condition ID (e.g., 800 for clear sky)
29
+ * @param dt - Unix timestamp in seconds
30
+ * @param timeZone - IANA timezone string (e.g., 'America/New_York')
31
+ * @returns Icon source string (Vite-imported SVG path)
32
+ */
33
+ export declare function getWeatherIcon(weatherId: number, dt: number, timeZone: string): string;
34
+ /**
35
+ * Validate OpenWeatherMap API response
36
+ * Note: `cod` can be number (200) or string ("200") depending on the endpoint
37
+ */
38
+ export declare function isValidWeatherResponse(data: {
39
+ cod?: number | string;
40
+ main?: {
41
+ temp?: number;
42
+ };
43
+ }): boolean;
44
+ export interface CurrentWeatherRawData {
45
+ temperature: number;
46
+ tempHigh: number;
47
+ tempLow: number;
48
+ weatherId: number;
49
+ description: string;
50
+ iconSrc: string;
51
+ iconAlt: string;
52
+ unit: MeasurementUnit;
53
+ }
54
+ /**
55
+ * Fetch current weather data from OpenWeatherMap API
56
+ * Returns raw weather data that each app can map to its own interface
57
+ * @param lat - Latitude
58
+ * @param lng - Longitude
59
+ * @param tz - Timezone
60
+ * @param unit - Measurement unit ('metric' or 'imperial')
61
+ */
62
+ export declare function fetchCurrentWeatherData(lat: number, lng: number, tz: string, unit?: MeasurementUnit): Promise<CurrentWeatherRawData | null>;
63
+ /**
64
+ * City information from reverse geocoding
65
+ */
66
+ export interface CityInfo {
67
+ cityName: string;
68
+ countryCode: string;
69
+ }
70
+ /**
71
+ * Get city information including name and country code from OpenWeatherMap reverse geocoding
72
+ * @param lat - Latitude
73
+ * @param lng - Longitude
74
+ * @returns Object containing cityName and countryCode
75
+ */
76
+ export declare function getCityInfo(lat: number, lng: number): Promise<CityInfo>;
77
+ /**
78
+ * Get city name from coordinates using OpenWeatherMap reverse geocoding
79
+ * @param lat - Latitude
80
+ * @param lng - Longitude
81
+ * @returns City name in format "City, Country" or fallback location
82
+ */
83
+ export declare function getCityName(lat: number, lng: number): Promise<string>;
84
+ //# sourceMappingURL=weather.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weather.d.ts","sourceRoot":"","sources":["../../src/utils/weather.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;AA2BhE,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAuBhD,CAAA;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CASzE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,GACf,MAAM,CAgCR;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,MAA+B,GACxC,MAAM,CA0BR;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,GACf,MAAM,CAGR;AAID;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACrB,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CACzB,GAAG,OAAO,CAOV;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,eAAe,CAAA;CACtB;AAED;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,EAAE,EAAE,MAAM,EACV,IAAI,GAAE,eAA0B,GAC/B,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CA8DvC;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CA+C7E;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG3E"}