Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support visual editing #949

Merged
merged 15 commits into from
Mar 6, 2024
Merged
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ node_modules
.DS_Store
coverage
dist

playground/.env
.vercel
7 changes: 7 additions & 0 deletions docs/content/1.getting-started/2.configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,10 @@ export default defineNuxtConfig({
},
})
```

### `visualEditing`

- Type: **Object**
- Default: **undefined**

Used to enable and configure Visual Editing. See the [Visual Editing](/getting-started/visual-editing) section for more details.
90 changes: 90 additions & 0 deletions docs/content/1.getting-started/4.visual-editing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Visual Editing

---

## Overview

`@nuxtjs/sanity` provides a simple method of integrating [visual editing](https://www.sanity.io/docs/visual-editing) in your Nuxt application. Before enabling this feature, make sure you have [Presentation](https://www.sanity.io/docs/presentation) installed in your studio.

::alert{type="warning"}
Installing `@sanity/client` is required for visual editing. The `minimal` client must not be enabled.
::

## Configuration

You can configure visual editing via the `sanity.visualEditing` key in your Nuxt config. The following options are available:

#### `studioUrl`

- **Required**
- Type: **string**

The URL of the Sanity Studio with Presentation installed.

#### `token`

- **Required**
- Type: **string**

A Sanity read token used for server side queries. This is required in order to fetch draft content. This value will not be exposed to the client.

#### `mode`

- Type: **string**
- Default: **`'live-visual-editing'`**

Accepts one of the following options:

- **`'live-visual-editing'`** - Default behaviour. Lets the module handle setup to provide fully featured visual editing with live updates. Queries should be executed using `useSanityQuery`.
- **`'visual-editing'`** - Used to enable visual editing without live updates, for example if fetching data using the Sanity client directly. Passing a custom `refresh` handler is recommended, as by default the entire app will refresh to display updates.
- **`'custom'`** - The module will not handle any setup, instead the `useSanityVisualEditing` and/or `useSanityLiveMode` composables will need to be called manually.


#### `previewMode`

- Type: **boolean**, **object**
- Default: **true**

To enable preview mode with defaults, or optionally configure the endpoints used to enable and disable preview mode. If passing an object, the options that can be provided are:

- `enable` - the path of the enable endpoint, defaults to `/preview/enable`
- `disable` - the path of the disable endpoint, defaults to `/preview/disable`

#### `stega`

- Type: **boolean**
- Default: **true**

Used to enable or disable [stega](https://www.sanity.io/docs/loaders-and-overlays#1dbcc04a7093).


#### `refresh`

- Type: **function**

An optional function for overriding the default handling of refresh events received from the studio. This is generally not need needed if the `mode` option is set to `live-visual-editing`.

#### `zIndex`

- Type: **number**, **string**
- Default: **9999999**

The CSS z-index on the root node that renders overlays.


### Recommended Configuration

For most use cases, the following minimum `visualEditing` configuration will suffice:

```ts{}[nuxt.config.ts]
export default defineNuxtConfig({
modules: ['@nuxtjs/sanity'],
sanity: {
// ... Sanity config
visualEditing: {
token: process.env.NUXT_SANITY_VISUAL_EDITING_TOKEN,
studioUrl: process.env.NUXT_SANITY_VISUAL_EDITING_STUDIO_URL,
}
},
})
```
63 changes: 62 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,68 @@
import { SanityHelper } from './src/runtime/composables'
import type { ClientPerspective, StegaConfig } from '@sanity/client'
import type { SanityHelper } from '#sanity-composables'
import type {
SanityVisualEditingMode,
SanityVisualEditingRefreshHandler,
SanityVisualEditingZIndex,
} from './src/module'

type nullish = null | undefined | void

declare module '#app' {
interface NuxtApp {
_sanity?: Record<string, SanityHelper>
}
}

declare module 'nuxt/schema' {
interface RuntimeConfig {
sanity: {
visualEditing:
| {
previewMode:
| false
| {
enable: string
disable: string
}
mode: SanityVisualEditingMode
studioUrl: string
previewModeId: string
token: string

}
| undefined
}
}

interface PublicRuntimeConfig {
sanity: {
additionalClients: Record<string, any>
apiVersion: string
dataset: string
disableSmartCdn: boolean
perspective: ClientPerspective
projectId: string
stega: StegaConfig
token: string
useCdn: boolean
visualEditing:
| {
previewMode:
| false
| {
enable: string
disable: string
}
mode: SanityVisualEditingMode,
studioUrl: string
refresh: SanityVisualEditingRefreshHandler,
zIndex: SanityVisualEditingZIndex
}
| nullish
}
withCredentials: boolean
}
}

export {}
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
"dependencies": {
"@nuxt/kit": "^3.9.0",
"@portabletext/types": "^2.0.8",
"@sanity/core-loader": "^1.4.0",
"@sanity/preview-url-secret": "^1.6.0",
"@sanity/visual-editing": "^1.5.2",
"chalk": "^5.3.0",
"defu": "^6.1.3",
"knitwork": "^1.0.0",
Expand Down
2 changes: 2 additions & 0 deletions playground/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# add a Viewer token issued from https://www.sanity.io/organizations/<org_id>/project/<project_id>/api#tokens
NUXT_SANITY_VISUAL_EDITING_TOKEN=
5 changes: 3 additions & 2 deletions playground/cms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"author": "Daniel Roe <daniel@roe.dev>",
"license": "MIT",
"scripts": {
"dev": "sanity dev",
"start": "sanity start",
"test": "sanity check"
},
Expand All @@ -18,11 +19,11 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"react-icons": "^4.12.0",
"sanity": "3.23.4",
"sanity": "3.30.1",
"styled-components": "^6.1.6"
},
"devDependencies": {
"@sanity/vision": "3.23.4",
"@sanity/vision": "3.30.1",
"@types/react": "18.2.61",
"@types/styled-components": "5.1.34"
}
Expand Down
20 changes: 16 additions & 4 deletions playground/cms/sanity.config.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
import { createConfig } from 'sanity'
import { deskTool } from 'sanity/desk'
import { structureTool } from 'sanity/structure'
import { presentationTool } from 'sanity/presentation'
import { defineConfig } from 'sanity'
import { visionTool } from '@sanity/vision'
import { schemaTypes } from './schemas'
import { debugSecrets } from '@sanity/preview-url-secret/sanity-plugin-debug-secrets'

export default createConfig({
export default defineConfig({
name: 'default',

projectId: 'j1o4tmjp',
dataset: 'production',

plugins: [
deskTool(),
structureTool(),
visionTool(),
presentationTool({
previewUrl: {
origin: 'http://localhost:3000',
previewMode: {
enable: '/preview/enable',
disable: '/preview/disable',
},
},
}),
debugSecrets(),
],

schema: {
Expand Down
5 changes: 5 additions & 0 deletions playground/nuxt.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@ export default defineNuxtConfig({
globalHelper: true,
projectId: 'j1o4tmjp',
dataset: 'production',
apiVersion: '2021-03-25',
additionalClients: {
another: {},
},
visualEditing: {
token: process.env.NUXT_SANITY_VISUAL_EDITING_TOKEN,
studioUrl: 'http://localhost:3333',
},
},
})
7 changes: 3 additions & 4 deletions playground/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
>
<h2>Project ID: {{ $sanity.config.projectId }}</h2>
<NuxtLink
v-for="{ title, poster, slug } in movies"
v-for="({ title, poster, slug }, i) in movies"
:key="title"
:to="`/movie/${slug}`"
class="flex w-64 h-48 relative justify-start"
>
<div
class="py-2 px-4 left-0 bottom-0 mb-4 flex-grow absolute bg-gray-100 rounded shadow-md font-semibold text-gray-800"
:data-sanity="encodeDataAttribute?.([i, 'title'])"
>
{{ title }}
</div>
Expand Down Expand Up @@ -38,7 +39,5 @@ interface QueryResult {
slug: string
}

const sanity = useSanity()

const { data: movies } = await useAsyncData<QueryResult[]>('movies', () => sanity.fetch(query))
const { data: movies, encodeDataAttribute } = await useSanityQuery<QueryResult[]>(query)
</script>
15 changes: 10 additions & 5 deletions playground/pages/movie/[slug].vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<template>
<div class="p-4">
<template v-if="details">
<p><strong>Title</strong>: {{ details.title }}</p>
<p :data-sanity="encodeDataAttribute?.(['title'])">
<strong>Title</strong>: {{ details.title }}
</p>
<p>
<strong>Release date</strong>:
{{
Expand All @@ -24,7 +26,9 @@
project-id="j1o4tmjp"
asset-id="image-e22a88d23751a84df81f03ef287ae85fc992fe12-780x1170-jpg"
/>
<SanityContent :blocks="details.overview" />
<div :data-sanity="encodeDataAttribute?.(['overview'])">
<SanityContent :blocks="details.overview" />
</div>
</template>
<template v-else>
Loading ...
Expand Down Expand Up @@ -56,7 +60,8 @@ interface QueryResult {
}

const route = useRoute()
const { data: details } = await useSanityQuery<QueryResult>(query, {
slug: route.params.slug,
})
const { data: details, encodeDataAttribute } =
await useSanityQuery<QueryResult>(query, {
slug: route.params.slug,
})
</script>
Loading
Loading