Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v18.16.1
v20.17.0
100 changes: 96 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,14 @@ type CustomPluginConfigOptions =
label?: string;
}
| {
type: 'action-effect';
name: string;
label?: string;
};
type: 'action-effect';
name: string;
label?: string;
}
| {
type: 'url-parameter';
name: string;
};
```

</details>
Expand Down Expand Up @@ -404,6 +408,14 @@ A configurable action trigger to trigger actions in other elements within your w

A configurable action effect that can be triggered by other elements within your workbook

**URL Parameter**

A configurable URL parameter that can be read from and written to the browser's URL. This allows plugins to sync state with the URL for bookmarking and sharing.

Additional Fields

- `name : string` - The config ID used to access this URL parameter via the API

#### PluginInstance

```ts
Expand Down Expand Up @@ -488,6 +500,24 @@ interface PluginInstance<T> {
callback: (input: WorkbookVariable) => void,
): Unsubscriber;

/**
* Allows users to subscribe to changes in the url parameter
*/
subscribeToUrlParameter(
configId: string,
callback: (input: UrlParameter) => void,
): Unsubscriber;

/**
* Gets the current value of a url parameter
*/
getUrlParameter(configId: string): UrlParameter;

/**
* Setter for url parameter
*/
setUrlParameter(configId: string, value: string): void;

/**
* @deprecated Use Action API instead
* Allows users to subscribe to changes in the passed in interaction ID
Expand Down Expand Up @@ -727,6 +757,68 @@ array or multiple parameters
function setVariableCallback(...values: unknown[]): void;
```

#### useUrlParameter()

Returns a given URL parameter's value and a setter to update that URL parameter

```ts
function useUrlParameter(
configId: string,
): [UrlParameter | undefined, (value: string) => void];
```

Arguments

- `configId : string` - The config ID corresponding to the URL parameter

The returned setter function accepts a string value that will be set as the URL parameter value

```ts
function setUrlParameterCallback(value: string): void;
```

The URL parameter value has the following structure:

```ts
interface UrlParameter {
value: string;
}
```

Example

```ts
const [urlParam, setUrlParam] = useUrlParameter('myParamId');

// Read the current value
console.log(urlParam?.value); // e.g., "current-value"

// Update the URL parameter
setUrlParam('new-value');
```

Framework Agnostic Usage

You can also use the URL parameter API without React hooks:

```ts
import { initialize } from '@sigmacomputing/plugin';

const client = initialize();

// Get current value
const urlParam = client.config.getUrlParameter('myParamId');
console.log(urlParam?.value);

// Set a new value
client.config.setUrlParameter('myParamId', 'new-value');

// Subscribe to changes
const unsubscribe = client.config.subscribeToUrlParameter('myParamId', (urlParam) => {
console.log('URL parameter updated:', urlParam.value);
});
```

#### useInteraction()

Returns a given interaction's selection state and a setter to update that interaction
Expand Down
29 changes: 29 additions & 0 deletions src/client/initialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
PluginInstance,
PluginMessageResponse,
PluginStyle,
UrlParameter,
WorkbookSelection,
WorkbookVariable,
} from '../types';
Expand All @@ -15,6 +16,7 @@ export function initialize<T = {}>(): PluginInstance<T> {

let subscribedInteractions: Record<string, WorkbookSelection[]> = {};
let subscribedWorkbookVars: Record<string, WorkbookVariable> = {};
let subscribedUrlParameters: Record<string, UrlParameter> = {};
const registeredEffects: Record<string, () => void> = {};

const listeners: {
Expand Down Expand Up @@ -61,6 +63,14 @@ export function initialize<T = {}>(): PluginInstance<T> {
Object.assign(subscribedInteractions, updatedInteractions);
});

on(
'wb:plugin:url-parameter:update',
(updatedUrlParameters: Record<string, UrlParameter>) => {
subscribedUrlParameters = {};
Object.assign(subscribedUrlParameters, updatedUrlParameters);
},
);

on('wb:plugin:action-effect:invoke', (configId: string) => {
const effect = registeredEffects[configId];
if (!effect) {
Expand Down Expand Up @@ -191,6 +201,25 @@ export function initialize<T = {}>(): PluginInstance<T> {
off('wb:plugin:selection:update', setValues);
};
},
subscribeToUrlParameter(configId, callback) {
validateConfigId(configId, 'url-parameter');
const setValues = (values: Record<string, UrlParameter>) => {
callback(values[configId]);
};
setValues(subscribedUrlParameters);
on('wb:plugin:url-parameter:update', setValues);
return () => {
off('wb:plugin:url-parameter:update', setValues);
};
},
getUrlParameter(configId: string) {
validateConfigId(configId, 'url-parameter');
return subscribedUrlParameters[configId];
},
setUrlParameter(configId: string, value: string) {
validateConfigId(configId, 'url-parameter');
void execPromise('wb:plugin:url-parameter:set', configId, value);
}
},
elements: {
getElementColumns(configId) {
Expand Down
30 changes: 30 additions & 0 deletions src/react/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
WorkbookSelection,
WorkbookVariable,
PluginStyle,
UrlParameter,
} from '../types';
import { deepEqual } from '../utils/deepEqual';

Expand Down Expand Up @@ -184,6 +185,35 @@ export function useVariable(
return [workbookVariable, setVariable];
}

/**
* React hook for accessing a url parameter
* @param {string} id ID from the config of type: 'url-parameter'
* @returns {[(UrlParameter | undefined), Function]} Constantly updating value of the url parameter and setter for the url parameter
*/
export function useUrlParameter(
id: string
): [UrlParameter | undefined, (value: string) => void] {
const client = usePlugin();
const [urlParameter, setUrlParameter] = useState<UrlParameter>();

const isFirstRender = useRef<boolean>(true);

useEffect(() => {
if (isFirstRender.current) {
setUrlParameter(client.config.getUrlParameter(id));
isFirstRender.current = false;
}
return client.config.subscribeToUrlParameter(id, setUrlParameter);
}, [client, id]);

const setVariable = useCallback(
Comment thread
ryan-sigma marked this conversation as resolved.
Outdated
(value: string) => client.config.setUrlParameter(id, value),
[client, id],
);

return [urlParameter, setVariable];
}

/**
* @deprecated Use Action API instead
* React hook for accessing a workbook interaction selections state
Expand Down
37 changes: 37 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ export interface WorkbookVariable {
defaultValue: { type: string };
}

/**
* @typedef {object} UrlParameter
* @property {string} value Current url value
*/
export interface UrlParameter {
value: string;
}

export type WorkbookSelection = Record<string, { type: string; val?: unknown }>;

export type PluginMessageResponse = MessageEvent<{
Expand Down Expand Up @@ -185,6 +193,10 @@ export type CustomPluginConfigOptions =
type: 'action-effect';
name: string;
label?: string;
}
| {
type: 'url-parameter',
name: string
};

/**
Expand Down Expand Up @@ -307,6 +319,31 @@ export interface PluginInstance<T = any> {
callback: (input: WorkbookVariable) => void,
): Unsubscriber;

/**
* Allows users to subscribe to changes in the url parameter
* @param {string} configId ID from config of type: 'url-parameter'
* @callback callback Function to be called upon receiving an updated url parameter
* @returns {Unsubscriber} A callable unsubscriber
*/
subscribeToUrlParameter(
configId: string,
callback: (input: UrlParameter) => void,
): Unsubscriber;

/**
* Gets the current value of a url parameter
* @param {string} configId ID from config of type: 'url-parameter'
* @returns {UrlParameter} Current value of the url parameter
*/
getUrlParameter(configId: string): UrlParameter;

/**
* Setter for url parameter
* @param {string} configId ID from config of type: 'url-parameter'
* @param {string} value Value to assign to the url parameter
*/
setUrlParameter(configId: string, value: string): void;

/**
* @deprecated Use Action API instead
* Allows users to subscribe to changes in the passed in interaction ID
Expand Down