Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
48 changes: 48 additions & 0 deletions packages/plugin-sdk-react/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<p align="center">
<a href="https://github.com/sigmacomputing/plugin">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/sigmacomputing/plugin/blob/main/assets/sigma-logo-dark.svg">
<img alt="Sigma Logo" src="https://github.com/sigmacomputing/plugin/blob/main/assets/sigma-logo-light.svg" width="400px">
</picture>
</a>
</p>

React bindings for the [`@sigmacomputing/plugin`](https://www.npmjs.com/package/@sigmacomputing/plugin) Client SDK.

This package provides the `SigmaClientProvider` context provider and a set of
React hooks (`usePlugin`, `useConfig`, `useElementColumns`, `useElementData`,
etc.) that wrap the framework-agnostic client exported from
`@sigmacomputing/plugin`.

## Installation

```sh
yarn add @sigmacomputing/plugin @sigmacomputing/plugin-sdk-react
# or
npm install @sigmacomputing/plugin @sigmacomputing/plugin-sdk-react
```

`react` (`>= 16.8`) is required as a peer dependency.

## Usage

```tsx
import { client } from '@sigmacomputing/plugin';
import { SigmaClientProvider, useConfig } from '@sigmacomputing/plugin-sdk-react';

function MyPlugin() {
const config = useConfig();
return <pre>{JSON.stringify(config, null, 2)}</pre>;
}

export function App() {
return (
<SigmaClientProvider client={client}>
<MyPlugin />
</SigmaClientProvider>
);
}
```

See the [`@sigmacomputing/plugin` README](https://github.com/sigmacomputing/plugin/blob/main/packages/plugin-sdk/README.md)
for the full hook reference.
54 changes: 54 additions & 0 deletions packages/plugin-sdk-react/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"name": "@sigmacomputing/plugin-sdk-react",
"version": "1.2.0",
"description": "React bindings for the Sigma Computing Plugin Client SDK",
"license": "MIT",
"type": "module",
"scripts": {
"build": "tsdown",
"build:watch": "tsdown --watch",
"format": "yarn g:format",
"lint": "yarn g:lint",
"publish": "yarn g:publlish",
"test": "vitest run",
"test:watch": "vitest",
"types": "yarn g:types"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
"dependencies": {
"@sigmacomputing/plugin": "^1.2.0",
"dequal": "^2.0.3"
},
"devDependencies": {
"tsdown": "^0.21.10",
"vitest": "^4.1.5"
},
"main": "./dist/cjs/index.cjs",
"module": "./dist/esm/index.js",
"types": "./dist/cjs/index.d.cts",
"unpkg": "./dist/umd/sigmacomputing-plugin-sdk-react.umd.js",
"jsdelivr": "./dist/umd/sigmacomputing-plugin-sdk-react.umd.js",
"exports": {
".": {
"import": {
"types": "./dist/esm/index.d.ts",
"default": "./dist/esm/index.js"
},
"require": {
"types": "./dist/cjs/index.d.cts",
"default": "./dist/cjs/index.cjs"
}
},
"./package.json": "./package.json"
},
"files": [
"dist/**/*",
"src/**/*",
"!src/**/__tests__/**/*"
],
"publishConfig": {
"access": "public"
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as React from 'react';

import { client } from '../client';
import { PluginInstance } from '../types';
import { client, PluginInstance } from '@sigmacomputing/plugin';

export const PluginContext = React.createContext<PluginInstance>(client);
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';

import { PluginInstance } from '../types';
import { PluginInstance } from '@sigmacomputing/plugin';

import { PluginContext } from './Context';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { act, renderHook } from '@testing-library/react';
import * as React from 'react';

import { initialize } from '../../client/initialize';
import { PluginInstance } from '../../types';
import { SigmaClientProvider } from '../Provider';
import { initialize, PluginInstance } from '@sigmacomputing/plugin';

import {
useActionEffect,
useActionTrigger,
Expand All @@ -19,6 +18,7 @@ import {
useUrlParameter,
useVariable,
} from '../hooks';
import { SigmaClientProvider } from '../Provider';

type Subscriber<T> = (value: T) => void;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { dequal } from 'dequal/lite';
import * as React from 'react';

import {
Expand All @@ -9,8 +10,7 @@
WorkbookVariable,
PluginStyle,
UrlParameter,
} from '../types';
import { deepEqual } from '../utils/deepEqual';
} from '@sigmacomputing/plugin';

import { PluginContext } from './Context';

Expand All @@ -34,7 +34,7 @@

React.useEffect(() => {
if (nextOptions == null) return;
if (!deepEqual(nextOptions, optionsRef.current)) {
if (!dequal(nextOptions, optionsRef.current)) {
client.config.configureEditorPanel(nextOptions);
optionsRef.current = nextOptions;
}
Expand Down Expand Up @@ -164,7 +164,7 @@
*/
export function useVariable(
id: string,
): [WorkbookVariable | undefined, Function] {

Check failure on line 167 in packages/plugin-sdk-react/src/hooks.ts

View workflow job for this annotation

GitHub Actions / Lint

typescript-eslint(no-redundant-type-constituents)

'WorkbookVariable' is an 'error' type that acts as 'any' and overrides all other types in this union type.
const client = usePlugin();
const [workbookVariable, setWorkbookVariable] =
React.useState<WorkbookVariable>();
Expand Down Expand Up @@ -194,7 +194,7 @@
*/
export function useUrlParameter(
id: string,
): [UrlParameter | undefined, (value: string) => void] {

Check failure on line 197 in packages/plugin-sdk-react/src/hooks.ts

View workflow job for this annotation

GitHub Actions / Lint

typescript-eslint(no-redundant-type-constituents)

'UrlParameter' is an 'error' type that acts as 'any' and overrides all other types in this union type.
const client = usePlugin();
const [urlParameter, setUrlParameter] = React.useState<UrlParameter>();

Expand Down Expand Up @@ -284,9 +284,9 @@
* React hook for accessing plugin style with live updates
* @returns {PluginStyle | undefined} Style properties from the workbook if available
*/
export function usePluginStyle(): PluginStyle | undefined {

Check failure on line 287 in packages/plugin-sdk-react/src/hooks.ts

View workflow job for this annotation

GitHub Actions / Lint

typescript-eslint(no-redundant-type-constituents)

'PluginStyle' is an 'error' type that acts as 'any' and overrides all other types in this union type.
const client = usePlugin();
const [style, setStyle] = React.useState<PluginStyle | undefined>();

Check failure on line 289 in packages/plugin-sdk-react/src/hooks.ts

View workflow job for this annotation

GitHub Actions / Lint

typescript-eslint(no-redundant-type-constituents)

'PluginStyle' is an 'error' type that acts as 'any' and overrides all other types in this union type.

React.useEffect(() => {
// Request initial style data on mount and subscribe to updates
Expand Down
3 changes: 3 additions & 0 deletions packages/plugin-sdk-react/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './hooks';
export type { SigmaClientProviderProps } from './Provider';
export { SigmaClientProvider } from './Provider';
7 changes: 7 additions & 0 deletions packages/plugin-sdk-react/tsconfig.app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.app.json",
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo"
},
"include": ["src"]
}
12 changes: 12 additions & 0 deletions packages/plugin-sdk-react/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.tsbuildinfo",

"noEmit": true
},
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}
7 changes: 7 additions & 0 deletions packages/plugin-sdk-react/tsconfig.node.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.node.json",
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo"
},
"include": ["tsdown.config.ts", "vitest.config.ts"]
}
37 changes: 37 additions & 0 deletions packages/plugin-sdk-react/tsdown.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { defineConfig } from 'tsdown';

// @ts-ignore - base config is defined outside of this package
import baseConfig from '../../tsdown.base.ts';

// Split into two configs so dequal stays external for ESM/CJS (consumers
// install it via npm) but is bundled into the UMD build, where shipping
// a self-contained file matters more than dedup.

const baseFormat = baseConfig.format as Record<string, any>;

export default [
defineConfig({
...baseConfig,
format: {
esm: baseFormat.esm,
cjs: baseFormat.cjs,
},
}),
defineConfig({
...baseConfig,
deps: { alwaysBundle: [/^dequal(\/|$)/] },
format: {
umd: {
outputOptions: {
...baseFormat.umd.outputOptions,
entryFileNames: 'sigmacomputing-plugin-sdk-react.umd.js',
globals: {
...baseFormat.umd.outputOptions.globals,
'@sigmacomputing/plugin': 'SigmaPlugin',
},
name: 'SigmaPluginReact',
},
},
},
}),
];
2 changes: 2 additions & 0 deletions packages/plugin-sdk-react/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// @ts-ignore - base config is defined outside of this package
export { default } from '../../vitest.base.ts';
8 changes: 0 additions & 8 deletions packages/plugin-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,6 @@
"test:watch": "vitest",
"types": "yarn g:types"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"react": {
"optional": true
}
},
"devDependencies": {
"tsdown": "^0.21.10",
"vitest": "^4.1.5"
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-sdk/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export * from './types';
export * from './react';
export * from './client';
export { initialize } from './client/initialize';

export { polyfillRequestAnimationFrame } from './utils/polyfillRequestAnimationFrame';
3 changes: 0 additions & 3 deletions packages/plugin-sdk/src/react.ts

This file was deleted.

15 changes: 1 addition & 14 deletions packages/plugin-sdk/tsdown.config.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,2 @@
import { defineConfig, mergeConfig } from 'tsdown';

// @ts-ignore - base config is defined outside of this package
import baseConfig from '../../tsdown.base.ts';

import packageJson from './package.json' with { type: 'json' };

export default mergeConfig(
baseConfig,
defineConfig({
define: {
__VERSION__: JSON.stringify(packageJson.version),
},
}),
);
export { default } from '../../tsdown.base.ts';
15 changes: 1 addition & 14 deletions packages/plugin-sdk/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,2 @@
import { defineConfig, mergeConfig } from 'vitest/config';

// @ts-ignore - base config is defined outside of this package
import baseConfig from '../../vitest.base.ts';

import packageJson from './package.json' with { type: 'json' };

export default mergeConfig(
baseConfig,
defineConfig({
define: {
__VERSION__: JSON.stringify(packageJson.version),
},
}),
);
export { default } from '../../vitest.base.ts';
36 changes: 31 additions & 5 deletions scripts/bump-version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,34 @@ const writeNewVersion = (pkgPath: string, version: string): void => {
writeFileSync(pkgPath, raw.replace(pattern, `$1${version}$2`));
};

const escapeRegex = (value: string): string =>
value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');

const bumpInternalDeps = (
pkgPath: string,
internalPackageNames: readonly string[],
version: string,
): void => {
let raw = readFileSync(pkgPath, 'utf8');
for (const depName of internalPackageNames) {
const pattern = new RegExp(
`("${escapeRegex(depName)}"\\s*:\\s*")(?!workspace:)[^"]+(")`,
'g',
);
raw = raw.replace(pattern, `$1^${version}$2`);
}
writeFileSync(pkgPath, raw);
};

type TurboQueryLsResponse = {
packages: {
items: { name: string; path: string }[];
};
};

const findWorkspacePackageJsons = (): string[] => {
type WorkspacePackage = { name: string; pkgPath: string };

const findWorkspacePackages = (): WorkspacePackage[] => {
const result = spawnSync(
'yarn',
['turbo', 'query', 'ls', '--output', 'json'],
Expand All @@ -137,19 +158,24 @@ const findWorkspacePackageJsons = (): string[] => {
result.stdout.slice(jsonStart),
) as TurboQueryLsResponse;

return parsed.packages.items.map(item =>
path.join(item.path, 'package.json'),
);
return parsed.packages.items.map(item => ({
name: item.name,
pkgPath: path.join(item.path, 'package.json'),
}));
};

const main = async (): Promise<void> => {
const current = readCurrentVersion();
const choices = buildChoices(current);
const choice = await promptChoice(current.version, choices);

const targets = [PACKAGE_JSON_PATH, ...findWorkspacePackageJsons()];
const workspaces = findWorkspacePackages();
const internalPackageNames = workspaces.map(w => w.name);
const targets = [PACKAGE_JSON_PATH, ...workspaces.map(w => w.pkgPath)];

for (const pkgPath of targets) {
writeNewVersion(pkgPath, choice.next);
bumpInternalDeps(pkgPath, internalPackageNames, choice.next);
console.log(`Bumped ${pkgPath}: ${current.version} -> ${choice.next}`);
}
};
Expand Down
3 changes: 3 additions & 0 deletions vitest.base.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { playwright } from '@vitest/browser-playwright';
import { defineConfig } from 'vitest/config';

import packageJson from './package.json' with { type: 'json' };

export default defineConfig({
define: {
__VERSION__: JSON.stringify(packageJson.version),
__VITEST_BROWSER__: true.toString(),
},
oxc: {
Expand Down
Loading
Loading