@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 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAA;AAGhC,cAAc,iBAAiB,CAAA;AAG/B,cAAc,uBAAuB,CAAA;AAGrC,cAAc,kBAAkB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ // Platform utilities (settings, theme, metadata, etc.)
2
+ export * from './utils/index.js';
3
+ // Core layout utilities (AutoScaler, etc.)
4
+ export * from './core/index.js';
5
+ // Web Components (AppHeader, AutoScaler, DevTools)
6
+ export * from './components/index.js';
7
+ // Types
8
+ export * from './types/index.js';
@@ -0,0 +1,3 @@
1
+ export * from './mock.js';
2
+ export * from './setup.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,YAAY,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './mock.js';
2
+ export * from './setup.js';
@@ -0,0 +1,23 @@
1
+ import type { ScreenlyObject, ScreenlyMetadata, ScreenlySettings } from '../types/index.js';
2
+ /**
3
+ * Default mock metadata for testing
4
+ */
5
+ export declare const mockMetadata: ScreenlyMetadata;
6
+ /**
7
+ * Default mock settings for testing
8
+ */
9
+ export declare const mockSettings: ScreenlySettings;
10
+ /**
11
+ * Create a mock Screenly object for testing
12
+ */
13
+ export declare function createMockScreenly(metadata?: Partial<ScreenlyMetadata>, settings?: Partial<ScreenlySettings>): ScreenlyObject;
14
+ /**
15
+ * Setup global screenly mock for testing
16
+ * Call this in your test setup to mock the global screenly object
17
+ */
18
+ export declare function setupScreenlyMock(metadata?: Partial<ScreenlyMetadata>, settings?: Partial<ScreenlySettings>): ScreenlyObject;
19
+ /**
20
+ * Reset the global screenly mock
21
+ */
22
+ export declare function resetScreenlyMock(): void;
23
+ //# sourceMappingURL=mock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../src/test/mock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,mBAAmB,CAAA;AAI1B;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,gBAQ1B,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,gBAM1B,CAAA;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,GAAE,OAAO,CAAC,gBAAgB,CAAM,EACxC,QAAQ,GAAE,OAAO,CAAC,gBAAgB,CAAM,GACvC,cAAc,CAOhB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,GAAE,OAAO,CAAC,gBAAgB,CAAM,EACxC,QAAQ,GAAE,OAAO,CAAC,gBAAgB,CAAM,GACvC,cAAc,CAIhB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
@@ -0,0 +1,49 @@
1
+ const global = globalThis;
2
+ /**
3
+ * Default mock metadata for testing
4
+ */
5
+ export const mockMetadata = {
6
+ coordinates: [37.3861, -122.0839],
7
+ hostname: 'test-hostname',
8
+ location: 'Test Location',
9
+ hardware: 'test-hardware',
10
+ screenly_version: '1.0.0-test',
11
+ screen_name: 'Test Screen',
12
+ tags: ['test', 'development'],
13
+ };
14
+ /**
15
+ * Default mock settings for testing
16
+ */
17
+ export const mockSettings = {
18
+ screenly_color_accent: '#972EFF',
19
+ screenly_color_light: '#ADAFBE',
20
+ screenly_color_dark: '#454BD2',
21
+ screenly_logo_light: '',
22
+ screenly_logo_dark: '',
23
+ };
24
+ /**
25
+ * Create a mock Screenly object for testing
26
+ */
27
+ export function createMockScreenly(metadata = {}, settings = {}) {
28
+ return {
29
+ signalReadyForRendering: () => { },
30
+ metadata: { ...mockMetadata, ...metadata },
31
+ settings: { ...mockSettings, ...settings },
32
+ cors_proxy_url: 'http://localhost:8080',
33
+ };
34
+ }
35
+ /**
36
+ * Setup global screenly mock for testing
37
+ * Call this in your test setup to mock the global screenly object
38
+ */
39
+ export function setupScreenlyMock(metadata = {}, settings = {}) {
40
+ const mock = createMockScreenly(metadata, settings);
41
+ global.screenly = mock;
42
+ return mock;
43
+ }
44
+ /**
45
+ * Reset the global screenly mock
46
+ */
47
+ export function resetScreenlyMock() {
48
+ delete global.screenly;
49
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Screenshot testing utilities and constants
3
+ */
4
+ import type { ScreenlyMetadata, ScreenlyObject, ScreenlySettings } from '../types/index.js';
5
+ import { createMockScreenly } from './mock.js';
6
+ export { createMockScreenly };
7
+ /**
8
+ * Fixed date used for screenshot tests to ensure idempotent output.
9
+ * If tests rely on specific timestamps from mocked APIs, keep those mocks
10
+ * consistent with this value.
11
+ */
12
+ export declare const FIXED_SCREENSHOT_DATE: Date;
13
+ interface PlaywrightRouteFulfillOptions {
14
+ status?: number;
15
+ contentType?: string;
16
+ body?: string;
17
+ }
18
+ interface PlaywrightRoute {
19
+ fulfill(options: PlaywrightRouteFulfillOptions): Promise<void>;
20
+ }
21
+ /**
22
+ * Standard resolutions for screenshot testing
23
+ * Covers all supported Screenly player resolutions
24
+ */
25
+ export declare const RESOLUTIONS: readonly [{
26
+ readonly width: 4096;
27
+ readonly height: 2160;
28
+ }, {
29
+ readonly width: 2160;
30
+ readonly height: 4096;
31
+ }, {
32
+ readonly width: 3840;
33
+ readonly height: 2160;
34
+ }, {
35
+ readonly width: 2160;
36
+ readonly height: 3840;
37
+ }, {
38
+ readonly width: 1920;
39
+ readonly height: 1080;
40
+ }, {
41
+ readonly width: 1080;
42
+ readonly height: 1920;
43
+ }, {
44
+ readonly width: 1280;
45
+ readonly height: 720;
46
+ }, {
47
+ readonly width: 720;
48
+ readonly height: 1280;
49
+ }, {
50
+ readonly width: 800;
51
+ readonly height: 480;
52
+ }, {
53
+ readonly width: 480;
54
+ readonly height: 800;
55
+ }];
56
+ /**
57
+ * Returns the screenshots output directory path, creating it if it doesn't exist.
58
+ * Resolves to `<cwd>/screenshots/`.
59
+ */
60
+ export declare function getScreenshotsDir(): string;
61
+ /**
62
+ * Creates the screenly.js content string for Playwright route mocking
63
+ * @param screenlyObject - The Screenly object to inject into window.screenly
64
+ * @returns JavaScript content string for route mocking
65
+ */
66
+ export declare function createScreenlyJsContent(screenlyObject: ScreenlyObject): string;
67
+ /**
68
+ * Creates a complete mock Screenly object with custom overrides and generates the JS content
69
+ * This is a convenience wrapper that combines createMockScreenly and createScreenlyJsContent
70
+ * @param metadata - Partial metadata overrides
71
+ * @param settings - Partial settings overrides
72
+ * @param corsProxyUrl - Custom CORS proxy URL (defaults to http://127.0.0.1:8080)
73
+ * @returns Object containing both the mock Screenly object and the JS content string
74
+ */
75
+ export declare function createMockScreenlyForScreenshots(metadata?: Partial<ScreenlyMetadata>, settings?: Partial<ScreenlySettings>, corsProxyUrl?: string): {
76
+ mockScreenly: ScreenlyObject;
77
+ screenlyJsContent: string;
78
+ };
79
+ /**
80
+ * OpenWeather API mock data for Playwright route mocking
81
+ */
82
+ export interface OpenWeatherMocks {
83
+ /** Mock data for reverse geocoding endpoint */
84
+ geocoding?: unknown;
85
+ /** Mock data for current weather endpoint */
86
+ weather?: unknown;
87
+ /** Mock data for forecast endpoint (optional) */
88
+ forecast?: unknown;
89
+ }
90
+ /**
91
+ * Setup OpenWeather API route mocks in Playwright
92
+ * @param page - Playwright page object
93
+ * @param mocks - Mock data for OpenWeather API endpoints
94
+ */
95
+ export declare function setupOpenWeatherMocks(page: {
96
+ route: (url: string, handler: (route: PlaywrightRoute) => Promise<void>) => Promise<void>;
97
+ }, mocks: OpenWeatherMocks): Promise<void>;
98
+ /**
99
+ * Setup screenly.js route mock in Playwright
100
+ * @param page - Playwright page object
101
+ * @param screenlyJsContent - JavaScript content string for screenly.js
102
+ */
103
+ export declare function setupScreenlyJsMock(page: {
104
+ route: (url: string, handler: (route: PlaywrightRoute) => Promise<void>) => Promise<void>;
105
+ }, screenlyJsContent: string): Promise<void>;
106
+ /**
107
+ * Freeze the browser clock to a fixed point in time before page load.
108
+ * Must be called before `page.goto()` to ensure the clock is set before
109
+ * any JavaScript runs. This makes screenshots idempotent regardless of
110
+ * when the test is executed.
111
+ *
112
+ * @param page - Playwright page object
113
+ * @param date - The date to freeze the clock at (defaults to FIXED_SCREENSHOT_DATE)
114
+ */
115
+ export declare function setupClockMock(page: {
116
+ clock: {
117
+ setFixedTime(time: Date | number | string): Promise<void>;
118
+ };
119
+ }, date?: Date | number | string): Promise<void>;
120
+ //# sourceMappingURL=screenshots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screenshots.d.ts","sourceRoot":"","sources":["../../src/test/screenshots.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EACjB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAE9C,OAAO,EAAE,kBAAkB,EAAE,CAAA;AAE7B;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,MAAmC,CAAA;AAErE,UAAU,6BAA6B;IACrC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,UAAU,eAAe;IACvB,OAAO,CAAC,OAAO,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/D;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWd,CAAA;AAEV;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAI1C;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,cAAc,GAC7B,MAAM,CAKR;AAED;;;;;;;GAOG;AACH,wBAAgB,gCAAgC,CAC9C,QAAQ,GAAE,OAAO,CAAC,gBAAgB,CAAM,EACxC,QAAQ,GAAE,OAAO,CAAC,gBAAgB,CAAM,EACxC,YAAY,SAA0B,GACrC;IAAE,YAAY,EAAE,cAAc,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CAS7D;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+CAA+C;IAC/C,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE;IACJ,KAAK,EAAE,CACL,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,KAC/C,OAAO,CAAC,IAAI,CAAC,CAAA;CACnB,EACD,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,IAAI,CAAC,CAuCf;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE;IACJ,KAAK,EAAE,CACL,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,KAC/C,OAAO,CAAC,IAAI,CAAC,CAAA;CACnB,EACD,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE;IACJ,KAAK,EAAE;QAAE,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAA;CACrE,EACD,IAAI,GAAE,IAAI,GAAG,MAAM,GAAG,MAA8B,GACnD,OAAO,CAAC,IAAI,CAAC,CAEf"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Screenshot testing utilities and constants
3
+ */
4
+ import fs from 'fs';
5
+ import path from 'path';
6
+ import { createMockScreenly } from './mock.js';
7
+ export { createMockScreenly };
8
+ /**
9
+ * Fixed date used for screenshot tests to ensure idempotent output.
10
+ * If tests rely on specific timestamps from mocked APIs, keep those mocks
11
+ * consistent with this value.
12
+ */
13
+ export const FIXED_SCREENSHOT_DATE = new Date('2025-02-19T21:20:00Z');
14
+ /**
15
+ * Standard resolutions for screenshot testing
16
+ * Covers all supported Screenly player resolutions
17
+ */
18
+ export const RESOLUTIONS = [
19
+ { width: 4096, height: 2160 },
20
+ { width: 2160, height: 4096 },
21
+ { width: 3840, height: 2160 },
22
+ { width: 2160, height: 3840 },
23
+ { width: 1920, height: 1080 },
24
+ { width: 1080, height: 1920 },
25
+ { width: 1280, height: 720 },
26
+ { width: 720, height: 1280 },
27
+ { width: 800, height: 480 },
28
+ { width: 480, height: 800 },
29
+ ];
30
+ /**
31
+ * Returns the screenshots output directory path, creating it if it doesn't exist.
32
+ * Resolves to `<cwd>/screenshots/`.
33
+ */
34
+ export function getScreenshotsDir() {
35
+ const dir = path.resolve('screenshots');
36
+ fs.mkdirSync(dir, { recursive: true });
37
+ return dir;
38
+ }
39
+ /**
40
+ * Creates the screenly.js content string for Playwright route mocking
41
+ * @param screenlyObject - The Screenly object to inject into window.screenly
42
+ * @returns JavaScript content string for route mocking
43
+ */
44
+ export function createScreenlyJsContent(screenlyObject) {
45
+ return `
46
+ window.screenly = ${JSON.stringify(screenlyObject, null, 2)};
47
+ window.screenly.signalReadyForRendering = function() {};
48
+ `;
49
+ }
50
+ /**
51
+ * Creates a complete mock Screenly object with custom overrides and generates the JS content
52
+ * This is a convenience wrapper that combines createMockScreenly and createScreenlyJsContent
53
+ * @param metadata - Partial metadata overrides
54
+ * @param settings - Partial settings overrides
55
+ * @param corsProxyUrl - Custom CORS proxy URL (defaults to http://127.0.0.1:8080)
56
+ * @returns Object containing both the mock Screenly object and the JS content string
57
+ */
58
+ export function createMockScreenlyForScreenshots(metadata = {}, settings = {}, corsProxyUrl = 'http://127.0.0.1:8080') {
59
+ const mockScreenly = {
60
+ ...createMockScreenly(metadata, settings),
61
+ cors_proxy_url: corsProxyUrl,
62
+ };
63
+ return {
64
+ mockScreenly,
65
+ screenlyJsContent: createScreenlyJsContent(mockScreenly),
66
+ };
67
+ }
68
+ /**
69
+ * Setup OpenWeather API route mocks in Playwright
70
+ * @param page - Playwright page object
71
+ * @param mocks - Mock data for OpenWeather API endpoints
72
+ */
73
+ export async function setupOpenWeatherMocks(page, mocks) {
74
+ if (mocks.geocoding) {
75
+ await page.route('**/api.openweathermap.org/geo/1.0/reverse**', async (route) => {
76
+ await route.fulfill({
77
+ status: 200,
78
+ contentType: 'application/json',
79
+ body: JSON.stringify(mocks.geocoding),
80
+ });
81
+ });
82
+ }
83
+ if (mocks.weather) {
84
+ await page.route('**/api.openweathermap.org/data/2.5/weather**', async (route) => {
85
+ await route.fulfill({
86
+ status: 200,
87
+ contentType: 'application/json',
88
+ body: JSON.stringify(mocks.weather),
89
+ });
90
+ });
91
+ }
92
+ if (mocks.forecast) {
93
+ await page.route('**/api.openweathermap.org/data/2.5/forecast**', async (route) => {
94
+ await route.fulfill({
95
+ status: 200,
96
+ contentType: 'application/json',
97
+ body: JSON.stringify(mocks.forecast),
98
+ });
99
+ });
100
+ }
101
+ }
102
+ /**
103
+ * Setup screenly.js route mock in Playwright
104
+ * @param page - Playwright page object
105
+ * @param screenlyJsContent - JavaScript content string for screenly.js
106
+ */
107
+ export async function setupScreenlyJsMock(page, screenlyJsContent) {
108
+ await page.route('/screenly.js?version=1', async (route) => {
109
+ await route.fulfill({
110
+ status: 200,
111
+ contentType: 'application/javascript',
112
+ body: screenlyJsContent,
113
+ });
114
+ });
115
+ }
116
+ /**
117
+ * Freeze the browser clock to a fixed point in time before page load.
118
+ * Must be called before `page.goto()` to ensure the clock is set before
119
+ * any JavaScript runs. This makes screenshots idempotent regardless of
120
+ * when the test is executed.
121
+ *
122
+ * @param page - Playwright page object
123
+ * @param date - The date to freeze the clock at (defaults to FIXED_SCREENSHOT_DATE)
124
+ */
125
+ export async function setupClockMock(page, date = FIXED_SCREENSHOT_DATE) {
126
+ await page.clock.setFixedTime(date);
127
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/test/setup.ts"],"names":[],"mappings":""}
@@ -0,0 +1,13 @@
1
+ import { JSDOM } from 'jsdom';
2
+ // Setup jsdom for DOM operations in tests
3
+ const dom = new JSDOM('<!DOCTYPE html><html><head></head><body></body></html>', {
4
+ url: 'http://localhost',
5
+ });
6
+ global.document = dom.window.document;
7
+ global.window = dom.window;
8
+ global.navigator = dom.window.navigator;
9
+ global.Node = dom.window.Node;
10
+ global.HTMLElement = dom.window.HTMLElement;
11
+ global.customElements = dom.window.customElements;
12
+ global.getComputedStyle = dom.window.getComputedStyle;
13
+ global.SVGSVGElement = dom.window.SVGSVGElement;
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Hardware types for Screenly devices
3
+ */
4
+ export declare enum Hardware {
5
+ Anywhere = "Anywhere",
6
+ RaspberryPi = "RaspberryPi",
7
+ ScreenlyPlayerMax = "ScreenlyPlayerMax",
8
+ Unknown = "Unknown"
9
+ }
10
+ /**
11
+ * Screenly metadata provided by the Edge Apps runtime
12
+ */
13
+ export interface ScreenlyMetadata {
14
+ /** GPS coordinates [latitude, longitude] */
15
+ coordinates: [number, number];
16
+ /** Hardware identifier */
17
+ hardware: string | undefined;
18
+ /** Device hostname */
19
+ hostname: string;
20
+ /** Physical location description */
21
+ location: string;
22
+ /** Screenly software version */
23
+ screenly_version: string;
24
+ /** Screen display name */
25
+ screen_name: string;
26
+ /** Tags associated with the screen */
27
+ tags: string[];
28
+ }
29
+ /**
30
+ * Screenly settings provided by the Edge Apps runtime
31
+ * This interface can be extended with custom settings
32
+ */
33
+ export interface ScreenlySettings extends Record<string, unknown> {
34
+ /** Primary accent color for branding */
35
+ screenly_color_accent?: string;
36
+ /** Light theme color */
37
+ screenly_color_light?: string;
38
+ /** Dark theme color */
39
+ screenly_color_dark?: string;
40
+ /** Light theme logo URL */
41
+ screenly_logo_light?: string;
42
+ /** Dark theme logo URL */
43
+ screenly_logo_dark?: string;
44
+ /** Theme mode: light or dark */
45
+ theme?: 'light' | 'dark';
46
+ /** Sentry DSN for error tracking */
47
+ sentry_dsn?: string;
48
+ }
49
+ /**
50
+ * The global screenly object provided by screenly.js
51
+ */
52
+ export interface ScreenlyObject {
53
+ /** Signal that the app is ready to be displayed */
54
+ signalReadyForRendering: () => void;
55
+ /** Device and screen metadata */
56
+ metadata: ScreenlyMetadata;
57
+ /** App settings and configuration */
58
+ settings: ScreenlySettings;
59
+ /** CORS proxy URL for fetching external resources */
60
+ cors_proxy_url: string;
61
+ }
62
+ /**
63
+ * Theme colors configuration
64
+ */
65
+ export interface ThemeColors {
66
+ primary: string;
67
+ secondary: string;
68
+ tertiary: string;
69
+ background: string;
70
+ }
71
+ /**
72
+ * Branding configuration
73
+ */
74
+ export interface BrandingConfig {
75
+ colors: ThemeColors;
76
+ logoUrl?: string;
77
+ }
78
+ /**
79
+ * Core UI/Layout types
80
+ */
81
+ /**
82
+ * Orientation type for edge apps
83
+ */
84
+ export type Orientation = 'landscape' | 'portrait' | 'auto';
85
+ /**
86
+ * Calendar view mode
87
+ */
88
+ export type CalendarViewMode = 'daily' | 'weekly' | 'schedule';
89
+ export declare const CALENDAR_VIEW_MODE: {
90
+ DAILY: CalendarViewMode;
91
+ WEEKLY: CalendarViewMode;
92
+ SCHEDULE: CalendarViewMode;
93
+ };
94
+ /**
95
+ * Reference resolution configuration
96
+ */
97
+ export interface ReferenceResolution {
98
+ width: number;
99
+ height: number;
100
+ orientation?: Orientation;
101
+ }
102
+ /**
103
+ * Safe zone configuration
104
+ */
105
+ export interface SafeZoneConfig {
106
+ top?: number | string;
107
+ right?: number | string;
108
+ bottom?: number | string;
109
+ left?: number | string;
110
+ all?: number | string;
111
+ }
112
+ /**
113
+ * AutoScaler options
114
+ */
115
+ export interface AutoScalerOptions {
116
+ padding?: number | string;
117
+ referenceWidth: number;
118
+ referenceHeight: number;
119
+ orientation?: Orientation;
120
+ centerContent?: boolean;
121
+ debounceMs?: number;
122
+ onScaleChange?: (scale: number) => void;
123
+ }
124
+ /**
125
+ * Edge app configuration
126
+ */
127
+ export interface EdgeAppConfig {
128
+ referenceResolution: ReferenceResolution;
129
+ enableDevTools?: boolean;
130
+ }
131
+ declare global {
132
+ interface Window {
133
+ screenly: ScreenlyObject;
134
+ }
135
+ const screenly: ScreenlyObject;
136
+ }
137
+ export {};
138
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Hardware types for Screenly devices
3
+ */
4
+ export var Hardware;
5
+ (function (Hardware) {
6
+ Hardware["Anywhere"] = "Anywhere";
7
+ Hardware["RaspberryPi"] = "RaspberryPi";
8
+ Hardware["ScreenlyPlayerMax"] = "ScreenlyPlayerMax";
9
+ Hardware["Unknown"] = "Unknown";
10
+ })(Hardware || (Hardware = {}));
11
+ export const CALENDAR_VIEW_MODE = {
12
+ DAILY: 'daily',
13
+ WEEKLY: 'weekly',
14
+ SCHEDULE: 'schedule',
15
+ };
@@ -0,0 +1,28 @@
1
+ import type { CalendarViewMode } from '../types/index.js';
2
+ import type { WeeklyCalendarView } from '../components/calendar-views/weekly-calendar-view/index.js';
3
+ import type { DailyCalendarView } from '../components/calendar-views/daily-calendar-view/index.js';
4
+ import type { ScheduleCalendarView } from '../components/calendar-views/schedule-calendar-view/index.js';
5
+ import type { CalendarEvent } from '../components/calendar-views/event-layout.js';
6
+ type CalendarViewElement = WeeklyCalendarView | DailyCalendarView | ScheduleCalendarView;
7
+ export declare function initCalendarApp(activeEl: CalendarViewElement, fetchEvents: (timezone: string) => Promise<CalendarEvent[]>): Promise<void>;
8
+ /**
9
+ * Read the `calendar_mode` setting and return the date range for the current
10
+ * view, anchored to today in the given timezone.
11
+ *
12
+ * The legacy `'monthly'` mode is treated as `'schedule'` since the schedule
13
+ * view replaced it.
14
+ */
15
+ export declare function getCalendarDateRange(timezone: string): {
16
+ startDate: Date;
17
+ endDate: Date;
18
+ };
19
+ /**
20
+ * Compute the start and end dates for the given calendar view mode,
21
+ * anchored to the current date in the specified timezone.
22
+ */
23
+ export declare function getDateRangeForViewMode(viewMode: CalendarViewMode, timezone: string): {
24
+ startDate: Date;
25
+ endDate: Date;
26
+ };
27
+ export {};
28
+ //# sourceMappingURL=calendar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.d.ts","sourceRoot":"","sources":["../../src/utils/calendar.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4DAA4D,CAAA;AACpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2DAA2D,CAAA;AAClG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAA;AACxG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8CAA8C,CAAA;AAQjF,KAAK,mBAAmB,GACpB,kBAAkB,GAClB,iBAAiB,GACjB,oBAAoB,CAAA;AAKxB,wBAAsB,eAAe,CACnC,QAAQ,EAAE,mBAAmB,EAC7B,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,EAAE,CAAC,GAC1D,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG;IACtD,SAAS,EAAE,IAAI,CAAA;IACf,OAAO,EAAE,IAAI,CAAA;CACd,CAOA;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,gBAAgB,EAC1B,QAAQ,EAAE,MAAM,GACf;IAAE,SAAS,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,IAAI,CAAA;CAAE,CAuBpC"}
@@ -0,0 +1,77 @@
1
+ import dayjs from 'dayjs';
2
+ import utc from 'dayjs/plugin/utc';
3
+ import timezone from 'dayjs/plugin/timezone';
4
+ import { CALENDAR_VIEW_MODE } from '../types/index.js';
5
+ import { centerAutoScalerVertically } from './screen.js';
6
+ import { getLocale, getTimeZone } from './locale.js';
7
+ import { signalReady, getSettingWithDefault } from './settings.js';
8
+ dayjs.extend(utc);
9
+ dayjs.extend(timezone);
10
+ const EVENTS_REFRESH_INTERVAL = 10_000;
11
+ const NOW_TICK_INTERVAL = 30_000;
12
+ export async function initCalendarApp(activeEl, fetchEvents) {
13
+ const scaler = document.querySelector('auto-scaler');
14
+ scaler?.addEventListener('scalechange', centerAutoScalerVertically);
15
+ window.addEventListener('resize', centerAutoScalerVertically);
16
+ centerAutoScalerVertically();
17
+ const timezone = await getTimeZone();
18
+ const locale = await getLocale();
19
+ activeEl.setAttribute('timezone', timezone);
20
+ activeEl.setAttribute('locale', locale);
21
+ const tick = () => {
22
+ activeEl.now = new Date();
23
+ };
24
+ tick();
25
+ setInterval(tick, NOW_TICK_INTERVAL);
26
+ const refresh = async () => {
27
+ try {
28
+ const events = await fetchEvents(timezone);
29
+ activeEl.events = events;
30
+ }
31
+ catch (error) {
32
+ console.error('Failed to fetch calendar events:', error);
33
+ }
34
+ };
35
+ await refresh();
36
+ setInterval(refresh, EVENTS_REFRESH_INTERVAL);
37
+ signalReady();
38
+ }
39
+ /**
40
+ * Read the `calendar_mode` setting and return the date range for the current
41
+ * view, anchored to today in the given timezone.
42
+ *
43
+ * The legacy `'monthly'` mode is treated as `'schedule'` since the schedule
44
+ * view replaced it.
45
+ */
46
+ export function getCalendarDateRange(timezone) {
47
+ const viewMode = getSettingWithDefault('calendar_mode', 'schedule');
48
+ const mappedViewMode = viewMode === 'monthly'
49
+ ? CALENDAR_VIEW_MODE.SCHEDULE
50
+ : viewMode;
51
+ return getDateRangeForViewMode(mappedViewMode, timezone);
52
+ }
53
+ /**
54
+ * Compute the start and end dates for the given calendar view mode,
55
+ * anchored to the current date in the specified timezone.
56
+ */
57
+ export function getDateRangeForViewMode(viewMode, timezone) {
58
+ const todayInTimezone = dayjs(Date.now()).tz(timezone).startOf('day');
59
+ if (viewMode === CALENDAR_VIEW_MODE.DAILY) {
60
+ return {
61
+ startDate: todayInTimezone.toDate(),
62
+ endDate: todayInTimezone.add(1, 'day').toDate(),
63
+ };
64
+ }
65
+ if (viewMode === CALENDAR_VIEW_MODE.WEEKLY) {
66
+ const weekStart = todayInTimezone.startOf('week');
67
+ return {
68
+ startDate: weekStart.toDate(),
69
+ endDate: weekStart.add(7, 'days').toDate(),
70
+ };
71
+ }
72
+ const monthStart = todayInTimezone.startOf('month');
73
+ return {
74
+ startDate: monthStart.toDate(),
75
+ endDate: monthStart.add(1, 'month').toDate(),
76
+ };
77
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Set up error handling with panic-overlay
3
+ * Configures panic-overlay to display errors on screen if the display_errors setting is enabled
4
+ */
5
+ export declare function setupErrorHandling(): void;
6
+ //# sourceMappingURL=error-handling.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-handling.d.ts","sourceRoot":"","sources":["../../src/utils/error-handling.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CASzC"}