@player-devtools/client 0.13.1--canary.13.753 → 0.13.1--canary.16.936

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.
@@ -30,7 +30,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/index.ts
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
- Panel: () => Panel
33
+ Panel: () => Panel,
34
+ createExtensionClient: () => createExtensionClient
34
35
  });
35
36
  module.exports = __toCommonJS(src_exports);
36
37
 
@@ -101,9 +102,12 @@ var PLAYER_PLUGINS = [
101
102
  ];
102
103
 
103
104
  // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/index.ts
104
- var import_messenger = require("@player-devtools/messenger");
105
105
  var import_react2 = require("react");
106
106
 
107
+ // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/client.ts
108
+ var import_messenger = require("@player-devtools/messenger");
109
+ var import_utils2 = require("@player-devtools/utils");
110
+
107
111
  // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/reducer.ts
108
112
  var import_utils = require("@player-devtools/utils");
109
113
  var import_immer = require("immer");
@@ -168,89 +172,83 @@ var reducer = (state, transaction) => {
168
172
  }
169
173
  };
170
174
 
171
- // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/index.ts
175
+ // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/client.ts
172
176
  var NOOP_ID = -1;
177
+ var createExtensionClient = (communicationLayer) => {
178
+ const store = (0, import_utils2.useStateReducer)(reducer, INITIAL_EXTENSION_STATE);
179
+ const messenger = new import_messenger.Messenger({
180
+ context: "devtools",
181
+ messageCallback: (message) => store.dispatch(message),
182
+ ...communicationLayer,
183
+ logger: console
184
+ });
185
+ const selectPlayer = (playerID) => {
186
+ store.dispatch({
187
+ id: NOOP_ID,
188
+ sender: "internal",
189
+ context: "devtools",
190
+ _messenger_: false,
191
+ timestamp: Date.now(),
192
+ type: "PLAYER_DEVTOOLS_PLAYER_SELECTED",
193
+ payload: { playerID }
194
+ });
195
+ messenger.sendMessage({
196
+ type: "PLAYER_DEVTOOLS_PLUGIN_INTERACTION",
197
+ payload: {
198
+ type: "player-selected",
199
+ payload: playerID
200
+ }
201
+ });
202
+ };
203
+ const selectPlugin = (pluginID) => {
204
+ store.dispatch({
205
+ id: NOOP_ID,
206
+ sender: "internal",
207
+ context: "devtools",
208
+ _messenger_: false,
209
+ timestamp: Date.now(),
210
+ type: "PLAYER_DEVTOOLS_PLUGIN_SELECTED",
211
+ payload: { pluginID }
212
+ });
213
+ };
214
+ const handleInteraction = ({
215
+ type,
216
+ payload,
217
+ target
218
+ }) => {
219
+ const resolvedTarget = target ?? store.getState().current.player;
220
+ messenger.sendMessage({
221
+ type: "PLAYER_DEVTOOLS_PLUGIN_INTERACTION",
222
+ payload: { type, payload },
223
+ ...resolvedTarget ? { target: resolvedTarget } : {}
224
+ });
225
+ };
226
+ return {
227
+ getState: store.getState,
228
+ subscribe: store.subscribe,
229
+ selectPlayer,
230
+ selectPlugin,
231
+ handleInteraction,
232
+ destroy: () => messenger.destroy()
233
+ };
234
+ };
235
+
236
+ // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/index.ts
173
237
  var useExtensionState = ({
174
238
  communicationLayer
175
239
  }) => {
176
- const [state, dispatch] = (0, import_react2.useReducer)(reducer, INITIAL_EXTENSION_STATE);
177
- const messengerOptions = (0, import_react2.useMemo)(
178
- () => ({
179
- context: "devtools",
180
- target: "player",
181
- messageCallback: (message) => {
182
- dispatch(message);
183
- },
184
- ...communicationLayer,
185
- logger: console
186
- }),
187
- [dispatch, communicationLayer]
188
- );
189
- const messenger = (0, import_react2.useMemo)(
190
- () => new import_messenger.Messenger(messengerOptions),
191
- [messengerOptions]
192
- );
193
- (0, import_react2.useEffect)(() => {
194
- return () => {
195
- messenger.destroy();
196
- };
197
- }, []);
198
- const selectPlayer = (0, import_react2.useCallback)(
199
- (playerID) => {
200
- dispatch({
201
- id: NOOP_ID,
202
- sender: "internal",
203
- context: "devtools",
204
- _messenger_: false,
205
- timestamp: Date.now(),
206
- type: "PLAYER_DEVTOOLS_PLAYER_SELECTED",
207
- payload: {
208
- playerID
209
- }
210
- });
211
- messenger.sendMessage({
212
- type: "PLAYER_DEVTOOLS_PLUGIN_INTERACTION",
213
- payload: {
214
- type: "player-selected",
215
- payload: playerID
216
- }
217
- });
218
- },
219
- [dispatch]
220
- );
221
- const selectPlugin = (0, import_react2.useCallback)(
222
- (pluginID) => {
223
- dispatch({
224
- id: NOOP_ID,
225
- sender: "internal",
226
- context: "devtools",
227
- _messenger_: false,
228
- timestamp: Date.now(),
229
- type: "PLAYER_DEVTOOLS_PLUGIN_SELECTED",
230
- payload: {
231
- pluginID
232
- }
233
- });
234
- },
235
- [dispatch]
240
+ const client = (0, import_react2.useMemo)(
241
+ () => createExtensionClient(communicationLayer),
242
+ [communicationLayer]
236
243
  );
237
- const handleInteraction = (0, import_react2.useCallback)(
238
- ({
239
- type,
240
- payload
241
- }) => {
242
- messenger.sendMessage({
243
- type: "PLAYER_DEVTOOLS_PLUGIN_INTERACTION",
244
- payload: {
245
- type,
246
- payload
247
- },
248
- ...state.current.player ? { target: state.current.player } : {}
249
- });
250
- },
251
- [messenger]
252
- );
253
- return { state, selectPlayer, selectPlugin, handleInteraction };
244
+ (0, import_react2.useEffect)(() => () => client.destroy(), [client]);
245
+ const state = (0, import_react2.useSyncExternalStore)(client.subscribe, client.getState);
246
+ return {
247
+ state,
248
+ selectPlayer: client.selectPlayer,
249
+ selectPlugin: client.selectPlugin,
250
+ handleInteraction: client.handleInteraction
251
+ };
254
252
  };
255
253
 
256
254
  // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/helpers/flowDiff.ts
@@ -371,6 +369,7 @@ var Panel = ({ communicationLayer, baseTheme }) => {
371
369
  };
372
370
  // Annotate the CommonJS export names for ESM import in node:
373
371
  0 && (module.exports = {
374
- Panel
372
+ Panel,
373
+ createExtensionClient
375
374
  });
376
375
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/index.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/panel/index.tsx","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/constants/index.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/plugins/index.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/index.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/reducer.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/helpers/flowDiff.ts"],"sourcesContent":["export { Panel } from \"./panel\";\n","import React, { useRef } from \"react\";\nimport type {\n MessengerOptions,\n ExtensionSupportedEvents,\n} from \"@player-devtools/types\";\nimport { DataController, Flow, useReactPlayer } from \"@player-ui/react\";\nimport { useEffect } from \"react\";\nimport { ErrorBoundary } from \"react-error-boundary\";\nimport {\n Card,\n CardBody,\n CardHeader,\n ChakraProvider,\n Container,\n extendTheme,\n Flex,\n FormControl,\n FormLabel,\n Heading,\n Select,\n Text,\n type ThemeConfig,\n} from \"@chakra-ui/react\";\n\nimport { ThemeProvider, useDarkMode } from \"@devtools-ds/themes\";\n\nimport { INITIAL_FLOW } from \"../constants\";\nimport { PLAYER_PLUGINS, PUBSUB_PLUGIN } from \"../plugins\";\nimport { useExtensionState } from \"../state\";\nimport { flowDiff } from \"../helpers/flowDiff\";\n\nconst fallbackRender: ErrorBoundary[\"props\"][\"fallbackRender\"] = ({\n error,\n}) => {\n return (\n <Container centerContent>\n <Card>\n <CardHeader>\n <Heading>Ops, something went wrong.</Heading>\n </CardHeader>\n <CardBody>\n <Text as=\"pre\">{error.message}</Text>\n </CardBody>\n </Card>\n </Container>\n );\n};\n\n/**\n * Panel Component\n *\n * This component serves as the main container for the devtools plugin content defined by plugin authors using Player-UI DSL.\n *\n * Props:\n * - `communicationLayer`: An object that allows communication between the devtools and the Player-UI plugins,\n * enabling the exchange of data and events.\n *\n * Features:\n * - Error Handling: Utilizes the `ErrorBoundary` component from `react-error-boundary` to gracefully handle and display errors\n * that may occur during the rendering of the plugin's content.\n * - State Management: Integrates with custom hooks such as `useExtensionState` to manage the state of the plugin and its components.\n * - Player Integration: Uses the `useReactPlayer` hook from `player-ui/react` to render interactive player components based on the\n * DSL defined by the plugin authors.\n *\n * Example Usage:\n * ```tsx\n * <Panel communicationLayer={myCommunicationLayer} />\n * ```\n *\n * Note: The `communicationLayer` prop is essential for the proper functioning of the `Panel` component, as it enables the necessary\n * communication and data exchange with the player-ui/react library.\n */\nexport const Panel: React.FC<{\n /** the communication layer to use for the extension */\n readonly communicationLayer: Pick<\n MessengerOptions<ExtensionSupportedEvents>,\n \"sendMessage\" | \"addListener\" | \"removeListener\"\n >;\n baseTheme?: Record<string, unknown>;\n}> = ({ communicationLayer, baseTheme }) => {\n const { state, selectPlayer, selectPlugin, handleInteraction } =\n useExtensionState({\n communicationLayer,\n });\n\n const { reactPlayer, playerState } = useReactPlayer({\n plugins: PLAYER_PLUGINS,\n });\n\n const dataController = useRef<WeakRef<DataController> | null>(null);\n\n const currentFlow = useRef<Flow | null>(null);\n\n useEffect(() => {\n reactPlayer.player.hooks.dataController.tap(\"devtools-panel\", (d) => {\n dataController.current = new WeakRef(d);\n });\n }, [reactPlayer]);\n\n useEffect(() => {\n // we subscribe to all messages from the devtools plugin\n // so the plugin author can define their own events\n PUBSUB_PLUGIN.subscribe(\"*\", (type: string, payload: string) => {\n handleInteraction({\n type,\n payload,\n });\n });\n }, []);\n\n useEffect(() => {\n const { player, plugin } = state.current;\n\n const flow =\n player && plugin\n ? state.players[player]?.plugins?.[plugin]?.flow || INITIAL_FLOW\n : INITIAL_FLOW;\n\n if (!currentFlow.current) {\n currentFlow.current = flow;\n reactPlayer.start(flow);\n return;\n }\n\n const diff = flowDiff({\n curr: currentFlow.current as Flow,\n next: flow,\n });\n\n if (diff) {\n const { change, value } = diff;\n\n if (change === \"flow\") {\n currentFlow.current = value;\n reactPlayer.start(value);\n } else if (change === \"data\") {\n if (dataController.current) {\n dataController.current.deref()?.set(value as Record<string, unknown>);\n } else {\n reactPlayer.start(flow);\n }\n }\n }\n }, [reactPlayer, state]);\n\n const isDarkMode = useDarkMode();\n const colorMode = isDarkMode ? \"dark\" : \"light\";\n\n const config: ThemeConfig = {\n initialColorMode: colorMode,\n useSystemColorMode: true,\n };\n const theme = extendTheme({ config, ...baseTheme });\n\n const Component = reactPlayer.Component as React.FC;\n\n return (\n <ChakraProvider resetCSS={false} theme={theme}>\n <ThemeProvider theme=\"chrome\" colorScheme={colorMode}>\n <ErrorBoundary fallbackRender={fallbackRender}>\n <Flex\n direction=\"column\"\n h=\"100vh\"\n alignItems={\"normal\"}\n overflow=\"scroll\"\n >\n {state.current.player ? (\n <Flex direction=\"column\" gap=\"20px\">\n <Flex gap=\"16px\">\n <FormControl>\n <FormLabel>Player</FormLabel>\n <Select\n id=\"player\"\n value={state.current.player || \"\"}\n onChange={(event) => selectPlayer(event.target.value)}\n >\n {Object.keys(state.players).map((playerID) => (\n <option key={playerID} value={playerID}>\n {playerID}\n </option>\n ))}\n </Select>\n </FormControl>\n <FormControl>\n <FormLabel>Plugin</FormLabel>\n <Select\n id=\"plugin\"\n value={state.current.plugin || \"\"}\n onChange={(event) => selectPlugin(event.target.value)}\n >\n {Object.keys(\n state.players[state.current.player]?.plugins ?? [],\n ).map((pluginID) => (\n <option key={pluginID} value={pluginID}>\n {pluginID}\n </option>\n ))}\n </Select>\n </FormControl>\n </Flex>\n <Flex width=\"100%\">\n {playerState.status === \"error\" ? (\n fallbackRender({\n error: playerState.error,\n resetErrorBoundary: () => {},\n })\n ) : (\n <Component />\n )}\n </Flex>\n <details>\n <summary>Debug</summary>\n <pre style={{ maxHeight: \"30vh\", overflow: \"scroll\" }}>\n {JSON.stringify(state, null, 2)}\n </pre>\n </details>\n </Flex>\n ) : (\n <Flex justifyContent=\"center\" padding=\"6\">\n <Text>\n No Player-UI instance or devtools plugin detected. Visit{\" \"}\n <a href=\"https://player-ui.github.io/\">\n https://player-ui.github.io/\n </a>{\" \"}\n for more info.\n </Text>\n </Flex>\n )}\n </Flex>\n </ErrorBoundary>\n </ThemeProvider>\n </ChakraProvider>\n );\n};\n","import type { ExtensionState } from \"@player-devtools/types\";\nimport type { Flow } from \"@player-ui/player\";\n\nexport const INITIAL_FLOW: Flow = {\n id: \"initial-flow\",\n views: [\n {\n id: \"view-1\",\n type: \"text\",\n value: \"connecting...\",\n },\n ],\n navigation: {\n BEGIN: \"FLOW_1\",\n FLOW_1: {\n startState: \"VIEW_1\",\n VIEW_1: {\n state_type: \"VIEW\",\n ref: \"view-1\",\n transitions: {},\n },\n },\n },\n};\n\nexport const INITIAL_EXTENSION_STATE: ExtensionState = {\n current: {\n player: null,\n plugin: null,\n },\n players: {},\n};\n","import DevtoolsUIAssetsPlugin from \"@devtools-ui/plugin\";\nimport { PubSubPlugin } from \"@player-ui/pubsub-plugin\";\nimport { CommonExpressionsPlugin } from \"@player-ui/common-expressions-plugin\";\nimport { CommonTypesPlugin } from \"@player-ui/common-types-plugin\";\nimport { DataChangeListenerPlugin } from \"@player-ui/data-change-listener-plugin\";\nimport {\n ConsoleLogger,\n Player,\n PlayerPlugin,\n ReactPlayer,\n type ReactPlayerPlugin,\n} from \"@player-ui/react\";\n\nclass LogForwarder implements PlayerPlugin, ReactPlayerPlugin {\n name = \"Log\";\n apply(player: Player) {\n player.logger.addHandler(new ConsoleLogger(\"trace\", console));\n }\n\n applyReact(reactPlayer: ReactPlayer) {\n this.apply(reactPlayer.player);\n }\n}\n\nexport const PUBSUB_PLUGIN = new PubSubPlugin();\n\nexport const PLAYER_PLUGINS: ReactPlayerPlugin[] = [\n new CommonTypesPlugin(),\n new CommonExpressionsPlugin(),\n new DataChangeListenerPlugin(),\n new DevtoolsUIAssetsPlugin(),\n new LogForwarder(),\n PUBSUB_PLUGIN,\n];\n","import { Messenger } from \"@player-devtools/messenger\";\nimport type {\n ExtensionSupportedEvents,\n MessengerOptions,\n} from \"@player-devtools/types\";\nimport { useCallback, useEffect, useMemo, useReducer } from \"react\";\n\nimport { INITIAL_EXTENSION_STATE } from \"../constants\";\nimport { reducer } from \"./reducer\";\n\nconst NOOP_ID = -1;\n\n/**\n * Custom React hook for managing the state of the devtools extension.\n *\n * This hook initializes the extension's state and sets up a communication layer\n * using the `Messenger` class. It provides methods to select a player or plugin,\n * and handle interactions, which dispatch actions to update the state accordingly.\n *\n */\nexport const useExtensionState = ({\n communicationLayer,\n}: {\n /** the communication layer to use for the extension */\n communicationLayer: Pick<\n MessengerOptions<ExtensionSupportedEvents>,\n \"sendMessage\" | \"addListener\" | \"removeListener\"\n >;\n}) => {\n const [state, dispatch] = useReducer(reducer, INITIAL_EXTENSION_STATE);\n\n const messengerOptions = useMemo<MessengerOptions<ExtensionSupportedEvents>>(\n () => ({\n context: \"devtools\",\n target: \"player\",\n messageCallback: (message) => {\n dispatch(message);\n },\n ...communicationLayer,\n logger: console,\n }),\n [dispatch, communicationLayer],\n );\n\n const messenger = useMemo(\n () => new Messenger(messengerOptions),\n [messengerOptions],\n );\n\n useEffect(() => {\n return () => {\n messenger.destroy();\n };\n }, []);\n\n const selectPlayer = useCallback(\n (playerID: string) => {\n dispatch({\n id: NOOP_ID,\n sender: \"internal\",\n context: \"devtools\",\n _messenger_: false,\n timestamp: Date.now(),\n type: \"PLAYER_DEVTOOLS_PLAYER_SELECTED\",\n payload: {\n playerID,\n },\n });\n\n messenger.sendMessage({\n type: \"PLAYER_DEVTOOLS_PLUGIN_INTERACTION\",\n payload: {\n type: \"player-selected\",\n payload: playerID,\n },\n });\n },\n [dispatch],\n );\n\n const selectPlugin = useCallback(\n (pluginID: string) => {\n dispatch({\n id: NOOP_ID,\n sender: \"internal\",\n context: \"devtools\",\n _messenger_: false,\n timestamp: Date.now(),\n type: \"PLAYER_DEVTOOLS_PLUGIN_SELECTED\",\n payload: {\n pluginID,\n },\n });\n },\n [dispatch],\n );\n\n /**\n * Plugin authors can add interactive elements to the Player-UI content by leveraging\n * the pub-sub plugin and having the handle interaction proxy the message to the inspected\n * Player-UI instance.\n */\n const handleInteraction = useCallback(\n ({\n type,\n payload,\n }: {\n /** interaction type */\n type: string;\n /** interaction payload */\n payload?: string;\n }) => {\n messenger.sendMessage({\n type: \"PLAYER_DEVTOOLS_PLUGIN_INTERACTION\",\n payload: {\n type,\n payload,\n },\n ...(state.current.player ? { target: state.current.player } : {}),\n });\n },\n [messenger],\n );\n\n return { state, selectPlayer, selectPlugin, handleInteraction };\n};\n","import type {\n ExtensionState,\n ExtensionSupportedEvents,\n Transaction,\n} from \"@player-devtools/types\";\nimport { dsetAssign } from \"@player-devtools/utils\";\nimport { produce } from \"immer\";\n\n/** Extension state reducer */\nexport const reducer = (\n state: ExtensionState,\n transaction: Transaction<ExtensionSupportedEvents>,\n): ExtensionState => {\n switch (transaction.type) {\n case \"PLAYER_DEVTOOLS_PLAYER_INIT\":\n return produce(state, (draft) => {\n const {\n sender,\n payload: { plugins },\n } = transaction;\n\n const [plugin] = Object.values(plugins);\n if (!plugin) return;\n\n draft.current.player = sender;\n draft.current.plugin = draft.current.plugin || plugin.id;\n\n // TODO: Verify this works with multiple plugins\n dsetAssign(draft, [\"players\", sender, \"plugins\"], plugins, true);\n dsetAssign(draft.players, [sender, \"active\"], true);\n });\n case \"PLAYER_DEVTOOLS_PLUGIN_FLOW_CHANGE\":\n return produce(state, (draft) => {\n const {\n sender,\n payload: { flow, pluginID },\n } = transaction;\n\n dsetAssign(\n draft,\n [\"players\", sender, \"plugins\", pluginID, \"flow\"],\n flow,\n );\n });\n case \"PLAYER_DEVTOOLS_PLUGIN_DATA_CHANGE\":\n return produce(state, (draft) => {\n const {\n sender,\n payload: { data, pluginID },\n } = transaction;\n dsetAssign(\n draft,\n [\"players\", sender, \"plugins\", pluginID, \"flow\", \"data\"],\n data,\n );\n });\n case \"MESSENGER_EVENT_BATCH\":\n return transaction.payload.events.reduce(reducer, state);\n case \"PLAYER_DEVTOOLS_PLAYER_STOPPED\":\n return produce(state, (draft) => {\n const { sender } = transaction;\n dsetAssign(draft, [\"players\", sender, \"active\"], false);\n });\n case \"PLAYER_DEVTOOLS_PLAYER_SELECTED\":\n return produce(state, (draft) => {\n const { playerID } = transaction.payload;\n draft.current.player = playerID;\n });\n case \"PLAYER_DEVTOOLS_PLUGIN_SELECTED\":\n return produce(state, (draft) => {\n const { pluginID } = transaction.payload;\n draft.current.plugin = pluginID;\n });\n default:\n return state;\n }\n};\n","import type { Flow } from \"@player-ui/react\";\nimport { dequal } from \"dequal\";\n\n/**\n * Compares two Flow objects and identifies if there's a change in their structure or data.\n *\n * This function takes two Flow objects as input, `curr` (current) and `next` (next), and compares them\n * to determine if there's a change in the flow's structure or its data. If there's a change in the flow's\n * structure (excluding the `data` property), it returns an object indicating a \"flow\" change along with the\n * new flow. If there's a change in the `data` property, it returns an object indicating a \"data\" change along\n * with the new data. If there are no changes, it returns null.\n */\nexport const flowDiff = ({\n curr,\n next,\n}: {\n curr: Flow;\n next: Flow;\n}):\n | { change: \"data\"; value: Flow[\"data\"] }\n | { change: \"flow\"; value: Flow }\n | null => {\n // compare flows except for the `data` property\n const currCopy = { ...curr, data: null };\n const nextCopy = { ...next, data: null };\n\n const baseFlowIsEqual = dequal(currCopy, nextCopy);\n\n if (!baseFlowIsEqual) {\n return { change: \"flow\", value: next };\n }\n\n // compare data\n const currData = curr.data;\n const nextData = next.data;\n\n const dataIsEqual = dequal(currData, nextData);\n\n if (!dataIsEqual) {\n return { change: \"data\", value: nextData };\n }\n\n return null;\n};\n"],"mappings":"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","names":["import_react","DevtoolsUIAssetsPlugin","import_react","React"]}
1
+ {"version":3,"sources":["../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/index.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/panel/index.tsx","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/constants/index.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/plugins/index.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/index.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/client.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/reducer.ts","../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/helpers/flowDiff.ts"],"sourcesContent":["export { Panel } from \"./panel\";\nexport { createExtensionClient, type ExtensionClient } from \"./state/client\";\n","import React, { useRef } from \"react\";\nimport type {\n MessengerOptions,\n ExtensionSupportedEvents,\n} from \"@player-devtools/types\";\nimport { DataController, Flow, useReactPlayer } from \"@player-ui/react\";\nimport { useEffect } from \"react\";\nimport { ErrorBoundary } from \"react-error-boundary\";\nimport {\n Card,\n CardBody,\n CardHeader,\n ChakraProvider,\n Container,\n extendTheme,\n Flex,\n FormControl,\n FormLabel,\n Heading,\n Select,\n Text,\n type ThemeConfig,\n} from \"@chakra-ui/react\";\n\nimport { ThemeProvider, useDarkMode } from \"@devtools-ds/themes\";\n\nimport { INITIAL_FLOW } from \"../constants\";\nimport { PLAYER_PLUGINS, PUBSUB_PLUGIN } from \"../plugins\";\nimport { useExtensionState } from \"../state\";\nimport { flowDiff } from \"../helpers/flowDiff\";\n\nconst fallbackRender: ErrorBoundary[\"props\"][\"fallbackRender\"] = ({\n error,\n}) => {\n return (\n <Container centerContent>\n <Card>\n <CardHeader>\n <Heading>Ops, something went wrong.</Heading>\n </CardHeader>\n <CardBody>\n <Text as=\"pre\">{error.message}</Text>\n </CardBody>\n </Card>\n </Container>\n );\n};\n\n/**\n * Panel Component\n *\n * This component serves as the main container for the devtools plugin content defined by plugin authors using Player-UI DSL.\n *\n * Props:\n * - `communicationLayer`: An object that allows communication between the devtools and the Player-UI plugins,\n * enabling the exchange of data and events.\n *\n * Features:\n * - Error Handling: Utilizes the `ErrorBoundary` component from `react-error-boundary` to gracefully handle and display errors\n * that may occur during the rendering of the plugin's content.\n * - State Management: Integrates with custom hooks such as `useExtensionState` to manage the state of the plugin and its components.\n * - Player Integration: Uses the `useReactPlayer` hook from `player-ui/react` to render interactive player components based on the\n * DSL defined by the plugin authors.\n *\n * Example Usage:\n * ```tsx\n * <Panel communicationLayer={myCommunicationLayer} />\n * ```\n *\n * Note: The `communicationLayer` prop is essential for the proper functioning of the `Panel` component, as it enables the necessary\n * communication and data exchange with the player-ui/react library.\n */\nexport const Panel: React.FC<{\n /** the communication layer to use for the extension */\n readonly communicationLayer: Pick<\n MessengerOptions<ExtensionSupportedEvents>,\n \"sendMessage\" | \"addListener\" | \"removeListener\"\n >;\n baseTheme?: Record<string, unknown>;\n}> = ({ communicationLayer, baseTheme }) => {\n const { state, selectPlayer, selectPlugin, handleInteraction } =\n useExtensionState({\n communicationLayer,\n });\n\n const { reactPlayer, playerState } = useReactPlayer({\n plugins: PLAYER_PLUGINS,\n });\n\n const dataController = useRef<WeakRef<DataController> | null>(null);\n\n const currentFlow = useRef<Flow | null>(null);\n\n useEffect(() => {\n reactPlayer.player.hooks.dataController.tap(\"devtools-panel\", (d) => {\n dataController.current = new WeakRef(d);\n });\n }, [reactPlayer]);\n\n useEffect(() => {\n // we subscribe to all messages from the devtools plugin\n // so the plugin author can define their own events\n PUBSUB_PLUGIN.subscribe(\"*\", (type: string, payload: string) => {\n handleInteraction({\n type,\n payload,\n });\n });\n }, []);\n\n useEffect(() => {\n const { player, plugin } = state.current;\n\n const flow =\n player && plugin\n ? state.players[player]?.plugins?.[plugin]?.flow || INITIAL_FLOW\n : INITIAL_FLOW;\n\n if (!currentFlow.current) {\n currentFlow.current = flow;\n reactPlayer.start(flow);\n return;\n }\n\n const diff = flowDiff({\n curr: currentFlow.current as Flow,\n next: flow,\n });\n\n if (diff) {\n const { change, value } = diff;\n\n if (change === \"flow\") {\n currentFlow.current = value;\n reactPlayer.start(value);\n } else if (change === \"data\") {\n if (dataController.current) {\n dataController.current.deref()?.set(value as Record<string, unknown>);\n } else {\n reactPlayer.start(flow);\n }\n }\n }\n }, [reactPlayer, state]);\n\n const isDarkMode = useDarkMode();\n const colorMode = isDarkMode ? \"dark\" : \"light\";\n\n const config: ThemeConfig = {\n initialColorMode: colorMode,\n useSystemColorMode: true,\n };\n const theme = extendTheme({ config, ...baseTheme });\n\n const Component = reactPlayer.Component as React.FC;\n\n return (\n <ChakraProvider resetCSS={false} theme={theme}>\n <ThemeProvider theme=\"chrome\" colorScheme={colorMode}>\n <ErrorBoundary fallbackRender={fallbackRender}>\n <Flex\n direction=\"column\"\n h=\"100vh\"\n alignItems={\"normal\"}\n overflow=\"scroll\"\n >\n {state.current.player ? (\n <Flex direction=\"column\" gap=\"20px\">\n <Flex gap=\"16px\">\n <FormControl>\n <FormLabel>Player</FormLabel>\n <Select\n id=\"player\"\n value={state.current.player || \"\"}\n onChange={(event) => selectPlayer(event.target.value)}\n >\n {Object.keys(state.players).map((playerID) => (\n <option key={playerID} value={playerID}>\n {playerID}\n </option>\n ))}\n </Select>\n </FormControl>\n <FormControl>\n <FormLabel>Plugin</FormLabel>\n <Select\n id=\"plugin\"\n value={state.current.plugin || \"\"}\n onChange={(event) => selectPlugin(event.target.value)}\n >\n {Object.keys(\n state.players[state.current.player]?.plugins ?? [],\n ).map((pluginID) => (\n <option key={pluginID} value={pluginID}>\n {pluginID}\n </option>\n ))}\n </Select>\n </FormControl>\n </Flex>\n <Flex width=\"100%\">\n {playerState.status === \"error\" ? (\n fallbackRender({\n error: playerState.error,\n resetErrorBoundary: () => {},\n })\n ) : (\n <Component />\n )}\n </Flex>\n <details>\n <summary>Debug</summary>\n <pre style={{ maxHeight: \"30vh\", overflow: \"scroll\" }}>\n {JSON.stringify(state, null, 2)}\n </pre>\n </details>\n </Flex>\n ) : (\n <Flex justifyContent=\"center\" padding=\"6\">\n <Text>\n No Player-UI instance or devtools plugin detected. Visit{\" \"}\n <a href=\"https://player-ui.github.io/\">\n https://player-ui.github.io/\n </a>{\" \"}\n for more info.\n </Text>\n </Flex>\n )}\n </Flex>\n </ErrorBoundary>\n </ThemeProvider>\n </ChakraProvider>\n );\n};\n","import type { ExtensionState } from \"@player-devtools/types\";\nimport type { Flow } from \"@player-ui/player\";\n\nexport const INITIAL_FLOW: Flow = {\n id: \"initial-flow\",\n views: [\n {\n id: \"view-1\",\n type: \"text\",\n value: \"connecting...\",\n },\n ],\n navigation: {\n BEGIN: \"FLOW_1\",\n FLOW_1: {\n startState: \"VIEW_1\",\n VIEW_1: {\n state_type: \"VIEW\",\n ref: \"view-1\",\n transitions: {},\n },\n },\n },\n};\n\nexport const INITIAL_EXTENSION_STATE: ExtensionState = {\n current: {\n player: null,\n plugin: null,\n },\n players: {},\n};\n","import DevtoolsUIAssetsPlugin from \"@devtools-ui/plugin\";\nimport { PubSubPlugin } from \"@player-ui/pubsub-plugin\";\nimport { CommonExpressionsPlugin } from \"@player-ui/common-expressions-plugin\";\nimport { CommonTypesPlugin } from \"@player-ui/common-types-plugin\";\nimport { DataChangeListenerPlugin } from \"@player-ui/data-change-listener-plugin\";\nimport {\n ConsoleLogger,\n Player,\n PlayerPlugin,\n ReactPlayer,\n type ReactPlayerPlugin,\n} from \"@player-ui/react\";\n\nclass LogForwarder implements PlayerPlugin, ReactPlayerPlugin {\n name = \"Log\";\n apply(player: Player) {\n player.logger.addHandler(new ConsoleLogger(\"trace\", console));\n }\n\n applyReact(reactPlayer: ReactPlayer) {\n this.apply(reactPlayer.player);\n }\n}\n\nexport const PUBSUB_PLUGIN = new PubSubPlugin();\n\nexport const PLAYER_PLUGINS: ReactPlayerPlugin[] = [\n new CommonTypesPlugin(),\n new CommonExpressionsPlugin(),\n new DataChangeListenerPlugin(),\n new DevtoolsUIAssetsPlugin(),\n new LogForwarder(),\n PUBSUB_PLUGIN,\n];\n","import type { CommunicationLayerMethods } from \"@player-devtools/types\";\nimport { useEffect, useMemo, useSyncExternalStore } from \"react\";\n\nimport { createExtensionClient } from \"./client\";\n\n/**\n * Thin React adapter over `createExtensionClient`.\n *\n * Creates the client once per `communicationLayer` identity, subscribes to\n * state via `useSyncExternalStore`, and tears down the Messenger on unmount.\n */\nexport const useExtensionState = ({\n communicationLayer,\n}: {\n /** the communication layer to use for the extension */\n communicationLayer: CommunicationLayerMethods;\n}) => {\n const client = useMemo(\n () => createExtensionClient(communicationLayer),\n [communicationLayer],\n );\n\n useEffect(() => () => client.destroy(), [client]);\n\n const state = useSyncExternalStore(client.subscribe, client.getState);\n\n return {\n state,\n selectPlayer: client.selectPlayer,\n selectPlugin: client.selectPlugin,\n handleInteraction: client.handleInteraction,\n };\n};\n","import { Messenger } from \"@player-devtools/messenger\";\nimport type {\n CommunicationLayerMethods,\n ExtensionState,\n ExtensionSupportedEvents,\n} from \"@player-devtools/types\";\nimport { useStateReducer } from \"@player-devtools/utils\";\n\nimport { INITIAL_EXTENSION_STATE } from \"../constants\";\nimport { reducer } from \"./reducer\";\n\nconst NOOP_ID = -1;\n\nexport type ExtensionClient = {\n getState: () => ExtensionState;\n subscribe: (fn: (state: ExtensionState) => void) => () => void;\n selectPlayer: (playerID: string) => void;\n selectPlugin: (pluginID: string) => void;\n handleInteraction: (interaction: {\n type: string;\n payload?: string;\n target?: string;\n }) => void;\n destroy: () => void;\n};\n\nexport const createExtensionClient = (\n communicationLayer: CommunicationLayerMethods,\n): ExtensionClient => {\n const store = useStateReducer(reducer, INITIAL_EXTENSION_STATE);\n\n const messenger = new Messenger<ExtensionSupportedEvents>({\n context: \"devtools\",\n messageCallback: (message) => store.dispatch(message),\n ...communicationLayer,\n logger: console,\n });\n\n const selectPlayer = (playerID: string): void => {\n store.dispatch({\n id: NOOP_ID,\n sender: \"internal\",\n context: \"devtools\",\n _messenger_: false,\n timestamp: Date.now(),\n type: \"PLAYER_DEVTOOLS_PLAYER_SELECTED\",\n payload: { playerID },\n });\n\n messenger.sendMessage({\n type: \"PLAYER_DEVTOOLS_PLUGIN_INTERACTION\",\n payload: {\n type: \"player-selected\",\n payload: playerID,\n },\n });\n };\n\n const selectPlugin = (pluginID: string): void => {\n store.dispatch({\n id: NOOP_ID,\n sender: \"internal\",\n context: \"devtools\",\n _messenger_: false,\n timestamp: Date.now(),\n type: \"PLAYER_DEVTOOLS_PLUGIN_SELECTED\",\n payload: { pluginID },\n });\n };\n\n const handleInteraction = ({\n type,\n payload,\n target,\n }: {\n type: string;\n payload?: string;\n /** Player to address; defaults to the currently selected player. */\n target?: string;\n }): void => {\n const resolvedTarget = target ?? store.getState().current.player;\n messenger.sendMessage({\n type: \"PLAYER_DEVTOOLS_PLUGIN_INTERACTION\",\n payload: { type, payload },\n ...(resolvedTarget ? { target: resolvedTarget } : {}),\n });\n };\n\n return {\n getState: store.getState,\n subscribe: store.subscribe,\n selectPlayer,\n selectPlugin,\n handleInteraction,\n destroy: () => messenger.destroy(),\n };\n};\n","import type {\n ExtensionState,\n ExtensionSupportedEvents,\n Transaction,\n} from \"@player-devtools/types\";\nimport { dsetAssign } from \"@player-devtools/utils\";\nimport { produce } from \"immer\";\n\n/** Extension state reducer */\nexport const reducer = (\n state: ExtensionState,\n transaction: Transaction<ExtensionSupportedEvents>,\n): ExtensionState => {\n switch (transaction.type) {\n case \"PLAYER_DEVTOOLS_PLAYER_INIT\":\n return produce(state, (draft) => {\n const {\n sender,\n payload: { plugins },\n } = transaction;\n\n const [plugin] = Object.values(plugins);\n if (!plugin) return;\n\n draft.current.player = sender;\n draft.current.plugin = draft.current.plugin || plugin.id;\n\n // TODO: Verify this works with multiple plugins\n dsetAssign(draft, [\"players\", sender, \"plugins\"], plugins, true);\n dsetAssign(draft.players, [sender, \"active\"], true);\n });\n case \"PLAYER_DEVTOOLS_PLUGIN_FLOW_CHANGE\":\n return produce(state, (draft) => {\n const {\n sender,\n payload: { flow, pluginID },\n } = transaction;\n\n dsetAssign(\n draft,\n [\"players\", sender, \"plugins\", pluginID, \"flow\"],\n flow,\n );\n });\n case \"PLAYER_DEVTOOLS_PLUGIN_DATA_CHANGE\":\n return produce(state, (draft) => {\n const {\n sender,\n payload: { data, pluginID },\n } = transaction;\n dsetAssign(\n draft,\n [\"players\", sender, \"plugins\", pluginID, \"flow\", \"data\"],\n data,\n );\n });\n case \"MESSENGER_EVENT_BATCH\":\n return transaction.payload.events.reduce(reducer, state);\n case \"PLAYER_DEVTOOLS_PLAYER_STOPPED\":\n return produce(state, (draft) => {\n const { sender } = transaction;\n dsetAssign(draft, [\"players\", sender, \"active\"], false);\n });\n case \"PLAYER_DEVTOOLS_PLAYER_SELECTED\":\n return produce(state, (draft) => {\n const { playerID } = transaction.payload;\n draft.current.player = playerID;\n });\n case \"PLAYER_DEVTOOLS_PLUGIN_SELECTED\":\n return produce(state, (draft) => {\n const { pluginID } = transaction.payload;\n draft.current.plugin = pluginID;\n });\n default:\n return state;\n }\n};\n","import type { Flow } from \"@player-ui/react\";\nimport { dequal } from \"dequal\";\n\n/**\n * Compares two Flow objects and identifies if there's a change in their structure or data.\n *\n * This function takes two Flow objects as input, `curr` (current) and `next` (next), and compares them\n * to determine if there's a change in the flow's structure or its data. If there's a change in the flow's\n * structure (excluding the `data` property), it returns an object indicating a \"flow\" change along with the\n * new flow. If there's a change in the `data` property, it returns an object indicating a \"data\" change along\n * with the new data. If there are no changes, it returns null.\n */\nexport const flowDiff = ({\n curr,\n next,\n}: {\n curr: Flow;\n next: Flow;\n}):\n | { change: \"data\"; value: Flow[\"data\"] }\n | { change: \"flow\"; value: Flow }\n | null => {\n // compare flows except for the `data` property\n const currCopy = { ...curr, data: null };\n const nextCopy = { ...next, data: null };\n\n const baseFlowIsEqual = dequal(currCopy, nextCopy);\n\n if (!baseFlowIsEqual) {\n return { change: \"flow\", value: next };\n }\n\n // compare data\n const currData = curr.data;\n const nextData = next.data;\n\n const dataIsEqual = dequal(currData, nextData);\n\n if (!dataIsEqual) {\n return { change: \"data\", value: nextData };\n }\n\n return null;\n};\n"],"mappings":"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","names":["import_react","DevtoolsUIAssetsPlugin","import_react","import_utils","React"]}
@@ -80,8 +80,11 @@ var PLAYER_PLUGINS = [
80
80
  ];
81
81
 
82
82
  // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/index.ts
83
+ import { useEffect, useMemo, useSyncExternalStore } from "react";
84
+
85
+ // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/client.ts
83
86
  import { Messenger } from "@player-devtools/messenger";
84
- import { useCallback, useEffect, useMemo, useReducer } from "react";
87
+ import { useStateReducer } from "@player-devtools/utils";
85
88
 
86
89
  // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/reducer.ts
87
90
  import { dsetAssign } from "@player-devtools/utils";
@@ -147,89 +150,83 @@ var reducer = (state, transaction) => {
147
150
  }
148
151
  };
149
152
 
150
- // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/index.ts
153
+ // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/client.ts
151
154
  var NOOP_ID = -1;
155
+ var createExtensionClient = (communicationLayer) => {
156
+ const store = useStateReducer(reducer, INITIAL_EXTENSION_STATE);
157
+ const messenger = new Messenger({
158
+ context: "devtools",
159
+ messageCallback: (message) => store.dispatch(message),
160
+ ...communicationLayer,
161
+ logger: console
162
+ });
163
+ const selectPlayer = (playerID) => {
164
+ store.dispatch({
165
+ id: NOOP_ID,
166
+ sender: "internal",
167
+ context: "devtools",
168
+ _messenger_: false,
169
+ timestamp: Date.now(),
170
+ type: "PLAYER_DEVTOOLS_PLAYER_SELECTED",
171
+ payload: { playerID }
172
+ });
173
+ messenger.sendMessage({
174
+ type: "PLAYER_DEVTOOLS_PLUGIN_INTERACTION",
175
+ payload: {
176
+ type: "player-selected",
177
+ payload: playerID
178
+ }
179
+ });
180
+ };
181
+ const selectPlugin = (pluginID) => {
182
+ store.dispatch({
183
+ id: NOOP_ID,
184
+ sender: "internal",
185
+ context: "devtools",
186
+ _messenger_: false,
187
+ timestamp: Date.now(),
188
+ type: "PLAYER_DEVTOOLS_PLUGIN_SELECTED",
189
+ payload: { pluginID }
190
+ });
191
+ };
192
+ const handleInteraction = ({
193
+ type,
194
+ payload,
195
+ target
196
+ }) => {
197
+ const resolvedTarget = target ?? store.getState().current.player;
198
+ messenger.sendMessage({
199
+ type: "PLAYER_DEVTOOLS_PLUGIN_INTERACTION",
200
+ payload: { type, payload },
201
+ ...resolvedTarget ? { target: resolvedTarget } : {}
202
+ });
203
+ };
204
+ return {
205
+ getState: store.getState,
206
+ subscribe: store.subscribe,
207
+ selectPlayer,
208
+ selectPlugin,
209
+ handleInteraction,
210
+ destroy: () => messenger.destroy()
211
+ };
212
+ };
213
+
214
+ // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/index.ts
152
215
  var useExtensionState = ({
153
216
  communicationLayer
154
217
  }) => {
155
- const [state, dispatch] = useReducer(reducer, INITIAL_EXTENSION_STATE);
156
- const messengerOptions = useMemo(
157
- () => ({
158
- context: "devtools",
159
- target: "player",
160
- messageCallback: (message) => {
161
- dispatch(message);
162
- },
163
- ...communicationLayer,
164
- logger: console
165
- }),
166
- [dispatch, communicationLayer]
167
- );
168
- const messenger = useMemo(
169
- () => new Messenger(messengerOptions),
170
- [messengerOptions]
171
- );
172
- useEffect(() => {
173
- return () => {
174
- messenger.destroy();
175
- };
176
- }, []);
177
- const selectPlayer = useCallback(
178
- (playerID) => {
179
- dispatch({
180
- id: NOOP_ID,
181
- sender: "internal",
182
- context: "devtools",
183
- _messenger_: false,
184
- timestamp: Date.now(),
185
- type: "PLAYER_DEVTOOLS_PLAYER_SELECTED",
186
- payload: {
187
- playerID
188
- }
189
- });
190
- messenger.sendMessage({
191
- type: "PLAYER_DEVTOOLS_PLUGIN_INTERACTION",
192
- payload: {
193
- type: "player-selected",
194
- payload: playerID
195
- }
196
- });
197
- },
198
- [dispatch]
218
+ const client = useMemo(
219
+ () => createExtensionClient(communicationLayer),
220
+ [communicationLayer]
199
221
  );
200
- const selectPlugin = useCallback(
201
- (pluginID) => {
202
- dispatch({
203
- id: NOOP_ID,
204
- sender: "internal",
205
- context: "devtools",
206
- _messenger_: false,
207
- timestamp: Date.now(),
208
- type: "PLAYER_DEVTOOLS_PLUGIN_SELECTED",
209
- payload: {
210
- pluginID
211
- }
212
- });
213
- },
214
- [dispatch]
215
- );
216
- const handleInteraction = useCallback(
217
- ({
218
- type,
219
- payload
220
- }) => {
221
- messenger.sendMessage({
222
- type: "PLAYER_DEVTOOLS_PLUGIN_INTERACTION",
223
- payload: {
224
- type,
225
- payload
226
- },
227
- ...state.current.player ? { target: state.current.player } : {}
228
- });
229
- },
230
- [messenger]
231
- );
232
- return { state, selectPlayer, selectPlugin, handleInteraction };
222
+ useEffect(() => () => client.destroy(), [client]);
223
+ const state = useSyncExternalStore(client.subscribe, client.getState);
224
+ return {
225
+ state,
226
+ selectPlayer: client.selectPlayer,
227
+ selectPlugin: client.selectPlugin,
228
+ handleInteraction: client.handleInteraction
229
+ };
233
230
  };
234
231
 
235
232
  // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/helpers/flowDiff.ts
@@ -349,6 +346,7 @@ var Panel = ({ communicationLayer, baseTheme }) => {
349
346
  ))));
350
347
  };
351
348
  export {
352
- Panel
349
+ Panel,
350
+ createExtensionClient
353
351
  };
354
352
  //# sourceMappingURL=index.mjs.map
package/dist/index.mjs CHANGED
@@ -80,8 +80,11 @@ var PLAYER_PLUGINS = [
80
80
  ];
81
81
 
82
82
  // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/index.ts
83
+ import { useEffect, useMemo, useSyncExternalStore } from "react";
84
+
85
+ // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/client.ts
83
86
  import { Messenger } from "@player-devtools/messenger";
84
- import { useCallback, useEffect, useMemo, useReducer } from "react";
87
+ import { useStateReducer } from "@player-devtools/utils";
85
88
 
86
89
  // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/reducer.ts
87
90
  import { dsetAssign } from "@player-devtools/utils";
@@ -147,89 +150,83 @@ var reducer = (state, transaction) => {
147
150
  }
148
151
  };
149
152
 
150
- // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/index.ts
153
+ // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/client.ts
151
154
  var NOOP_ID = -1;
155
+ var createExtensionClient = (communicationLayer) => {
156
+ const store = useStateReducer(reducer, INITIAL_EXTENSION_STATE);
157
+ const messenger = new Messenger({
158
+ context: "devtools",
159
+ messageCallback: (message) => store.dispatch(message),
160
+ ...communicationLayer,
161
+ logger: console
162
+ });
163
+ const selectPlayer = (playerID) => {
164
+ store.dispatch({
165
+ id: NOOP_ID,
166
+ sender: "internal",
167
+ context: "devtools",
168
+ _messenger_: false,
169
+ timestamp: Date.now(),
170
+ type: "PLAYER_DEVTOOLS_PLAYER_SELECTED",
171
+ payload: { playerID }
172
+ });
173
+ messenger.sendMessage({
174
+ type: "PLAYER_DEVTOOLS_PLUGIN_INTERACTION",
175
+ payload: {
176
+ type: "player-selected",
177
+ payload: playerID
178
+ }
179
+ });
180
+ };
181
+ const selectPlugin = (pluginID) => {
182
+ store.dispatch({
183
+ id: NOOP_ID,
184
+ sender: "internal",
185
+ context: "devtools",
186
+ _messenger_: false,
187
+ timestamp: Date.now(),
188
+ type: "PLAYER_DEVTOOLS_PLUGIN_SELECTED",
189
+ payload: { pluginID }
190
+ });
191
+ };
192
+ const handleInteraction = ({
193
+ type,
194
+ payload,
195
+ target
196
+ }) => {
197
+ const resolvedTarget = target ?? store.getState().current.player;
198
+ messenger.sendMessage({
199
+ type: "PLAYER_DEVTOOLS_PLUGIN_INTERACTION",
200
+ payload: { type, payload },
201
+ ...resolvedTarget ? { target: resolvedTarget } : {}
202
+ });
203
+ };
204
+ return {
205
+ getState: store.getState,
206
+ subscribe: store.subscribe,
207
+ selectPlayer,
208
+ selectPlugin,
209
+ handleInteraction,
210
+ destroy: () => messenger.destroy()
211
+ };
212
+ };
213
+
214
+ // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/index.ts
152
215
  var useExtensionState = ({
153
216
  communicationLayer
154
217
  }) => {
155
- const [state, dispatch] = useReducer(reducer, INITIAL_EXTENSION_STATE);
156
- const messengerOptions = useMemo(
157
- () => ({
158
- context: "devtools",
159
- target: "player",
160
- messageCallback: (message) => {
161
- dispatch(message);
162
- },
163
- ...communicationLayer,
164
- logger: console
165
- }),
166
- [dispatch, communicationLayer]
167
- );
168
- const messenger = useMemo(
169
- () => new Messenger(messengerOptions),
170
- [messengerOptions]
171
- );
172
- useEffect(() => {
173
- return () => {
174
- messenger.destroy();
175
- };
176
- }, []);
177
- const selectPlayer = useCallback(
178
- (playerID) => {
179
- dispatch({
180
- id: NOOP_ID,
181
- sender: "internal",
182
- context: "devtools",
183
- _messenger_: false,
184
- timestamp: Date.now(),
185
- type: "PLAYER_DEVTOOLS_PLAYER_SELECTED",
186
- payload: {
187
- playerID
188
- }
189
- });
190
- messenger.sendMessage({
191
- type: "PLAYER_DEVTOOLS_PLUGIN_INTERACTION",
192
- payload: {
193
- type: "player-selected",
194
- payload: playerID
195
- }
196
- });
197
- },
198
- [dispatch]
218
+ const client = useMemo(
219
+ () => createExtensionClient(communicationLayer),
220
+ [communicationLayer]
199
221
  );
200
- const selectPlugin = useCallback(
201
- (pluginID) => {
202
- dispatch({
203
- id: NOOP_ID,
204
- sender: "internal",
205
- context: "devtools",
206
- _messenger_: false,
207
- timestamp: Date.now(),
208
- type: "PLAYER_DEVTOOLS_PLUGIN_SELECTED",
209
- payload: {
210
- pluginID
211
- }
212
- });
213
- },
214
- [dispatch]
215
- );
216
- const handleInteraction = useCallback(
217
- ({
218
- type,
219
- payload
220
- }) => {
221
- messenger.sendMessage({
222
- type: "PLAYER_DEVTOOLS_PLUGIN_INTERACTION",
223
- payload: {
224
- type,
225
- payload
226
- },
227
- ...state.current.player ? { target: state.current.player } : {}
228
- });
229
- },
230
- [messenger]
231
- );
232
- return { state, selectPlayer, selectPlugin, handleInteraction };
222
+ useEffect(() => () => client.destroy(), [client]);
223
+ const state = useSyncExternalStore(client.subscribe, client.getState);
224
+ return {
225
+ state,
226
+ selectPlayer: client.selectPlayer,
227
+ selectPlugin: client.selectPlugin,
228
+ handleInteraction: client.handleInteraction
229
+ };
233
230
  };
234
231
 
235
232
  // ../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/helpers/flowDiff.ts
@@ -349,6 +346,7 @@ var Panel = ({ communicationLayer, baseTheme }) => {
349
346
  ))));
350
347
  };
351
348
  export {
352
- Panel
349
+ Panel,
350
+ createExtensionClient
353
351
  };
354
352
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/panel/index.tsx","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/constants/index.ts","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/plugins/index.ts","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/index.ts","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/reducer.ts","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/helpers/flowDiff.ts"],"sourcesContent":["import React, { useRef } from \"react\";\nimport type {\n MessengerOptions,\n ExtensionSupportedEvents,\n} from \"@player-devtools/types\";\nimport { DataController, Flow, useReactPlayer } from \"@player-ui/react\";\nimport { useEffect } from \"react\";\nimport { ErrorBoundary } from \"react-error-boundary\";\nimport {\n Card,\n CardBody,\n CardHeader,\n ChakraProvider,\n Container,\n extendTheme,\n Flex,\n FormControl,\n FormLabel,\n Heading,\n Select,\n Text,\n type ThemeConfig,\n} from \"@chakra-ui/react\";\n\nimport { ThemeProvider, useDarkMode } from \"@devtools-ds/themes\";\n\nimport { INITIAL_FLOW } from \"../constants\";\nimport { PLAYER_PLUGINS, PUBSUB_PLUGIN } from \"../plugins\";\nimport { useExtensionState } from \"../state\";\nimport { flowDiff } from \"../helpers/flowDiff\";\n\nconst fallbackRender: ErrorBoundary[\"props\"][\"fallbackRender\"] = ({\n error,\n}) => {\n return (\n <Container centerContent>\n <Card>\n <CardHeader>\n <Heading>Ops, something went wrong.</Heading>\n </CardHeader>\n <CardBody>\n <Text as=\"pre\">{error.message}</Text>\n </CardBody>\n </Card>\n </Container>\n );\n};\n\n/**\n * Panel Component\n *\n * This component serves as the main container for the devtools plugin content defined by plugin authors using Player-UI DSL.\n *\n * Props:\n * - `communicationLayer`: An object that allows communication between the devtools and the Player-UI plugins,\n * enabling the exchange of data and events.\n *\n * Features:\n * - Error Handling: Utilizes the `ErrorBoundary` component from `react-error-boundary` to gracefully handle and display errors\n * that may occur during the rendering of the plugin's content.\n * - State Management: Integrates with custom hooks such as `useExtensionState` to manage the state of the plugin and its components.\n * - Player Integration: Uses the `useReactPlayer` hook from `player-ui/react` to render interactive player components based on the\n * DSL defined by the plugin authors.\n *\n * Example Usage:\n * ```tsx\n * <Panel communicationLayer={myCommunicationLayer} />\n * ```\n *\n * Note: The `communicationLayer` prop is essential for the proper functioning of the `Panel` component, as it enables the necessary\n * communication and data exchange with the player-ui/react library.\n */\nexport const Panel: React.FC<{\n /** the communication layer to use for the extension */\n readonly communicationLayer: Pick<\n MessengerOptions<ExtensionSupportedEvents>,\n \"sendMessage\" | \"addListener\" | \"removeListener\"\n >;\n baseTheme?: Record<string, unknown>;\n}> = ({ communicationLayer, baseTheme }) => {\n const { state, selectPlayer, selectPlugin, handleInteraction } =\n useExtensionState({\n communicationLayer,\n });\n\n const { reactPlayer, playerState } = useReactPlayer({\n plugins: PLAYER_PLUGINS,\n });\n\n const dataController = useRef<WeakRef<DataController> | null>(null);\n\n const currentFlow = useRef<Flow | null>(null);\n\n useEffect(() => {\n reactPlayer.player.hooks.dataController.tap(\"devtools-panel\", (d) => {\n dataController.current = new WeakRef(d);\n });\n }, [reactPlayer]);\n\n useEffect(() => {\n // we subscribe to all messages from the devtools plugin\n // so the plugin author can define their own events\n PUBSUB_PLUGIN.subscribe(\"*\", (type: string, payload: string) => {\n handleInteraction({\n type,\n payload,\n });\n });\n }, []);\n\n useEffect(() => {\n const { player, plugin } = state.current;\n\n const flow =\n player && plugin\n ? state.players[player]?.plugins?.[plugin]?.flow || INITIAL_FLOW\n : INITIAL_FLOW;\n\n if (!currentFlow.current) {\n currentFlow.current = flow;\n reactPlayer.start(flow);\n return;\n }\n\n const diff = flowDiff({\n curr: currentFlow.current as Flow,\n next: flow,\n });\n\n if (diff) {\n const { change, value } = diff;\n\n if (change === \"flow\") {\n currentFlow.current = value;\n reactPlayer.start(value);\n } else if (change === \"data\") {\n if (dataController.current) {\n dataController.current.deref()?.set(value as Record<string, unknown>);\n } else {\n reactPlayer.start(flow);\n }\n }\n }\n }, [reactPlayer, state]);\n\n const isDarkMode = useDarkMode();\n const colorMode = isDarkMode ? \"dark\" : \"light\";\n\n const config: ThemeConfig = {\n initialColorMode: colorMode,\n useSystemColorMode: true,\n };\n const theme = extendTheme({ config, ...baseTheme });\n\n const Component = reactPlayer.Component as React.FC;\n\n return (\n <ChakraProvider resetCSS={false} theme={theme}>\n <ThemeProvider theme=\"chrome\" colorScheme={colorMode}>\n <ErrorBoundary fallbackRender={fallbackRender}>\n <Flex\n direction=\"column\"\n h=\"100vh\"\n alignItems={\"normal\"}\n overflow=\"scroll\"\n >\n {state.current.player ? (\n <Flex direction=\"column\" gap=\"20px\">\n <Flex gap=\"16px\">\n <FormControl>\n <FormLabel>Player</FormLabel>\n <Select\n id=\"player\"\n value={state.current.player || \"\"}\n onChange={(event) => selectPlayer(event.target.value)}\n >\n {Object.keys(state.players).map((playerID) => (\n <option key={playerID} value={playerID}>\n {playerID}\n </option>\n ))}\n </Select>\n </FormControl>\n <FormControl>\n <FormLabel>Plugin</FormLabel>\n <Select\n id=\"plugin\"\n value={state.current.plugin || \"\"}\n onChange={(event) => selectPlugin(event.target.value)}\n >\n {Object.keys(\n state.players[state.current.player]?.plugins ?? [],\n ).map((pluginID) => (\n <option key={pluginID} value={pluginID}>\n {pluginID}\n </option>\n ))}\n </Select>\n </FormControl>\n </Flex>\n <Flex width=\"100%\">\n {playerState.status === \"error\" ? (\n fallbackRender({\n error: playerState.error,\n resetErrorBoundary: () => {},\n })\n ) : (\n <Component />\n )}\n </Flex>\n <details>\n <summary>Debug</summary>\n <pre style={{ maxHeight: \"30vh\", overflow: \"scroll\" }}>\n {JSON.stringify(state, null, 2)}\n </pre>\n </details>\n </Flex>\n ) : (\n <Flex justifyContent=\"center\" padding=\"6\">\n <Text>\n No Player-UI instance or devtools plugin detected. Visit{\" \"}\n <a href=\"https://player-ui.github.io/\">\n https://player-ui.github.io/\n </a>{\" \"}\n for more info.\n </Text>\n </Flex>\n )}\n </Flex>\n </ErrorBoundary>\n </ThemeProvider>\n </ChakraProvider>\n );\n};\n","import type { ExtensionState } from \"@player-devtools/types\";\nimport type { Flow } from \"@player-ui/player\";\n\nexport const INITIAL_FLOW: Flow = {\n id: \"initial-flow\",\n views: [\n {\n id: \"view-1\",\n type: \"text\",\n value: \"connecting...\",\n },\n ],\n navigation: {\n BEGIN: \"FLOW_1\",\n FLOW_1: {\n startState: \"VIEW_1\",\n VIEW_1: {\n state_type: \"VIEW\",\n ref: \"view-1\",\n transitions: {},\n },\n },\n },\n};\n\nexport const INITIAL_EXTENSION_STATE: ExtensionState = {\n current: {\n player: null,\n plugin: null,\n },\n players: {},\n};\n","import DevtoolsUIAssetsPlugin from \"@devtools-ui/plugin\";\nimport { PubSubPlugin } from \"@player-ui/pubsub-plugin\";\nimport { CommonExpressionsPlugin } from \"@player-ui/common-expressions-plugin\";\nimport { CommonTypesPlugin } from \"@player-ui/common-types-plugin\";\nimport { DataChangeListenerPlugin } from \"@player-ui/data-change-listener-plugin\";\nimport {\n ConsoleLogger,\n Player,\n PlayerPlugin,\n ReactPlayer,\n type ReactPlayerPlugin,\n} from \"@player-ui/react\";\n\nclass LogForwarder implements PlayerPlugin, ReactPlayerPlugin {\n name = \"Log\";\n apply(player: Player) {\n player.logger.addHandler(new ConsoleLogger(\"trace\", console));\n }\n\n applyReact(reactPlayer: ReactPlayer) {\n this.apply(reactPlayer.player);\n }\n}\n\nexport const PUBSUB_PLUGIN = new PubSubPlugin();\n\nexport const PLAYER_PLUGINS: ReactPlayerPlugin[] = [\n new CommonTypesPlugin(),\n new CommonExpressionsPlugin(),\n new DataChangeListenerPlugin(),\n new DevtoolsUIAssetsPlugin(),\n new LogForwarder(),\n PUBSUB_PLUGIN,\n];\n","import { Messenger } from \"@player-devtools/messenger\";\nimport type {\n ExtensionSupportedEvents,\n MessengerOptions,\n} from \"@player-devtools/types\";\nimport { useCallback, useEffect, useMemo, useReducer } from \"react\";\n\nimport { INITIAL_EXTENSION_STATE } from \"../constants\";\nimport { reducer } from \"./reducer\";\n\nconst NOOP_ID = -1;\n\n/**\n * Custom React hook for managing the state of the devtools extension.\n *\n * This hook initializes the extension's state and sets up a communication layer\n * using the `Messenger` class. It provides methods to select a player or plugin,\n * and handle interactions, which dispatch actions to update the state accordingly.\n *\n */\nexport const useExtensionState = ({\n communicationLayer,\n}: {\n /** the communication layer to use for the extension */\n communicationLayer: Pick<\n MessengerOptions<ExtensionSupportedEvents>,\n \"sendMessage\" | \"addListener\" | \"removeListener\"\n >;\n}) => {\n const [state, dispatch] = useReducer(reducer, INITIAL_EXTENSION_STATE);\n\n const messengerOptions = useMemo<MessengerOptions<ExtensionSupportedEvents>>(\n () => ({\n context: \"devtools\",\n target: \"player\",\n messageCallback: (message) => {\n dispatch(message);\n },\n ...communicationLayer,\n logger: console,\n }),\n [dispatch, communicationLayer],\n );\n\n const messenger = useMemo(\n () => new Messenger(messengerOptions),\n [messengerOptions],\n );\n\n useEffect(() => {\n return () => {\n messenger.destroy();\n };\n }, []);\n\n const selectPlayer = useCallback(\n (playerID: string) => {\n dispatch({\n id: NOOP_ID,\n sender: \"internal\",\n context: \"devtools\",\n _messenger_: false,\n timestamp: Date.now(),\n type: \"PLAYER_DEVTOOLS_PLAYER_SELECTED\",\n payload: {\n playerID,\n },\n });\n\n messenger.sendMessage({\n type: \"PLAYER_DEVTOOLS_PLUGIN_INTERACTION\",\n payload: {\n type: \"player-selected\",\n payload: playerID,\n },\n });\n },\n [dispatch],\n );\n\n const selectPlugin = useCallback(\n (pluginID: string) => {\n dispatch({\n id: NOOP_ID,\n sender: \"internal\",\n context: \"devtools\",\n _messenger_: false,\n timestamp: Date.now(),\n type: \"PLAYER_DEVTOOLS_PLUGIN_SELECTED\",\n payload: {\n pluginID,\n },\n });\n },\n [dispatch],\n );\n\n /**\n * Plugin authors can add interactive elements to the Player-UI content by leveraging\n * the pub-sub plugin and having the handle interaction proxy the message to the inspected\n * Player-UI instance.\n */\n const handleInteraction = useCallback(\n ({\n type,\n payload,\n }: {\n /** interaction type */\n type: string;\n /** interaction payload */\n payload?: string;\n }) => {\n messenger.sendMessage({\n type: \"PLAYER_DEVTOOLS_PLUGIN_INTERACTION\",\n payload: {\n type,\n payload,\n },\n ...(state.current.player ? { target: state.current.player } : {}),\n });\n },\n [messenger],\n );\n\n return { state, selectPlayer, selectPlugin, handleInteraction };\n};\n","import type {\n ExtensionState,\n ExtensionSupportedEvents,\n Transaction,\n} from \"@player-devtools/types\";\nimport { dsetAssign } from \"@player-devtools/utils\";\nimport { produce } from \"immer\";\n\n/** Extension state reducer */\nexport const reducer = (\n state: ExtensionState,\n transaction: Transaction<ExtensionSupportedEvents>,\n): ExtensionState => {\n switch (transaction.type) {\n case \"PLAYER_DEVTOOLS_PLAYER_INIT\":\n return produce(state, (draft) => {\n const {\n sender,\n payload: { plugins },\n } = transaction;\n\n const [plugin] = Object.values(plugins);\n if (!plugin) return;\n\n draft.current.player = sender;\n draft.current.plugin = draft.current.plugin || plugin.id;\n\n // TODO: Verify this works with multiple plugins\n dsetAssign(draft, [\"players\", sender, \"plugins\"], plugins, true);\n dsetAssign(draft.players, [sender, \"active\"], true);\n });\n case \"PLAYER_DEVTOOLS_PLUGIN_FLOW_CHANGE\":\n return produce(state, (draft) => {\n const {\n sender,\n payload: { flow, pluginID },\n } = transaction;\n\n dsetAssign(\n draft,\n [\"players\", sender, \"plugins\", pluginID, \"flow\"],\n flow,\n );\n });\n case \"PLAYER_DEVTOOLS_PLUGIN_DATA_CHANGE\":\n return produce(state, (draft) => {\n const {\n sender,\n payload: { data, pluginID },\n } = transaction;\n dsetAssign(\n draft,\n [\"players\", sender, \"plugins\", pluginID, \"flow\", \"data\"],\n data,\n );\n });\n case \"MESSENGER_EVENT_BATCH\":\n return transaction.payload.events.reduce(reducer, state);\n case \"PLAYER_DEVTOOLS_PLAYER_STOPPED\":\n return produce(state, (draft) => {\n const { sender } = transaction;\n dsetAssign(draft, [\"players\", sender, \"active\"], false);\n });\n case \"PLAYER_DEVTOOLS_PLAYER_SELECTED\":\n return produce(state, (draft) => {\n const { playerID } = transaction.payload;\n draft.current.player = playerID;\n });\n case \"PLAYER_DEVTOOLS_PLUGIN_SELECTED\":\n return produce(state, (draft) => {\n const { pluginID } = transaction.payload;\n draft.current.plugin = pluginID;\n });\n default:\n return state;\n }\n};\n","import type { Flow } from \"@player-ui/react\";\nimport { dequal } from \"dequal\";\n\n/**\n * Compares two Flow objects and identifies if there's a change in their structure or data.\n *\n * This function takes two Flow objects as input, `curr` (current) and `next` (next), and compares them\n * to determine if there's a change in the flow's structure or its data. If there's a change in the flow's\n * structure (excluding the `data` property), it returns an object indicating a \"flow\" change along with the\n * new flow. If there's a change in the `data` property, it returns an object indicating a \"data\" change along\n * with the new data. If there are no changes, it returns null.\n */\nexport const flowDiff = ({\n curr,\n next,\n}: {\n curr: Flow;\n next: Flow;\n}):\n | { change: \"data\"; value: Flow[\"data\"] }\n | { change: \"flow\"; value: Flow }\n | null => {\n // compare flows except for the `data` property\n const currCopy = { ...curr, data: null };\n const nextCopy = { ...next, data: null };\n\n const baseFlowIsEqual = dequal(currCopy, nextCopy);\n\n if (!baseFlowIsEqual) {\n return { change: \"flow\", value: next };\n }\n\n // compare data\n const currData = curr.data;\n const nextData = next.data;\n\n const dataIsEqual = dequal(currData, nextData);\n\n if (!dataIsEqual) {\n return { change: \"data\", value: nextData };\n }\n\n return null;\n};\n"],"mappings":"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","names":["useEffect","useEffect"]}
1
+ {"version":3,"sources":["../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/panel/index.tsx","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/constants/index.ts","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/plugins/index.ts","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/index.ts","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/client.ts","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/state/reducer.ts","../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/devtools/client/src/helpers/flowDiff.ts"],"sourcesContent":["import React, { useRef } from \"react\";\nimport type {\n MessengerOptions,\n ExtensionSupportedEvents,\n} from \"@player-devtools/types\";\nimport { DataController, Flow, useReactPlayer } from \"@player-ui/react\";\nimport { useEffect } from \"react\";\nimport { ErrorBoundary } from \"react-error-boundary\";\nimport {\n Card,\n CardBody,\n CardHeader,\n ChakraProvider,\n Container,\n extendTheme,\n Flex,\n FormControl,\n FormLabel,\n Heading,\n Select,\n Text,\n type ThemeConfig,\n} from \"@chakra-ui/react\";\n\nimport { ThemeProvider, useDarkMode } from \"@devtools-ds/themes\";\n\nimport { INITIAL_FLOW } from \"../constants\";\nimport { PLAYER_PLUGINS, PUBSUB_PLUGIN } from \"../plugins\";\nimport { useExtensionState } from \"../state\";\nimport { flowDiff } from \"../helpers/flowDiff\";\n\nconst fallbackRender: ErrorBoundary[\"props\"][\"fallbackRender\"] = ({\n error,\n}) => {\n return (\n <Container centerContent>\n <Card>\n <CardHeader>\n <Heading>Ops, something went wrong.</Heading>\n </CardHeader>\n <CardBody>\n <Text as=\"pre\">{error.message}</Text>\n </CardBody>\n </Card>\n </Container>\n );\n};\n\n/**\n * Panel Component\n *\n * This component serves as the main container for the devtools plugin content defined by plugin authors using Player-UI DSL.\n *\n * Props:\n * - `communicationLayer`: An object that allows communication between the devtools and the Player-UI plugins,\n * enabling the exchange of data and events.\n *\n * Features:\n * - Error Handling: Utilizes the `ErrorBoundary` component from `react-error-boundary` to gracefully handle and display errors\n * that may occur during the rendering of the plugin's content.\n * - State Management: Integrates with custom hooks such as `useExtensionState` to manage the state of the plugin and its components.\n * - Player Integration: Uses the `useReactPlayer` hook from `player-ui/react` to render interactive player components based on the\n * DSL defined by the plugin authors.\n *\n * Example Usage:\n * ```tsx\n * <Panel communicationLayer={myCommunicationLayer} />\n * ```\n *\n * Note: The `communicationLayer` prop is essential for the proper functioning of the `Panel` component, as it enables the necessary\n * communication and data exchange with the player-ui/react library.\n */\nexport const Panel: React.FC<{\n /** the communication layer to use for the extension */\n readonly communicationLayer: Pick<\n MessengerOptions<ExtensionSupportedEvents>,\n \"sendMessage\" | \"addListener\" | \"removeListener\"\n >;\n baseTheme?: Record<string, unknown>;\n}> = ({ communicationLayer, baseTheme }) => {\n const { state, selectPlayer, selectPlugin, handleInteraction } =\n useExtensionState({\n communicationLayer,\n });\n\n const { reactPlayer, playerState } = useReactPlayer({\n plugins: PLAYER_PLUGINS,\n });\n\n const dataController = useRef<WeakRef<DataController> | null>(null);\n\n const currentFlow = useRef<Flow | null>(null);\n\n useEffect(() => {\n reactPlayer.player.hooks.dataController.tap(\"devtools-panel\", (d) => {\n dataController.current = new WeakRef(d);\n });\n }, [reactPlayer]);\n\n useEffect(() => {\n // we subscribe to all messages from the devtools plugin\n // so the plugin author can define their own events\n PUBSUB_PLUGIN.subscribe(\"*\", (type: string, payload: string) => {\n handleInteraction({\n type,\n payload,\n });\n });\n }, []);\n\n useEffect(() => {\n const { player, plugin } = state.current;\n\n const flow =\n player && plugin\n ? state.players[player]?.plugins?.[plugin]?.flow || INITIAL_FLOW\n : INITIAL_FLOW;\n\n if (!currentFlow.current) {\n currentFlow.current = flow;\n reactPlayer.start(flow);\n return;\n }\n\n const diff = flowDiff({\n curr: currentFlow.current as Flow,\n next: flow,\n });\n\n if (diff) {\n const { change, value } = diff;\n\n if (change === \"flow\") {\n currentFlow.current = value;\n reactPlayer.start(value);\n } else if (change === \"data\") {\n if (dataController.current) {\n dataController.current.deref()?.set(value as Record<string, unknown>);\n } else {\n reactPlayer.start(flow);\n }\n }\n }\n }, [reactPlayer, state]);\n\n const isDarkMode = useDarkMode();\n const colorMode = isDarkMode ? \"dark\" : \"light\";\n\n const config: ThemeConfig = {\n initialColorMode: colorMode,\n useSystemColorMode: true,\n };\n const theme = extendTheme({ config, ...baseTheme });\n\n const Component = reactPlayer.Component as React.FC;\n\n return (\n <ChakraProvider resetCSS={false} theme={theme}>\n <ThemeProvider theme=\"chrome\" colorScheme={colorMode}>\n <ErrorBoundary fallbackRender={fallbackRender}>\n <Flex\n direction=\"column\"\n h=\"100vh\"\n alignItems={\"normal\"}\n overflow=\"scroll\"\n >\n {state.current.player ? (\n <Flex direction=\"column\" gap=\"20px\">\n <Flex gap=\"16px\">\n <FormControl>\n <FormLabel>Player</FormLabel>\n <Select\n id=\"player\"\n value={state.current.player || \"\"}\n onChange={(event) => selectPlayer(event.target.value)}\n >\n {Object.keys(state.players).map((playerID) => (\n <option key={playerID} value={playerID}>\n {playerID}\n </option>\n ))}\n </Select>\n </FormControl>\n <FormControl>\n <FormLabel>Plugin</FormLabel>\n <Select\n id=\"plugin\"\n value={state.current.plugin || \"\"}\n onChange={(event) => selectPlugin(event.target.value)}\n >\n {Object.keys(\n state.players[state.current.player]?.plugins ?? [],\n ).map((pluginID) => (\n <option key={pluginID} value={pluginID}>\n {pluginID}\n </option>\n ))}\n </Select>\n </FormControl>\n </Flex>\n <Flex width=\"100%\">\n {playerState.status === \"error\" ? (\n fallbackRender({\n error: playerState.error,\n resetErrorBoundary: () => {},\n })\n ) : (\n <Component />\n )}\n </Flex>\n <details>\n <summary>Debug</summary>\n <pre style={{ maxHeight: \"30vh\", overflow: \"scroll\" }}>\n {JSON.stringify(state, null, 2)}\n </pre>\n </details>\n </Flex>\n ) : (\n <Flex justifyContent=\"center\" padding=\"6\">\n <Text>\n No Player-UI instance or devtools plugin detected. Visit{\" \"}\n <a href=\"https://player-ui.github.io/\">\n https://player-ui.github.io/\n </a>{\" \"}\n for more info.\n </Text>\n </Flex>\n )}\n </Flex>\n </ErrorBoundary>\n </ThemeProvider>\n </ChakraProvider>\n );\n};\n","import type { ExtensionState } from \"@player-devtools/types\";\nimport type { Flow } from \"@player-ui/player\";\n\nexport const INITIAL_FLOW: Flow = {\n id: \"initial-flow\",\n views: [\n {\n id: \"view-1\",\n type: \"text\",\n value: \"connecting...\",\n },\n ],\n navigation: {\n BEGIN: \"FLOW_1\",\n FLOW_1: {\n startState: \"VIEW_1\",\n VIEW_1: {\n state_type: \"VIEW\",\n ref: \"view-1\",\n transitions: {},\n },\n },\n },\n};\n\nexport const INITIAL_EXTENSION_STATE: ExtensionState = {\n current: {\n player: null,\n plugin: null,\n },\n players: {},\n};\n","import DevtoolsUIAssetsPlugin from \"@devtools-ui/plugin\";\nimport { PubSubPlugin } from \"@player-ui/pubsub-plugin\";\nimport { CommonExpressionsPlugin } from \"@player-ui/common-expressions-plugin\";\nimport { CommonTypesPlugin } from \"@player-ui/common-types-plugin\";\nimport { DataChangeListenerPlugin } from \"@player-ui/data-change-listener-plugin\";\nimport {\n ConsoleLogger,\n Player,\n PlayerPlugin,\n ReactPlayer,\n type ReactPlayerPlugin,\n} from \"@player-ui/react\";\n\nclass LogForwarder implements PlayerPlugin, ReactPlayerPlugin {\n name = \"Log\";\n apply(player: Player) {\n player.logger.addHandler(new ConsoleLogger(\"trace\", console));\n }\n\n applyReact(reactPlayer: ReactPlayer) {\n this.apply(reactPlayer.player);\n }\n}\n\nexport const PUBSUB_PLUGIN = new PubSubPlugin();\n\nexport const PLAYER_PLUGINS: ReactPlayerPlugin[] = [\n new CommonTypesPlugin(),\n new CommonExpressionsPlugin(),\n new DataChangeListenerPlugin(),\n new DevtoolsUIAssetsPlugin(),\n new LogForwarder(),\n PUBSUB_PLUGIN,\n];\n","import type { CommunicationLayerMethods } from \"@player-devtools/types\";\nimport { useEffect, useMemo, useSyncExternalStore } from \"react\";\n\nimport { createExtensionClient } from \"./client\";\n\n/**\n * Thin React adapter over `createExtensionClient`.\n *\n * Creates the client once per `communicationLayer` identity, subscribes to\n * state via `useSyncExternalStore`, and tears down the Messenger on unmount.\n */\nexport const useExtensionState = ({\n communicationLayer,\n}: {\n /** the communication layer to use for the extension */\n communicationLayer: CommunicationLayerMethods;\n}) => {\n const client = useMemo(\n () => createExtensionClient(communicationLayer),\n [communicationLayer],\n );\n\n useEffect(() => () => client.destroy(), [client]);\n\n const state = useSyncExternalStore(client.subscribe, client.getState);\n\n return {\n state,\n selectPlayer: client.selectPlayer,\n selectPlugin: client.selectPlugin,\n handleInteraction: client.handleInteraction,\n };\n};\n","import { Messenger } from \"@player-devtools/messenger\";\nimport type {\n CommunicationLayerMethods,\n ExtensionState,\n ExtensionSupportedEvents,\n} from \"@player-devtools/types\";\nimport { useStateReducer } from \"@player-devtools/utils\";\n\nimport { INITIAL_EXTENSION_STATE } from \"../constants\";\nimport { reducer } from \"./reducer\";\n\nconst NOOP_ID = -1;\n\nexport type ExtensionClient = {\n getState: () => ExtensionState;\n subscribe: (fn: (state: ExtensionState) => void) => () => void;\n selectPlayer: (playerID: string) => void;\n selectPlugin: (pluginID: string) => void;\n handleInteraction: (interaction: {\n type: string;\n payload?: string;\n target?: string;\n }) => void;\n destroy: () => void;\n};\n\nexport const createExtensionClient = (\n communicationLayer: CommunicationLayerMethods,\n): ExtensionClient => {\n const store = useStateReducer(reducer, INITIAL_EXTENSION_STATE);\n\n const messenger = new Messenger<ExtensionSupportedEvents>({\n context: \"devtools\",\n messageCallback: (message) => store.dispatch(message),\n ...communicationLayer,\n logger: console,\n });\n\n const selectPlayer = (playerID: string): void => {\n store.dispatch({\n id: NOOP_ID,\n sender: \"internal\",\n context: \"devtools\",\n _messenger_: false,\n timestamp: Date.now(),\n type: \"PLAYER_DEVTOOLS_PLAYER_SELECTED\",\n payload: { playerID },\n });\n\n messenger.sendMessage({\n type: \"PLAYER_DEVTOOLS_PLUGIN_INTERACTION\",\n payload: {\n type: \"player-selected\",\n payload: playerID,\n },\n });\n };\n\n const selectPlugin = (pluginID: string): void => {\n store.dispatch({\n id: NOOP_ID,\n sender: \"internal\",\n context: \"devtools\",\n _messenger_: false,\n timestamp: Date.now(),\n type: \"PLAYER_DEVTOOLS_PLUGIN_SELECTED\",\n payload: { pluginID },\n });\n };\n\n const handleInteraction = ({\n type,\n payload,\n target,\n }: {\n type: string;\n payload?: string;\n /** Player to address; defaults to the currently selected player. */\n target?: string;\n }): void => {\n const resolvedTarget = target ?? store.getState().current.player;\n messenger.sendMessage({\n type: \"PLAYER_DEVTOOLS_PLUGIN_INTERACTION\",\n payload: { type, payload },\n ...(resolvedTarget ? { target: resolvedTarget } : {}),\n });\n };\n\n return {\n getState: store.getState,\n subscribe: store.subscribe,\n selectPlayer,\n selectPlugin,\n handleInteraction,\n destroy: () => messenger.destroy(),\n };\n};\n","import type {\n ExtensionState,\n ExtensionSupportedEvents,\n Transaction,\n} from \"@player-devtools/types\";\nimport { dsetAssign } from \"@player-devtools/utils\";\nimport { produce } from \"immer\";\n\n/** Extension state reducer */\nexport const reducer = (\n state: ExtensionState,\n transaction: Transaction<ExtensionSupportedEvents>,\n): ExtensionState => {\n switch (transaction.type) {\n case \"PLAYER_DEVTOOLS_PLAYER_INIT\":\n return produce(state, (draft) => {\n const {\n sender,\n payload: { plugins },\n } = transaction;\n\n const [plugin] = Object.values(plugins);\n if (!plugin) return;\n\n draft.current.player = sender;\n draft.current.plugin = draft.current.plugin || plugin.id;\n\n // TODO: Verify this works with multiple plugins\n dsetAssign(draft, [\"players\", sender, \"plugins\"], plugins, true);\n dsetAssign(draft.players, [sender, \"active\"], true);\n });\n case \"PLAYER_DEVTOOLS_PLUGIN_FLOW_CHANGE\":\n return produce(state, (draft) => {\n const {\n sender,\n payload: { flow, pluginID },\n } = transaction;\n\n dsetAssign(\n draft,\n [\"players\", sender, \"plugins\", pluginID, \"flow\"],\n flow,\n );\n });\n case \"PLAYER_DEVTOOLS_PLUGIN_DATA_CHANGE\":\n return produce(state, (draft) => {\n const {\n sender,\n payload: { data, pluginID },\n } = transaction;\n dsetAssign(\n draft,\n [\"players\", sender, \"plugins\", pluginID, \"flow\", \"data\"],\n data,\n );\n });\n case \"MESSENGER_EVENT_BATCH\":\n return transaction.payload.events.reduce(reducer, state);\n case \"PLAYER_DEVTOOLS_PLAYER_STOPPED\":\n return produce(state, (draft) => {\n const { sender } = transaction;\n dsetAssign(draft, [\"players\", sender, \"active\"], false);\n });\n case \"PLAYER_DEVTOOLS_PLAYER_SELECTED\":\n return produce(state, (draft) => {\n const { playerID } = transaction.payload;\n draft.current.player = playerID;\n });\n case \"PLAYER_DEVTOOLS_PLUGIN_SELECTED\":\n return produce(state, (draft) => {\n const { pluginID } = transaction.payload;\n draft.current.plugin = pluginID;\n });\n default:\n return state;\n }\n};\n","import type { Flow } from \"@player-ui/react\";\nimport { dequal } from \"dequal\";\n\n/**\n * Compares two Flow objects and identifies if there's a change in their structure or data.\n *\n * This function takes two Flow objects as input, `curr` (current) and `next` (next), and compares them\n * to determine if there's a change in the flow's structure or its data. If there's a change in the flow's\n * structure (excluding the `data` property), it returns an object indicating a \"flow\" change along with the\n * new flow. If there's a change in the `data` property, it returns an object indicating a \"data\" change along\n * with the new data. If there are no changes, it returns null.\n */\nexport const flowDiff = ({\n curr,\n next,\n}: {\n curr: Flow;\n next: Flow;\n}):\n | { change: \"data\"; value: Flow[\"data\"] }\n | { change: \"flow\"; value: Flow }\n | null => {\n // compare flows except for the `data` property\n const currCopy = { ...curr, data: null };\n const nextCopy = { ...next, data: null };\n\n const baseFlowIsEqual = dequal(currCopy, nextCopy);\n\n if (!baseFlowIsEqual) {\n return { change: \"flow\", value: next };\n }\n\n // compare data\n const currData = curr.data;\n const nextData = next.data;\n\n const dataIsEqual = dequal(currData, nextData);\n\n if (!dataIsEqual) {\n return { change: \"data\", value: nextData };\n }\n\n return null;\n};\n"],"mappings":"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","names":["useEffect","useEffect"]}
package/package.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "types"
7
7
  ],
8
8
  "name": "@player-devtools/client",
9
- "version": "0.13.1--canary.13.753",
9
+ "version": "0.13.1--canary.16.936",
10
10
  "main": "dist/cjs/index.cjs",
11
11
  "dependencies": {
12
- "@player-devtools/messenger": "0.13.1--canary.13.753",
13
- "@player-devtools/types": "0.13.1--canary.13.753",
14
- "@player-devtools/utils": "0.13.1--canary.13.753",
12
+ "@player-devtools/messenger": "0.13.1--canary.16.936",
13
+ "@player-devtools/types": "0.13.1--canary.16.936",
14
+ "@player-devtools/utils": "0.13.1--canary.16.936",
15
15
  "@chakra-ui/react": "2.8.2",
16
16
  "@player-ui/pubsub-plugin": "0.12.0-next.1",
17
17
  "@player-ui/player": "0.12.0-next.1",
package/src/index.ts CHANGED
@@ -1 +1,2 @@
1
1
  export { Panel } from "./panel";
2
+ export { createExtensionClient, type ExtensionClient } from "./state/client";
@@ -0,0 +1,97 @@
1
+ import { Messenger } from "@player-devtools/messenger";
2
+ import type {
3
+ CommunicationLayerMethods,
4
+ ExtensionState,
5
+ ExtensionSupportedEvents,
6
+ } from "@player-devtools/types";
7
+ import { useStateReducer } from "@player-devtools/utils";
8
+
9
+ import { INITIAL_EXTENSION_STATE } from "../constants";
10
+ import { reducer } from "./reducer";
11
+
12
+ const NOOP_ID = -1;
13
+
14
+ export type ExtensionClient = {
15
+ getState: () => ExtensionState;
16
+ subscribe: (fn: (state: ExtensionState) => void) => () => void;
17
+ selectPlayer: (playerID: string) => void;
18
+ selectPlugin: (pluginID: string) => void;
19
+ handleInteraction: (interaction: {
20
+ type: string;
21
+ payload?: string;
22
+ target?: string;
23
+ }) => void;
24
+ destroy: () => void;
25
+ };
26
+
27
+ export const createExtensionClient = (
28
+ communicationLayer: CommunicationLayerMethods,
29
+ ): ExtensionClient => {
30
+ const store = useStateReducer(reducer, INITIAL_EXTENSION_STATE);
31
+
32
+ const messenger = new Messenger<ExtensionSupportedEvents>({
33
+ context: "devtools",
34
+ messageCallback: (message) => store.dispatch(message),
35
+ ...communicationLayer,
36
+ logger: console,
37
+ });
38
+
39
+ const selectPlayer = (playerID: string): void => {
40
+ store.dispatch({
41
+ id: NOOP_ID,
42
+ sender: "internal",
43
+ context: "devtools",
44
+ _messenger_: false,
45
+ timestamp: Date.now(),
46
+ type: "PLAYER_DEVTOOLS_PLAYER_SELECTED",
47
+ payload: { playerID },
48
+ });
49
+
50
+ messenger.sendMessage({
51
+ type: "PLAYER_DEVTOOLS_PLUGIN_INTERACTION",
52
+ payload: {
53
+ type: "player-selected",
54
+ payload: playerID,
55
+ },
56
+ });
57
+ };
58
+
59
+ const selectPlugin = (pluginID: string): void => {
60
+ store.dispatch({
61
+ id: NOOP_ID,
62
+ sender: "internal",
63
+ context: "devtools",
64
+ _messenger_: false,
65
+ timestamp: Date.now(),
66
+ type: "PLAYER_DEVTOOLS_PLUGIN_SELECTED",
67
+ payload: { pluginID },
68
+ });
69
+ };
70
+
71
+ const handleInteraction = ({
72
+ type,
73
+ payload,
74
+ target,
75
+ }: {
76
+ type: string;
77
+ payload?: string;
78
+ /** Player to address; defaults to the currently selected player. */
79
+ target?: string;
80
+ }): void => {
81
+ const resolvedTarget = target ?? store.getState().current.player;
82
+ messenger.sendMessage({
83
+ type: "PLAYER_DEVTOOLS_PLUGIN_INTERACTION",
84
+ payload: { type, payload },
85
+ ...(resolvedTarget ? { target: resolvedTarget } : {}),
86
+ });
87
+ };
88
+
89
+ return {
90
+ getState: store.getState,
91
+ subscribe: store.subscribe,
92
+ selectPlayer,
93
+ selectPlugin,
94
+ handleInteraction,
95
+ destroy: () => messenger.destroy(),
96
+ };
97
+ };
@@ -1,126 +1,33 @@
1
- import { Messenger } from "@player-devtools/messenger";
2
- import type {
3
- ExtensionSupportedEvents,
4
- MessengerOptions,
5
- } from "@player-devtools/types";
6
- import { useCallback, useEffect, useMemo, useReducer } from "react";
1
+ import type { CommunicationLayerMethods } from "@player-devtools/types";
2
+ import { useEffect, useMemo, useSyncExternalStore } from "react";
7
3
 
8
- import { INITIAL_EXTENSION_STATE } from "../constants";
9
- import { reducer } from "./reducer";
10
-
11
- const NOOP_ID = -1;
4
+ import { createExtensionClient } from "./client";
12
5
 
13
6
  /**
14
- * Custom React hook for managing the state of the devtools extension.
15
- *
16
- * This hook initializes the extension's state and sets up a communication layer
17
- * using the `Messenger` class. It provides methods to select a player or plugin,
18
- * and handle interactions, which dispatch actions to update the state accordingly.
7
+ * Thin React adapter over `createExtensionClient`.
19
8
  *
9
+ * Creates the client once per `communicationLayer` identity, subscribes to
10
+ * state via `useSyncExternalStore`, and tears down the Messenger on unmount.
20
11
  */
21
12
  export const useExtensionState = ({
22
13
  communicationLayer,
23
14
  }: {
24
15
  /** the communication layer to use for the extension */
25
- communicationLayer: Pick<
26
- MessengerOptions<ExtensionSupportedEvents>,
27
- "sendMessage" | "addListener" | "removeListener"
28
- >;
16
+ communicationLayer: CommunicationLayerMethods;
29
17
  }) => {
30
- const [state, dispatch] = useReducer(reducer, INITIAL_EXTENSION_STATE);
31
-
32
- const messengerOptions = useMemo<MessengerOptions<ExtensionSupportedEvents>>(
33
- () => ({
34
- context: "devtools",
35
- target: "player",
36
- messageCallback: (message) => {
37
- dispatch(message);
38
- },
39
- ...communicationLayer,
40
- logger: console,
41
- }),
42
- [dispatch, communicationLayer],
18
+ const client = useMemo(
19
+ () => createExtensionClient(communicationLayer),
20
+ [communicationLayer],
43
21
  );
44
22
 
45
- const messenger = useMemo(
46
- () => new Messenger(messengerOptions),
47
- [messengerOptions],
48
- );
49
-
50
- useEffect(() => {
51
- return () => {
52
- messenger.destroy();
53
- };
54
- }, []);
55
-
56
- const selectPlayer = useCallback(
57
- (playerID: string) => {
58
- dispatch({
59
- id: NOOP_ID,
60
- sender: "internal",
61
- context: "devtools",
62
- _messenger_: false,
63
- timestamp: Date.now(),
64
- type: "PLAYER_DEVTOOLS_PLAYER_SELECTED",
65
- payload: {
66
- playerID,
67
- },
68
- });
23
+ useEffect(() => () => client.destroy(), [client]);
69
24
 
70
- messenger.sendMessage({
71
- type: "PLAYER_DEVTOOLS_PLUGIN_INTERACTION",
72
- payload: {
73
- type: "player-selected",
74
- payload: playerID,
75
- },
76
- });
77
- },
78
- [dispatch],
79
- );
80
-
81
- const selectPlugin = useCallback(
82
- (pluginID: string) => {
83
- dispatch({
84
- id: NOOP_ID,
85
- sender: "internal",
86
- context: "devtools",
87
- _messenger_: false,
88
- timestamp: Date.now(),
89
- type: "PLAYER_DEVTOOLS_PLUGIN_SELECTED",
90
- payload: {
91
- pluginID,
92
- },
93
- });
94
- },
95
- [dispatch],
96
- );
97
-
98
- /**
99
- * Plugin authors can add interactive elements to the Player-UI content by leveraging
100
- * the pub-sub plugin and having the handle interaction proxy the message to the inspected
101
- * Player-UI instance.
102
- */
103
- const handleInteraction = useCallback(
104
- ({
105
- type,
106
- payload,
107
- }: {
108
- /** interaction type */
109
- type: string;
110
- /** interaction payload */
111
- payload?: string;
112
- }) => {
113
- messenger.sendMessage({
114
- type: "PLAYER_DEVTOOLS_PLUGIN_INTERACTION",
115
- payload: {
116
- type,
117
- payload,
118
- },
119
- ...(state.current.player ? { target: state.current.player } : {}),
120
- });
121
- },
122
- [messenger],
123
- );
25
+ const state = useSyncExternalStore(client.subscribe, client.getState);
124
26
 
125
- return { state, selectPlayer, selectPlugin, handleInteraction };
27
+ return {
28
+ state,
29
+ selectPlayer: client.selectPlayer,
30
+ selectPlugin: client.selectPlugin,
31
+ handleInteraction: client.handleInteraction,
32
+ };
126
33
  };
package/types/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { Panel } from "./panel";
2
+ export { createExtensionClient, type ExtensionClient } from "./state/client";
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,15 @@
1
+ import type { CommunicationLayerMethods, ExtensionState } from "@player-devtools/types";
2
+ export type ExtensionClient = {
3
+ getState: () => ExtensionState;
4
+ subscribe: (fn: (state: ExtensionState) => void) => () => void;
5
+ selectPlayer: (playerID: string) => void;
6
+ selectPlugin: (pluginID: string) => void;
7
+ handleInteraction: (interaction: {
8
+ type: string;
9
+ payload?: string;
10
+ target?: string;
11
+ }) => void;
12
+ destroy: () => void;
13
+ };
14
+ export declare const createExtensionClient: (communicationLayer: CommunicationLayerMethods) => ExtensionClient;
15
+ //# sourceMappingURL=client.d.ts.map
@@ -1,24 +1,21 @@
1
- import type { ExtensionSupportedEvents, MessengerOptions } from "@player-devtools/types";
1
+ import type { CommunicationLayerMethods } from "@player-devtools/types";
2
2
  /**
3
- * Custom React hook for managing the state of the devtools extension.
4
- *
5
- * This hook initializes the extension's state and sets up a communication layer
6
- * using the `Messenger` class. It provides methods to select a player or plugin,
7
- * and handle interactions, which dispatch actions to update the state accordingly.
3
+ * Thin React adapter over `createExtensionClient`.
8
4
  *
5
+ * Creates the client once per `communicationLayer` identity, subscribes to
6
+ * state via `useSyncExternalStore`, and tears down the Messenger on unmount.
9
7
  */
10
8
  export declare const useExtensionState: ({ communicationLayer, }: {
11
9
  /** the communication layer to use for the extension */
12
- communicationLayer: Pick<MessengerOptions<ExtensionSupportedEvents>, "sendMessage" | "addListener" | "removeListener">;
10
+ communicationLayer: CommunicationLayerMethods;
13
11
  }) => {
14
12
  state: import("@player-devtools/types").ExtensionState;
15
13
  selectPlayer: (playerID: string) => void;
16
14
  selectPlugin: (pluginID: string) => void;
17
- handleInteraction: ({ type, payload, }: {
18
- /** interaction type */
15
+ handleInteraction: (interaction: {
19
16
  type: string;
20
- /** interaction payload */
21
17
  payload?: string;
18
+ target?: string;
22
19
  }) => void;
23
20
  };
24
21
  //# sourceMappingURL=index.d.ts.map