@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 +0 -14
- package/LICENSE +1 -1
- package/README.md +19 -24
- package/dist/cjs/index.cjs +506 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/index.d.cts +438 -0
- package/dist/esm/index.d.ts +438 -0
- package/dist/esm/index.js +466 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/umd/sigmacomputing-plugin.umd.js +2 -0
- package/dist/umd/sigmacomputing-plugin.umd.js.map +1 -0
- package/package.json +69 -33
- package/src/client/initialize.ts +280 -0
- package/src/client.ts +3 -0
- package/src/globals.d.ts +2 -0
- package/{dist/index.d.ts → src/index.ts} +1 -1
- package/src/react/Context.ts +6 -0
- package/src/react/Provider.tsx +20 -0
- package/src/react/hooks.ts +298 -0
- package/src/react.ts +3 -0
- package/src/types.ts +412 -0
- package/src/utils/deepEqual.ts +23 -0
- package/src/utils/error.ts +10 -0
- package/src/utils/polyfillRequestAnimationFrame.ts +13 -0
- package/dist/client.d.ts +0 -2
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -5
- package/dist/error.d.ts +0 -3
- package/dist/error.d.ts.map +0 -1
- package/dist/error.js +0 -9
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -22
- package/dist/react.d.ts +0 -3
- package/dist/react.d.ts.map +0 -1
- package/dist/react.js +0 -20
- package/dist/types.d.ts +0 -332
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
|
@@ -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":"wyBAAA,SAAS,EAAS,EAAU,CAIxB,MAHF,GAAI,OAAO,GAAQ,UAAY,GAOjC,SAAgB,EAAU,EAAW,EAAW,CAC9C,GAAI,IAAS,EACX,MAAO,MACE,EAAS,EAAK,EAAI,EAAS,EAAK,CAAE,CAC3C,GAAI,OAAO,KAAK,EAAK,CAAC,SAAW,OAAO,KAAK,EAAK,CAAC,OACjD,MAAO,GAET,IAAK,IAAM,KAAQ,EACjB,GAAI,CAAC,EAAU,EAAK,GAAO,EAAK,GAAM,CACpC,MAAO,GAGX,MAAO,IClBX,SAAgB,EACd,EACA,EACA,CACI,IAAa,IAAA,IACf,QAAQ,KAAK,kBAAkB,EAAmB,IAAI,IAAW,CCIrE,SAAgB,GAAwC,CACtD,IAAM,EAAyC,CAC7C,OAAQ,EAAE,CACX,CAEG,EAA8D,EAAE,CAChE,EAA2D,EAAE,CAC7D,EAAwD,EAAE,CACxD,EAAgD,EAAE,CAElD,EAEF,EAAE,CAEA,EAAW,IAAI,IAAI,SAAS,SAAS,KAAK,CAChD,IAAK,GAAM,CAAC,EAAK,KAAU,EAAS,aAAa,SAAS,CACxD,GAAI,CACF,EAAa,GAAO,KAAK,MAAM,EAAM,MACf,CAIpB,QAAQ,MACN,6BAA6B,EAAI,cAAc,EAAM,WACtD,CAKP,IAAM,EAAY,GAA6B,CAC7C,EAAK,EAAE,KAAK,KAAM,EAAE,KAAK,OAAQ,EAAE,KAAK,MAAM,EAGhD,OAAO,iBAAiB,UAAW,EAAU,GAAM,CACnD,OAAO,iBAAiB,YAAe,EAAY,kBAAkB,CAAC,CAEtE,EAAG,0BAA4B,GAA4B,CACzD,OAAO,OAAO,EAAc,EAAO,CACnC,EAAK,SAAU,EAAa,QAAU,EAAE,CAAC,EACzC,CAGG,EAAY,iBAAA,QAA8B,CAAC,KAAK,GAAU,CAC7D,OAAO,OAAO,EAAc,EAAO,CACnC,EAAK,OAAQ,EAAa,CAC1B,EAAK,SAAU,EAAa,OAAO,EACnC,CAEF,EACE,4BACC,GAAuD,CACtD,EAAyB,EAAE,CAC3B,OAAO,OAAO,EAAwB,EAAiB,EAE1D,CAED,EAAG,6BAA+B,GAAiC,CACjE,EAAyB,EAAE,CAC3B,OAAO,OAAO,EAAwB,EAAoB,EAC1D,CAEF,EACE,iCACC,GAAuD,CACtD,EAA0B,EAAE,CAC5B,OAAO,OAAO,EAAyB,EAAqB,EAE/D,CAED,EAAG,iCAAmC,GAAqB,CACzD,IAAM,EAAS,EAAkB,GACjC,GAAI,CAAC,EACH,MAAU,MAAM,oCAAoC,IAAW,CAEjE,GAAQ,EACR,CAEF,SAAS,EAAG,EAAe,EAAoB,CAC7C,EAAU,GAAS,EAAU,IAAU,EAAE,CACzC,EAAU,GAAO,KAAK,EAAS,CAGjC,SAAS,EAAI,EAAe,EAAoB,CAC1C,EAAU,IAAU,OACxB,EAAU,GAAS,EAAU,GAAO,OAAO,GAAK,IAAM,EAAS,EAGjE,SAAS,EAAK,EAAe,GAAG,EAAW,CACzC,OAAO,OAAO,EAAU,IAAU,EAAE,CAAC,CAAC,QAAQ,GAAM,EAAG,GAAG,EAAK,CAAC,CAGlE,SAAS,EAAe,EAAe,GAAG,EAAuB,CAC/D,OAAO,IAAI,SAAS,EAAS,IAAW,CACtC,IAAM,GAAY,EAAS,IAAe,CACpC,EAAO,EAAO,EAAM,CACnB,EAAQ,EAAK,CAClB,EAAI,EAAO,EAAS,EAEtB,EAAG,EAAO,EAAS,CACnB,OAAO,OAAO,YACZ,CAAE,KAAM,EAAO,OAAM,UAAW,EAAa,GAAI,CACjD,GAAc,UAAY,IAC3B,EACD,CAGJ,MAAO,CACL,IAAI,UAAW,CACb,OAAO,EAAa,UAGtB,IAAI,cAAe,CACjB,OAAO,EAAa,YAGtB,OAAQ,CAEN,OAAO,EAAK,CACV,OAAO,GAAc,SAAS,IAEhC,KAAM,CACJ,OAAO,EAAa,QAEtB,IAAI,EAAe,CACZ,EAAY,0BAA2B,EAAc,EAE5D,OAAO,EAAK,EAAO,CACZ,EAAY,0BAA2B,EACzC,GAAM,EACR,CAAC,EAEJ,UAAU,EAAU,CAElB,OADA,EAAG,SAAU,EAAS,KACT,EAAI,SAAU,EAAS,EAEtC,YAAY,EAAkB,CAE5B,OADA,EAAiB,EAAU,WAAW,CAC/B,EAAuB,IAEhC,YAAY,EAAkB,GAAG,EAAmB,CAClD,EAAiB,EAAU,WAAW,CACjC,EAAY,yBAA0B,EAAU,GAAG,EAAO,EAEjE,eAAe,EAAkB,CAE/B,OADA,EAAiB,EAAU,cAAc,CAClC,EAAuB,IAEhC,eACE,EACA,EACA,EAGA,CACA,EAAiB,EAAU,cAAc,CACpC,EACH,0BACA,EACA,EACA,EACD,EAEH,cAAc,EAAkB,CAC9B,EAAiB,EAAU,iBAAiB,CACvC,EAAY,kCAAmC,EAAS,EAE/D,eAAe,EAAkB,EAAoB,CAGnD,OAFA,EAAiB,EAAU,gBAAgB,CAC3C,EAAkB,GAAY,MACjB,CACX,OAAO,EAAkB,KAG7B,qBAAqB,EAAS,CACvB,EAAY,6BAA8B,EAAQ,EAEzD,gBAAgB,EAAc,CACvB,EAAY,iCAAkC,EAAa,EAElE,4BAA4B,EAAU,EAAU,CAC9C,EAAiB,EAAU,WAAW,CACtC,IAAM,EAAa,GAA6C,CAC9D,EAAS,EAAO,GAAU,EAG5B,OADA,EAAG,4BAA6B,EAAU,KAC7B,CACX,EAAI,4BAA6B,EAAU,GAG/C,+BAA+B,EAAU,EAAU,CACjD,EAAiB,EAAU,cAAc,CACzC,IAAM,EAAa,GAAgD,CACjE,EAAS,EAAO,GAAU,EAG5B,OADA,EAAG,6BAA8B,EAAU,KAC9B,CACX,EAAI,6BAA8B,EAAU,GAGhD,wBAAwB,EAAU,EAAU,CAC1C,EAAiB,EAAU,gBAAgB,CAC3C,IAAM,EAAa,GAAyC,CAC1D,EAAS,EAAO,GAAU,EAI5B,OAFA,EAAU,EAAwB,CAClC,EAAG,iCAAkC,EAAU,KAClC,CACX,EAAI,iCAAkC,EAAU,GAGpD,gBAAgB,EAAkB,CAEhC,OADA,EAAiB,EAAU,gBAAgB,CACpC,EAAwB,IAEjC,gBAAgB,EAAkB,EAAe,CAC/C,EAAiB,EAAU,gBAAgB,CACtC,EAAY,8BAA+B,EAAU,EAAM,EAEnE,CACD,SAAU,CACR,kBAAkB,EAAU,CAE1B,OADA,EAAiB,EAAU,UAAU,CAC9B,EAAY,gCAAiC,EAAS,EAE/D,0BAA0B,EAAU,EAAU,CAC5C,EAAiB,EAAU,UAAU,CACrC,IAAM,EAAY,qBAAqB,EAAS,UAIhD,OAHA,EAAG,EAAW,EAAS,CAClB,EAAY,sCAAuC,EAAS,KAEpD,CACX,EAAI,EAAW,EAAS,CACnB,EAAY,wCAAyC,EAAS,GAGvE,uBAAuB,EAAU,EAAU,CACzC,EAAiB,EAAU,UAAU,CACrC,IAAM,EAAY,qBAAqB,EAAS,OAIhD,OAHA,EAAG,EAAW,EAAS,CAClB,EAAY,mCAAoC,EAAS,KAEjD,CACX,EAAI,EAAW,EAAS,CACnB,EAAY,qCAAsC,EAAS,GAGpE,qBAAqB,EAAU,CAC7B,EAAiB,EAAU,UAAU,CAChC,EAAY,+BAAgC,EAAS,EAE7D,CAED,MAAO,CACL,UAAU,EAAwC,CAEhD,OADA,EAAG,yBAA0B,EAAS,KACzB,EAAI,yBAA0B,EAAS,EAGtD,KAAM,CACJ,OAAO,EAAY,sBAAsB,EAE5C,CAED,SAAU,CACR,OAAO,KAAK,EAAU,CAAC,QAAQ,GAAS,OAAO,EAAU,GAAO,CAChE,OAAO,oBAAoB,UAAW,EAAU,GAAM,EAEzD,CCpRH,IAAa,EAAS,GAAY,CCGrB,EAAgBA,EAAM,cAA8B,EAAO,CCexE,SAAgB,GAAiC,CAC/C,OAAOC,EAAM,WAAW,EAAc,CAOxC,SAAgB,EACd,EACM,CACN,IAAM,EAAS,GAAW,CACpB,EAAaA,EAAM,OAAO,EAAE,CAAC,CAEnC,EAAM,cAAgB,CAChB,GAAe,OACd,EAAU,EAAa,EAAW,QAAQ,GAC7C,EAAO,OAAO,qBAAqB,EAAY,CAC/C,EAAW,QAAU,KAEtB,CAAC,EAAQ,EAAY,CAAC,CAQ3B,SAAgB,EACd,EACyC,CACzC,IAAM,EAAS,GAAW,CACpB,CAAC,EAAS,GAAcA,EAAM,cAClC,EAAO,OAAO,gBAAgB,EAAa,CACpC,GACP,CAEF,MAAO,CACL,EACA,GAAa,CACP,IAAc,IAClB,EAAW,EAAU,CACrB,EAAO,OAAO,gBAAgB,EAAU,GAE3C,CASH,SAAgB,EAAkB,EAA0C,CAC1E,IAAM,EAAS,GAAW,CACpB,CAAC,EAAS,GAAcA,EAAM,SAAiC,EAAE,CAAC,CAQxE,OANA,EAAM,cAAgB,CACpB,GAAI,EACF,OAAO,EAAO,SAAS,0BAA0B,EAAU,EAAW,EAEvE,CAAC,EAAQ,EAAS,CAAC,CAEf,EAQT,SAAgB,EAAe,EAAuC,CACpE,IAAM,EAAS,GAAW,CACpB,CAAC,EAAM,GAAWA,EAAM,SAA8B,EAAE,CAAC,CAQ/D,OANA,EAAM,cAAgB,CACpB,GAAI,EACF,OAAO,EAAO,SAAS,uBAAuB,EAAU,EAAQ,EAEjE,CAAC,EAAQ,EAAS,CAAC,CAEf,EAUT,SAAgB,EACd,EACmC,CACnC,IAAM,EAAS,GAAW,CACpB,CAAC,EAAM,GAAWA,EAAM,SAA8B,EAAE,CAAC,CAEzD,EAAWA,EAAM,gBAAkB,CACnC,GACF,EAAO,SAAS,qBAAqB,EAAS,EAE/C,CAAC,EAAU,EAAO,SAAS,CAAC,CAQ/B,OANA,EAAM,cAAgB,CACpB,GAAI,EACF,OAAO,EAAO,SAAS,uBAAuB,EAAU,EAAQ,EAEjE,CAAC,EAAQ,EAAS,CAAC,CAEf,CAAC,EAAM,EAAS,CAQzB,SAAgB,EAAU,EAAmB,CAC3C,IAAM,EAAS,GAAW,CACpB,CAAC,EAAQ,GAAaA,EAAM,SAChC,GAAO,KAAmC,EAAO,OAAO,KAAK,CAA/C,EAAO,OAAO,OAAO,EAAI,CACxC,CAcD,OAZA,EAAM,cAEF,EAAO,OAAO,UAAU,GAAa,CAC/B,GAAO,MAAQ,EAAU,KAAS,EAAO,GAC3C,EAAU,EAAU,GAAK,CAEzB,EAAU,EAAU,EAEtB,CACJ,CAAC,EAAQ,EAAK,EAAO,CACtB,CAEM,EAST,SAAgB,EACd,EAC0C,CAC1C,IAAM,EAAS,GAAW,CACpB,CAAC,EAAkB,GACvBA,EAAM,UAA4B,CAE9B,EAAgBA,EAAM,OAAgB,GAAK,CAejD,OAbA,EAAM,eACJ,AAEE,EAAc,WADd,EAAoB,EAAO,OAAO,YAAY,EAAG,CAAC,CAC1B,IAEnB,EAAO,OAAO,4BAA4B,EAAI,EAAoB,EACxE,CAAC,EAAQ,EAAG,CAAC,CAOT,CAAC,EALYA,EAAM,aACvB,GAAG,IAAsB,EAAO,OAAO,YAAY,EAAI,GAAG,EAAO,CAClE,CAAC,EAAI,EAAO,OAAO,CAGgB,CAAC,CAQxC,SAAgB,EACd,EACqD,CACrD,IAAM,EAAS,GAAW,CACpB,CAAC,EAAc,GAAmBA,EAAM,UAAwB,CAEhE,EAAgBA,EAAM,OAAgB,GAAK,CAejD,OAbA,EAAM,eACJ,AAEE,EAAc,WADd,EAAgB,EAAO,OAAO,gBAAgB,EAAG,CAAC,CAC1B,IAEnB,EAAO,OAAO,wBAAwB,EAAI,EAAgB,EAChE,CAAC,EAAQ,EAAG,CAAC,CAOT,CAAC,EALOA,EAAM,YAClB,GAAkB,EAAO,OAAO,gBAAgB,EAAI,EAAM,CAC3D,CAAC,EAAQ,EAAG,CAGc,CAAC,CAS/B,SAAgB,EACd,EACA,EACqB,CACrB,IAAM,EAAS,GAAW,CACpB,CAAC,EAAqB,GAC1BA,EAAM,UAA+B,CAgBvC,OAdA,EAAM,cACG,EAAO,OAAO,+BACnB,EACA,EACD,CACA,CAAC,EAAQ,EAAG,CAAC,CAST,CAAC,EAPeA,EAAM,YAC1B,GAA+B,CAC9B,EAAO,OAAO,eAAe,EAAI,EAAW,EAAM,EAEpD,CAAC,EAAI,EAAW,EAAO,OAAO,CAGW,CAAC,CAS9C,SAAgB,EAAiB,EAA8B,CAC7D,IAAM,EAAS,GAAW,CAE1B,OAAOA,EAAM,gBAAkB,CAC7B,EAAO,OAAO,cAAc,EAAS,EACpC,CAAC,EAAQ,EAAS,CAAC,CAQxB,SAAgB,EAAgB,EAAkB,EAAoB,CACpE,IAAM,EAAS,GAAW,CAEpB,EAAYA,EAAM,OAAO,EAAO,CAEtC,EAAM,cAAgB,CACpB,EAAU,QAAU,GACpB,CAEF,EAAM,cACG,EAAO,OAAO,eAAe,EAAU,EAAU,QAAQ,CAC/D,CAAC,EAAQ,EAAU,EAAO,CAAC,CAOhC,SAAgB,GAA0C,CACxD,IAAM,EAAS,GAAW,CACpB,CAAC,EAAO,GAAYA,EAAM,UAAmC,CAQnE,OANA,EAAM,eAEC,EAAO,MAAM,KAAK,CAAC,KAAK,GAAY,EAAS,EAAS,CAAC,CACrD,EAAO,MAAM,UAAU,EAAS,EACtC,CAAC,EAAO,CAAC,CAEL,EC7RT,SAAgB,EACd,EACA,CACA,OACE,EAAA,cAAC,EAAc,SAAf,CAAwB,MAAO,EAAM,OAEZ,CADtB,EAAM,SACgB,CCX7B,SAAgB,EAA8B,EAAgB,CACxD,0BAA2B,IAC7B,EAAO,sBAAwB,GAAY,EAAO,WAAW,EAAU,mBAAI,CAE3E,EAAO,qBAAuB,GAAM,EAAO,aAAa,EAAG"}
|