# JavaScript SDK

Learn more about our JavaScript SDK, which allows you to build UI Extensions using native JavaScript, or the framework and bundler of your choice.

The JavaScript SDK allows you to build UI Extensions using native JavaScript, or the framework and bundler of your choice.

**Note:**

If your are using React, we advise you to use our [React SDK](./react-sdk) instead.

## Setup the SDK

You need to include the UI Extensions SDK in your project by either adding the script tag to the `head` of your HTML file, or importing it from NPM.

**Directly in your HTML, via CDN:**

```html
<script src="https://www.unpkg.com/@graphcms/zoid/lib/zoid.min.js"></script>
<script src="https://www.unpkg.com/@graphcms/uix-sdk@0.2.7/dist/gcuix.umd.production.min.js"></script>
```

**Note:**

Notice that you also need to include our patched version of&nbsp;<a href="https://github.com/krakenjs/zoid" target="_blank" rel="nofollow">
Zoid</a>&nbsp;before the SDK.

**Or if you use a bundler, as an npm package:**

```bash
npm install @graphcms/uix-sdk
```

Next, create an [extension declaration](https://hygraph.com/classic-docs/ui-extensions/getting-started/extension-declaration).
Let's assume you are building a custom input for a String field:

```js
const declaration = {
  extensionType: 'field',
  fieldType: 'STRING',
  name: 'My first custom input',
  description: '',
  features: ['FieldRenderer'],
};
```

Finally, initialize the SDK:

  **NPM**

```js
import { init } from '@graphcms/uix-sdk';

// const declaration = ...

init({
  declaration,
}).then((initialState) => {
  const { status, props } = initialState;
  if (status === 'ok') {
    const { value } = props;

    console.log(`Custom field initialized with value ${value}`);
  }
});
```

  
  **HTML**

```js
document.addEventListener('DOMContentLoaded', () => {
  window.GCUIX.init({
    declaration,
  }).then((initialState) => {
    const { status, props } = initialState;
    if (status === 'ok') {
      const { value } = props;

      console.log(`Custom field initialized with value ${value}`);
    }
  });
});
```


## Interact with Hygraph

Now that you have initialized the SDK, you can read data from Hygraph, subscribe to value changes, and change values from within the extension.

Let's continue with the custom string input scenario, and use this simplistic HTML markup for diplayed text field:

```html
<input type="text" id="myCustomInput" />
```

We now want to synchronise this input with Hygraph. It should display the previously saved value on first load, and all user input should be sent back to Hygraph.

By providing an `onProps` callback at initialization, you can subscribe to all props changes (values, methods, etc..) that happen after initialization.

```js
// we need a reference to the input element
const myInput = document.getElementById('myCustomInput');

init({
  declaration,
  onProps: (newProps) => {
    // each time Hygraph send new props, we update the displayed value to the new one
    const { value } = newProps;
    myInput.value = value;
  },
}).then((initialState) => {
  const { status, props } = initialState;
  if (status === 'ok') {
    // this will only be called once
    const { value, onChange } = props;

    // we initialize the input with the previously saved value, or a default one if there is none
    myInput.value = value || '';

    // each time we change the input value, we notify Hygraph of the change
    myInput.addEventListener('change', (e) => onChange(e.target.value));
  }
});
```

## Using TypeScript

The JavaScript SDK is written in TypeScript, and can be used with TypeScript projects.

```ts
import {
  init,
  FieldExtensionDeclaration,
  FieldExtensionType,
  FieldExtensionFeature,
} from '@graphcms/uix-sdk';

// validate the shape of your declaration object by
const declaration: FieldExtensionDeclaration = {
  extensionType: 'field',
  fieldType: FieldExtensionType.STRING,
  name: 'My first custom input',
  description: '',
  features: [FieldExtensionFeature.FieldRenderer],
};

// Create a new type from your declaration object.
type MyExactDeclarationType = typeof declaration;

// And give it to the init function, allowing it do dynamically type the props transmitted by Hygraph to reflect your extension configuration.
init<MyExactDeclarationType>({
  declaration,
  onProps: (newProps) => {
    // newProps is now typed
    const { value } = newProps;
    myInput.value = value;
  },
}).then((initialState) => {
  const { status, props } = initialState; // initialState is now typed
  if (status === 'ok') {
    // props is now typed
    const { value, onChange } = props;
  }
});
```
