@xibosignage/xibo-layout-renderer 1.0.24 → 1.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -67,3 +67,52 @@ The library supports multiple platforms via `ConsumerPlatform` enum and the `opt
67
67
  | `chromeOS` | Local file path | Fault reporting via Service Worker |
68
68
  | `electron` | App host + URL | Standard playback |
69
69
  | PWA | Proxy/hosted | Service Worker caching |
70
+
71
+ ## CMS Integration — postMessage Protocol
72
+
73
+ When XLR is embedded in a sandboxed `<iframe>` (e.g. in CMS Preview), it communicates with the parent frame via `window.parent.postMessage` instead of using browser dialogs that require `allow-modals`.
74
+
75
+ ### Iframe requirements
76
+
77
+ The iframe must include `allow-scripts` in its `sandbox` attribute. `allow-modals` is **not** required.
78
+
79
+ ```html
80
+ <iframe src="..." sandbox="allow-scripts allow-same-origin"></iframe>
81
+ ```
82
+
83
+ ### Messages sent by XLR
84
+
85
+ #### `xlr:navLayout`
86
+
87
+ Fired when a "Navigate to Layout" touch/webhook action is triggered. The parent frame is responsible for showing a confirmation prompt and opening the layout.
88
+
89
+ ```typescript
90
+ interface XlrNavLayoutMessage {
91
+ type: 'xlr:navLayout';
92
+ layoutCode: string; // The layout code from the action
93
+ url: string; // Pre-constructed preview URL (ready to open)
94
+ }
95
+ ```
96
+
97
+ **CMS listener example:**
98
+
99
+ ```javascript
100
+ window.addEventListener('message', (event) => {
101
+ // In production, validate event.origin against your known CMS origin.
102
+ if (event.data?.type === 'xlr:navLayout') {
103
+ if (confirm(`Navigate to layout with code ${event.data.layoutCode}?`)) {
104
+ window.open(event.data.url, '_blank');
105
+ }
106
+ }
107
+ });
108
+ ```
109
+
110
+ ### Event API (non-iframe consumers)
111
+
112
+ The same action also emits a `navLayout` event via the XLR event system, usable by consumers that have direct access to the `IXlr` object:
113
+
114
+ ```typescript
115
+ xlr.on('navLayout', (layoutCode: string, url: string) => {
116
+ // Show your own confirmation UI and open the URL as needed.
117
+ });
118
+ ```
@@ -40,6 +40,17 @@ export declare function getAllAttributes(elem: Element): {
40
40
  * @returns JSON string format of date
41
41
  */
42
42
  export declare function setExpiry(numDays: number): string;
43
+ /**
44
+ * Check whether a media item is currently within its valid date window.
45
+ * Returns true when the media should be shown, false when it should be skipped.
46
+ *
47
+ * Rules:
48
+ * - Empty / invalid fromDt → treat as "no start restriction"
49
+ * - Empty / invalid toDt → treat as "no expiry"
50
+ * - now < fromDt → not yet active → skip
51
+ * - now > toDt → expired → skip
52
+ */
53
+ export declare function isMediaActive(fromDt: string, toDt: string): boolean;
43
54
  /**
44
55
  * Check if given layout exists in the loop using layoutId
45
56
  * @param layouts Schedule loop unique layouts (uniqueLayouts)
@@ -61,5 +72,10 @@ export declare function prepareVideoMedia(media: IMedia, region: IRegion): void;
61
72
  export declare function prepareImageMedia(media: IMedia, region: IRegion): void;
62
73
  export declare function prepareAudioMedia(media: IMedia, region: IRegion): void;
63
74
  export declare function prepareHtmlMedia(media: IMedia, region: IRegion): void;
64
- export declare function playerReportFault(msg: string, media: IMedia): Promise<void>;
75
+ export declare enum FaultCodes {
76
+ FaultVideoSource = 2001,
77
+ FaultVideoUnexpected = 2099
78
+ }
79
+ export declare function playerReportFault(msg: string, media: IMedia, code?: number): Promise<void>;
80
+ export declare function setLayoutIndex(layout: ILayout | undefined, layoutIndex: number): ILayout | undefined;
65
81
  export {};
@@ -1 +1 @@
1
- export { getFileExt, nextId, preloadMediaBlob, getMediaId, fetchJSON, capitalizeStr, audioFileType, videoFileType, setExpiry, composeMediaUrl, fetchText, getDataBlob, composeResourceUrl, composeResourceUrlByPlatform, getIndexByLayoutId, isEmpty, composeBgUrlByPlatform, hasDefaultOnly, isLayoutValid, createMediaElement, playerReportFault, getAllAttributes, prepareAudioMedia, prepareHtmlMedia, prepareImageMedia, prepareVideoMedia, getLayoutIndexByLayoutId, hasSspLayout, type MediaTypes, } from './Generators';
1
+ export { getFileExt, nextId, preloadMediaBlob, getMediaId, fetchJSON, capitalizeStr, audioFileType, videoFileType, setExpiry, composeMediaUrl, fetchText, getDataBlob, composeResourceUrl, composeResourceUrlByPlatform, getIndexByLayoutId, isEmpty, composeBgUrlByPlatform, hasDefaultOnly, isLayoutValid, createMediaElement, playerReportFault, getAllAttributes, prepareAudioMedia, prepareHtmlMedia, prepareImageMedia, prepareVideoMedia, getLayoutIndexByLayoutId, hasSspLayout, isMediaActive, type MediaTypes, FaultCodes, } from './Generators';
@@ -67,6 +67,7 @@ export default class Layout implements ILayout {
67
67
  resetLayout(): Promise<void>;
68
68
  finishAllRegions(): Promise<void[]>;
69
69
  removeLayout(caller?: LayoutPlaybackType): void;
70
+ discardLayout(caller?: LayoutPlaybackType): void;
70
71
  getXlf(): string;
71
72
  isInterrupt(): boolean;
72
73
  on<E extends keyof ILayoutEvents>(event: E, callback: ILayoutEvents[E]): import("nanoevents").Unsubscribe;
@@ -18,6 +18,7 @@ export declare class Media implements IMedia {
18
18
  enableStat: boolean;
19
19
  fileId: string;
20
20
  finished: boolean;
21
+ fromDt: string;
21
22
  html: HTMLElement | null;
22
23
  id: string;
23
24
  idCounter: number;
@@ -41,6 +42,7 @@ export declare class Media implements IMedia {
41
42
  state: MediaState;
42
43
  tempSrc: string;
43
44
  timeoutId: ReturnType<typeof setTimeout>;
45
+ toDt: string;
44
46
  type: string;
45
47
  uri: string;
46
48
  url: string | null;
@@ -1,6 +1,6 @@
1
1
  import Player from "video.js/dist/types/player";
2
2
  import { IMedia } from '../../Types/Media';
3
- import { IXlr } from '../../types';
3
+ import { ConsumerPlatform, IXlr } from '../../types';
4
4
  import './media.css';
5
5
  export declare function composeVideoSource($media: HTMLVideoElement, media: IMedia): HTMLVideoElement;
6
6
  export declare const defaultVjsOpts: {
@@ -13,9 +13,13 @@ export declare const vjsDefaultOptions: (opts?: any) => any;
13
13
  export interface IVideoMediaHandler {
14
14
  player: Player | undefined;
15
15
  duration: number;
16
+ init(): void;
17
+ play(): void;
16
18
  stop(disposeOnly?: boolean): void;
17
19
  }
20
+ export declare const reportToPlayerPlatform: ConsumerPlatform[];
18
21
  export declare function VideoMedia(media: IMedia, xlr: IXlr): {
22
+ player: Player | undefined;
19
23
  duration: number;
20
24
  init: () => void;
21
25
  stop: (disposeOnly?: boolean) => void;
@@ -26,6 +26,7 @@ export type InputLayoutType = {
26
26
  getXlf?(): string;
27
27
  duration?: number;
28
28
  isOverlay?: boolean;
29
+ shareOfVoice?: number;
29
30
  };
30
31
  export type OptionsType = {
31
32
  xlfUrl: string;
@@ -100,6 +101,7 @@ export interface ILayout {
100
101
  finishAllRegions(): Promise<void[]>;
101
102
  inLoop: boolean;
102
103
  removeLayout(caller?: LayoutPlaybackType): void;
104
+ discardLayout(caller?: LayoutPlaybackType): void;
103
105
  xlfString: string;
104
106
  getXlf(): string;
105
107
  ad: any;
@@ -22,6 +22,7 @@ export interface IMedia {
22
22
  enableStat: boolean;
23
23
  fileId: string;
24
24
  finished: boolean;
25
+ fromDt: string;
25
26
  html: HTMLElement | null;
26
27
  id: string;
27
28
  idCounter: number;
@@ -47,6 +48,7 @@ export interface IMedia {
47
48
  stop(): Promise<void>;
48
49
  tempSrc: string;
49
50
  timeoutId: ReturnType<typeof setTimeout>;
51
+ toDt: string;
50
52
  type: string;
51
53
  uri: string;
52
54
  url: string | null;
@@ -55,4 +57,3 @@ export interface IMedia {
55
57
  videoHandler?: IVideoMediaHandler;
56
58
  mediaTimer: ReturnType<typeof setInterval> | undefined;
57
59
  }
58
- export declare const initialMedia: IMedia;
@@ -1,2 +1,2 @@
1
1
  export type { IMedia, } from './Media.types';
2
- export { initialMedia, MediaState, } from './Media.types';
2
+ export { MediaState, } from './Media.types';
@@ -23,6 +23,7 @@ export type IXlrEvents = {
23
23
  overlayEnd: (overlay: ILayout) => void;
24
24
  commandCodeReceived: (commandCode: string) => void;
25
25
  commandStringReceived: (commandString: string) => void;
26
+ navLayout: (layoutCode: string, url: string) => void;
26
27
  };
27
28
  export interface IXlrPlayback {
28
29
  currentLayout: ILayout | undefined;
@@ -48,6 +49,7 @@ export interface IXlr {
48
49
  inputLayouts: InputLayoutType[];
49
50
  isInterrupted: boolean;
50
51
  isLayoutInDOM(containerName: string, layoutId: number): boolean;
52
+ cleanupOrphanedLayouts(keepCurrent?: ILayout | null, keepNext?: ILayout | null): void;
51
53
  isSspEnabled: boolean;
52
54
  isUpdatingLoop: boolean;
53
55
  isUpdatingOverlays: boolean;