@player-ui/react 0.3.0-next.3 → 0.3.0-next.4

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/src/player.tsx CHANGED
@@ -1,5 +1,8 @@
1
1
  /* eslint-disable react/no-this-in-sfc */
2
2
  import React from 'react';
3
+ import { SyncWaterfallHook, AsyncParallelHook } from 'tapable-ts';
4
+ import { Subscribe, useSubscribedState } from '@player-ui/react-subscribe';
5
+ import { Registry } from '@player-ui/partial-match-registry';
3
6
  import type {
4
7
  CompletedState,
5
8
  PlayerPlugin,
@@ -7,25 +10,22 @@ import type {
7
10
  View,
8
11
  } from '@player-ui/player';
9
12
  import { Player } from '@player-ui/player';
10
- import type { AssetRegistryType } from '@player-ui/react-asset';
11
- import { AssetContext } from '@player-ui/react-asset';
12
13
  import { ErrorBoundary } from 'react-error-boundary';
13
- import { PlayerContext } from '@player-ui/react-utils';
14
- import { SyncWaterfallHook, AsyncParallelHook } from 'tapable-ts';
15
- import { Subscribe, useSubscribedState } from '@player-ui/react-subscribe';
16
- import { Registry } from '@player-ui/partial-match-registry';
14
+ import type { AssetRegistryType } from './asset';
15
+ import { AssetContext } from './asset';
16
+ import { PlayerContext } from './utils';
17
17
 
18
- import type { WebPlayerProps } from './app';
18
+ import type { ReactPlayerProps } from './app';
19
19
  import PlayerComp from './app';
20
20
  import OnUpdatePlugin from './plugins/onupdate-plugin';
21
21
 
22
- const WEB_PLAYER_VERSION = '0.3.0-next.3';
23
- const COMMIT = '92ff0044b739d9cce3b1e37bd729f8241d04a2da';
22
+ const WEB_PLAYER_VERSION = '0.3.0-next.4';
23
+ const COMMIT = '774a3cf3b0765796901d03a311a06ee68e690a74';
24
24
 
25
25
  export interface DevtoolsGlobals {
26
26
  /** A global for a plugin to load to Player for devtools */
27
27
  __PLAYER_DEVTOOLS_PLUGIN?: {
28
- new (): WebPlayerPlugin;
28
+ new (): ReactPlayerPlugin;
29
29
  };
30
30
  }
31
31
 
@@ -34,52 +34,52 @@ export type DevtoolsWindow = typeof window & DevtoolsGlobals;
34
34
  const _window: DevtoolsWindow | undefined =
35
35
  typeof window === 'undefined' ? undefined : window;
36
36
 
37
- export interface WebPlayerInfo {
37
+ export interface ReactPlayerInfo {
38
38
  /** Version of the running player */
39
39
  playerVersion: string;
40
40
 
41
- /** Version of the running webplayer */
42
- webplayerVersion: string;
41
+ /** Version of the running reactPlayer */
42
+ reactPlayerVersion: string;
43
43
 
44
44
  /** Hash of the HEAD commit used to build the current player version */
45
45
  playerCommit: string;
46
46
 
47
- /** Hash of the HEAD commit used to build the current webplayer version */
48
- webplayerCommit: string;
47
+ /** Hash of the HEAD commit used to build the current reactPlayer version */
48
+ reactPlayerCommit: string;
49
49
  }
50
50
 
51
- export interface WebPlayerPlugin extends Partial<PlayerPlugin> {
51
+ export interface ReactPlayerPlugin extends Partial<PlayerPlugin> {
52
52
  /** The name of this plugin */
53
53
  name: string;
54
54
 
55
55
  /**
56
56
  * Attach listeners to the web-player instance
57
57
  */
58
- applyWeb?: (webPlayer: WebPlayer) => void;
58
+ applyReact?: (reactPlayer: ReactPlayer) => void;
59
59
  }
60
60
 
61
- export interface WebPlayerOptions {
61
+ export interface ReactPlayerOptions {
62
62
  /** A headless player instance to use */
63
63
  player?: Player;
64
64
 
65
65
  /** A set of plugins to apply to this player */
66
- plugins?: Array<WebPlayerPlugin>;
66
+ plugins?: Array<ReactPlayerPlugin>;
67
67
 
68
68
  /**
69
- * If the underlying webPlayer.Component should use `React.Suspense` to trigger a loading state while waiting for content or content updates.
70
- * It requires that a `React.Suspense` component handler be somewhere in the `webPlayer.Component` hierarchy.
69
+ * If the underlying reactPlayer.Component should use `React.Suspense` to trigger a loading state while waiting for content or content updates.
70
+ * It requires that a `React.Suspense` component handler be somewhere in the `reactPlayer.Component` hierarchy.
71
71
  */
72
72
  suspend?: boolean;
73
73
  }
74
74
 
75
- export type WebPlayerComponentProps = Record<string, unknown>;
75
+ export type ReactPlayerComponentProps = Record<string, unknown>;
76
76
 
77
- /** The React webplayer */
78
- export class WebPlayer {
79
- public readonly options: WebPlayerOptions;
77
+ /** A Player that renders UI through React */
78
+ export class ReactPlayer {
79
+ public readonly options: ReactPlayerOptions;
80
80
  public readonly player: Player;
81
81
  public readonly assetRegistry: AssetRegistryType = new Registry();
82
- public readonly Component: React.ComponentType<WebPlayerComponentProps>;
82
+ public readonly Component: React.ComponentType<ReactPlayerComponentProps>;
83
83
  public readonly hooks = {
84
84
  /**
85
85
  * A hook to create a React Component to be used for Player, regardless of the current flow state
@@ -92,7 +92,7 @@ export class WebPlayer {
92
92
  * Typically this will just be `Asset`
93
93
  */
94
94
  playerComponent: new SyncWaterfallHook<
95
- [React.ComponentType<WebPlayerProps>]
95
+ [React.ComponentType<ReactPlayerProps>]
96
96
  >(),
97
97
 
98
98
  /**
@@ -102,9 +102,9 @@ export class WebPlayer {
102
102
  };
103
103
 
104
104
  private viewUpdateSubscription = new Subscribe<View>();
105
- private webplayerInfo: WebPlayerInfo;
105
+ private reactPlayerInfo: ReactPlayerInfo;
106
106
 
107
- constructor(options?: WebPlayerOptions) {
107
+ constructor(options?: ReactPlayerOptions) {
108
108
  this.options = options ?? {};
109
109
 
110
110
  // Default the suspend option to `true` unless explicitly unset
@@ -131,62 +131,62 @@ export class WebPlayer {
131
131
  this.player = options?.player ?? new Player({ plugins: playerPlugins });
132
132
 
133
133
  plugins.forEach((plugin) => {
134
- if (plugin.applyWeb) {
135
- plugin.applyWeb(this);
134
+ if (plugin.applyReact) {
135
+ plugin.applyReact(this);
136
136
  }
137
137
  });
138
138
 
139
139
  onUpdatePlugin.apply(this.player);
140
140
 
141
141
  this.Component = this.hooks.webComponent.call(this.createReactComp());
142
- this.webplayerInfo = {
142
+ this.reactPlayerInfo = {
143
143
  playerVersion: this.player.getVersion(),
144
144
  playerCommit: this.player.getCommit(),
145
- webplayerVersion: WEB_PLAYER_VERSION,
146
- webplayerCommit: COMMIT,
145
+ reactPlayerVersion: WEB_PLAYER_VERSION,
146
+ reactPlayerCommit: COMMIT,
147
147
  };
148
148
  }
149
149
 
150
150
  /** Returns the current version of the underlying core Player */
151
151
  public getPlayerVersion(): string {
152
- return this.webplayerInfo.playerVersion;
152
+ return this.reactPlayerInfo.playerVersion;
153
153
  }
154
154
 
155
155
  /** Returns the git commit used to build this core Player version */
156
156
  public getPlayerCommit(): string {
157
- return this.webplayerInfo.playerCommit;
157
+ return this.reactPlayerInfo.playerCommit;
158
158
  }
159
159
 
160
160
  /** Find instance of [Plugin] that has been registered to the web player */
161
- public findPlugin<Plugin extends WebPlayerPlugin>(
161
+ public findPlugin<Plugin extends ReactPlayerPlugin>(
162
162
  symbol: symbol
163
163
  ): Plugin | undefined {
164
164
  return this.options.plugins?.find((el) => el.symbol === symbol) as Plugin;
165
165
  }
166
166
 
167
167
  /** Register and apply [Plugin] if one with the same symbol is not already registered. */
168
- public registerPlugin(plugin: WebPlayerPlugin): void {
169
- if (!plugin.applyWeb) return;
168
+ public registerPlugin(plugin: ReactPlayerPlugin): void {
169
+ if (!plugin.applyReact) return;
170
170
 
171
- plugin.applyWeb(this);
171
+ plugin.applyReact(this);
172
172
  this.options.plugins?.push(plugin);
173
173
  }
174
174
 
175
175
  /** Returns the current version of the running React Player */
176
- public getWebPlayerVersion(): string {
177
- return this.webplayerInfo.webplayerVersion;
176
+ public getReactPlayerVersion(): string {
177
+ return this.reactPlayerInfo.reactPlayerVersion;
178
178
  }
179
179
 
180
180
  /** Returns the git commit used to build the React Player version */
181
- public getWebPlayerCommit(): string {
182
- return this.webplayerInfo.webplayerCommit;
181
+ public getReactPlayerCommit(): string {
182
+ return this.reactPlayerInfo.reactPlayerCommit;
183
183
  }
184
184
 
185
- private createReactComp(): React.ComponentType<WebPlayerComponentProps> {
185
+ private createReactComp(): React.ComponentType<ReactPlayerComponentProps> {
186
186
  const ActualPlayerComp = this.hooks.playerComponent.call(PlayerComp);
187
187
 
188
188
  /** the component to use to render Player */
189
- const WebPlayerComponent = () => {
189
+ const ReactPlayerComponent = () => {
190
190
  const view = useSubscribedState<View>(this.viewUpdateSubscription);
191
191
 
192
192
  if (this.options.suspend) {
@@ -217,11 +217,11 @@ export class WebPlayer {
217
217
  );
218
218
  };
219
219
 
220
- return WebPlayerComponent;
220
+ return ReactPlayerComponent;
221
221
  }
222
222
 
223
223
  /**
224
- * Call this method to force the WebPlayer to wait for the next view-update before performing the next render.
224
+ * Call this method to force the ReactPlayer to wait for the next view-update before performing the next render.
225
225
  * If the `suspense` option is set, this will suspend while an update is pending, otherwise nothing will be rendered.
226
226
  */
227
227
  public setWaitForNextViewUpdate() {
@@ -244,3 +244,6 @@ export class WebPlayer {
244
244
  });
245
245
  }
246
246
  }
247
+
248
+ // For compatibility
249
+ export const WebPlayer = ReactPlayer;
@@ -1,10 +1,10 @@
1
1
  import type { PlayerFlowState, Player } from '@player-ui/player';
2
- import type { WebPlayerPlugin } from '../player';
2
+ import type { ReactPlayerPlugin } from '../player';
3
3
 
4
4
  /**
5
5
  * A plugin to tap into state transition changes and call an arbitrary update function
6
6
  */
7
- export class StateTapPlugin implements WebPlayerPlugin {
7
+ export class StateTapPlugin implements ReactPlayerPlugin {
8
8
  name = 'statetap';
9
9
  private callbackFunction: (state: PlayerFlowState) => void;
10
10
 
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Trim leading and trailing slashes from string
3
+ */
4
+ export function trimSlashes(str: string) {
5
+ return str.replace(/^\/+|\/+$/g, '');
6
+ }
7
+
8
+ /**
9
+ * Removes any key: value pairs from an object when the value is null or undefined
10
+ */
11
+ export function removeEmptyValuesFromObject(
12
+ obj: Record<string, any>
13
+ ): Record<string, NonNullable<any>> {
14
+ return Object.keys(obj).reduce((acc, key) => {
15
+ const value = obj[key];
16
+
17
+ if (value !== null && value !== undefined) {
18
+ acc[key] = value;
19
+ }
20
+
21
+ return acc;
22
+ }, {} as Record<string, any>);
23
+ }
24
+
25
+ /** Check if the object has no keys */
26
+ export function isEmptyObject(obj: Record<string, unknown>) {
27
+ return Object.keys(obj).length === 0 && obj.constructor === Object;
28
+ }
29
+
30
+ /** Check if the argument is a function */
31
+ export function isFunction<ReturnType>(
32
+ maybeFn: ReturnType | ((...args: unknown[]) => ReturnType)
33
+ ): maybeFn is (...args: unknown[]) => ReturnType {
34
+ return Boolean(maybeFn instanceof Function || typeof maybeFn === 'function');
35
+ }
36
+
37
+ /**
38
+ * Calls function with provided data or returns original value
39
+ */
40
+ export function callOrReturn<
41
+ ReturnType,
42
+ FnArgs extends Array<unknown> = unknown[],
43
+ FnType = (...args: FnArgs) => ReturnType
44
+ >(maybeFn: FnType | ReturnType, fnArgs: FnArgs): ReturnType {
45
+ if (isFunction(maybeFn)) {
46
+ return maybeFn(fnArgs) as ReturnType;
47
+ }
48
+
49
+ return maybeFn as ReturnType;
50
+ }
@@ -0,0 +1,6 @@
1
+ export * from './player-context';
2
+ export * from './use-logger';
3
+ export * from './use-asset-props';
4
+ export * from './helpers';
5
+ export * from './url';
6
+ export * from './shared-constants';
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import type { Player, NavigationFlowViewState } from '@player-ui/player';
3
+
4
+ export interface PlayerContextType {
5
+ /**
6
+ * An instance of a headless player
7
+ */
8
+ player?: Player;
9
+
10
+ /** The currently rendered view state */
11
+ viewState?: NavigationFlowViewState;
12
+ }
13
+
14
+ export const PlayerContext = React.createContext<PlayerContextType>({});
15
+
16
+ /**
17
+ * A hook to get the current player
18
+ */
19
+ export const usePlayer = () => {
20
+ const { player } = React.useContext(PlayerContext);
21
+
22
+ return player;
23
+ };
@@ -0,0 +1,15 @@
1
+ import { usePlayer } from './player-context';
2
+
3
+ /** Hook to get a constant under a specific namespace */
4
+ export function useGetConstantByType(type: string, key: string): unknown {
5
+ const player = usePlayer();
6
+
7
+ return player?.constantsController.getConstants(key, type);
8
+ }
9
+
10
+ /** Get a constant under the default namespace */
11
+ export function useGetConstant(key: string): unknown {
12
+ const player = usePlayer();
13
+
14
+ return player?.constantsController.getConstants(key, 'constants');
15
+ }
@@ -0,0 +1,22 @@
1
+ import { isEmptyObject } from './helpers';
2
+
3
+ /**
4
+ * Combines a URL with any additional parameters
5
+ */
6
+ export function buildUrl(
7
+ url: string,
8
+ params: Record<string, unknown> = {}
9
+ ): string {
10
+ const baseUrl = new URL(url);
11
+
12
+ if (params && isEmptyObject(params)) {
13
+ return baseUrl.toString();
14
+ }
15
+
16
+ Object.keys(params).forEach((key) => {
17
+ const value = params[key];
18
+ baseUrl.searchParams.append(key, String(value));
19
+ });
20
+
21
+ return baseUrl.toString();
22
+ }
@@ -0,0 +1,9 @@
1
+ import type { Asset } from '@player-ui/player';
2
+
3
+ /** Common props for any dom node */
4
+ export function useAssetProps(asset: Asset) {
5
+ return {
6
+ id: asset.id,
7
+ 'data-asset-type': asset.type,
8
+ };
9
+ }
@@ -0,0 +1,14 @@
1
+ import type { Logger } from '@player-ui/player';
2
+ import { NoopLogger } from '@player-ui/player';
3
+ import { usePlayer } from './player-context';
4
+
5
+ const noopLogger = new NoopLogger();
6
+
7
+ /**
8
+ * A hook to get the logger instance from the current player
9
+ */
10
+ export function useLogger(): Logger {
11
+ const player = usePlayer();
12
+
13
+ return player?.logger ?? noopLogger;
14
+ }
@@ -1,2 +0,0 @@
1
- // Declaration for libraries that don't have types
2
- declare module 'babel-plugin-preval/macro';