npm package: @siteone/seo-toolbar
Description: Component for editing SEO tags
Author: Ondřej Tůma
Latest version: 0.4.1

# SEO toolbar

Widget for managing meta tags. Build on top of `react-jsonschema-form`

[Default Widgets and Fields](https://react-jsonschema-form.readthedocs.io/en/latest/advanced-customization/custom-widgets-fields/#customizing-the-default-fields-and-widgets)

## Usage

Simply install latest stable version of `@siteone/seo-toolbar`

```shell
yarn add @siteone/seo-toolbar
```

There are two components exported as Seo Toolbar with slightly different API:

### 1) SeoToolbarExtended

Convenient export for minimal setup. Generates rjsf schema from `data` object for you and selects corresponding field widgets, labels and descriptions.
But lacks sophisticated customization.

```jsx
import { SeoToolbarExtended } from '@siteone/seo-toolbar'

const data = {
  title: 'Some test page title',
  sitemapChangefreq: 'DAILY',
  description: 'SEO friendly page description',
  robotsFollow: true,
}
const onSubmit = data => alert(JSON.stringify(data, null, 2))

export default function Toolbar() {
  return (
    <SeoToolbarExtended
      data={data}
      onSubmit={onSubmit}
    />
  )
}
```

### 2) SeoToolbar

Allows complex setup but requires deeper understanding of [rjsf](#https://react-jsonschema-form.readthedocs.io/en/latest/)

For easier use, `@siteone/seo-toolbar` also exports `transformObjectToSchema` and `generateUiSchema` 
for generating basic settins. These functions generates JSON schema with predefined form labels, descriptions and uiSchema with widgets for your data.

Note that it form labels, descriptions, select options and widgets are only applied to standardized [SeoToolbarData](#SeoToolbarData)

Other data will also work but may not look exactly how you desire.

For that case, you may consider using more [customized Seo Toolbar](#CustomizedSeoToolbar)

```jsx
import SeoToolbar, { transformObjectToSchema, generateUiSchema } from '@siteone/seo-toolbar'

const data = {
  title: 'Some test page title',
  sitemapChangefreq: 'DAILY',
  description: 'SEO friendly page description',
  robotsFollow: true,
}
const onSubmit = data => alert(JSON.stringify(data, null, 2))

const schema = transformObjectToSchema(data)
const uiSchema = generateUiSchema(schema)

export default function Toolbar() {
  return (
    <SeoToolbar
      schema={schema}
      onSubmit={onSubmit}
      uiSchema={uiSchema}
    />
  )
}
```

<a name="CustomizedSeoToolbar"></a>

If you want to have more control, here's how to achieve the same result as above without utility functions

```jsx
import SeoToolbar from '@siteone/seo-toolbar'

const data = {
  title: 'Some test page title',
  sitemapChangefreq: 'DAILY',
  description: 'SEO friendly page description',
  robotsFollow: true,
}
const onSubmit = data => alert(JSON.stringify(data, null, 2))

const schema = {
  type: 'object',
  properties: {
    title: {
      type: 'string',
      default: 'Some test page title',
      title: 'Title',
    },
    sitemapChangefreq: {
      type: 'string',
      default: 'DAILY',
      enum: [ 'ALWAYS', 'HOURLY', 'DAILY', 'WEEKLY', 'MONTHLY', 'YEARLY', 'NEVER' ],
      title: 'Sitemap (changefreq)',
      description: 'Jak často má Google reindexovat tuto stránku? (je to jen hint, ne příkaz)',
    },
    description: {
      type: 'string',
      default: 'SEO friendly page description',
      title: 'Description',
    },
    robotsFollow: {
      type: 'boolean',
      default: true,
      title: 'Robots (follow): mají vyhledávače nasledovat odkazy na této stránce?',
    },
  }
}
const uiSchema = {
  description: {
    'ui:widget': 'textarea',
  },
}

export default function Toolbar() {
  return (
    <SeoToolbar
      schema={schema}
      onSubmit={onSubmit}
      uiSchema={uiSchema}
    />
  )
}
```

### Customizing Send button

By default, submit button with basic caption and styling is applied. 
But what if you need a little customization?

```jsx
import { SeoToolbarExtended } from '@siteone/seo-toolbar'

const data = {
  title: 'Some test page title',
  sitemapChangefreq: 'DAILY',
  description: 'SEO friendly page description',
  robotsFollow: true,
}
const onSubmit = data => alert(JSON.stringify(data, null, 2))

export default function Toolbar() {
  return (
    <SeoToolbarExtended
      data={data}
      onSubmit={onSubmit}
    >
        <button type={'reset'}>Reset</button>
        <button type={'submit'}>Send</button>
    </SeoToolbarExtended>
  )
}
```

It's only important to use `type="submit"` so that `onSubmit` function is mapped properly

**Remember to import this package on non user-facing pages 
so that is does not get into your main bundle, or load it asynchronously. 
This package contains `@rjsf/core` package which is quite hefty** 

## Documentation

You can use all props from `@rjsf/core` on both `SeoToolbarExtended` and `SeoToolbar`.

### `import { SeoToolbarExtended } from '@siteone/seo-toolbar'`

| Prop | Type | Default | Required | Description |
| :--- | :--- | :---: | :--- | :--- |
| data | [SeoToolbarData](#SeoToolbarData) | | ✓ | Initial data from which the rjsf schema will be constructed. |
| onSubmit | (data: [SeoToolbarData](#SeoToolbarData)) => void | | ✓ | Function called after form is submitted |
| titles | Object<String, String> | | | If you want to override default form labels for data. Object keys must match `data` keys |
| required | Array<String> | | | Required fields. Strings must match `data` keys |
| title | String | | | Title of the form group. By default represented by a `legend` element inside a `fieldset` |

### `import SeoToolbar from '@siteone/seo-toolbar'`

| Prop | Type | Default | Required | Description |
| :--- | :--- | :---: | :--- | :--- |
| schema | Object | | ✓ | JSON schema |
| onSubmit | (data: [SeoToolbarData](#SeoToolbarData)) => void | | ✓ | Function called after form is submitted |

<a name="SeoToolbarData"></a>

#### Input Data

```typescript
type SeoToolbarData = {
  uri?: String,
  title?: String,
  keywords?: String,
  description?: String,
  robotsIndex?: Boolean,
  robotsFollow?: Boolean,
  robotsArchive?: Boolean,
  robotsSnippet?: Boolean,
  sitemapChangefreq?: 'ALWAYS' | 'HOURLY' | 'DAILY' | 'WEEKLY' | 'MONTHLY' | 'YEARLY' | 'NEVER',
  sitemapPriority?: '1.0' | '0.9' | '0.8' | '0.7' | '0.6' | '0.5' | '0.4' | '0.3' | '0.2' | '0.1' | '0.0',
  updateDatetime?: String,
  note?: String
}
```

## Development

This package uses `storybook` for development and examples

Check it outwith:

```shell
yarn install && yarn dev
```

## Build & Deployment

This package uses `microbundle` package for bundling. Run basic build with

```shell
yarn build
```