npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@nrk/nrkno-iframe-preview-api

v1.2.0

Published

Framework-agnostic library for interacting with [IFramePreview](https://github.com/nrkno/nrkno-sanity-libs/tree/master/packages/sanity-plugin-nrkno-iframe-preview#nrksanity-plugin-nrkno-iframe-preview) in Sanity Studio.

Downloads

86

Maintainers

larsjorgentvedtlarsjorgentvedtebrautasetebrautasetmmepmmepshieldyarmorshieldyarmortheasparrowhawktheasparrowhawkn07073n07073siddisesiddisestiansstianskjellovenordlienkjellovenordlienmaar1052maar1052joakimmohnjoakimmohnmariehovlandmariehovlandsondrbwsondrbwingryeeingryeeellenulrikellenulrikkristjgrkristjgrhenrkhenrksokkemannensokkemannenihlnrkihlnrkknutboknutbojanerikbrjanerikbrthormodbthormodbsiiverssiiverstorsrextorsrexharaldskharaldskeskilgheskilghragnaroh-nrkragnaroh-nrkdaardaldaardalarevjensenarevjensenjulusianjulusianmadsernmadsernandrefauandrefaujfjeldskaarjfjeldskaarmuddahmuddahjensragejensragephajsiphajsijorn_georgjorn_georgbjornhelsbjornhelshalvorhhalvorhmorten-nrkmorten-nrknicklassvendsrudnicklassvendsrudkjellvnnrkkjellvnnrksanderknrksanderknrkeirikjstnrkeirikjstnrkcarinafraningcarinafraninghelenperhelenperstefanogdennrkstefanogdennrkjimmeloysundjimmeloysundtobiasrptobiasrpmartioskmartioskjimalexbergerjimalexbergergunderwondergunderwonderluminrkluminrksupermeisensupermeisenvagifabilovvagifabilovclaudio-nrkclaudio-nrkhaakemonhaakemonzenangstzenangstrannveigncrannveignceschoieneschoienbaltebaltetoshbtoshbemte123emte123opetopetklizterkliztermikkelnygardmikkelnygardfeiringfeiringdervodevdervodevgrimburgrimburgardkroyergardkroyerkariaankariaanedplayzedplayzmiatollaksvikmiatollaksvikytterboytterbomachineboycommachineboycomtrulsltrulslmslhmmslhmcbjerkancbjerkanhermangudesenhermangudesenandreeldareideandreeldareidehenningkollerhenningkollerespenhalstensenespenhalstensendanjohnrkdanjohnrkolapeterolapeterteodor-elstadteodor-elstadlorecasterlorecasternrk-ps-teamcitynrk-ps-teamcityswlaswlanrk-midas-jenkinsnrk-midas-jenkinsandorpandorandorpandornrkrichardnrkrichardgesigesigundelsby-nrkgundelsby-nrkjonstalecarlsenjonstalecarlsennrk-sofie-cinrk-sofie-cinytaminnytaminjesperstarkarjesperstarkarskjalgepalgskjalgepalgeirikhalvardeirikhalvardastokkeastokken640071n640071henrik-mattssonhenrik-mattssonhaavardmhaavardmyryrnrk-kurator-jenkinsnrk-kurator-jenkinstorgeilotorgeilonrk-user-syncnrk-user-syncdhdeploydhdeployespenwaespenwaovstetunovstetunstianljstianljharaldkjharaldkjmariusumariusucristobalcristobalknuthaugknuthaugthohalvthohalvjohnarnejohnarneeshaswinieshaswinimorrowmorrowoyvindehoyvindehlaatlaattoggutoggunrk-jenkinsnrk-jenkinsplommaplommaevjandevjandmoltubakkmoltubakkingridgureningridgurenlu-luxlu-luxanderslianderslisiljesiljestiandgstiandgsjurlursjurlurandipodnrkandipodnrkpkejpkejyosrimtiyosrimtimorten.nyhaugmorten.nyhaugingvildcathingvildcatherlend.joneserlend.jonesbrneirikbrneirikmollersemollersetbnrktbnrknordankenordankesimonmitternachtsimonmitternachtmartintorgersenmartintorgersenrebchrrebchrsteipalsteipaldiscobusdiscobusmartingundersenmartingundersentinkajtstinkajtshallvardlidhallvardlidtomivartomivarajacoajacotobinustobinusmortenokmortenoknrk-ark-deploynrk-ark-deployjeangilbertlouisjeangilbertlouisheidimorkheidimorkingriddraageningriddraagenfridajalborgfridajalborgbruusibruusirosvollrosvollchristianeidechristianeideenordbyenordbyglen_imrieglen_imriemia.aasbakkenmia.aasbakkenelathamnaelathamnaevjjan17evjjan17olatoftolatoftkongsrudkongsrudchrpeterchrpeteringvildforsethingvildforsethharaldk76haraldk76stigokstigokjohannesodlandjohannesodlandanders993anders993vildefjvildefjvildepkvildepkrolerbolerrolerbolermeloyguttmeloyguttanders.baggethunanders.baggethun

Keywords

Readme

@nrk/nrkno-iframe-preview-api

Framework-agnostic library for interacting with IFramePreview in Sanity Studio.

initPreview should be used by the app rendered inside the iframe.

See docs in @nrk/sanity-plugin-nrkno-iframe-preview for a detailed description of how this library works.

preview.png Figure 1: Sanity form editor in the left pane, IFramePreview showing iframe content in the right pane.

Installation

npm install --save @nrk/nrkno-iframe-preview-api

Usage

Refer to jsdocs for each config-param for details.

For any issues, see "Usage checklist" and "Debugging issues" below.

Basic usage

import { initPreview } from '@nrk/nrkno-iframe-preview-api'

// Somewhere after page load
const unloadPreview = initPreview<QueryResult | undefined>(
    {
      // _rev field is REQUIRED. See note about _rev field below.
      // query passed as the first param to sanityClient.fetch
      groqQuery: "* [_type='my-page' && _id == $id]{_rev, ...}[0]",
      
      // query params are passed as the second param to sanityClient.fetch,
      // and can be used in the groqQuery (ie $id) 
      queryParams: (doc) => ({id: doc._id}), // default
    },
    (data) => {
      if (!data) {
        //we will end up in here if the query has no data and
        //during inital load becuase initialData param is undefined.
        return;
      }
      // When this page is loaded by IFramePreview in Sanity Studio,
      // this callback will receive updated query-data whenever the Studio makes edits.
      // Use it to update your page in whatever way makes sense.
      
      // setData can be async
    }
)


// when the component that uses the preview is unmounted, ensure to call
unloadPreview()

Usage Checklist

Ensure that:

  • your query explicitly contains _rev as a projected field. For details, see "About the _rev field".
  • queryParams function is invoked, and that you are returning an object with all query parameters used by your query.
    • Example query: * [slug=$slug]{_rev, _id, slug, title, body }[0]
    • Example queryParams: doc => {slug: doc.slug}
    • Note: the doc passed to queryParams is active document in Sanity Studio, not the one returned by the groqQuery
  • the setData function handles undefined values.
  • the setData function is receiving data, is updating your view and not is throwing an error.

Use debug: true for diagnostics (see below). Use it to find the query and params used for each update by the Studio to debug parameterized queries (for instance, by running them in Vision).

Advanced usage

import { initPreview } from '@nrk/nrkno-iframe-preview-api'

// assume the page is server side rendered, and prepobulated with data
const prefetchedData = {_rev: '123', _id: '2'}

// Somewhere after page load
const unloadPreview = initPreview<QueryResult | undefined>(
    {
      sanityClientVersion: "2021-06-01",
      groqQuery: "* [_type='my-page' && slug._current == $slug]{_rev, ...}[0]",
      queryParams: (doc) => ({slug: doc.slug._current}),
      initialData: prefetchedData,
      origin: 'https://my-sanity-studio.example'
    },
    (data) => {
      if (!data) {
        return;
      }
      // update app
    }
)


// whenever the component that uses the preview is unmounted, ensure to call
unloadPreview()

Debugging issues

Provide debug: true as a config parameter. The log messages in console.log should provide a trace of any issues.

initPreview<QueryResult | undefined>(
    {
      // This flag will make the lib log messages being passed between Sanity Studio and the iframe 
      debug: true,
      // debug: process.env.NODE_ENV !== production
      groqQuery: "* [_type='my-page' && _id == $id]{_rev, ...}[0]",
    },
    (data) => {/* omitted */ }
)

Use Studio document as is

Omit groqQuery param completly.

Now data will always be the document used by the studio (possibly passed through by mapDocument in IFramePreview).

import { initPreview } from '@nrk/nrkno-iframe-preview-api'

// Somewhere after page load
const unloadPreview = initPreview<QueryResult | undefined>({},
    (data) => {
      if (!data) {
        return;
      }
      // data will be what the Sanity studio has; no groq queries will be execuded.
    }
)

// when the component that uses the preview is unmounted, ensure to call
unloadPreview()

Use with React

import React, {useState, useEffect} from 'react'
import { initPreview } from '@nrk/nrkno-iframe-preview-api'

export function MyApp(props: {initialData: QueryResult, enabledPreview: boolean}) {
  const [appState, setAppState] = useState<QueryResult>(props.initialData)
  
  useEffect(() => {
    if (!props.enabledPreview) {
      return 
    }
    // cleanup function is returned to React
    return initPreview<QueryResult | undefined>(
      {
        groqQuery: "* [_type='my-page' && _id == $id]{_rev, ...}[0]",
        queryParams: (doc) => ({id: doc._id}),
        initialData
      },
      (data) => {
        if (!data) {
          return;
        }
        setAppState(data)
      }
    );
  }, [] /* only run effect on mount */)
  
  // updates whenever we get data from Sanity studio
  return <div>{JSON.stringify(appState)}</div>
}

About the _rev field

All Sanity documents contains a _rev field. It changes everytime the document changes, and is unique.

For Sanity Studio to know when the groq-query returns up-to-date data, IFramePreview will compare the _rev field in the current studio document, with the _rev field in the query.

Therefore the groqQuery MUST contain the _rev-field projected at the top level, and it should correspond to the _rev field of the document edited in the studio.

It has to be explicitly projected, so it can be validated without running the query. Queries without projections can be easily rewritten like this:

  • Query without projection and _rev field: *[_id == $id][0]
  • Query WITH projection and _rev field: *[_id == $id][0]{_rev, ...}

If the query contains no _rev an error will be thrown.

Sequence diagram for dataflow

sequence.png Figure 2: Sequence diagram for dataflow between Sanity Studio and the iframe

Develop

Test

In this directory

npm run build
npm link
cd /path/to/your/render/app
npm link  @nrk/sanity-plugin-nrkno-iframe-preview

If you use volta, you must ensure that your render app also uses volta, otherwise npm link will not work correctly.

Remember to use localhost url in the Studio to test the IFramePreview component with the app using the linked lib.