@sigmacomputing/plugin 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +0 -14
  2. package/LICENSE +1 -1
  3. package/README.md +19 -24
  4. package/dist/cjs/index.cjs +506 -0
  5. package/dist/cjs/index.cjs.map +1 -0
  6. package/dist/cjs/index.d.cts +438 -0
  7. package/dist/esm/index.d.ts +438 -0
  8. package/dist/esm/index.js +466 -0
  9. package/dist/esm/index.js.map +1 -0
  10. package/dist/umd/sigmacomputing-plugin.umd.js +2 -0
  11. package/dist/umd/sigmacomputing-plugin.umd.js.map +1 -0
  12. package/package.json +69 -36
  13. package/src/client/initialize.ts +280 -0
  14. package/src/client.ts +3 -0
  15. package/src/globals.d.ts +2 -0
  16. package/{dist/index.d.ts → src/index.ts} +1 -1
  17. package/src/react/Context.ts +6 -0
  18. package/src/react/Provider.tsx +20 -0
  19. package/src/react/hooks.ts +298 -0
  20. package/src/react.ts +3 -0
  21. package/src/types.ts +412 -0
  22. package/src/utils/deepEqual.ts +23 -0
  23. package/src/utils/error.ts +10 -0
  24. package/src/utils/polyfillRequestAnimationFrame.ts +13 -0
  25. package/dist/client/initialize.d.ts +0 -3
  26. package/dist/client/initialize.d.ts.map +0 -1
  27. package/dist/client/initialize.js +0 -223
  28. package/dist/client.d.ts +0 -2
  29. package/dist/client.d.ts.map +0 -1
  30. package/dist/client.js +0 -5
  31. package/dist/error.d.ts +0 -3
  32. package/dist/error.d.ts.map +0 -1
  33. package/dist/error.js +0 -9
  34. package/dist/index.d.ts.map +0 -1
  35. package/dist/index.js +0 -22
  36. package/dist/react/Context.d.ts +0 -4
  37. package/dist/react/Context.d.ts.map +0 -1
  38. package/dist/react/Context.js +0 -6
  39. package/dist/react/Provider.d.ts +0 -8
  40. package/dist/react/Provider.d.ts.map +0 -1
  41. package/dist/react/Provider.js +0 -9
  42. package/dist/react/hooks.d.ts +0 -83
  43. package/dist/react/hooks.d.ts.map +0 -1
  44. package/dist/react/hooks.js +0 -231
  45. package/dist/react.d.ts +0 -3
  46. package/dist/react.d.ts.map +0 -1
  47. package/dist/react.js +0 -20
  48. package/dist/types.d.ts +0 -332
  49. package/dist/types.d.ts.map +0 -1
  50. package/dist/types.js +0 -2
  51. package/dist/utils/deepEqual.d.ts +0 -2
  52. package/dist/utils/deepEqual.d.ts.map +0 -1
  53. package/dist/utils/deepEqual.js +0 -28
  54. package/dist/utils/polyfillRequestAnimationFrame.d.ts +0 -8
  55. package/dist/utils/polyfillRequestAnimationFrame.d.ts.map +0 -1
  56. package/dist/utils/polyfillRequestAnimationFrame.js +0 -16
@@ -0,0 +1,466 @@
1
+ import * as React from "react";
2
+ //#region src/utils/deepEqual.ts
3
+ function isObject(obj) {
4
+ if (typeof obj === "object" && obj != null) return true;
5
+ else return false;
6
+ }
7
+ function deepEqual(obj1, obj2) {
8
+ if (obj1 === obj2) return true;
9
+ else if (isObject(obj1) && isObject(obj2)) {
10
+ if (Object.keys(obj1).length !== Object.keys(obj2).length) return false;
11
+ for (const prop in obj1) if (!deepEqual(obj1[prop], obj2[prop])) return false;
12
+ return true;
13
+ }
14
+ }
15
+ //#endregion
16
+ //#region src/utils/error.ts
17
+ function validateConfigId(configId, expectedConfigType) {
18
+ if (configId === void 0) console.warn(`Invalid config ${expectedConfigType}: ${configId}`);
19
+ }
20
+ //#endregion
21
+ //#region src/client/initialize.ts
22
+ function initialize() {
23
+ const pluginConfig = { config: {} };
24
+ let subscribedInteractions = {};
25
+ let subscribedWorkbookVars = {};
26
+ let subscribedUrlParameters = {};
27
+ const registeredEffects = {};
28
+ const listeners = {};
29
+ const location = new URL(document.location.href);
30
+ for (const [key, value] of location.searchParams.entries()) try {
31
+ pluginConfig[key] = JSON.parse(value);
32
+ } catch (_err) {
33
+ console.error(`Failed to parse URL param ${key} with value ${value} as JSON.`);
34
+ }
35
+ const listener = (e) => {
36
+ emit(e.data.type, e.data.result, e.data.error);
37
+ };
38
+ window.addEventListener("message", listener, false);
39
+ window.addEventListener("click", () => execPromise("wb:plugin:focus"));
40
+ on("wb:plugin:config:update", (config) => {
41
+ Object.assign(pluginConfig, config);
42
+ emit("config", pluginConfig.config ?? {});
43
+ });
44
+ execPromise("wb:plugin:init", "1.2.0").then((config) => {
45
+ Object.assign(pluginConfig, config);
46
+ emit("init", pluginConfig);
47
+ emit("config", pluginConfig.config);
48
+ });
49
+ on("wb:plugin:variable:update", (updatedVariables) => {
50
+ subscribedWorkbookVars = {};
51
+ Object.assign(subscribedWorkbookVars, updatedVariables);
52
+ });
53
+ on("wb:plugin:selection:update", (updatedInteractions) => {
54
+ subscribedInteractions = {};
55
+ Object.assign(subscribedInteractions, updatedInteractions);
56
+ });
57
+ on("wb:plugin:url-parameter:update", (updatedUrlParameters) => {
58
+ subscribedUrlParameters = {};
59
+ Object.assign(subscribedUrlParameters, updatedUrlParameters);
60
+ });
61
+ on("wb:plugin:action-effect:invoke", (configId) => {
62
+ const effect = registeredEffects[configId];
63
+ if (!effect) throw new Error(`Unknown action effect with name: ${configId}`);
64
+ effect();
65
+ });
66
+ function on(event, listener) {
67
+ listeners[event] = listeners[event] || [];
68
+ listeners[event].push(listener);
69
+ }
70
+ function off(event, listener) {
71
+ if (listeners[event] == null) return;
72
+ listeners[event] = listeners[event].filter((a) => a !== listener);
73
+ }
74
+ function emit(event, ...args) {
75
+ Object.values(listeners[event] || []).forEach((fn) => fn(...args));
76
+ }
77
+ function execPromise(event, ...args) {
78
+ return new Promise((resolve, reject) => {
79
+ const callback = (data, error) => {
80
+ if (error) reject(error);
81
+ else resolve(data);
82
+ off(event, callback);
83
+ };
84
+ on(event, callback);
85
+ window.parent.postMessage({
86
+ type: event,
87
+ args,
88
+ elementId: pluginConfig.id
89
+ }, pluginConfig?.wbOrigin ?? "*");
90
+ });
91
+ }
92
+ return {
93
+ get sigmaEnv() {
94
+ return pluginConfig.sigmaEnv;
95
+ },
96
+ get isScreenshot() {
97
+ return pluginConfig.screenshot;
98
+ },
99
+ config: {
100
+ getKey(key) {
101
+ return pluginConfig?.config?.[key];
102
+ },
103
+ get() {
104
+ return pluginConfig.config;
105
+ },
106
+ set(partialConfig) {
107
+ execPromise("wb:plugin:config:update", partialConfig);
108
+ },
109
+ setKey(key, value) {
110
+ execPromise("wb:plugin:config:update", { [key]: value });
111
+ },
112
+ subscribe(listener) {
113
+ on("config", listener);
114
+ return () => off("config", listener);
115
+ },
116
+ getVariable(configId) {
117
+ validateConfigId(configId, "variable");
118
+ return subscribedWorkbookVars[configId];
119
+ },
120
+ setVariable(configId, ...values) {
121
+ validateConfigId(configId, "variable");
122
+ execPromise("wb:plugin:variable:set", configId, ...values);
123
+ },
124
+ getInteraction(configId) {
125
+ validateConfigId(configId, "interaction");
126
+ return subscribedInteractions[configId];
127
+ },
128
+ setInteraction(configId, elementId, selection) {
129
+ validateConfigId(configId, "interaction");
130
+ execPromise("wb:plugin:selection:set", configId, elementId, selection);
131
+ },
132
+ triggerAction(configId) {
133
+ validateConfigId(configId, "action-trigger");
134
+ execPromise("wb:plugin:action-trigger:invoke", configId);
135
+ },
136
+ registerEffect(configId, effect) {
137
+ validateConfigId(configId, "action-effect");
138
+ registeredEffects[configId] = effect;
139
+ return () => {
140
+ delete registeredEffects[configId];
141
+ };
142
+ },
143
+ configureEditorPanel(options) {
144
+ execPromise("wb:plugin:config:inspector", options);
145
+ },
146
+ setLoadingState(loadingState) {
147
+ execPromise("wb:plugin:config:loading-state", loadingState);
148
+ },
149
+ subscribeToWorkbookVariable(configId, callback) {
150
+ validateConfigId(configId, "variable");
151
+ const setValues = (values) => {
152
+ callback(values[configId]);
153
+ };
154
+ on("wb:plugin:variable:update", setValues);
155
+ return () => {
156
+ off("wb:plugin:variable:update", setValues);
157
+ };
158
+ },
159
+ subscribeToWorkbookInteraction(configId, callback) {
160
+ validateConfigId(configId, "interaction");
161
+ const setValues = (values) => {
162
+ callback(values[configId]);
163
+ };
164
+ on("wb:plugin:selection:update", setValues);
165
+ return () => {
166
+ off("wb:plugin:selection:update", setValues);
167
+ };
168
+ },
169
+ subscribeToUrlParameter(configId, callback) {
170
+ validateConfigId(configId, "url-parameter");
171
+ const setValues = (values) => {
172
+ callback(values[configId]);
173
+ };
174
+ setValues(subscribedUrlParameters);
175
+ on("wb:plugin:url-parameter:update", setValues);
176
+ return () => {
177
+ off("wb:plugin:url-parameter:update", setValues);
178
+ };
179
+ },
180
+ getUrlParameter(configId) {
181
+ validateConfigId(configId, "url-parameter");
182
+ return subscribedUrlParameters[configId];
183
+ },
184
+ setUrlParameter(configId, value) {
185
+ validateConfigId(configId, "url-parameter");
186
+ execPromise("wb:plugin:url-parameter:set", configId, value);
187
+ }
188
+ },
189
+ elements: {
190
+ getElementColumns(configId) {
191
+ validateConfigId(configId, "element");
192
+ return execPromise("wb:plugin:element:columns:get", configId);
193
+ },
194
+ subscribeToElementColumns(configId, callback) {
195
+ validateConfigId(configId, "element");
196
+ const eventName = `wb:plugin:element:${configId}:columns`;
197
+ on(eventName, callback);
198
+ execPromise("wb:plugin:element:subscribe:columns", configId);
199
+ return () => {
200
+ off(eventName, callback);
201
+ execPromise("wb:plugin:element:unsubscribe:columns", configId);
202
+ };
203
+ },
204
+ subscribeToElementData(configId, callback) {
205
+ validateConfigId(configId, "element");
206
+ const eventName = `wb:plugin:element:${configId}:data`;
207
+ on(eventName, callback);
208
+ execPromise("wb:plugin:element:subscribe:data", configId);
209
+ return () => {
210
+ off(eventName, callback);
211
+ execPromise("wb:plugin:element:unsubscribe:data", configId);
212
+ };
213
+ },
214
+ fetchMoreElementData(configId) {
215
+ validateConfigId(configId, "element");
216
+ execPromise("wb:plugin:element:fetch-more", configId);
217
+ }
218
+ },
219
+ style: {
220
+ subscribe(callback) {
221
+ on("wb:plugin:style:update", callback);
222
+ return () => off("wb:plugin:style:update", callback);
223
+ },
224
+ get() {
225
+ return execPromise("wb:plugin:style:get");
226
+ }
227
+ },
228
+ destroy() {
229
+ Object.keys(listeners).forEach((event) => delete listeners[event]);
230
+ window.removeEventListener("message", listener, false);
231
+ }
232
+ };
233
+ }
234
+ //#endregion
235
+ //#region src/client.ts
236
+ const client = initialize();
237
+ //#endregion
238
+ //#region src/react/Context.ts
239
+ const PluginContext = React.createContext(client);
240
+ //#endregion
241
+ //#region src/react/hooks.ts
242
+ /**
243
+ * Gets the entire plugin instance
244
+ * @returns {PluginInstance} Context for the current plugin instance
245
+ */
246
+ function usePlugin() {
247
+ return React.useContext(PluginContext);
248
+ }
249
+ /**
250
+ * Provides a setter for the Plugin's Config Options
251
+ * @param {CustomPluginConfigOptions[]} nextOptions Updated possible Config Options
252
+ */
253
+ function useEditorPanelConfig(nextOptions) {
254
+ const client = usePlugin();
255
+ const optionsRef = React.useRef({});
256
+ React.useEffect(() => {
257
+ if (nextOptions == null) return;
258
+ if (!deepEqual(nextOptions, optionsRef.current)) {
259
+ client.config.configureEditorPanel(nextOptions);
260
+ optionsRef.current = nextOptions;
261
+ }
262
+ }, [client, nextOptions]);
263
+ }
264
+ /**
265
+ * React hook for Plugin Config loading state
266
+ * @param {boolean} initialState Initial value to set loading state to
267
+ * @returns {[boolean, Function]} Boolean value corresponding to loading state for plugin config and setter for loading state
268
+ */
269
+ function useLoadingState(initialState) {
270
+ const client = usePlugin();
271
+ const [loading, setLoading] = React.useState(() => {
272
+ client.config.setLoadingState(initialState);
273
+ return initialState;
274
+ });
275
+ return [loading, (nextState) => {
276
+ if (nextState === loading) return;
277
+ setLoading(nextState);
278
+ client.config.setLoadingState(nextState);
279
+ }];
280
+ }
281
+ /**
282
+ * Provides the latest column values from corresponding config element
283
+ * @param {string} configId ID from the config for fetching element columns, with type: 'element'
284
+ * @returns {WorkbookElementColumns} Values of corresponding columns contained
285
+ * within the config element
286
+ */
287
+ function useElementColumns(configId) {
288
+ const client = usePlugin();
289
+ const [columns, setColumns] = React.useState({});
290
+ React.useEffect(() => {
291
+ if (configId) return client.elements.subscribeToElementColumns(configId, setColumns);
292
+ }, [client, configId]);
293
+ return columns;
294
+ }
295
+ /**
296
+ * Provides the latest data values from config element (max 25_000)
297
+ * @param {string} configId ID from the config for fetching element data, with type: 'element'
298
+ * @returns {WorkbookElementData} Element Data for config element, if any
299
+ */
300
+ function useElementData(configId) {
301
+ const client = usePlugin();
302
+ const [data, setData] = React.useState({});
303
+ React.useEffect(() => {
304
+ if (configId) return client.elements.subscribeToElementData(configId, setData);
305
+ }, [client, configId]);
306
+ return data;
307
+ }
308
+ /**
309
+ * Provides the latest data values from corresponding config element with a callback to
310
+ * fetch more in chunks of 25_000 data points
311
+ * @param {string} configId ID from the config for fetching paginated
312
+ * element data, with type: 'element'
313
+ * @returns {WorkbookElementData} Element Data for configured config element, if any
314
+ */
315
+ function usePaginatedElementData(configId) {
316
+ const client = usePlugin();
317
+ const [data, setData] = React.useState({});
318
+ const loadMore = React.useCallback(() => {
319
+ if (configId) client.elements.fetchMoreElementData(configId);
320
+ }, [configId, client.elements]);
321
+ React.useEffect(() => {
322
+ if (configId) return client.elements.subscribeToElementData(configId, setData);
323
+ }, [client, configId]);
324
+ return [data, loadMore];
325
+ }
326
+ /**
327
+ * Provides the latest value for entire config or certain key within the config
328
+ * @param {string} key Key within Plugin Config, optional
329
+ * @returns Entire config if no key passed in or value for key within plugin config
330
+ */
331
+ function useConfig(key) {
332
+ const client = usePlugin();
333
+ const [config, setConfig] = React.useState(key != null ? client.config.getKey(key) : client.config.get());
334
+ React.useEffect(() => client.config.subscribe((newConfig) => {
335
+ if (key != null && newConfig[key] !== config[key]) setConfig(newConfig[key]);
336
+ else setConfig(newConfig);
337
+ }), [
338
+ client,
339
+ key,
340
+ config
341
+ ]);
342
+ return config;
343
+ }
344
+ /**
345
+ * React hook for accessing a workbook control variable
346
+ * @param {string} id ID from the config of type: 'variable'
347
+ * @returns {[(WorkbookVariable | undefined), Function]} Constantly updating
348
+ * value of the control variable and setter for the variable
349
+ */
350
+ function useVariable(id) {
351
+ const client = usePlugin();
352
+ const [workbookVariable, setWorkbookVariable] = React.useState();
353
+ const isFirstRender = React.useRef(true);
354
+ React.useEffect(() => {
355
+ if (isFirstRender.current) {
356
+ setWorkbookVariable(client.config.getVariable(id));
357
+ isFirstRender.current = false;
358
+ }
359
+ return client.config.subscribeToWorkbookVariable(id, setWorkbookVariable);
360
+ }, [client, id]);
361
+ return [workbookVariable, React.useCallback((...values) => client.config.setVariable(id, ...values), [id, client.config])];
362
+ }
363
+ /**
364
+ * React hook for accessing a url parameter
365
+ * @param {string} id ID from the config of type: 'url-parameter'
366
+ * @returns {[(UrlParameter | undefined), Function]} Constantly updating value of the url parameter and setter for the url parameter
367
+ */
368
+ function useUrlParameter(id) {
369
+ const client = usePlugin();
370
+ const [urlParameter, setUrlParameter] = React.useState();
371
+ const isFirstRender = React.useRef(true);
372
+ React.useEffect(() => {
373
+ if (isFirstRender.current) {
374
+ setUrlParameter(client.config.getUrlParameter(id));
375
+ isFirstRender.current = false;
376
+ }
377
+ return client.config.subscribeToUrlParameter(id, setUrlParameter);
378
+ }, [client, id]);
379
+ return [urlParameter, React.useCallback((value) => client.config.setUrlParameter(id, value), [client, id])];
380
+ }
381
+ /**
382
+ * @deprecated Use Action API instead
383
+ * React hook for accessing a workbook interaction selections state
384
+ * @param {string} id ID from the config of type: 'interaction'
385
+ * @returns {[(WorkbookSelection | undefined), Function]} Constantly updating selection state and setter thereof
386
+ */
387
+ function useInteraction(id, elementId) {
388
+ const client = usePlugin();
389
+ const [workbookInteraction, setWorkbookInteraction] = React.useState();
390
+ React.useEffect(() => {
391
+ return client.config.subscribeToWorkbookInteraction(id, setWorkbookInteraction);
392
+ }, [client, id]);
393
+ return [workbookInteraction, React.useCallback((value) => {
394
+ client.config.setInteraction(id, elementId, value);
395
+ }, [
396
+ id,
397
+ elementId,
398
+ client.config
399
+ ])];
400
+ }
401
+ /**
402
+ * React hook for returning a triggering callback function for the registered
403
+ * action trigger
404
+ * @param {string} configId ID from the config of type: 'action-trigger'
405
+ * @returns {Function} A callback function to trigger the action
406
+ */
407
+ function useActionTrigger(configId) {
408
+ const client = usePlugin();
409
+ return React.useCallback(() => {
410
+ client.config.triggerAction(configId);
411
+ }, [client, configId]);
412
+ }
413
+ /**
414
+ * React hook for registering and unregistering an action effect
415
+ * @param {string} configId ID from the config of type: 'action-effect'
416
+ * @param {Function} effect The function to be called when the action is triggered
417
+ */
418
+ function useActionEffect(configId, effect) {
419
+ const client = usePlugin();
420
+ const effectRef = React.useRef(effect);
421
+ React.useEffect(() => {
422
+ effectRef.current = effect;
423
+ });
424
+ React.useEffect(() => {
425
+ return client.config.registerEffect(configId, effectRef.current);
426
+ }, [
427
+ client,
428
+ configId,
429
+ effect
430
+ ]);
431
+ }
432
+ /**
433
+ * React hook for accessing plugin style with live updates
434
+ * @returns {PluginStyle | undefined} Style properties from the workbook if available
435
+ */
436
+ function usePluginStyle() {
437
+ const client = usePlugin();
438
+ const [style, setStyle] = React.useState();
439
+ React.useEffect(() => {
440
+ client.style.get().then((response) => setStyle(response));
441
+ return client.style.subscribe(setStyle);
442
+ }, [client]);
443
+ return style;
444
+ }
445
+ //#endregion
446
+ //#region src/react/Provider.tsx
447
+ function SigmaClientProvider(props) {
448
+ return /* @__PURE__ */ React.createElement(PluginContext.Provider, { value: props.client }, props.children);
449
+ }
450
+ //#endregion
451
+ //#region src/utils/polyfillRequestAnimationFrame.ts
452
+ const FPS = 1e3 / 60;
453
+ /**
454
+ * requestAnimationFrame() calls are paused in most browsers when running in background tabs or hidden <iframe>s in order to improve performance and battery life
455
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
456
+ */
457
+ function polyfillRequestAnimationFrame(window) {
458
+ if ("requestAnimationFrame" in window) {
459
+ window.requestAnimationFrame = (callback) => window.setTimeout(callback, FPS);
460
+ window.cancelAnimationFrame = (id) => window.clearTimeout(id);
461
+ }
462
+ }
463
+ //#endregion
464
+ export { SigmaClientProvider, client, polyfillRequestAnimationFrame, useActionEffect, useActionTrigger, useConfig, useEditorPanelConfig, useElementColumns, useElementData, useInteraction, useLoadingState, usePaginatedElementData, usePlugin, usePluginStyle, useUrlParameter, useVariable };
465
+
466
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/utils/deepEqual.ts","../../src/utils/error.ts","../../src/client/initialize.ts","../../src/client.ts","../../src/react/Context.ts","../../src/react/hooks.ts","../../src/react/Provider.tsx","../../src/utils/polyfillRequestAnimationFrame.ts"],"sourcesContent":["function isObject(obj: any) {\n if (typeof obj === 'object' && obj != null) {\n return true;\n } else {\n return false;\n }\n}\n\nexport function deepEqual(obj1: any, obj2: any) {\n if (obj1 === obj2) {\n return true;\n } else if (isObject(obj1) && isObject(obj2)) {\n if (Object.keys(obj1).length !== Object.keys(obj2).length) {\n return false;\n }\n for (const prop in obj1) {\n if (!deepEqual(obj1[prop], obj2[prop])) {\n return false;\n }\n }\n return true;\n }\n}\n","import { CustomPluginConfigOptions } from '../types';\n\nexport function validateConfigId(\n configId: string,\n expectedConfigType: CustomPluginConfigOptions['type'],\n) {\n if (configId === undefined) {\n console.warn(`Invalid config ${expectedConfigType}: ${configId}`);\n }\n}\n","import {\n PluginConfig,\n PluginInstance,\n PluginMessageResponse,\n PluginStyle,\n UrlParameter,\n WorkbookSelection,\n WorkbookVariable,\n} from '../types';\nimport { validateConfigId } from '../utils/error';\n\nexport function initialize<T = {}>(): PluginInstance<T> {\n const pluginConfig: Partial<PluginConfig<T>> = {\n config: {} as T,\n };\n\n let subscribedInteractions: Record<string, WorkbookSelection[]> = {};\n let subscribedWorkbookVars: Record<string, WorkbookVariable> = {};\n let subscribedUrlParameters: Record<string, UrlParameter> = {};\n const registeredEffects: Record<string, () => void> = {};\n\n const listeners: {\n [event: string]: Function[];\n } = {};\n\n const location = new URL(document.location.href);\n for (const [key, value] of location.searchParams.entries()) {\n try {\n pluginConfig[key] = JSON.parse(value);\n } catch (_err: unknown) {\n if (__VITEST_BROWSER__ && (key === 'iframeId' || key === 'sessionId')) {\n // noop: vitest browser injects these into the test iframe URL\n } else {\n console.error(\n `Failed to parse URL param ${key} with value ${value} as JSON.`,\n );\n }\n }\n }\n\n const listener = (e: PluginMessageResponse) => {\n emit(e.data.type, e.data.result, e.data.error);\n };\n\n window.addEventListener('message', listener, false);\n window.addEventListener('click', () => execPromise('wb:plugin:focus'));\n\n on('wb:plugin:config:update', (config: PluginConfig<T>) => {\n Object.assign(pluginConfig, config);\n emit('config', pluginConfig.config ?? {});\n });\n\n // send initialize event\n void execPromise('wb:plugin:init', __VERSION__).then(config => {\n Object.assign(pluginConfig, config);\n emit('init', pluginConfig);\n emit('config', pluginConfig.config);\n });\n\n on(\n 'wb:plugin:variable:update',\n (updatedVariables: Record<string, WorkbookVariable>) => {\n subscribedWorkbookVars = {};\n Object.assign(subscribedWorkbookVars, updatedVariables);\n },\n );\n\n on('wb:plugin:selection:update', (updatedInteractions: unknown) => {\n subscribedInteractions = {};\n Object.assign(subscribedInteractions, updatedInteractions);\n });\n\n on(\n 'wb:plugin:url-parameter:update',\n (updatedUrlParameters: Record<string, UrlParameter>) => {\n subscribedUrlParameters = {};\n Object.assign(subscribedUrlParameters, updatedUrlParameters);\n },\n );\n\n on('wb:plugin:action-effect:invoke', (configId: string) => {\n const effect = registeredEffects[configId];\n if (!effect) {\n throw new Error(`Unknown action effect with name: ${configId}`);\n }\n effect();\n });\n\n function on(event: string, listener: Function) {\n listeners[event] = listeners[event] || [];\n listeners[event].push(listener);\n }\n\n function off(event: string, listener: Function) {\n if (listeners[event] == null) return;\n listeners[event] = listeners[event].filter(a => a !== listener);\n }\n\n function emit(event: string, ...args: any) {\n Object.values(listeners[event] || []).forEach(fn => fn(...args));\n }\n\n function execPromise<R>(event: string, ...args: any): Promise<R> {\n return new Promise((resolve, reject) => {\n const callback = (data: R, error: any) => {\n if (error) reject(error);\n else resolve(data);\n off(event, callback);\n };\n on(event, callback);\n window.parent.postMessage(\n { type: event, args, elementId: pluginConfig.id },\n pluginConfig?.wbOrigin ?? '*',\n );\n });\n }\n\n return {\n get sigmaEnv() {\n return pluginConfig.sigmaEnv;\n },\n\n get isScreenshot() {\n return pluginConfig.screenshot;\n },\n\n config: {\n // @ts-ignore TODO: Fix\n getKey(key) {\n return pluginConfig?.config?.[key];\n },\n get() {\n return pluginConfig.config;\n },\n set(partialConfig) {\n void execPromise('wb:plugin:config:update', partialConfig);\n },\n setKey(key, value) {\n void execPromise('wb:plugin:config:update', {\n [key]: value,\n });\n },\n subscribe(listener) {\n on('config', listener);\n return () => off('config', listener);\n },\n getVariable(configId: string) {\n validateConfigId(configId, 'variable');\n return subscribedWorkbookVars[configId];\n },\n setVariable(configId: string, ...values: unknown[]) {\n validateConfigId(configId, 'variable');\n void execPromise('wb:plugin:variable:set', configId, ...values);\n },\n getInteraction(configId: string) {\n validateConfigId(configId, 'interaction');\n return subscribedInteractions[configId];\n },\n setInteraction(\n configId: string,\n elementId: string,\n selection:\n | string[]\n | Array<Record<string, { type: string; val?: unknown }>>,\n ) {\n validateConfigId(configId, 'interaction');\n void execPromise(\n 'wb:plugin:selection:set',\n configId,\n elementId,\n selection,\n );\n },\n triggerAction(configId: string) {\n validateConfigId(configId, 'action-trigger');\n void execPromise('wb:plugin:action-trigger:invoke', configId);\n },\n registerEffect(configId: string, effect: () => void) {\n validateConfigId(configId, 'action-effect');\n registeredEffects[configId] = effect;\n return () => {\n delete registeredEffects[configId];\n };\n },\n configureEditorPanel(options) {\n void execPromise('wb:plugin:config:inspector', options);\n },\n setLoadingState(loadingState) {\n void execPromise('wb:plugin:config:loading-state', loadingState);\n },\n subscribeToWorkbookVariable(configId, callback) {\n validateConfigId(configId, 'variable');\n const setValues = (values: Record<string, WorkbookVariable>) => {\n callback(values[configId]);\n };\n on('wb:plugin:variable:update', setValues);\n return () => {\n off('wb:plugin:variable:update', setValues);\n };\n },\n subscribeToWorkbookInteraction(configId, callback) {\n validateConfigId(configId, 'interaction');\n const setValues = (values: Record<string, WorkbookSelection[]>) => {\n callback(values[configId]);\n };\n on('wb:plugin:selection:update', setValues);\n return () => {\n off('wb:plugin:selection:update', setValues);\n };\n },\n subscribeToUrlParameter(configId, callback) {\n validateConfigId(configId, 'url-parameter');\n const setValues = (values: Record<string, UrlParameter>) => {\n callback(values[configId]);\n };\n setValues(subscribedUrlParameters);\n on('wb:plugin:url-parameter:update', setValues);\n return () => {\n off('wb:plugin:url-parameter:update', setValues);\n };\n },\n getUrlParameter(configId: string) {\n validateConfigId(configId, 'url-parameter');\n return subscribedUrlParameters[configId];\n },\n setUrlParameter(configId: string, value: string) {\n validateConfigId(configId, 'url-parameter');\n void execPromise('wb:plugin:url-parameter:set', configId, value);\n },\n },\n elements: {\n getElementColumns(configId) {\n validateConfigId(configId, 'element');\n return execPromise('wb:plugin:element:columns:get', configId);\n },\n subscribeToElementColumns(configId, callback) {\n validateConfigId(configId, 'element');\n const eventName = `wb:plugin:element:${configId}:columns`;\n on(eventName, callback);\n void execPromise('wb:plugin:element:subscribe:columns', configId);\n\n return () => {\n off(eventName, callback);\n void execPromise('wb:plugin:element:unsubscribe:columns', configId);\n };\n },\n subscribeToElementData(configId, callback) {\n validateConfigId(configId, 'element');\n const eventName = `wb:plugin:element:${configId}:data`;\n on(eventName, callback);\n void execPromise('wb:plugin:element:subscribe:data', configId);\n\n return () => {\n off(eventName, callback);\n void execPromise('wb:plugin:element:unsubscribe:data', configId);\n };\n },\n fetchMoreElementData(configId) {\n validateConfigId(configId, 'element');\n void execPromise('wb:plugin:element:fetch-more', configId);\n },\n },\n\n style: {\n subscribe(callback: (style: PluginStyle) => void) {\n on('wb:plugin:style:update', callback);\n return () => off('wb:plugin:style:update', callback);\n },\n\n get() {\n return execPromise('wb:plugin:style:get');\n },\n },\n\n destroy() {\n Object.keys(listeners).forEach(event => delete listeners[event]);\n window.removeEventListener('message', listener, false);\n },\n };\n}\n","import { initialize } from './client/initialize';\n\nexport const client = initialize();\n","import * as React from 'react';\n\nimport { client } from '../client';\nimport { PluginInstance } from '../types';\n\nexport const PluginContext = React.createContext<PluginInstance>(client);\n","import * as React from 'react';\n\nimport {\n PluginInstance,\n CustomPluginConfigOptions,\n WorkbookElementColumns,\n WorkbookElementData,\n WorkbookSelection,\n WorkbookVariable,\n PluginStyle,\n UrlParameter,\n} from '../types';\nimport { deepEqual } from '../utils/deepEqual';\n\nimport { PluginContext } from './Context';\n\n/**\n * Gets the entire plugin instance\n * @returns {PluginInstance} Context for the current plugin instance\n */\nexport function usePlugin(): PluginInstance<any> {\n return React.useContext(PluginContext);\n}\n\n/**\n * Provides a setter for the Plugin's Config Options\n * @param {CustomPluginConfigOptions[]} nextOptions Updated possible Config Options\n */\nexport function useEditorPanelConfig(\n nextOptions: CustomPluginConfigOptions[],\n): void {\n const client = usePlugin();\n const optionsRef = React.useRef({});\n\n React.useEffect(() => {\n if (nextOptions == null) return;\n if (!deepEqual(nextOptions, optionsRef.current)) {\n client.config.configureEditorPanel(nextOptions);\n optionsRef.current = nextOptions;\n }\n }, [client, nextOptions]);\n}\n\n/**\n * React hook for Plugin Config loading state\n * @param {boolean} initialState Initial value to set loading state to\n * @returns {[boolean, Function]} Boolean value corresponding to loading state for plugin config and setter for loading state\n */\nexport function useLoadingState(\n initialState: boolean,\n): [boolean, (nextState: boolean) => void] {\n const client = usePlugin();\n const [loading, setLoading] = React.useState(() => {\n client.config.setLoadingState(initialState);\n return initialState;\n });\n\n return [\n loading,\n nextState => {\n if (nextState === loading) return;\n setLoading(nextState);\n client.config.setLoadingState(nextState);\n },\n ];\n}\n\n/**\n * Provides the latest column values from corresponding config element\n * @param {string} configId ID from the config for fetching element columns, with type: 'element'\n * @returns {WorkbookElementColumns} Values of corresponding columns contained\n * within the config element\n */\nexport function useElementColumns(configId: string): WorkbookElementColumns {\n const client = usePlugin();\n const [columns, setColumns] = React.useState<WorkbookElementColumns>({});\n\n React.useEffect(() => {\n if (configId) {\n return client.elements.subscribeToElementColumns(configId, setColumns);\n }\n }, [client, configId]);\n\n return columns;\n}\n\n/**\n * Provides the latest data values from config element (max 25_000)\n * @param {string} configId ID from the config for fetching element data, with type: 'element'\n * @returns {WorkbookElementData} Element Data for config element, if any\n */\nexport function useElementData(configId: string): WorkbookElementData {\n const client = usePlugin();\n const [data, setData] = React.useState<WorkbookElementData>({});\n\n React.useEffect(() => {\n if (configId) {\n return client.elements.subscribeToElementData(configId, setData);\n }\n }, [client, configId]);\n\n return data;\n}\n\n/**\n * Provides the latest data values from corresponding config element with a callback to\n * fetch more in chunks of 25_000 data points\n * @param {string} configId ID from the config for fetching paginated\n * element data, with type: 'element'\n * @returns {WorkbookElementData} Element Data for configured config element, if any\n */\nexport function usePaginatedElementData(\n configId: string,\n): [WorkbookElementData, () => void] {\n const client = usePlugin();\n const [data, setData] = React.useState<WorkbookElementData>({});\n\n const loadMore = React.useCallback(() => {\n if (configId) {\n client.elements.fetchMoreElementData(configId);\n }\n }, [configId, client.elements]);\n\n React.useEffect(() => {\n if (configId) {\n return client.elements.subscribeToElementData(configId, setData);\n }\n }, [client, configId]);\n\n return [data, loadMore];\n}\n\n/**\n * Provides the latest value for entire config or certain key within the config\n * @param {string} key Key within Plugin Config, optional\n * @returns Entire config if no key passed in or value for key within plugin config\n */\nexport function useConfig(key?: string): any {\n const client = usePlugin();\n const [config, setConfig] = React.useState<any>(\n key != null ? client.config.getKey(key) : client.config.get(),\n );\n\n React.useEffect(\n () =>\n client.config.subscribe(newConfig => {\n if (key != null && newConfig[key] !== config[key]) {\n setConfig(newConfig[key]);\n } else {\n setConfig(newConfig);\n }\n }),\n [client, key, config],\n );\n\n return config;\n}\n\n/**\n * React hook for accessing a workbook control variable\n * @param {string} id ID from the config of type: 'variable'\n * @returns {[(WorkbookVariable | undefined), Function]} Constantly updating\n * value of the control variable and setter for the variable\n */\nexport function useVariable(\n id: string,\n): [WorkbookVariable | undefined, Function] {\n const client = usePlugin();\n const [workbookVariable, setWorkbookVariable] =\n React.useState<WorkbookVariable>();\n\n const isFirstRender = React.useRef<boolean>(true);\n\n React.useEffect(() => {\n if (isFirstRender.current) {\n setWorkbookVariable(client.config.getVariable(id));\n isFirstRender.current = false;\n }\n return client.config.subscribeToWorkbookVariable(id, setWorkbookVariable);\n }, [client, id]);\n\n const setVariable = React.useCallback(\n (...values: unknown[]) => client.config.setVariable(id, ...values),\n [id, client.config],\n );\n\n return [workbookVariable, setVariable];\n}\n\n/**\n * React hook for accessing a url parameter\n * @param {string} id ID from the config of type: 'url-parameter'\n * @returns {[(UrlParameter | undefined), Function]} Constantly updating value of the url parameter and setter for the url parameter\n */\nexport function useUrlParameter(\n id: string,\n): [UrlParameter | undefined, (value: string) => void] {\n const client = usePlugin();\n const [urlParameter, setUrlParameter] = React.useState<UrlParameter>();\n\n const isFirstRender = React.useRef<boolean>(true);\n\n React.useEffect(() => {\n if (isFirstRender.current) {\n setUrlParameter(client.config.getUrlParameter(id));\n isFirstRender.current = false;\n }\n return client.config.subscribeToUrlParameter(id, setUrlParameter);\n }, [client, id]);\n\n const setter = React.useCallback(\n (value: string) => client.config.setUrlParameter(id, value),\n [client, id],\n );\n\n return [urlParameter, setter];\n}\n\n/**\n * @deprecated Use Action API instead\n * React hook for accessing a workbook interaction selections state\n * @param {string} id ID from the config of type: 'interaction'\n * @returns {[(WorkbookSelection | undefined), Function]} Constantly updating selection state and setter thereof\n */\nexport function useInteraction(\n id: string,\n elementId: string,\n): [unknown, Function] {\n const client = usePlugin();\n const [workbookInteraction, setWorkbookInteraction] =\n React.useState<WorkbookSelection[]>();\n\n React.useEffect(() => {\n return client.config.subscribeToWorkbookInteraction(\n id,\n setWorkbookInteraction,\n );\n }, [client, id]);\n\n const setInteraction = React.useCallback(\n (value: WorkbookSelection[]) => {\n client.config.setInteraction(id, elementId, value);\n },\n [id, elementId, client.config],\n );\n\n return [workbookInteraction, setInteraction];\n}\n\n/**\n * React hook for returning a triggering callback function for the registered\n * action trigger\n * @param {string} configId ID from the config of type: 'action-trigger'\n * @returns {Function} A callback function to trigger the action\n */\nexport function useActionTrigger(configId: string): () => void {\n const client = usePlugin();\n\n return React.useCallback(() => {\n client.config.triggerAction(configId);\n }, [client, configId]);\n}\n\n/**\n * React hook for registering and unregistering an action effect\n * @param {string} configId ID from the config of type: 'action-effect'\n * @param {Function} effect The function to be called when the action is triggered\n */\nexport function useActionEffect(configId: string, effect: () => void) {\n const client = usePlugin();\n\n const effectRef = React.useRef(effect);\n\n React.useEffect(() => {\n effectRef.current = effect;\n });\n\n React.useEffect(() => {\n return client.config.registerEffect(configId, effectRef.current);\n }, [client, configId, effect]);\n}\n\n/**\n * React hook for accessing plugin style with live updates\n * @returns {PluginStyle | undefined} Style properties from the workbook if available\n */\nexport function usePluginStyle(): PluginStyle | undefined {\n const client = usePlugin();\n const [style, setStyle] = React.useState<PluginStyle | undefined>();\n\n React.useEffect(() => {\n // Request initial style data on mount and subscribe to updates\n void client.style.get().then(response => setStyle(response));\n return client.style.subscribe(setStyle);\n }, [client]);\n\n return style;\n}\n","import * as React from 'react';\n\nimport { PluginInstance } from '../types';\n\nimport { PluginContext } from './Context';\n\nexport interface SigmaClientProviderProps<T = any> {\n client: PluginInstance<T>;\n children?: React.ReactNode;\n}\n\nexport function SigmaClientProvider<T = any>(\n props: SigmaClientProviderProps<T>,\n) {\n return (\n <PluginContext.Provider value={props.client}>\n {props.children}\n </PluginContext.Provider>\n );\n}\n","const FPS = 1000 / 60;\n\n/**\n * requestAnimationFrame() calls are paused in most browsers when running in background tabs or hidden <iframe>s in order to improve performance and battery life\n * @see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame\n */\nexport function polyfillRequestAnimationFrame(window: Window) {\n if ('requestAnimationFrame' in window) {\n window.requestAnimationFrame = callback => window.setTimeout(callback, FPS);\n\n window.cancelAnimationFrame = id => window.clearTimeout(id);\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`react`)):typeof define==`function`&&define.amd?define([`exports`,`react`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.SigmaPlugin={},e.React))})(this,function(e,t){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var n=Object.create,r=Object.defineProperty,i=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,o=Object.getPrototypeOf,s=Object.prototype.hasOwnProperty,c=(e,t,n,o)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=a(t),l=0,u=c.length,d;l<u;l++)d=c[l],!s.call(e,d)&&d!==n&&r(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(o=i(t,d))||o.enumerable});return e},l=(e,t,i)=>(i=e==null?{}:n(o(e)),c(t||!e||!e.__esModule?r(i,`default`,{value:e,enumerable:!0}):i,e));let u=l(t,1);t=l(t);function d(e){return!!(typeof e==`object`&&e)}function f(e,t){if(e===t)return!0;if(d(e)&&d(t)){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(let n in e)if(!f(e[n],t[n]))return!1;return!0}}function p(e,t){e===void 0&&console.warn(`Invalid config ${t}: ${e}`)}function m(){let e={config:{}},t={},n={},r={},i={},a={},o=new URL(document.location.href);for(let[t,n]of o.searchParams.entries())try{e[t]=JSON.parse(n)}catch{console.error(`Failed to parse URL param ${t} with value ${n} as JSON.`)}let s=e=>{u(e.data.type,e.data.result,e.data.error)};window.addEventListener(`message`,s,!1),window.addEventListener(`click`,()=>d(`wb:plugin:focus`)),c(`wb:plugin:config:update`,t=>{Object.assign(e,t),u(`config`,e.config??{})}),d(`wb:plugin:init`,`1.2.0`).then(t=>{Object.assign(e,t),u(`init`,e),u(`config`,e.config)}),c(`wb:plugin:variable:update`,e=>{n={},Object.assign(n,e)}),c(`wb:plugin:selection:update`,e=>{t={},Object.assign(t,e)}),c(`wb:plugin:url-parameter:update`,e=>{r={},Object.assign(r,e)}),c(`wb:plugin:action-effect:invoke`,e=>{let t=i[e];if(!t)throw Error(`Unknown action effect with name: ${e}`);t()});function c(e,t){a[e]=a[e]||[],a[e].push(t)}function l(e,t){a[e]!=null&&(a[e]=a[e].filter(e=>e!==t))}function u(e,...t){Object.values(a[e]||[]).forEach(e=>e(...t))}function d(t,...n){return new Promise((r,i)=>{let a=(e,n)=>{n?i(n):r(e),l(t,a)};c(t,a),window.parent.postMessage({type:t,args:n,elementId:e.id},e?.wbOrigin??`*`)})}return{get sigmaEnv(){return e.sigmaEnv},get isScreenshot(){return e.screenshot},config:{getKey(t){return e?.config?.[t]},get(){return e.config},set(e){d(`wb:plugin:config:update`,e)},setKey(e,t){d(`wb:plugin:config:update`,{[e]:t})},subscribe(e){return c(`config`,e),()=>l(`config`,e)},getVariable(e){return p(e,`variable`),n[e]},setVariable(e,...t){p(e,`variable`),d(`wb:plugin:variable:set`,e,...t)},getInteraction(e){return p(e,`interaction`),t[e]},setInteraction(e,t,n){p(e,`interaction`),d(`wb:plugin:selection:set`,e,t,n)},triggerAction(e){p(e,`action-trigger`),d(`wb:plugin:action-trigger:invoke`,e)},registerEffect(e,t){return p(e,`action-effect`),i[e]=t,()=>{delete i[e]}},configureEditorPanel(e){d(`wb:plugin:config:inspector`,e)},setLoadingState(e){d(`wb:plugin:config:loading-state`,e)},subscribeToWorkbookVariable(e,t){p(e,`variable`);let n=n=>{t(n[e])};return c(`wb:plugin:variable:update`,n),()=>{l(`wb:plugin:variable:update`,n)}},subscribeToWorkbookInteraction(e,t){p(e,`interaction`);let n=n=>{t(n[e])};return c(`wb:plugin:selection:update`,n),()=>{l(`wb:plugin:selection:update`,n)}},subscribeToUrlParameter(e,t){p(e,`url-parameter`);let n=n=>{t(n[e])};return n(r),c(`wb:plugin:url-parameter:update`,n),()=>{l(`wb:plugin:url-parameter:update`,n)}},getUrlParameter(e){return p(e,`url-parameter`),r[e]},setUrlParameter(e,t){p(e,`url-parameter`),d(`wb:plugin:url-parameter:set`,e,t)}},elements:{getElementColumns(e){return p(e,`element`),d(`wb:plugin:element:columns:get`,e)},subscribeToElementColumns(e,t){p(e,`element`);let n=`wb:plugin:element:${e}:columns`;return c(n,t),d(`wb:plugin:element:subscribe:columns`,e),()=>{l(n,t),d(`wb:plugin:element:unsubscribe:columns`,e)}},subscribeToElementData(e,t){p(e,`element`);let n=`wb:plugin:element:${e}:data`;return c(n,t),d(`wb:plugin:element:subscribe:data`,e),()=>{l(n,t),d(`wb:plugin:element:unsubscribe:data`,e)}},fetchMoreElementData(e){p(e,`element`),d(`wb:plugin:element:fetch-more`,e)}},style:{subscribe(e){return c(`wb:plugin:style:update`,e),()=>l(`wb:plugin:style:update`,e)},get(){return d(`wb:plugin:style:get`)}},destroy(){Object.keys(a).forEach(e=>delete a[e]),window.removeEventListener(`message`,s,!1)}}}let h=m(),g=u.createContext(h);function _(){return u.useContext(g)}function v(e){let t=_(),n=u.useRef({});u.useEffect(()=>{e!=null&&(f(e,n.current)||(t.config.configureEditorPanel(e),n.current=e))},[t,e])}function y(e){let t=_(),[n,r]=u.useState(()=>(t.config.setLoadingState(e),e));return[n,e=>{e!==n&&(r(e),t.config.setLoadingState(e))}]}function b(e){let t=_(),[n,r]=u.useState({});return u.useEffect(()=>{if(e)return t.elements.subscribeToElementColumns(e,r)},[t,e]),n}function x(e){let t=_(),[n,r]=u.useState({});return u.useEffect(()=>{if(e)return t.elements.subscribeToElementData(e,r)},[t,e]),n}function S(e){let t=_(),[n,r]=u.useState({}),i=u.useCallback(()=>{e&&t.elements.fetchMoreElementData(e)},[e,t.elements]);return u.useEffect(()=>{if(e)return t.elements.subscribeToElementData(e,r)},[t,e]),[n,i]}function C(e){let t=_(),[n,r]=u.useState(e==null?t.config.get():t.config.getKey(e));return u.useEffect(()=>t.config.subscribe(t=>{e!=null&&t[e]!==n[e]?r(t[e]):r(t)}),[t,e,n]),n}function w(e){let t=_(),[n,r]=u.useState(),i=u.useRef(!0);return u.useEffect(()=>(i.current&&=(r(t.config.getVariable(e)),!1),t.config.subscribeToWorkbookVariable(e,r)),[t,e]),[n,u.useCallback((...n)=>t.config.setVariable(e,...n),[e,t.config])]}function T(e){let t=_(),[n,r]=u.useState(),i=u.useRef(!0);return u.useEffect(()=>(i.current&&=(r(t.config.getUrlParameter(e)),!1),t.config.subscribeToUrlParameter(e,r)),[t,e]),[n,u.useCallback(n=>t.config.setUrlParameter(e,n),[t,e])]}function E(e,t){let n=_(),[r,i]=u.useState();return u.useEffect(()=>n.config.subscribeToWorkbookInteraction(e,i),[n,e]),[r,u.useCallback(r=>{n.config.setInteraction(e,t,r)},[e,t,n.config])]}function D(e){let t=_();return u.useCallback(()=>{t.config.triggerAction(e)},[t,e])}function O(e,t){let n=_(),r=u.useRef(t);u.useEffect(()=>{r.current=t}),u.useEffect(()=>n.config.registerEffect(e,r.current),[n,e,t])}function k(){let e=_(),[t,n]=u.useState();return u.useEffect(()=>(e.style.get().then(e=>n(e)),e.style.subscribe(n)),[e]),t}function A(e){return t.createElement(g.Provider,{value:e.client},e.children)}function j(e){`requestAnimationFrame`in e&&(e.requestAnimationFrame=t=>e.setTimeout(t,16.666666666666668),e.cancelAnimationFrame=t=>e.clearTimeout(t))}e.SigmaClientProvider=A,e.client=h,e.polyfillRequestAnimationFrame=j,e.useActionEffect=O,e.useActionTrigger=D,e.useConfig=C,e.useEditorPanelConfig=v,e.useElementColumns=b,e.useElementData=x,e.useInteraction=E,e.useLoadingState=y,e.usePaginatedElementData=S,e.usePlugin=_,e.usePluginStyle=k,e.useUrlParameter=T,e.useVariable=w});
2
+ //# sourceMappingURL=sigmacomputing-plugin.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sigmacomputing-plugin.umd.js","names":["React","React"],"sources":["../../src/utils/deepEqual.ts","../../src/utils/error.ts","../../src/client/initialize.ts","../../src/client.ts","../../src/react/Context.ts","../../src/react/hooks.ts","../../src/react/Provider.tsx","../../src/utils/polyfillRequestAnimationFrame.ts"],"sourcesContent":["function isObject(obj: any) {\n if (typeof obj === 'object' && obj != null) {\n return true;\n } else {\n return false;\n }\n}\n\nexport function deepEqual(obj1: any, obj2: any) {\n if (obj1 === obj2) {\n return true;\n } else if (isObject(obj1) && isObject(obj2)) {\n if (Object.keys(obj1).length !== Object.keys(obj2).length) {\n return false;\n }\n for (const prop in obj1) {\n if (!deepEqual(obj1[prop], obj2[prop])) {\n return false;\n }\n }\n return true;\n }\n}\n","import { CustomPluginConfigOptions } from '../types';\n\nexport function validateConfigId(\n configId: string,\n expectedConfigType: CustomPluginConfigOptions['type'],\n) {\n if (configId === undefined) {\n console.warn(`Invalid config ${expectedConfigType}: ${configId}`);\n }\n}\n","import {\n PluginConfig,\n PluginInstance,\n PluginMessageResponse,\n PluginStyle,\n UrlParameter,\n WorkbookSelection,\n WorkbookVariable,\n} from '../types';\nimport { validateConfigId } from '../utils/error';\n\nexport function initialize<T = {}>(): PluginInstance<T> {\n const pluginConfig: Partial<PluginConfig<T>> = {\n config: {} as T,\n };\n\n let subscribedInteractions: Record<string, WorkbookSelection[]> = {};\n let subscribedWorkbookVars: Record<string, WorkbookVariable> = {};\n let subscribedUrlParameters: Record<string, UrlParameter> = {};\n const registeredEffects: Record<string, () => void> = {};\n\n const listeners: {\n [event: string]: Function[];\n } = {};\n\n const location = new URL(document.location.href);\n for (const [key, value] of location.searchParams.entries()) {\n try {\n pluginConfig[key] = JSON.parse(value);\n } catch (_err: unknown) {\n if (__VITEST_BROWSER__ && (key === 'iframeId' || key === 'sessionId')) {\n // noop: vitest browser injects these into the test iframe URL\n } else {\n console.error(\n `Failed to parse URL param ${key} with value ${value} as JSON.`,\n );\n }\n }\n }\n\n const listener = (e: PluginMessageResponse) => {\n emit(e.data.type, e.data.result, e.data.error);\n };\n\n window.addEventListener('message', listener, false);\n window.addEventListener('click', () => execPromise('wb:plugin:focus'));\n\n on('wb:plugin:config:update', (config: PluginConfig<T>) => {\n Object.assign(pluginConfig, config);\n emit('config', pluginConfig.config ?? {});\n });\n\n // send initialize event\n void execPromise('wb:plugin:init', __VERSION__).then(config => {\n Object.assign(pluginConfig, config);\n emit('init', pluginConfig);\n emit('config', pluginConfig.config);\n });\n\n on(\n 'wb:plugin:variable:update',\n (updatedVariables: Record<string, WorkbookVariable>) => {\n subscribedWorkbookVars = {};\n Object.assign(subscribedWorkbookVars, updatedVariables);\n },\n );\n\n on('wb:plugin:selection:update', (updatedInteractions: unknown) => {\n subscribedInteractions = {};\n Object.assign(subscribedInteractions, updatedInteractions);\n });\n\n on(\n 'wb:plugin:url-parameter:update',\n (updatedUrlParameters: Record<string, UrlParameter>) => {\n subscribedUrlParameters = {};\n Object.assign(subscribedUrlParameters, updatedUrlParameters);\n },\n );\n\n on('wb:plugin:action-effect:invoke', (configId: string) => {\n const effect = registeredEffects[configId];\n if (!effect) {\n throw new Error(`Unknown action effect with name: ${configId}`);\n }\n effect();\n });\n\n function on(event: string, listener: Function) {\n listeners[event] = listeners[event] || [];\n listeners[event].push(listener);\n }\n\n function off(event: string, listener: Function) {\n if (listeners[event] == null) return;\n listeners[event] = listeners[event].filter(a => a !== listener);\n }\n\n function emit(event: string, ...args: any) {\n Object.values(listeners[event] || []).forEach(fn => fn(...args));\n }\n\n function execPromise<R>(event: string, ...args: any): Promise<R> {\n return new Promise((resolve, reject) => {\n const callback = (data: R, error: any) => {\n if (error) reject(error);\n else resolve(data);\n off(event, callback);\n };\n on(event, callback);\n window.parent.postMessage(\n { type: event, args, elementId: pluginConfig.id },\n pluginConfig?.wbOrigin ?? '*',\n );\n });\n }\n\n return {\n get sigmaEnv() {\n return pluginConfig.sigmaEnv;\n },\n\n get isScreenshot() {\n return pluginConfig.screenshot;\n },\n\n config: {\n // @ts-ignore TODO: Fix\n getKey(key) {\n return pluginConfig?.config?.[key];\n },\n get() {\n return pluginConfig.config;\n },\n set(partialConfig) {\n void execPromise('wb:plugin:config:update', partialConfig);\n },\n setKey(key, value) {\n void execPromise('wb:plugin:config:update', {\n [key]: value,\n });\n },\n subscribe(listener) {\n on('config', listener);\n return () => off('config', listener);\n },\n getVariable(configId: string) {\n validateConfigId(configId, 'variable');\n return subscribedWorkbookVars[configId];\n },\n setVariable(configId: string, ...values: unknown[]) {\n validateConfigId(configId, 'variable');\n void execPromise('wb:plugin:variable:set', configId, ...values);\n },\n getInteraction(configId: string) {\n validateConfigId(configId, 'interaction');\n return subscribedInteractions[configId];\n },\n setInteraction(\n configId: string,\n elementId: string,\n selection:\n | string[]\n | Array<Record<string, { type: string; val?: unknown }>>,\n ) {\n validateConfigId(configId, 'interaction');\n void execPromise(\n 'wb:plugin:selection:set',\n configId,\n elementId,\n selection,\n );\n },\n triggerAction(configId: string) {\n validateConfigId(configId, 'action-trigger');\n void execPromise('wb:plugin:action-trigger:invoke', configId);\n },\n registerEffect(configId: string, effect: () => void) {\n validateConfigId(configId, 'action-effect');\n registeredEffects[configId] = effect;\n return () => {\n delete registeredEffects[configId];\n };\n },\n configureEditorPanel(options) {\n void execPromise('wb:plugin:config:inspector', options);\n },\n setLoadingState(loadingState) {\n void execPromise('wb:plugin:config:loading-state', loadingState);\n },\n subscribeToWorkbookVariable(configId, callback) {\n validateConfigId(configId, 'variable');\n const setValues = (values: Record<string, WorkbookVariable>) => {\n callback(values[configId]);\n };\n on('wb:plugin:variable:update', setValues);\n return () => {\n off('wb:plugin:variable:update', setValues);\n };\n },\n subscribeToWorkbookInteraction(configId, callback) {\n validateConfigId(configId, 'interaction');\n const setValues = (values: Record<string, WorkbookSelection[]>) => {\n callback(values[configId]);\n };\n on('wb:plugin:selection:update', setValues);\n return () => {\n off('wb:plugin:selection:update', setValues);\n };\n },\n subscribeToUrlParameter(configId, callback) {\n validateConfigId(configId, 'url-parameter');\n const setValues = (values: Record<string, UrlParameter>) => {\n callback(values[configId]);\n };\n setValues(subscribedUrlParameters);\n on('wb:plugin:url-parameter:update', setValues);\n return () => {\n off('wb:plugin:url-parameter:update', setValues);\n };\n },\n getUrlParameter(configId: string) {\n validateConfigId(configId, 'url-parameter');\n return subscribedUrlParameters[configId];\n },\n setUrlParameter(configId: string, value: string) {\n validateConfigId(configId, 'url-parameter');\n void execPromise('wb:plugin:url-parameter:set', configId, value);\n },\n },\n elements: {\n getElementColumns(configId) {\n validateConfigId(configId, 'element');\n return execPromise('wb:plugin:element:columns:get', configId);\n },\n subscribeToElementColumns(configId, callback) {\n validateConfigId(configId, 'element');\n const eventName = `wb:plugin:element:${configId}:columns`;\n on(eventName, callback);\n void execPromise('wb:plugin:element:subscribe:columns', configId);\n\n return () => {\n off(eventName, callback);\n void execPromise('wb:plugin:element:unsubscribe:columns', configId);\n };\n },\n subscribeToElementData(configId, callback) {\n validateConfigId(configId, 'element');\n const eventName = `wb:plugin:element:${configId}:data`;\n on(eventName, callback);\n void execPromise('wb:plugin:element:subscribe:data', configId);\n\n return () => {\n off(eventName, callback);\n void execPromise('wb:plugin:element:unsubscribe:data', configId);\n };\n },\n fetchMoreElementData(configId) {\n validateConfigId(configId, 'element');\n void execPromise('wb:plugin:element:fetch-more', configId);\n },\n },\n\n style: {\n subscribe(callback: (style: PluginStyle) => void) {\n on('wb:plugin:style:update', callback);\n return () => off('wb:plugin:style:update', callback);\n },\n\n get() {\n return execPromise('wb:plugin:style:get');\n },\n },\n\n destroy() {\n Object.keys(listeners).forEach(event => delete listeners[event]);\n window.removeEventListener('message', listener, false);\n },\n };\n}\n","import { initialize } from './client/initialize';\n\nexport const client = initialize();\n","import * as React from 'react';\n\nimport { client } from '../client';\nimport { PluginInstance } from '../types';\n\nexport const PluginContext = React.createContext<PluginInstance>(client);\n","import * as React from 'react';\n\nimport {\n PluginInstance,\n CustomPluginConfigOptions,\n WorkbookElementColumns,\n WorkbookElementData,\n WorkbookSelection,\n WorkbookVariable,\n PluginStyle,\n UrlParameter,\n} from '../types';\nimport { deepEqual } from '../utils/deepEqual';\n\nimport { PluginContext } from './Context';\n\n/**\n * Gets the entire plugin instance\n * @returns {PluginInstance} Context for the current plugin instance\n */\nexport function usePlugin(): PluginInstance<any> {\n return React.useContext(PluginContext);\n}\n\n/**\n * Provides a setter for the Plugin's Config Options\n * @param {CustomPluginConfigOptions[]} nextOptions Updated possible Config Options\n */\nexport function useEditorPanelConfig(\n nextOptions: CustomPluginConfigOptions[],\n): void {\n const client = usePlugin();\n const optionsRef = React.useRef({});\n\n React.useEffect(() => {\n if (nextOptions == null) return;\n if (!deepEqual(nextOptions, optionsRef.current)) {\n client.config.configureEditorPanel(nextOptions);\n optionsRef.current = nextOptions;\n }\n }, [client, nextOptions]);\n}\n\n/**\n * React hook for Plugin Config loading state\n * @param {boolean} initialState Initial value to set loading state to\n * @returns {[boolean, Function]} Boolean value corresponding to loading state for plugin config and setter for loading state\n */\nexport function useLoadingState(\n initialState: boolean,\n): [boolean, (nextState: boolean) => void] {\n const client = usePlugin();\n const [loading, setLoading] = React.useState(() => {\n client.config.setLoadingState(initialState);\n return initialState;\n });\n\n return [\n loading,\n nextState => {\n if (nextState === loading) return;\n setLoading(nextState);\n client.config.setLoadingState(nextState);\n },\n ];\n}\n\n/**\n * Provides the latest column values from corresponding config element\n * @param {string} configId ID from the config for fetching element columns, with type: 'element'\n * @returns {WorkbookElementColumns} Values of corresponding columns contained\n * within the config element\n */\nexport function useElementColumns(configId: string): WorkbookElementColumns {\n const client = usePlugin();\n const [columns, setColumns] = React.useState<WorkbookElementColumns>({});\n\n React.useEffect(() => {\n if (configId) {\n return client.elements.subscribeToElementColumns(configId, setColumns);\n }\n }, [client, configId]);\n\n return columns;\n}\n\n/**\n * Provides the latest data values from config element (max 25_000)\n * @param {string} configId ID from the config for fetching element data, with type: 'element'\n * @returns {WorkbookElementData} Element Data for config element, if any\n */\nexport function useElementData(configId: string): WorkbookElementData {\n const client = usePlugin();\n const [data, setData] = React.useState<WorkbookElementData>({});\n\n React.useEffect(() => {\n if (configId) {\n return client.elements.subscribeToElementData(configId, setData);\n }\n }, [client, configId]);\n\n return data;\n}\n\n/**\n * Provides the latest data values from corresponding config element with a callback to\n * fetch more in chunks of 25_000 data points\n * @param {string} configId ID from the config for fetching paginated\n * element data, with type: 'element'\n * @returns {WorkbookElementData} Element Data for configured config element, if any\n */\nexport function usePaginatedElementData(\n configId: string,\n): [WorkbookElementData, () => void] {\n const client = usePlugin();\n const [data, setData] = React.useState<WorkbookElementData>({});\n\n const loadMore = React.useCallback(() => {\n if (configId) {\n client.elements.fetchMoreElementData(configId);\n }\n }, [configId, client.elements]);\n\n React.useEffect(() => {\n if (configId) {\n return client.elements.subscribeToElementData(configId, setData);\n }\n }, [client, configId]);\n\n return [data, loadMore];\n}\n\n/**\n * Provides the latest value for entire config or certain key within the config\n * @param {string} key Key within Plugin Config, optional\n * @returns Entire config if no key passed in or value for key within plugin config\n */\nexport function useConfig(key?: string): any {\n const client = usePlugin();\n const [config, setConfig] = React.useState<any>(\n key != null ? client.config.getKey(key) : client.config.get(),\n );\n\n React.useEffect(\n () =>\n client.config.subscribe(newConfig => {\n if (key != null && newConfig[key] !== config[key]) {\n setConfig(newConfig[key]);\n } else {\n setConfig(newConfig);\n }\n }),\n [client, key, config],\n );\n\n return config;\n}\n\n/**\n * React hook for accessing a workbook control variable\n * @param {string} id ID from the config of type: 'variable'\n * @returns {[(WorkbookVariable | undefined), Function]} Constantly updating\n * value of the control variable and setter for the variable\n */\nexport function useVariable(\n id: string,\n): [WorkbookVariable | undefined, Function] {\n const client = usePlugin();\n const [workbookVariable, setWorkbookVariable] =\n React.useState<WorkbookVariable>();\n\n const isFirstRender = React.useRef<boolean>(true);\n\n React.useEffect(() => {\n if (isFirstRender.current) {\n setWorkbookVariable(client.config.getVariable(id));\n isFirstRender.current = false;\n }\n return client.config.subscribeToWorkbookVariable(id, setWorkbookVariable);\n }, [client, id]);\n\n const setVariable = React.useCallback(\n (...values: unknown[]) => client.config.setVariable(id, ...values),\n [id, client.config],\n );\n\n return [workbookVariable, setVariable];\n}\n\n/**\n * React hook for accessing a url parameter\n * @param {string} id ID from the config of type: 'url-parameter'\n * @returns {[(UrlParameter | undefined), Function]} Constantly updating value of the url parameter and setter for the url parameter\n */\nexport function useUrlParameter(\n id: string,\n): [UrlParameter | undefined, (value: string) => void] {\n const client = usePlugin();\n const [urlParameter, setUrlParameter] = React.useState<UrlParameter>();\n\n const isFirstRender = React.useRef<boolean>(true);\n\n React.useEffect(() => {\n if (isFirstRender.current) {\n setUrlParameter(client.config.getUrlParameter(id));\n isFirstRender.current = false;\n }\n return client.config.subscribeToUrlParameter(id, setUrlParameter);\n }, [client, id]);\n\n const setter = React.useCallback(\n (value: string) => client.config.setUrlParameter(id, value),\n [client, id],\n );\n\n return [urlParameter, setter];\n}\n\n/**\n * @deprecated Use Action API instead\n * React hook for accessing a workbook interaction selections state\n * @param {string} id ID from the config of type: 'interaction'\n * @returns {[(WorkbookSelection | undefined), Function]} Constantly updating selection state and setter thereof\n */\nexport function useInteraction(\n id: string,\n elementId: string,\n): [unknown, Function] {\n const client = usePlugin();\n const [workbookInteraction, setWorkbookInteraction] =\n React.useState<WorkbookSelection[]>();\n\n React.useEffect(() => {\n return client.config.subscribeToWorkbookInteraction(\n id,\n setWorkbookInteraction,\n );\n }, [client, id]);\n\n const setInteraction = React.useCallback(\n (value: WorkbookSelection[]) => {\n client.config.setInteraction(id, elementId, value);\n },\n [id, elementId, client.config],\n );\n\n return [workbookInteraction, setInteraction];\n}\n\n/**\n * React hook for returning a triggering callback function for the registered\n * action trigger\n * @param {string} configId ID from the config of type: 'action-trigger'\n * @returns {Function} A callback function to trigger the action\n */\nexport function useActionTrigger(configId: string): () => void {\n const client = usePlugin();\n\n return React.useCallback(() => {\n client.config.triggerAction(configId);\n }, [client, configId]);\n}\n\n/**\n * React hook for registering and unregistering an action effect\n * @param {string} configId ID from the config of type: 'action-effect'\n * @param {Function} effect The function to be called when the action is triggered\n */\nexport function useActionEffect(configId: string, effect: () => void) {\n const client = usePlugin();\n\n const effectRef = React.useRef(effect);\n\n React.useEffect(() => {\n effectRef.current = effect;\n });\n\n React.useEffect(() => {\n return client.config.registerEffect(configId, effectRef.current);\n }, [client, configId, effect]);\n}\n\n/**\n * React hook for accessing plugin style with live updates\n * @returns {PluginStyle | undefined} Style properties from the workbook if available\n */\nexport function usePluginStyle(): PluginStyle | undefined {\n const client = usePlugin();\n const [style, setStyle] = React.useState<PluginStyle | undefined>();\n\n React.useEffect(() => {\n // Request initial style data on mount and subscribe to updates\n void client.style.get().then(response => setStyle(response));\n return client.style.subscribe(setStyle);\n }, [client]);\n\n return style;\n}\n","import * as React from 'react';\n\nimport { PluginInstance } from '../types';\n\nimport { PluginContext } from './Context';\n\nexport interface SigmaClientProviderProps<T = any> {\n client: PluginInstance<T>;\n children?: React.ReactNode;\n}\n\nexport function SigmaClientProvider<T = any>(\n props: SigmaClientProviderProps<T>,\n) {\n return (\n <PluginContext.Provider value={props.client}>\n {props.children}\n </PluginContext.Provider>\n );\n}\n","const FPS = 1000 / 60;\n\n/**\n * requestAnimationFrame() calls are paused in most browsers when running in background tabs or hidden <iframe>s in order to improve performance and battery life\n * @see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame\n */\nexport function polyfillRequestAnimationFrame(window: Window) {\n if ('requestAnimationFrame' in window) {\n window.requestAnimationFrame = callback => window.setTimeout(callback, FPS);\n\n window.cancelAnimationFrame = id => window.clearTimeout(id);\n }\n}\n"],"mappings":"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"}