@sigmacomputing/plugin 1.1.0 → 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.
package/CHANGELOG.md CHANGED
@@ -9,17 +9,3 @@ request. Read our `CONTRIBUTING.md` guide to get started.
9
9
  - `@sigmacomputing/plugin-types` has been merged with `@sigmacomputing/plugin`
10
10
  and will no longer received updates in the future. Please use only
11
11
  `@sigmacomputing/plugin` going forward.
12
-
13
- - All `react` exports (`SigmaClientProvider` and all hooks) have been moved to
14
- a separate explicit export. This will allow better bundle splitting by not
15
- including `react` specific code for plugins that do not use `react`.
16
-
17
- ```ts
18
- // before
19
- import { SigmaClientProvider, usePlugin } from '@sigmacomputing/plugin';
20
-
21
- // after
22
- import { SigmaClientProvider, usePlugin } from '@sigmacomputing/plugin/react';
23
- ```
24
-
25
- All types can be imported from either `@sigmacomputing/plugin` or `@sigmacomputing/plugin/react`
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2021 Sigma Computing
3
+ Copyright (c) 2026 Sigma Computing
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -32,7 +32,6 @@ To test your plugin in Sigma Plugin Dev Playground, you must:
32
32
  To test a development version of a registered plugin, you must:
33
33
 
34
34
  - Have either:
35
-
36
35
  - An Admin account type
37
36
  - A custom account type that supports plugin developer feature permissions
38
37
 
@@ -106,7 +105,6 @@ and a React Hooks API.
106
105
  ```
107
106
 
108
107
  7. Start developing:
109
-
110
108
  - Get started with Sigma’s Plugin APIs.
111
109
  - Test your plugin directly in a Sigma workbook using the Sigma Plugin Dev
112
110
  Playground.
@@ -137,7 +135,7 @@ Before you start:
137
135
  > following command in your terminal:
138
136
  >
139
137
  > ```sh
140
- > yarn && yarn start
138
+ > yarn && yarn dev
141
139
  > ```
142
140
 
143
141
  1. Create/open a workbook.
@@ -264,14 +262,14 @@ type CustomPluginConfigOptions =
264
262
  label?: string;
265
263
  }
266
264
  | {
267
- type: 'action-effect';
268
- name: string;
269
- label?: string;
270
- }
265
+ type: 'action-effect';
266
+ name: string;
267
+ label?: string;
268
+ }
271
269
  | {
272
- type: 'url-parameter';
273
- name: string;
274
- };
270
+ type: 'url-parameter';
271
+ name: string;
272
+ };
275
273
  ```
276
274
 
277
275
  </details>
@@ -488,9 +486,9 @@ interface PluginInstance<T> {
488
486
  registerEffect(configId: string, effect: Function): void;
489
487
 
490
488
  /**
491
- * Overrider function for Config Ready state
489
+ * Overrider function for Config loading state
492
490
  */
493
- setLoadingState(ready: boolean): void;
491
+ setLoadingState(isLoading: boolean): void;
494
492
 
495
493
  /**
496
494
  * Allows users to subscribe to changes in the passed in variable
@@ -655,8 +653,8 @@ Arguments
655
653
 
656
654
  #### useLoadingState()
657
655
 
658
- Gets the current plugin's loading stat. Returns a value and a setter allowing
659
- you to update the plugin's loading state
656
+ Gets the current plugin's loading state and a setter. Call the setter with
657
+ `false` when your plugin has finished loading
660
658
 
661
659
  ```ts
662
660
  function useLoadingState(
@@ -666,7 +664,7 @@ function useLoadingState(
666
664
 
667
665
  Arguments
668
666
 
669
- - `initialState : boolean` - Initial value to set loading state to
667
+ - `initialState : boolean` - Initial loading state (typically `true`; then set to `false` when ready)
670
668
 
671
669
  #### useElementColumns()
672
670
 
@@ -814,9 +812,12 @@ console.log(urlParam?.value);
814
812
  client.config.setUrlParameter('myParamId', 'new-value');
815
813
 
816
814
  // Subscribe to changes
817
- const unsubscribe = client.config.subscribeToUrlParameter('myParamId', (urlParam) => {
818
- console.log('URL parameter updated:', urlParam.value);
819
- });
815
+ const unsubscribe = client.config.subscribeToUrlParameter(
816
+ 'myParamId',
817
+ urlParam => {
818
+ console.log('URL parameter updated:', urlParam.value);
819
+ },
820
+ );
820
821
  ```
821
822
 
822
823
  #### useInteraction()
@@ -904,33 +905,27 @@ Github.
904
905
  ### Available Plugins
905
906
 
906
907
  - **Recharts Bar Chart** - A basic bar chart built with the Recharts library.
907
-
908
908
  - [Source Code](https://github.com/sigmacomputing/sigma-sample-plugins/tree/main/sample-plugin-bar-chart)
909
909
  - Production URL: https://sigma-sample-bar-chart-54049.netlify.app/
910
910
 
911
911
  - **D3 Candlestick** - A candlestick visualization built with D3.
912
-
913
912
  - [Source Code](https://github.com/sigmacomputing/sigma-sample-plugins/tree/main/sample-plugin-bar-chart)
914
913
  - Production URL: https://sigma-sample-candlestick-chart-1664e5.netlify.app/
915
914
 
916
915
  - **Narrative Science Quill** - Demonstrates secure text entry.
917
-
918
916
  - [Source Code]()
919
917
  - Production URL: https://narrativescience-quill-3ee312.netlify.app/
920
918
 
921
919
  - **D3 Graph** - Demonstrates usage of multiple data sources and in-memory
922
920
  joins.
923
-
924
921
  - [Source Code](https://github.com/sigmacomputing/sigma-sample-plugins/tree/main/d3-graph)
925
922
  - Production URL: https://d3-graph-3a0d0f.netlify.app/
926
923
 
927
924
  - **D3 Sunburst** - A sunburst visualization built with D3.
928
-
929
925
  - [Source Code](https://github.com/sigmacomputing/sigma-sample-plugins/tree/main/d3-sunburst)
930
926
  - Production URL: https://d3-sunburst-b97c7c.netlify.app/
931
927
 
932
928
  - **Frappe Heatmap** - A basic Frappe visualization example.
933
-
934
929
  - [Source Code](https://github.com/sigmacomputing/sigma-sample-plugins/tree/main/frappe-heatmap)
935
930
  - Production URL: https://frappe-heatmap-9a4163.netlify.app/
936
931
 
@@ -0,0 +1,506 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ let react = require("react");
25
+ let react$1 = __toESM(react, 1);
26
+ react = __toESM(react);
27
+ //#region src/utils/deepEqual.ts
28
+ function isObject(obj) {
29
+ if (typeof obj === "object" && obj != null) return true;
30
+ else return false;
31
+ }
32
+ function deepEqual(obj1, obj2) {
33
+ if (obj1 === obj2) return true;
34
+ else if (isObject(obj1) && isObject(obj2)) {
35
+ if (Object.keys(obj1).length !== Object.keys(obj2).length) return false;
36
+ for (const prop in obj1) if (!deepEqual(obj1[prop], obj2[prop])) return false;
37
+ return true;
38
+ }
39
+ }
40
+ //#endregion
41
+ //#region src/utils/error.ts
42
+ function validateConfigId(configId, expectedConfigType) {
43
+ if (configId === void 0) console.warn(`Invalid config ${expectedConfigType}: ${configId}`);
44
+ }
45
+ //#endregion
46
+ //#region src/client/initialize.ts
47
+ function initialize() {
48
+ const pluginConfig = { config: {} };
49
+ let subscribedInteractions = {};
50
+ let subscribedWorkbookVars = {};
51
+ let subscribedUrlParameters = {};
52
+ const registeredEffects = {};
53
+ const listeners = {};
54
+ const location = new URL(document.location.href);
55
+ for (const [key, value] of location.searchParams.entries()) try {
56
+ pluginConfig[key] = JSON.parse(value);
57
+ } catch (_err) {
58
+ console.error(`Failed to parse URL param ${key} with value ${value} as JSON.`);
59
+ }
60
+ const listener = (e) => {
61
+ emit(e.data.type, e.data.result, e.data.error);
62
+ };
63
+ window.addEventListener("message", listener, false);
64
+ window.addEventListener("click", () => execPromise("wb:plugin:focus"));
65
+ on("wb:plugin:config:update", (config) => {
66
+ Object.assign(pluginConfig, config);
67
+ emit("config", pluginConfig.config ?? {});
68
+ });
69
+ execPromise("wb:plugin:init", "1.2.0").then((config) => {
70
+ Object.assign(pluginConfig, config);
71
+ emit("init", pluginConfig);
72
+ emit("config", pluginConfig.config);
73
+ });
74
+ on("wb:plugin:variable:update", (updatedVariables) => {
75
+ subscribedWorkbookVars = {};
76
+ Object.assign(subscribedWorkbookVars, updatedVariables);
77
+ });
78
+ on("wb:plugin:selection:update", (updatedInteractions) => {
79
+ subscribedInteractions = {};
80
+ Object.assign(subscribedInteractions, updatedInteractions);
81
+ });
82
+ on("wb:plugin:url-parameter:update", (updatedUrlParameters) => {
83
+ subscribedUrlParameters = {};
84
+ Object.assign(subscribedUrlParameters, updatedUrlParameters);
85
+ });
86
+ on("wb:plugin:action-effect:invoke", (configId) => {
87
+ const effect = registeredEffects[configId];
88
+ if (!effect) throw new Error(`Unknown action effect with name: ${configId}`);
89
+ effect();
90
+ });
91
+ function on(event, listener) {
92
+ listeners[event] = listeners[event] || [];
93
+ listeners[event].push(listener);
94
+ }
95
+ function off(event, listener) {
96
+ if (listeners[event] == null) return;
97
+ listeners[event] = listeners[event].filter((a) => a !== listener);
98
+ }
99
+ function emit(event, ...args) {
100
+ Object.values(listeners[event] || []).forEach((fn) => fn(...args));
101
+ }
102
+ function execPromise(event, ...args) {
103
+ return new Promise((resolve, reject) => {
104
+ const callback = (data, error) => {
105
+ if (error) reject(error);
106
+ else resolve(data);
107
+ off(event, callback);
108
+ };
109
+ on(event, callback);
110
+ window.parent.postMessage({
111
+ type: event,
112
+ args,
113
+ elementId: pluginConfig.id
114
+ }, pluginConfig?.wbOrigin ?? "*");
115
+ });
116
+ }
117
+ return {
118
+ get sigmaEnv() {
119
+ return pluginConfig.sigmaEnv;
120
+ },
121
+ get isScreenshot() {
122
+ return pluginConfig.screenshot;
123
+ },
124
+ config: {
125
+ getKey(key) {
126
+ return pluginConfig?.config?.[key];
127
+ },
128
+ get() {
129
+ return pluginConfig.config;
130
+ },
131
+ set(partialConfig) {
132
+ execPromise("wb:plugin:config:update", partialConfig);
133
+ },
134
+ setKey(key, value) {
135
+ execPromise("wb:plugin:config:update", { [key]: value });
136
+ },
137
+ subscribe(listener) {
138
+ on("config", listener);
139
+ return () => off("config", listener);
140
+ },
141
+ getVariable(configId) {
142
+ validateConfigId(configId, "variable");
143
+ return subscribedWorkbookVars[configId];
144
+ },
145
+ setVariable(configId, ...values) {
146
+ validateConfigId(configId, "variable");
147
+ execPromise("wb:plugin:variable:set", configId, ...values);
148
+ },
149
+ getInteraction(configId) {
150
+ validateConfigId(configId, "interaction");
151
+ return subscribedInteractions[configId];
152
+ },
153
+ setInteraction(configId, elementId, selection) {
154
+ validateConfigId(configId, "interaction");
155
+ execPromise("wb:plugin:selection:set", configId, elementId, selection);
156
+ },
157
+ triggerAction(configId) {
158
+ validateConfigId(configId, "action-trigger");
159
+ execPromise("wb:plugin:action-trigger:invoke", configId);
160
+ },
161
+ registerEffect(configId, effect) {
162
+ validateConfigId(configId, "action-effect");
163
+ registeredEffects[configId] = effect;
164
+ return () => {
165
+ delete registeredEffects[configId];
166
+ };
167
+ },
168
+ configureEditorPanel(options) {
169
+ execPromise("wb:plugin:config:inspector", options);
170
+ },
171
+ setLoadingState(loadingState) {
172
+ execPromise("wb:plugin:config:loading-state", loadingState);
173
+ },
174
+ subscribeToWorkbookVariable(configId, callback) {
175
+ validateConfigId(configId, "variable");
176
+ const setValues = (values) => {
177
+ callback(values[configId]);
178
+ };
179
+ on("wb:plugin:variable:update", setValues);
180
+ return () => {
181
+ off("wb:plugin:variable:update", setValues);
182
+ };
183
+ },
184
+ subscribeToWorkbookInteraction(configId, callback) {
185
+ validateConfigId(configId, "interaction");
186
+ const setValues = (values) => {
187
+ callback(values[configId]);
188
+ };
189
+ on("wb:plugin:selection:update", setValues);
190
+ return () => {
191
+ off("wb:plugin:selection:update", setValues);
192
+ };
193
+ },
194
+ subscribeToUrlParameter(configId, callback) {
195
+ validateConfigId(configId, "url-parameter");
196
+ const setValues = (values) => {
197
+ callback(values[configId]);
198
+ };
199
+ setValues(subscribedUrlParameters);
200
+ on("wb:plugin:url-parameter:update", setValues);
201
+ return () => {
202
+ off("wb:plugin:url-parameter:update", setValues);
203
+ };
204
+ },
205
+ getUrlParameter(configId) {
206
+ validateConfigId(configId, "url-parameter");
207
+ return subscribedUrlParameters[configId];
208
+ },
209
+ setUrlParameter(configId, value) {
210
+ validateConfigId(configId, "url-parameter");
211
+ execPromise("wb:plugin:url-parameter:set", configId, value);
212
+ }
213
+ },
214
+ elements: {
215
+ getElementColumns(configId) {
216
+ validateConfigId(configId, "element");
217
+ return execPromise("wb:plugin:element:columns:get", configId);
218
+ },
219
+ subscribeToElementColumns(configId, callback) {
220
+ validateConfigId(configId, "element");
221
+ const eventName = `wb:plugin:element:${configId}:columns`;
222
+ on(eventName, callback);
223
+ execPromise("wb:plugin:element:subscribe:columns", configId);
224
+ return () => {
225
+ off(eventName, callback);
226
+ execPromise("wb:plugin:element:unsubscribe:columns", configId);
227
+ };
228
+ },
229
+ subscribeToElementData(configId, callback) {
230
+ validateConfigId(configId, "element");
231
+ const eventName = `wb:plugin:element:${configId}:data`;
232
+ on(eventName, callback);
233
+ execPromise("wb:plugin:element:subscribe:data", configId);
234
+ return () => {
235
+ off(eventName, callback);
236
+ execPromise("wb:plugin:element:unsubscribe:data", configId);
237
+ };
238
+ },
239
+ fetchMoreElementData(configId) {
240
+ validateConfigId(configId, "element");
241
+ execPromise("wb:plugin:element:fetch-more", configId);
242
+ }
243
+ },
244
+ style: {
245
+ subscribe(callback) {
246
+ on("wb:plugin:style:update", callback);
247
+ return () => off("wb:plugin:style:update", callback);
248
+ },
249
+ get() {
250
+ return execPromise("wb:plugin:style:get");
251
+ }
252
+ },
253
+ destroy() {
254
+ Object.keys(listeners).forEach((event) => delete listeners[event]);
255
+ window.removeEventListener("message", listener, false);
256
+ }
257
+ };
258
+ }
259
+ //#endregion
260
+ //#region src/client.ts
261
+ const client = initialize();
262
+ //#endregion
263
+ //#region src/react/Context.ts
264
+ const PluginContext = react$1.createContext(client);
265
+ //#endregion
266
+ //#region src/react/hooks.ts
267
+ /**
268
+ * Gets the entire plugin instance
269
+ * @returns {PluginInstance} Context for the current plugin instance
270
+ */
271
+ function usePlugin() {
272
+ return react$1.useContext(PluginContext);
273
+ }
274
+ /**
275
+ * Provides a setter for the Plugin's Config Options
276
+ * @param {CustomPluginConfigOptions[]} nextOptions Updated possible Config Options
277
+ */
278
+ function useEditorPanelConfig(nextOptions) {
279
+ const client = usePlugin();
280
+ const optionsRef = react$1.useRef({});
281
+ react$1.useEffect(() => {
282
+ if (nextOptions == null) return;
283
+ if (!deepEqual(nextOptions, optionsRef.current)) {
284
+ client.config.configureEditorPanel(nextOptions);
285
+ optionsRef.current = nextOptions;
286
+ }
287
+ }, [client, nextOptions]);
288
+ }
289
+ /**
290
+ * React hook for Plugin Config loading state
291
+ * @param {boolean} initialState Initial value to set loading state to
292
+ * @returns {[boolean, Function]} Boolean value corresponding to loading state for plugin config and setter for loading state
293
+ */
294
+ function useLoadingState(initialState) {
295
+ const client = usePlugin();
296
+ const [loading, setLoading] = react$1.useState(() => {
297
+ client.config.setLoadingState(initialState);
298
+ return initialState;
299
+ });
300
+ return [loading, (nextState) => {
301
+ if (nextState === loading) return;
302
+ setLoading(nextState);
303
+ client.config.setLoadingState(nextState);
304
+ }];
305
+ }
306
+ /**
307
+ * Provides the latest column values from corresponding config element
308
+ * @param {string} configId ID from the config for fetching element columns, with type: 'element'
309
+ * @returns {WorkbookElementColumns} Values of corresponding columns contained
310
+ * within the config element
311
+ */
312
+ function useElementColumns(configId) {
313
+ const client = usePlugin();
314
+ const [columns, setColumns] = react$1.useState({});
315
+ react$1.useEffect(() => {
316
+ if (configId) return client.elements.subscribeToElementColumns(configId, setColumns);
317
+ }, [client, configId]);
318
+ return columns;
319
+ }
320
+ /**
321
+ * Provides the latest data values from config element (max 25_000)
322
+ * @param {string} configId ID from the config for fetching element data, with type: 'element'
323
+ * @returns {WorkbookElementData} Element Data for config element, if any
324
+ */
325
+ function useElementData(configId) {
326
+ const client = usePlugin();
327
+ const [data, setData] = react$1.useState({});
328
+ react$1.useEffect(() => {
329
+ if (configId) return client.elements.subscribeToElementData(configId, setData);
330
+ }, [client, configId]);
331
+ return data;
332
+ }
333
+ /**
334
+ * Provides the latest data values from corresponding config element with a callback to
335
+ * fetch more in chunks of 25_000 data points
336
+ * @param {string} configId ID from the config for fetching paginated
337
+ * element data, with type: 'element'
338
+ * @returns {WorkbookElementData} Element Data for configured config element, if any
339
+ */
340
+ function usePaginatedElementData(configId) {
341
+ const client = usePlugin();
342
+ const [data, setData] = react$1.useState({});
343
+ const loadMore = react$1.useCallback(() => {
344
+ if (configId) client.elements.fetchMoreElementData(configId);
345
+ }, [configId, client.elements]);
346
+ react$1.useEffect(() => {
347
+ if (configId) return client.elements.subscribeToElementData(configId, setData);
348
+ }, [client, configId]);
349
+ return [data, loadMore];
350
+ }
351
+ /**
352
+ * Provides the latest value for entire config or certain key within the config
353
+ * @param {string} key Key within Plugin Config, optional
354
+ * @returns Entire config if no key passed in or value for key within plugin config
355
+ */
356
+ function useConfig(key) {
357
+ const client = usePlugin();
358
+ const [config, setConfig] = react$1.useState(key != null ? client.config.getKey(key) : client.config.get());
359
+ react$1.useEffect(() => client.config.subscribe((newConfig) => {
360
+ if (key != null && newConfig[key] !== config[key]) setConfig(newConfig[key]);
361
+ else setConfig(newConfig);
362
+ }), [
363
+ client,
364
+ key,
365
+ config
366
+ ]);
367
+ return config;
368
+ }
369
+ /**
370
+ * React hook for accessing a workbook control variable
371
+ * @param {string} id ID from the config of type: 'variable'
372
+ * @returns {[(WorkbookVariable | undefined), Function]} Constantly updating
373
+ * value of the control variable and setter for the variable
374
+ */
375
+ function useVariable(id) {
376
+ const client = usePlugin();
377
+ const [workbookVariable, setWorkbookVariable] = react$1.useState();
378
+ const isFirstRender = react$1.useRef(true);
379
+ react$1.useEffect(() => {
380
+ if (isFirstRender.current) {
381
+ setWorkbookVariable(client.config.getVariable(id));
382
+ isFirstRender.current = false;
383
+ }
384
+ return client.config.subscribeToWorkbookVariable(id, setWorkbookVariable);
385
+ }, [client, id]);
386
+ return [workbookVariable, react$1.useCallback((...values) => client.config.setVariable(id, ...values), [id, client.config])];
387
+ }
388
+ /**
389
+ * React hook for accessing a url parameter
390
+ * @param {string} id ID from the config of type: 'url-parameter'
391
+ * @returns {[(UrlParameter | undefined), Function]} Constantly updating value of the url parameter and setter for the url parameter
392
+ */
393
+ function useUrlParameter(id) {
394
+ const client = usePlugin();
395
+ const [urlParameter, setUrlParameter] = react$1.useState();
396
+ const isFirstRender = react$1.useRef(true);
397
+ react$1.useEffect(() => {
398
+ if (isFirstRender.current) {
399
+ setUrlParameter(client.config.getUrlParameter(id));
400
+ isFirstRender.current = false;
401
+ }
402
+ return client.config.subscribeToUrlParameter(id, setUrlParameter);
403
+ }, [client, id]);
404
+ return [urlParameter, react$1.useCallback((value) => client.config.setUrlParameter(id, value), [client, id])];
405
+ }
406
+ /**
407
+ * @deprecated Use Action API instead
408
+ * React hook for accessing a workbook interaction selections state
409
+ * @param {string} id ID from the config of type: 'interaction'
410
+ * @returns {[(WorkbookSelection | undefined), Function]} Constantly updating selection state and setter thereof
411
+ */
412
+ function useInteraction(id, elementId) {
413
+ const client = usePlugin();
414
+ const [workbookInteraction, setWorkbookInteraction] = react$1.useState();
415
+ react$1.useEffect(() => {
416
+ return client.config.subscribeToWorkbookInteraction(id, setWorkbookInteraction);
417
+ }, [client, id]);
418
+ return [workbookInteraction, react$1.useCallback((value) => {
419
+ client.config.setInteraction(id, elementId, value);
420
+ }, [
421
+ id,
422
+ elementId,
423
+ client.config
424
+ ])];
425
+ }
426
+ /**
427
+ * React hook for returning a triggering callback function for the registered
428
+ * action trigger
429
+ * @param {string} configId ID from the config of type: 'action-trigger'
430
+ * @returns {Function} A callback function to trigger the action
431
+ */
432
+ function useActionTrigger(configId) {
433
+ const client = usePlugin();
434
+ return react$1.useCallback(() => {
435
+ client.config.triggerAction(configId);
436
+ }, [client, configId]);
437
+ }
438
+ /**
439
+ * React hook for registering and unregistering an action effect
440
+ * @param {string} configId ID from the config of type: 'action-effect'
441
+ * @param {Function} effect The function to be called when the action is triggered
442
+ */
443
+ function useActionEffect(configId, effect) {
444
+ const client = usePlugin();
445
+ const effectRef = react$1.useRef(effect);
446
+ react$1.useEffect(() => {
447
+ effectRef.current = effect;
448
+ });
449
+ react$1.useEffect(() => {
450
+ return client.config.registerEffect(configId, effectRef.current);
451
+ }, [
452
+ client,
453
+ configId,
454
+ effect
455
+ ]);
456
+ }
457
+ /**
458
+ * React hook for accessing plugin style with live updates
459
+ * @returns {PluginStyle | undefined} Style properties from the workbook if available
460
+ */
461
+ function usePluginStyle() {
462
+ const client = usePlugin();
463
+ const [style, setStyle] = react$1.useState();
464
+ react$1.useEffect(() => {
465
+ client.style.get().then((response) => setStyle(response));
466
+ return client.style.subscribe(setStyle);
467
+ }, [client]);
468
+ return style;
469
+ }
470
+ //#endregion
471
+ //#region src/react/Provider.tsx
472
+ function SigmaClientProvider(props) {
473
+ return /* @__PURE__ */ react.createElement(PluginContext.Provider, { value: props.client }, props.children);
474
+ }
475
+ //#endregion
476
+ //#region src/utils/polyfillRequestAnimationFrame.ts
477
+ const FPS = 1e3 / 60;
478
+ /**
479
+ * requestAnimationFrame() calls are paused in most browsers when running in background tabs or hidden <iframe>s in order to improve performance and battery life
480
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
481
+ */
482
+ function polyfillRequestAnimationFrame(window) {
483
+ if ("requestAnimationFrame" in window) {
484
+ window.requestAnimationFrame = (callback) => window.setTimeout(callback, FPS);
485
+ window.cancelAnimationFrame = (id) => window.clearTimeout(id);
486
+ }
487
+ }
488
+ //#endregion
489
+ exports.SigmaClientProvider = SigmaClientProvider;
490
+ exports.client = client;
491
+ exports.polyfillRequestAnimationFrame = polyfillRequestAnimationFrame;
492
+ exports.useActionEffect = useActionEffect;
493
+ exports.useActionTrigger = useActionTrigger;
494
+ exports.useConfig = useConfig;
495
+ exports.useEditorPanelConfig = useEditorPanelConfig;
496
+ exports.useElementColumns = useElementColumns;
497
+ exports.useElementData = useElementData;
498
+ exports.useInteraction = useInteraction;
499
+ exports.useLoadingState = useLoadingState;
500
+ exports.usePaginatedElementData = usePaginatedElementData;
501
+ exports.usePlugin = usePlugin;
502
+ exports.usePluginStyle = usePluginStyle;
503
+ exports.useUrlParameter = useUrlParameter;
504
+ exports.useVariable = useVariable;
505
+
506
+ //# sourceMappingURL=index.cjs.map