sanity-plugin-markdown 3.0.0-v3-studio.6 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,10 +1,7 @@
1
1
  # sanity-plugin-markdown
2
2
 
3
- > **NOTE**
4
- >
5
- > This is the **Sanity Studio v3 version** of sanity-plugin-markdown.
6
- >
7
- > For the v2 version, please refer to the [v2-branch](https://github.com/sanity-io/sanity-plugin-markdown).
3
+ > This is a **Sanity Studio v3** plugin.
4
+ > For the v2 version, please refer to the [v2-branch](https://github.com/sanity-io/sanity-plugin-markdown/tree/studio-v2).
8
5
 
9
6
  ## What is it?
10
7
 
@@ -23,13 +20,13 @@ You can still add markdown image tags, but you will have to get the image url yo
23
20
  ## Installation
24
21
 
25
22
  ```
26
- npm install --save sanity-plugin-markdown@studio-v3
23
+ npm install --save sanity-plugin-markdown
27
24
  ```
28
25
 
29
26
  or
30
27
 
31
28
  ```
32
- yarn add sanity-plugin-markdown@studio-v3
29
+ yarn add sanity-plugin-markdown
33
30
  ```
34
31
 
35
32
  ## Usage
package/lib/index.esm.js CHANGED
@@ -1,2 +1,2 @@
1
- function e(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function r(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}import{jsx as t}from"react/jsx-runtime";import n from"@uiw/react-md-editor";import{useState as o,useEffect as i,forwardRef as c}from"react";import{PatchEvent as a,unset as u,set as p,defineType as s,definePlugin as m}from"sanity";import{useTheme as l,Card as f}from"@sanity/ui";import d from"rehype-sanitize";const y=c((function(e,r){const{value:c="",onChange:s,elementProps:{onBlur:m,onFocus:y},readOnly:O}=e,[b,g]=o(c),w=function(e,r){const[t,n]=o(e);return i((()=>{const t=setTimeout((()=>{n(e)}),r);return()=>clearTimeout(t)}),[e,r]),t}(b,100);i((()=>{g(c)}),[c]),i((()=>{!w&&c?s(a.from([u()])):w!==c&&s(a.from([p(w)]))}),[w,s]);const{sanity:h}=l();return t("div",{ref:r,"data-color-mode":h.color.dark?"dark":"light",children:O?t(f,{border:!0,padding:3,children:t(n.Markdown,{source:c,rehypePlugins:[[d]]})}):t(n,{value:b,onChange:g,onBlur:m,onFocus:y,previewOptions:{rehypePlugins:[[d]]},preview:"edit"})})})),O=s(function(t){for(var n=1;n<arguments.length;n++){var o=null!=arguments[n]?arguments[n]:{};n%2?e(Object(o),!0).forEach((function(e){r(t,e,o[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(o)):e(Object(o)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(o,e))}))}return t}({type:"string",name:"markdown",title:"Markdown"},{components:{input:y}})),b=y,g=m({name:"markdown-editor",schema:{types:[O]}});export{b as MarkdownEditor,g as markdownSchema,O as markdownSchemaType};
1
+ function e(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function t(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}import{jsx as r}from"react/jsx-runtime";import n from"@uiw/react-md-editor";import{useState as o,useEffect as a,forwardRef as i,useCallback as c}from"react";import{useClient as s,PatchEvent as l,unset as u,set as p,defineType as m,definePlugin as f}from"sanity";import{useTheme as d,Card as y}from"@sanity/ui";import b from"rehype-sanitize";const g=i((function(e,t){const{value:i="",onChange:m,elementProps:{onBlur:f,onFocus:g},readOnly:w}=e,[h,P]=o(i),j=function(e,t){const[r,n]=o(e);return a((()=>{const r=setTimeout((()=>{n(e)}),t);return()=>clearTimeout(r)}),[e,t]),r}(h,100),v=s({apiVersion:"2022-01-01"});a((()=>{P(i)}),[i]),a((()=>{!j&&i?m(l.from([u()])):j!==i&&m(l.from([p(j)]))}),[j,m]);const{sanity:k}=d(),D=c((async e=>{await O(e.clipboardData,P,v)}),[P,v]),E=c((async e=>{e.preventDefault(),e.stopPropagation(),e.dataTransfer&&await O(e.dataTransfer,P,v)}),[P,v]);return r("div",{ref:t,"data-color-mode":k.color.dark?"dark":"light",children:w?r(y,{border:!0,padding:3,children:r(n.Markdown,{source:i,rehypePlugins:[[b]]})}):r(n,{value:h,onChange:P,onBlur:f,onFocus:g,previewOptions:{rehypePlugins:[[b]]},preview:"edit",onPaste:D,onDrop:E})})}));async function O(e,t,r){const n=[];for(let t=0;t<e.items.length;t+=1){const r=e.files.item(t);r&&n.push(r)}await Promise.all(n.map((async e=>{const n=await r.assets.upload("image",e).then((e=>"".concat(e.url,"?w=450"))),o=function(e){const t=document.querySelector("textarea");if(!t)return null;let r=t.value;const n=r.length,o=t.selectionStart,a=t.selectionEnd,i=r.slice(0,o),c=r.slice(o,n);return r=i+e+c,t.value=r,t.selectionEnd=a+e.length,r}("![](".concat(n,")"));o&&t(o)})))}const w=m(function(r){for(var n=1;n<arguments.length;n++){var o=null!=arguments[n]?arguments[n]:{};n%2?e(Object(o),!0).forEach((function(e){t(r,e,o[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(r,Object.getOwnPropertyDescriptors(o)):e(Object(o)).forEach((function(e){Object.defineProperty(r,e,Object.getOwnPropertyDescriptor(o,e))}))}return r}({type:"string",name:"markdown",title:"Markdown"},{components:{input:g}})),h=g,P=f({name:"markdown-editor",schema:{types:[w]}});export{h as MarkdownEditor,P as markdownSchema,w as markdownSchemaType};
2
2
  //# sourceMappingURL=index.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/components/Editor.tsx","../src/hooks/useDebounce.ts","../src/schema.ts","../src/index.ts"],"sourcesContent":["import MDEditor from '@uiw/react-md-editor'\nimport useDebounce from '../hooks/useDebounce'\nimport {StringInputProps, PatchEvent, set, unset} from 'sanity'\nimport React, {forwardRef, Ref, useEffect, useState} from 'react'\nimport {Card, useTheme} from '@sanity/ui'\nimport rehypeSanitize from 'rehype-sanitize'\n\nexport const MarkdownEditor = forwardRef(function MarkdownEditor(\n props: StringInputProps,\n ref: Ref<any>\n) {\n const {\n value = '',\n onChange,\n elementProps: {onBlur, onFocus},\n readOnly,\n } = props\n const [editedValue, setEditedValue] = useState<string | undefined>(value)\n const debouncedValue = useDebounce(editedValue, 100)\n // const client = useClient({apiVersion: '2021-03-25'})\n\n useEffect(() => {\n setEditedValue(value)\n }, [value])\n\n useEffect(() => {\n if (!debouncedValue && value) {\n onChange(PatchEvent.from([unset()]))\n } else if (debouncedValue !== value) {\n onChange(PatchEvent.from([set(debouncedValue)]))\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [debouncedValue, onChange])\n\n /* const saveImage = async function* (data: any) {\n\n let success = true\n const result = await client.assets\n .upload('image', data)\n .then((doc) => `${doc.url}?w=450`)\n .catch(() => {\n success = false\n return `Error: Could not upload file. Only images are supported.`\n })\n\n yield result\n return success\n }*/\n\n const {sanity: studioTheme} = useTheme()\n return (\n <div ref={ref} data-color-mode={studioTheme.color.dark ? 'dark' : 'light'}>\n {readOnly ? (\n <Card border padding={3}>\n <MDEditor.Markdown source={value} rehypePlugins={[[rehypeSanitize]]} />\n </Card>\n ) : (\n <MDEditor\n value={editedValue}\n onChange={setEditedValue}\n onBlur={onBlur}\n onFocus={onFocus}\n previewOptions={{\n rehypePlugins: [[rehypeSanitize]],\n }}\n preview=\"edit\"\n />\n )}\n </div>\n )\n})\n","import {useState, useEffect} from 'react'\n\nexport default function useDebounce(value: unknown, delay: number) {\n const [debouncedValue, setDebouncedValue] = useState(value)\n useEffect(() => {\n const handler = setTimeout(() => {\n setDebouncedValue(value)\n }, delay)\n\n return () => clearTimeout(handler)\n }, [value, delay])\n\n return debouncedValue\n}\n","import {defineType, StringDefinition} from 'sanity'\nimport {MarkdownEditor} from './components/Editor'\n\nconst markdownTypeName = 'markdown' as const\n\n/**\n * @public\n */\nexport interface MarkdownDefinition extends Omit<StringDefinition, 'type' | 'fields' | 'options'> {\n type: typeof markdownTypeName\n}\n\ndeclare module '@sanity/types' {\n // makes type: 'markdown' narrow correctly when using defineType/defineField/defineArrayMember\n export interface IntrinsicDefinitions {\n markdown: MarkdownDefinition\n }\n}\n\nexport const markdownSchemaType = defineType({\n type: 'string',\n name: markdownTypeName,\n title: 'Markdown',\n ...({components: {input: MarkdownEditor}} as {}), //TODO revert when rc.1 ships\n})\n","import {MarkdownEditor as Editor} from './components/Editor'\nimport {definePlugin} from 'sanity'\nimport {markdownSchemaType, MarkdownDefinition} from './schema'\n\n// re-exporting MarkdownEditor directly explodes @parcel/transformer-typescript-types :shrug:\nconst MarkdownEditor = Editor\n\nexport {MarkdownEditor, markdownSchemaType}\nexport type {MarkdownDefinition}\n\nexport const markdownSchema = definePlugin({\n name: 'markdown-editor',\n schema: {\n types: [markdownSchemaType],\n },\n})\n"],"names":["MarkdownEditor","forwardRef","props","ref","value","onChange","elementProps","onBlur","onFocus","readOnly","editedValue","setEditedValue","useState","debouncedValue","delay","setDebouncedValue","useEffect","handler","setTimeout","clearTimeout","useDebounce","PatchEvent","from","unset","set","sanity","studioTheme","useTheme","jsx","color","dark","children","Card","border","padding","MDEditor","Markdown","source","rehypePlugins","rehypeSanitize","previewOptions","preview","markdownSchemaType","defineType","_objectSpread","type","name","title","components","input","Editor","markdownSchema","definePlugin","schema","types"],"mappings":"2oBAOO,MAAMA,EAAiBC,GAAW,SACvCC,EACAC,GAEM,MAAAC,MACJA,EAAQ,GAAAC,SACRA,EACAC,cAAcC,OAACA,EAAAC,QAAQA,GAAOC,SAC9BA,GACEP,GACGQ,EAAaC,GAAkBC,EAA6BR,GAC7DS,EChBgB,SAAYT,EAAgBU,GAClD,MAAOD,EAAgBE,GAAqBH,EAASR,GAS9C,OARPY,GAAU,KACF,MAAAC,EAAUC,YAAW,KACzBH,EAAkBX,EAAK,GACtBU,GAEI,MAAA,IAAMK,aAAaF,EAAO,GAChC,CAACb,EAAOU,IAEJD,CACT,CDKyBO,CAAYV,EAAa,KAGhDM,GAAU,KACRL,EAAeP,EAAK,GACnB,CAACA,IAEJY,GAAU,MACHH,GAAkBT,EACrBC,EAASgB,EAAWC,KAAK,CAACC,OACjBV,IAAmBT,GAC5BC,EAASgB,EAAWC,KAAK,CAACE,EAAIX,KAChC,GAEC,CAACA,EAAgBR,IAiBpB,MAAOoB,OAAQC,GAAeC,IAC9B,OACGC,EAAA,MAAA,CAAIzB,MAAU,kBAAiBuB,EAAYG,MAAMC,KAAO,OAAS,QAC/DC,WACEH,EAAAI,EAAA,CAAKC,QAAM,EAACC,QAAS,EACpBH,SAAAH,EAACO,EAASC,SAAT,CAAkBC,OAAQjC,EAAOkC,cAAe,CAAC,CAACC,QAGpDX,EAAAO,EAAA,CACC/B,MAAOM,EACPL,SAAUM,EACVJ,SACAC,UACAgC,eAAgB,CACdF,cAAe,CAAC,CAACC,KAEnBE,QAAQ,UAKlB,IEnDaC,EAAqBC,iWAAWC,CAAA,CAC3CC,KAAM,SACNC,KAlBuB,WAmBvBC,MAAO,YACH,CAACC,WAAY,CAACC,MAAOjD,MClBrBA,EAAiBkD,EAKVC,EAAiBC,EAAa,CACzCN,KAAM,kBACNO,OAAQ,CACNC,MAAO,CAACZ"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/components/Editor.tsx","../src/hooks/useDebounce.ts","../src/schema.ts","../src/index.ts"],"sourcesContent":["import MDEditor from '@uiw/react-md-editor'\nimport useDebounce from '../hooks/useDebounce'\nimport {PatchEvent, SanityClient, set, StringInputProps, unset, useClient} from 'sanity'\nimport React, {\n ClipboardEvent,\n forwardRef,\n Ref,\n SetStateAction,\n useCallback,\n useEffect,\n useState,\n DragEvent,\n} from 'react'\nimport {Card, useTheme} from '@sanity/ui'\nimport rehypeSanitize from 'rehype-sanitize'\n\nexport const MarkdownEditor = forwardRef(function MarkdownEditor(\n props: StringInputProps,\n ref: Ref<any>\n) {\n const {\n value = '',\n onChange,\n elementProps: {onBlur, onFocus},\n readOnly,\n } = props\n const [editedValue, setEditedValue] = useState<string | undefined>(value)\n const debouncedValue = useDebounce(editedValue, 100)\n // const client = useClient({apiVersion: '2021-03-25'})\n const client = useClient({apiVersion: '2022-01-01'})\n useEffect(() => {\n setEditedValue(value)\n }, [value])\n\n useEffect(() => {\n if (!debouncedValue && value) {\n onChange(PatchEvent.from([unset()]))\n } else if (debouncedValue !== value) {\n onChange(PatchEvent.from([set(debouncedValue)]))\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [debouncedValue, onChange])\n\n const {sanity: studioTheme} = useTheme()\n const onPaste = useCallback(\n async (event: ClipboardEvent<HTMLDivElement>) => {\n await onImagePasted(event.clipboardData, setEditedValue, client)\n },\n [setEditedValue, client]\n )\n\n const onDrop = useCallback(\n async (event: DragEvent<HTMLDivElement>) => {\n event.preventDefault()\n event.stopPropagation()\n if (event.dataTransfer) {\n await onImagePasted(event.dataTransfer, setEditedValue, client)\n }\n },\n [setEditedValue, client]\n )\n\n return (\n <div ref={ref} data-color-mode={studioTheme.color.dark ? 'dark' : 'light'}>\n {readOnly ? (\n <Card border padding={3}>\n <MDEditor.Markdown source={value} rehypePlugins={[[rehypeSanitize]]} />\n </Card>\n ) : (\n <MDEditor\n value={editedValue}\n onChange={setEditedValue}\n onBlur={onBlur}\n onFocus={onFocus}\n previewOptions={{\n rehypePlugins: [[rehypeSanitize]],\n }}\n preview=\"edit\"\n onPaste={onPaste}\n onDrop={onDrop}\n />\n )}\n </div>\n )\n})\n\n// https://github.com/uiwjs/react-md-editor/issues/83#issuecomment-1185471844\nasync function onImagePasted(\n dataTransfer: DataTransfer,\n setMarkdown: (value: SetStateAction<string | undefined>) => void,\n client: SanityClient\n) {\n const files: File[] = []\n for (let index = 0; index < dataTransfer.items.length; index += 1) {\n const file = dataTransfer.files.item(index)\n\n if (file) {\n files.push(file)\n }\n }\n\n await Promise.all(\n files.map(async (file) => {\n const url = await client.assets.upload('image', file).then((doc) => `${doc.url}?w=450`)\n const insertedMarkdown = insertToTextArea(`![](${url})`)\n if (!insertedMarkdown) {\n return\n }\n setMarkdown(insertedMarkdown)\n })\n )\n}\n\nfunction insertToTextArea(insertString: string) {\n const textarea = document.querySelector('textarea')\n if (!textarea) {\n return null\n }\n\n let sentence = textarea.value\n const len = sentence.length\n const pos = textarea.selectionStart\n const end = textarea.selectionEnd\n\n const front = sentence.slice(0, pos)\n const back = sentence.slice(pos, len)\n\n sentence = front + insertString + back\n\n textarea.value = sentence\n textarea.selectionEnd = end + insertString.length\n\n return sentence\n}\n","import {useState, useEffect} from 'react'\n\nexport default function useDebounce(value: unknown, delay: number) {\n const [debouncedValue, setDebouncedValue] = useState(value)\n useEffect(() => {\n const handler = setTimeout(() => {\n setDebouncedValue(value)\n }, delay)\n\n return () => clearTimeout(handler)\n }, [value, delay])\n\n return debouncedValue\n}\n","import {defineType, StringDefinition} from 'sanity'\nimport {MarkdownEditor} from './components/Editor'\n\nconst markdownTypeName = 'markdown' as const\n\n/**\n * @public\n */\nexport interface MarkdownDefinition extends Omit<StringDefinition, 'type' | 'fields' | 'options'> {\n type: typeof markdownTypeName\n}\n\ndeclare module '@sanity/types' {\n // makes type: 'markdown' narrow correctly when using defineType/defineField/defineArrayMember\n export interface IntrinsicDefinitions {\n markdown: MarkdownDefinition\n }\n}\n\nexport const markdownSchemaType = defineType({\n type: 'string',\n name: markdownTypeName,\n title: 'Markdown',\n ...({components: {input: MarkdownEditor}} as {}), //TODO revert when rc.1 ships\n})\n","import {MarkdownEditor as Editor} from './components/Editor'\nimport {definePlugin} from 'sanity'\nimport {markdownSchemaType, MarkdownDefinition} from './schema'\n\n// re-exporting MarkdownEditor directly explodes @parcel/transformer-typescript-types :shrug:\nconst MarkdownEditor = Editor\n\nexport {MarkdownEditor, markdownSchemaType}\nexport type {MarkdownDefinition}\n\nexport const markdownSchema = definePlugin({\n name: 'markdown-editor',\n schema: {\n types: [markdownSchemaType],\n },\n})\n"],"names":["MarkdownEditor","forwardRef","props","ref","value","onChange","elementProps","onBlur","onFocus","readOnly","editedValue","setEditedValue","useState","debouncedValue","delay","setDebouncedValue","useEffect","handler","setTimeout","clearTimeout","useDebounce","client","useClient","apiVersion","PatchEvent","from","unset","set","sanity","studioTheme","useTheme","onPaste","useCallback","async","onImagePasted","event","clipboardData","onDrop","preventDefault","stopPropagation","dataTransfer","jsx","color","dark","children","Card","border","padding","MDEditor","Markdown","source","rehypePlugins","rehypeSanitize","previewOptions","preview","setMarkdown","files","index","items","length","file","item","push","Promise","all","map","url","assets","upload","then","doc","insertedMarkdown","insertString","textarea","document","querySelector","sentence","len","pos","selectionStart","end","selectionEnd","front","slice","back","insertToTextArea","concat","markdownSchemaType","defineType","_objectSpread","type","name","title","components","input","Editor","markdownSchema","definePlugin","schema","types"],"mappings":"2qBAgBO,MAAMA,EAAiBC,GAAW,SACvCC,EACAC,GAEM,MAAAC,MACJA,EAAQ,GAAAC,SACRA,EACAC,cAAcC,OAACA,EAAAC,QAAQA,GAAOC,SAC9BA,GACEP,GACGQ,EAAaC,GAAkBC,EAA6BR,GAC7DS,ECzBgB,SAAYT,EAAgBU,GAClD,MAAOD,EAAgBE,GAAqBH,EAASR,GAS9C,OARPY,GAAU,KACF,MAAAC,EAAUC,YAAW,KACzBH,EAAkBX,EAAK,GACtBU,GAEI,MAAA,IAAMK,aAAaF,EAAO,GAChC,CAACb,EAAOU,IAEJD,CACT,CDcyBO,CAAYV,EAAa,KAE1CW,EAASC,EAAU,CAACC,WAAY,eACtCP,GAAU,KACRL,EAAeP,EAAK,GACnB,CAACA,IAEJY,GAAU,MACHH,GAAkBT,EACrBC,EAASmB,EAAWC,KAAK,CAACC,OACjBb,IAAmBT,GAC5BC,EAASmB,EAAWC,KAAK,CAACE,EAAId,KAChC,GAEC,CAACA,EAAgBR,IAEpB,MAAOuB,OAAQC,GAAeC,IACxBC,EAAUC,GACdC,gBACQC,EAAcC,EAAMC,cAAezB,EAAgBU,EAAM,GAEjE,CAACV,EAAgBU,IAGbgB,EAASL,GACbC,UACEE,EAAMG,iBACNH,EAAMI,kBACFJ,EAAMK,oBACFN,EAAcC,EAAMK,aAAc7B,EAAgBU,EAC1D,GAEF,CAACV,EAAgBU,IAGnB,OACGoB,EAAA,MAAA,CAAItC,MAAU,kBAAiB0B,EAAYa,MAAMC,KAAO,OAAS,QAC/DC,WACEH,EAAAI,EAAA,CAAKC,QAAM,EAACC,QAAS,EACpBH,SAAAH,EAACO,EAASC,SAAT,CAAkBC,OAAQ9C,EAAO+C,cAAe,CAAC,CAACC,QAGpDX,EAAAO,EAAA,CACC5C,MAAOM,EACPL,SAAUM,EACVJ,SACAC,UACA6C,eAAgB,CACdF,cAAe,CAAC,CAACC,KAEnBE,QAAQ,OACRvB,UACAM,YAKV,IAGAJ,eAAeC,EACbM,EACAe,EACAlC,GAEA,MAAMmC,EAAgB,GACtB,IAAA,IAASC,EAAQ,EAAGA,EAAQjB,EAAakB,MAAMC,OAAQF,GAAS,EAAG,CACjE,MAAMG,EAAOpB,EAAagB,MAAMK,KAAKJ,GAEjCG,GACFJ,EAAMM,KAAKF,EAEf,OAEMG,QAAQC,IACZR,EAAMS,KAAIhC,UACR,MAAMiC,QAAY7C,EAAO8C,OAAOC,OAAO,QAASR,GAAMS,MAAMC,aAAWA,EAAIJ,IAAW,YAChFK,EASZ,SAA0BC,GAClB,MAAAC,EAAWC,SAASC,cAAc,YACxC,IAAKF,EACI,OAAA,KAGT,IAAIG,EAAWH,EAASrE,MACxB,MAAMyE,EAAMD,EAASjB,OACfmB,EAAML,EAASM,eACfC,EAAMP,EAASQ,aAEfC,EAAQN,EAASO,MAAM,EAAGL,GAC1BM,EAAOR,EAASO,MAAML,EAAKD,GAO1B,OALPD,EAAWM,EAAQV,EAAeY,EAElCX,EAASrE,MAAQwE,EACRH,EAAAQ,aAAeD,EAAMR,EAAab,OAEpCiB,CACT,CA7B+BS,CAAiB,OAAAC,OAAOpB,EAAM,MAClDK,GAGLhB,EAAYgB,EAAgB,IAGlC,CE5GA,MAgBagB,EAAqBC,iWAAWC,CAAA,CAC3CC,KAAM,SACNC,KAlBuB,WAmBvBC,MAAO,YACH,CAACC,WAAY,CAACC,MAAO9F,MClBrBA,EAAiB+F,EAKVC,EAAiBC,EAAa,CACzCN,KAAM,kBACNO,OAAQ,CACNC,MAAO,CAACZ"}
package/lib/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";function e(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function r(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}Object.defineProperty(exports,"__esModule",{value:!0});var t=require("react/jsx-runtime"),n=require("@uiw/react-md-editor"),o=require("react"),i=require("sanity"),u=require("@sanity/ui"),a=require("rehype-sanitize");function c(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var s=c(n),f=c(a);const d=o.forwardRef((function(e,r){const{value:n="",onChange:a,elementProps:{onBlur:c,onFocus:d},readOnly:l}=e,[p,y]=o.useState(n),m=function(e,r){const[t,n]=o.useState(e);return o.useEffect((()=>{const t=setTimeout((()=>{n(e)}),r);return()=>clearTimeout(t)}),[e,r]),t}(p,100);o.useEffect((()=>{y(n)}),[n]),o.useEffect((()=>{!m&&n?a(i.PatchEvent.from([i.unset()])):m!==n&&a(i.PatchEvent.from([i.set(m)]))}),[m,a]);const{sanity:b}=u.useTheme();return t.jsx("div",{ref:r,"data-color-mode":b.color.dark?"dark":"light",children:l?t.jsx(u.Card,{border:!0,padding:3,children:t.jsx(s.default.Markdown,{source:n,rehypePlugins:[[f.default]]})}):t.jsx(s.default,{value:p,onChange:y,onBlur:c,onFocus:d,previewOptions:{rehypePlugins:[[f.default]]},preview:"edit"})})})),l=i.defineType(function(t){for(var n=1;n<arguments.length;n++){var o=null!=arguments[n]?arguments[n]:{};n%2?e(Object(o),!0).forEach((function(e){r(t,e,o[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(o)):e(Object(o)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(o,e))}))}return t}({type:"string",name:"markdown",title:"Markdown"},{components:{input:d}})),p=d,y=i.definePlugin({name:"markdown-editor",schema:{types:[l]}});exports.MarkdownEditor=p,exports.markdownSchema=y,exports.markdownSchemaType=l;
1
+ "use strict";function e(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function t(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}Object.defineProperty(exports,"__esModule",{value:!0});var r=require("react/jsx-runtime"),n=require("@uiw/react-md-editor"),o=require("react"),a=require("sanity"),i=require("@sanity/ui"),c=require("rehype-sanitize");function s(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var u=s(n),l=s(c);const f=o.forwardRef((function(e,t){const{value:n="",onChange:c,elementProps:{onBlur:s,onFocus:f},readOnly:p}=e,[y,m]=o.useState(n),b=function(e,t){const[r,n]=o.useState(e);return o.useEffect((()=>{const r=setTimeout((()=>{n(e)}),t);return()=>clearTimeout(r)}),[e,t]),r}(y,100),h=a.useClient({apiVersion:"2022-01-01"});o.useEffect((()=>{m(n)}),[n]),o.useEffect((()=>{!b&&n?c(a.PatchEvent.from([a.unset()])):b!==n&&c(a.PatchEvent.from([a.set(b)]))}),[b,c]);const{sanity:w}=i.useTheme(),g=o.useCallback((async e=>{await d(e.clipboardData,m,h)}),[m,h]),O=o.useCallback((async e=>{e.preventDefault(),e.stopPropagation(),e.dataTransfer&&await d(e.dataTransfer,m,h)}),[m,h]);return r.jsx("div",{ref:t,"data-color-mode":w.color.dark?"dark":"light",children:p?r.jsx(i.Card,{border:!0,padding:3,children:r.jsx(u.default.Markdown,{source:n,rehypePlugins:[[l.default]]})}):r.jsx(u.default,{value:y,onChange:m,onBlur:s,onFocus:f,previewOptions:{rehypePlugins:[[l.default]]},preview:"edit",onPaste:g,onDrop:O})})}));async function d(e,t,r){const n=[];for(let t=0;t<e.items.length;t+=1){const r=e.files.item(t);r&&n.push(r)}await Promise.all(n.map((async e=>{const n=await r.assets.upload("image",e).then((e=>"".concat(e.url,"?w=450"))),o=function(e){const t=document.querySelector("textarea");if(!t)return null;let r=t.value;const n=r.length,o=t.selectionStart,a=t.selectionEnd,i=r.slice(0,o),c=r.slice(o,n);return r=i+e+c,t.value=r,t.selectionEnd=a+e.length,r}("![](".concat(n,")"));o&&t(o)})))}const p=a.defineType(function(r){for(var n=1;n<arguments.length;n++){var o=null!=arguments[n]?arguments[n]:{};n%2?e(Object(o),!0).forEach((function(e){t(r,e,o[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(r,Object.getOwnPropertyDescriptors(o)):e(Object(o)).forEach((function(e){Object.defineProperty(r,e,Object.getOwnPropertyDescriptor(o,e))}))}return r}({type:"string",name:"markdown",title:"Markdown"},{components:{input:f}})),y=f,m=a.definePlugin({name:"markdown-editor",schema:{types:[p]}});exports.MarkdownEditor=y,exports.markdownSchema=m,exports.markdownSchemaType=p;
2
2
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/components/Editor.tsx","../src/hooks/useDebounce.ts","../src/schema.ts","../src/index.ts"],"sourcesContent":["import MDEditor from '@uiw/react-md-editor'\nimport useDebounce from '../hooks/useDebounce'\nimport {StringInputProps, PatchEvent, set, unset} from 'sanity'\nimport React, {forwardRef, Ref, useEffect, useState} from 'react'\nimport {Card, useTheme} from '@sanity/ui'\nimport rehypeSanitize from 'rehype-sanitize'\n\nexport const MarkdownEditor = forwardRef(function MarkdownEditor(\n props: StringInputProps,\n ref: Ref<any>\n) {\n const {\n value = '',\n onChange,\n elementProps: {onBlur, onFocus},\n readOnly,\n } = props\n const [editedValue, setEditedValue] = useState<string | undefined>(value)\n const debouncedValue = useDebounce(editedValue, 100)\n // const client = useClient({apiVersion: '2021-03-25'})\n\n useEffect(() => {\n setEditedValue(value)\n }, [value])\n\n useEffect(() => {\n if (!debouncedValue && value) {\n onChange(PatchEvent.from([unset()]))\n } else if (debouncedValue !== value) {\n onChange(PatchEvent.from([set(debouncedValue)]))\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [debouncedValue, onChange])\n\n /* const saveImage = async function* (data: any) {\n\n let success = true\n const result = await client.assets\n .upload('image', data)\n .then((doc) => `${doc.url}?w=450`)\n .catch(() => {\n success = false\n return `Error: Could not upload file. Only images are supported.`\n })\n\n yield result\n return success\n }*/\n\n const {sanity: studioTheme} = useTheme()\n return (\n <div ref={ref} data-color-mode={studioTheme.color.dark ? 'dark' : 'light'}>\n {readOnly ? (\n <Card border padding={3}>\n <MDEditor.Markdown source={value} rehypePlugins={[[rehypeSanitize]]} />\n </Card>\n ) : (\n <MDEditor\n value={editedValue}\n onChange={setEditedValue}\n onBlur={onBlur}\n onFocus={onFocus}\n previewOptions={{\n rehypePlugins: [[rehypeSanitize]],\n }}\n preview=\"edit\"\n />\n )}\n </div>\n )\n})\n","import {useState, useEffect} from 'react'\n\nexport default function useDebounce(value: unknown, delay: number) {\n const [debouncedValue, setDebouncedValue] = useState(value)\n useEffect(() => {\n const handler = setTimeout(() => {\n setDebouncedValue(value)\n }, delay)\n\n return () => clearTimeout(handler)\n }, [value, delay])\n\n return debouncedValue\n}\n","import {defineType, StringDefinition} from 'sanity'\nimport {MarkdownEditor} from './components/Editor'\n\nconst markdownTypeName = 'markdown' as const\n\n/**\n * @public\n */\nexport interface MarkdownDefinition extends Omit<StringDefinition, 'type' | 'fields' | 'options'> {\n type: typeof markdownTypeName\n}\n\ndeclare module '@sanity/types' {\n // makes type: 'markdown' narrow correctly when using defineType/defineField/defineArrayMember\n export interface IntrinsicDefinitions {\n markdown: MarkdownDefinition\n }\n}\n\nexport const markdownSchemaType = defineType({\n type: 'string',\n name: markdownTypeName,\n title: 'Markdown',\n ...({components: {input: MarkdownEditor}} as {}), //TODO revert when rc.1 ships\n})\n","import {MarkdownEditor as Editor} from './components/Editor'\nimport {definePlugin} from 'sanity'\nimport {markdownSchemaType, MarkdownDefinition} from './schema'\n\n// re-exporting MarkdownEditor directly explodes @parcel/transformer-typescript-types :shrug:\nconst MarkdownEditor = Editor\n\nexport {MarkdownEditor, markdownSchemaType}\nexport type {MarkdownDefinition}\n\nexport const markdownSchema = definePlugin({\n name: 'markdown-editor',\n schema: {\n types: [markdownSchemaType],\n },\n})\n"],"names":["MarkdownEditor","forwardRef","props","ref","value","onChange","elementProps","onBlur","onFocus","readOnly","editedValue","setEditedValue","useState","debouncedValue","delay","setDebouncedValue","useEffect","handler","setTimeout","clearTimeout","useDebounce","PatchEvent","from","unset","set","sanity","studioTheme","useTheme","jsx","color","dark","children","Card","border","padding","MDEditor","Markdown","source","rehypePlugins","rehypeSanitize","previewOptions","preview","markdownSchemaType","defineType","_objectSpread","type","name","title","components","input","Editor","markdownSchema","definePlugin","schema","types"],"mappings":"qpBAOO,MAAMA,EAAiBC,EAAAA,YAAW,SACvCC,EACAC,GAEM,MAAAC,MACJA,EAAQ,GAAAC,SACRA,EACAC,cAAcC,OAACA,EAAAC,QAAQA,GAAOC,SAC9BA,GACEP,GACGQ,EAAaC,GAAkBC,WAA6BR,GAC7DS,EChBgB,SAAYT,EAAgBU,GAClD,MAAOD,EAAgBE,GAAqBH,WAASR,GAS9C,OARPY,EAAAA,WAAU,KACF,MAAAC,EAAUC,YAAW,KACzBH,EAAkBX,EAAK,GACtBU,GAEI,MAAA,IAAMK,aAAaF,EAAO,GAChC,CAACb,EAAOU,IAEJD,CACT,CDKyBO,CAAYV,EAAa,KAGhDM,EAAAA,WAAU,KACRL,EAAeP,EAAK,GACnB,CAACA,IAEJY,EAAAA,WAAU,MACHH,GAAkBT,EACrBC,EAASgB,aAAWC,KAAK,CAACC,EAAAA,WACjBV,IAAmBT,GAC5BC,EAASgB,aAAWC,KAAK,CAACE,MAAIX,KAChC,GAEC,CAACA,EAAgBR,IAiBpB,MAAOoB,OAAQC,GAAeC,EAASA,WACvC,OACGC,EAAAA,IAAA,MAAA,CAAIzB,MAAU,kBAAiBuB,EAAYG,MAAMC,KAAO,OAAS,QAC/DC,WACEH,EAAAA,IAAAI,OAAA,CAAKC,QAAM,EAACC,QAAS,EACpBH,SAAAH,EAAAA,IAACO,UAASC,SAAT,CAAkBC,OAAQjC,EAAOkC,cAAe,CAAC,CAACC,EAAAA,cAGpDX,EAAAA,IAAAO,UAAA,CACC/B,MAAOM,EACPL,SAAUM,EACVJ,SACAC,UACAgC,eAAgB,CACdF,cAAe,CAAC,CAACC,EAAAA,WAEnBE,QAAQ,UAKlB,IEnDaC,EAAqBC,EAAAA,0WAAWC,CAAA,CAC3CC,KAAM,SACNC,KAlBuB,WAmBvBC,MAAO,YACH,CAACC,WAAY,CAACC,MAAOjD,MClBrBA,EAAiBkD,EAKVC,EAAiBC,EAAAA,aAAa,CACzCN,KAAM,kBACNO,OAAQ,CACNC,MAAO,CAACZ"}
1
+ {"version":3,"file":"index.js","sources":["../src/components/Editor.tsx","../src/hooks/useDebounce.ts","../src/schema.ts","../src/index.ts"],"sourcesContent":["import MDEditor from '@uiw/react-md-editor'\nimport useDebounce from '../hooks/useDebounce'\nimport {PatchEvent, SanityClient, set, StringInputProps, unset, useClient} from 'sanity'\nimport React, {\n ClipboardEvent,\n forwardRef,\n Ref,\n SetStateAction,\n useCallback,\n useEffect,\n useState,\n DragEvent,\n} from 'react'\nimport {Card, useTheme} from '@sanity/ui'\nimport rehypeSanitize from 'rehype-sanitize'\n\nexport const MarkdownEditor = forwardRef(function MarkdownEditor(\n props: StringInputProps,\n ref: Ref<any>\n) {\n const {\n value = '',\n onChange,\n elementProps: {onBlur, onFocus},\n readOnly,\n } = props\n const [editedValue, setEditedValue] = useState<string | undefined>(value)\n const debouncedValue = useDebounce(editedValue, 100)\n // const client = useClient({apiVersion: '2021-03-25'})\n const client = useClient({apiVersion: '2022-01-01'})\n useEffect(() => {\n setEditedValue(value)\n }, [value])\n\n useEffect(() => {\n if (!debouncedValue && value) {\n onChange(PatchEvent.from([unset()]))\n } else if (debouncedValue !== value) {\n onChange(PatchEvent.from([set(debouncedValue)]))\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [debouncedValue, onChange])\n\n const {sanity: studioTheme} = useTheme()\n const onPaste = useCallback(\n async (event: ClipboardEvent<HTMLDivElement>) => {\n await onImagePasted(event.clipboardData, setEditedValue, client)\n },\n [setEditedValue, client]\n )\n\n const onDrop = useCallback(\n async (event: DragEvent<HTMLDivElement>) => {\n event.preventDefault()\n event.stopPropagation()\n if (event.dataTransfer) {\n await onImagePasted(event.dataTransfer, setEditedValue, client)\n }\n },\n [setEditedValue, client]\n )\n\n return (\n <div ref={ref} data-color-mode={studioTheme.color.dark ? 'dark' : 'light'}>\n {readOnly ? (\n <Card border padding={3}>\n <MDEditor.Markdown source={value} rehypePlugins={[[rehypeSanitize]]} />\n </Card>\n ) : (\n <MDEditor\n value={editedValue}\n onChange={setEditedValue}\n onBlur={onBlur}\n onFocus={onFocus}\n previewOptions={{\n rehypePlugins: [[rehypeSanitize]],\n }}\n preview=\"edit\"\n onPaste={onPaste}\n onDrop={onDrop}\n />\n )}\n </div>\n )\n})\n\n// https://github.com/uiwjs/react-md-editor/issues/83#issuecomment-1185471844\nasync function onImagePasted(\n dataTransfer: DataTransfer,\n setMarkdown: (value: SetStateAction<string | undefined>) => void,\n client: SanityClient\n) {\n const files: File[] = []\n for (let index = 0; index < dataTransfer.items.length; index += 1) {\n const file = dataTransfer.files.item(index)\n\n if (file) {\n files.push(file)\n }\n }\n\n await Promise.all(\n files.map(async (file) => {\n const url = await client.assets.upload('image', file).then((doc) => `${doc.url}?w=450`)\n const insertedMarkdown = insertToTextArea(`![](${url})`)\n if (!insertedMarkdown) {\n return\n }\n setMarkdown(insertedMarkdown)\n })\n )\n}\n\nfunction insertToTextArea(insertString: string) {\n const textarea = document.querySelector('textarea')\n if (!textarea) {\n return null\n }\n\n let sentence = textarea.value\n const len = sentence.length\n const pos = textarea.selectionStart\n const end = textarea.selectionEnd\n\n const front = sentence.slice(0, pos)\n const back = sentence.slice(pos, len)\n\n sentence = front + insertString + back\n\n textarea.value = sentence\n textarea.selectionEnd = end + insertString.length\n\n return sentence\n}\n","import {useState, useEffect} from 'react'\n\nexport default function useDebounce(value: unknown, delay: number) {\n const [debouncedValue, setDebouncedValue] = useState(value)\n useEffect(() => {\n const handler = setTimeout(() => {\n setDebouncedValue(value)\n }, delay)\n\n return () => clearTimeout(handler)\n }, [value, delay])\n\n return debouncedValue\n}\n","import {defineType, StringDefinition} from 'sanity'\nimport {MarkdownEditor} from './components/Editor'\n\nconst markdownTypeName = 'markdown' as const\n\n/**\n * @public\n */\nexport interface MarkdownDefinition extends Omit<StringDefinition, 'type' | 'fields' | 'options'> {\n type: typeof markdownTypeName\n}\n\ndeclare module '@sanity/types' {\n // makes type: 'markdown' narrow correctly when using defineType/defineField/defineArrayMember\n export interface IntrinsicDefinitions {\n markdown: MarkdownDefinition\n }\n}\n\nexport const markdownSchemaType = defineType({\n type: 'string',\n name: markdownTypeName,\n title: 'Markdown',\n ...({components: {input: MarkdownEditor}} as {}), //TODO revert when rc.1 ships\n})\n","import {MarkdownEditor as Editor} from './components/Editor'\nimport {definePlugin} from 'sanity'\nimport {markdownSchemaType, MarkdownDefinition} from './schema'\n\n// re-exporting MarkdownEditor directly explodes @parcel/transformer-typescript-types :shrug:\nconst MarkdownEditor = Editor\n\nexport {MarkdownEditor, markdownSchemaType}\nexport type {MarkdownDefinition}\n\nexport const markdownSchema = definePlugin({\n name: 'markdown-editor',\n schema: {\n types: [markdownSchemaType],\n },\n})\n"],"names":["MarkdownEditor","forwardRef","props","ref","value","onChange","elementProps","onBlur","onFocus","readOnly","editedValue","setEditedValue","useState","debouncedValue","delay","setDebouncedValue","useEffect","handler","setTimeout","clearTimeout","useDebounce","client","useClient","apiVersion","PatchEvent","from","unset","set","sanity","studioTheme","useTheme","onPaste","useCallback","async","onImagePasted","event","clipboardData","onDrop","preventDefault","stopPropagation","dataTransfer","jsx","color","dark","children","Card","border","padding","MDEditor","Markdown","source","rehypePlugins","rehypeSanitize","previewOptions","preview","setMarkdown","files","index","items","length","file","item","push","Promise","all","map","url","assets","upload","then","doc","insertedMarkdown","insertString","textarea","document","querySelector","sentence","len","pos","selectionStart","end","selectionEnd","front","slice","back","insertToTextArea","concat","markdownSchemaType","defineType","_objectSpread","type","name","title","components","input","Editor","markdownSchema","definePlugin","schema","types"],"mappings":"qpBAgBO,MAAMA,EAAiBC,EAAAA,YAAW,SACvCC,EACAC,GAEM,MAAAC,MACJA,EAAQ,GAAAC,SACRA,EACAC,cAAcC,OAACA,EAAAC,QAAQA,GAAOC,SAC9BA,GACEP,GACGQ,EAAaC,GAAkBC,WAA6BR,GAC7DS,ECzBgB,SAAYT,EAAgBU,GAClD,MAAOD,EAAgBE,GAAqBH,WAASR,GAS9C,OARPY,EAAAA,WAAU,KACF,MAAAC,EAAUC,YAAW,KACzBH,EAAkBX,EAAK,GACtBU,GAEI,MAAA,IAAMK,aAAaF,EAAO,GAChC,CAACb,EAAOU,IAEJD,CACT,CDcyBO,CAAYV,EAAa,KAE1CW,EAASC,EAAAA,UAAU,CAACC,WAAY,eACtCP,EAAAA,WAAU,KACRL,EAAeP,EAAK,GACnB,CAACA,IAEJY,EAAAA,WAAU,MACHH,GAAkBT,EACrBC,EAASmB,aAAWC,KAAK,CAACC,EAAAA,WACjBb,IAAmBT,GAC5BC,EAASmB,aAAWC,KAAK,CAACE,MAAId,KAChC,GAEC,CAACA,EAAgBR,IAEpB,MAAOuB,OAAQC,GAAeC,EAASA,WACjCC,EAAUC,EAAAA,aACdC,gBACQC,EAAcC,EAAMC,cAAezB,EAAgBU,EAAM,GAEjE,CAACV,EAAgBU,IAGbgB,EAASL,EAAAA,aACbC,UACEE,EAAMG,iBACNH,EAAMI,kBACFJ,EAAMK,oBACFN,EAAcC,EAAMK,aAAc7B,EAAgBU,EAC1D,GAEF,CAACV,EAAgBU,IAGnB,OACGoB,EAAAA,IAAA,MAAA,CAAItC,MAAU,kBAAiB0B,EAAYa,MAAMC,KAAO,OAAS,QAC/DC,WACEH,EAAAA,IAAAI,OAAA,CAAKC,QAAM,EAACC,QAAS,EACpBH,SAAAH,EAAAA,IAACO,UAASC,SAAT,CAAkBC,OAAQ9C,EAAO+C,cAAe,CAAC,CAACC,EAAAA,cAGpDX,EAAAA,IAAAO,UAAA,CACC5C,MAAOM,EACPL,SAAUM,EACVJ,SACAC,UACA6C,eAAgB,CACdF,cAAe,CAAC,CAACC,EAAAA,WAEnBE,QAAQ,OACRvB,UACAM,YAKV,IAGAJ,eAAeC,EACbM,EACAe,EACAlC,GAEA,MAAMmC,EAAgB,GACtB,IAAA,IAASC,EAAQ,EAAGA,EAAQjB,EAAakB,MAAMC,OAAQF,GAAS,EAAG,CACjE,MAAMG,EAAOpB,EAAagB,MAAMK,KAAKJ,GAEjCG,GACFJ,EAAMM,KAAKF,EAEf,OAEMG,QAAQC,IACZR,EAAMS,KAAIhC,UACR,MAAMiC,QAAY7C,EAAO8C,OAAOC,OAAO,QAASR,GAAMS,MAAMC,aAAWA,EAAIJ,IAAW,YAChFK,EASZ,SAA0BC,GAClB,MAAAC,EAAWC,SAASC,cAAc,YACxC,IAAKF,EACI,OAAA,KAGT,IAAIG,EAAWH,EAASrE,MACxB,MAAMyE,EAAMD,EAASjB,OACfmB,EAAML,EAASM,eACfC,EAAMP,EAASQ,aAEfC,EAAQN,EAASO,MAAM,EAAGL,GAC1BM,EAAOR,EAASO,MAAML,EAAKD,GAO1B,OALPD,EAAWM,EAAQV,EAAeY,EAElCX,EAASrE,MAAQwE,EACRH,EAAAQ,aAAeD,EAAMR,EAAab,OAEpCiB,CACT,CA7B+BS,CAAiB,OAAAC,OAAOpB,EAAM,MAClDK,GAGLhB,EAAYgB,EAAgB,IAGlC,CE5GA,MAgBagB,EAAqBC,EAAAA,0WAAWC,CAAA,CAC3CC,KAAM,SACNC,KAlBuB,WAmBvBC,MAAO,YACH,CAACC,WAAY,CAACC,MAAO9F,MClBrBA,EAAiB+F,EAKVC,EAAiBC,EAAAA,aAAa,CACzCN,KAAM,kBACNO,OAAQ,CACNC,MAAO,CAACZ"}
@@ -31,7 +31,7 @@ declare const markdownTypeName: 'markdown'
31
31
  export {}
32
32
 
33
33
  declare module '@sanity/types' {
34
- interface IntrinsicDefinitions {
35
- markdown: MarkdownDefinition;
36
- }
37
- }
34
+ interface IntrinsicDefinitions {
35
+ markdown: MarkdownDefinition
36
+ }
37
+ }
package/package.json CHANGED
@@ -1,25 +1,24 @@
1
1
  {
2
2
  "name": "sanity-plugin-markdown",
3
- "version": "3.0.0-v3-studio.6",
3
+ "version": "3.0.0",
4
4
  "description": "Markdown fields in Sanity Studio. Supports Github flavored Markdown and image uploads.",
5
- "author": "Sanity.io <hello@sanity.io>",
6
- "license": "MIT",
7
- "scripts": {
8
- "clean": "rimraf lib",
9
- "prebuild": "npm run clean && plugin-kit verify-package --silent && pkg-utils",
10
- "build": "pkg-utils build",
11
- "watch": "pkg-utils watch",
12
- "link-watch": "plugin-kit link-watch",
13
- "lint": "eslint .",
14
- "format": "prettier src -w",
15
- "prepare": "husky install",
16
- "compile": "tsc --noEmit",
17
- "prepublishOnly": " npm run build"
5
+ "keywords": [
6
+ "sanity",
7
+ "sanity-plugin",
8
+ "studio",
9
+ "markdown",
10
+ "github flavored markdown"
11
+ ],
12
+ "homepage": "https://github.com/sanity-io/sanity-plugin-markdown#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/sanity-io/sanity-plugin-markdown/issues"
18
15
  },
19
- "source": "./src/index.ts",
20
- "main": "./lib/index.js",
21
- "module": "./lib/index.esm.js",
22
- "types": "./lib/src/index.d.ts",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/sanity-io/sanity-plugin-markdown.git"
19
+ },
20
+ "license": "MIT",
21
+ "author": "Sanity.io <hello@sanity.io>",
23
22
  "exports": {
24
23
  ".": {
25
24
  "types": "./lib/src/index.d.ts",
@@ -27,33 +26,42 @@
27
26
  "import": "./lib/index.esm.js",
28
27
  "require": "./lib/index.js",
29
28
  "default": "./lib/index.esm.js"
30
- }
29
+ },
30
+ "./package.json": "./package.json"
31
31
  },
32
+ "main": "./lib/index.js",
33
+ "module": "./lib/index.esm.js",
34
+ "source": "./src/index.ts",
35
+ "types": "./lib/src/index.d.ts",
32
36
  "files": [
33
37
  "src",
34
38
  "lib",
35
39
  "v2-incompatible.js",
36
40
  "sanity.json"
37
41
  ],
38
- "keywords": [
39
- "sanity",
40
- "sanity-plugin",
41
- "studio",
42
- "markdown",
43
- "github flavored markdown"
44
- ],
42
+ "scripts": {
43
+ "prebuild": "npm run clean && plugin-kit verify-package --silent && pkg-utils",
44
+ "build": "pkg-utils build --strict",
45
+ "clean": "rimraf lib",
46
+ "compile": "tsc --noEmit",
47
+ "format": "prettier src -w",
48
+ "link-watch": "plugin-kit link-watch",
49
+ "lint": "eslint .",
50
+ "prepare": "husky install",
51
+ "prepublishOnly": " npm run build",
52
+ "watch": "pkg-utils watch"
53
+ },
45
54
  "dependencies": {
46
- "@reach/auto-id": "^0.17.0",
47
55
  "@sanity/incompatible-plugin": "^1.0.4",
48
56
  "@sanity/ui": "1.0.0-beta.32",
49
- "@uiw/react-md-editor": "^3.18.1",
57
+ "@uiw/react-md-editor": "^3.19.7",
50
58
  "rehype-sanitize": "^5.0.1"
51
59
  },
52
60
  "devDependencies": {
53
61
  "@commitlint/cli": "^17.2.0",
54
62
  "@commitlint/config-conventional": "^17.2.0",
55
- "@sanity/pkg-utils": "^1.16.2",
56
- "@sanity/plugin-kit": "^2.0.9",
63
+ "@sanity/pkg-utils": "^1.18.0",
64
+ "@sanity/plugin-kit": "^2.1.16",
57
65
  "@sanity/semantic-release-preset": "^2.0.2",
58
66
  "@types/styled-components": "^5.1.26",
59
67
  "@typescript-eslint/eslint-plugin": "^5.42.0",
@@ -67,27 +75,20 @@
67
75
  "husky": "^8.0.1",
68
76
  "lint-staged": "^13.0.3",
69
77
  "prettier": "^2.7.1",
70
- "react": "^18.2.0",
78
+ "prettier-plugin-packagejson": "^2.3.0",
79
+ "react": "^18",
71
80
  "rimraf": "^3.0.2",
72
- "sanity": "3.0.0-rc.0",
81
+ "sanity": "3.0.0-rc.2",
73
82
  "styled-components": "^5.3.6",
74
83
  "typescript": "^4.8.4"
75
84
  },
76
85
  "peerDependencies": {
77
86
  "react": "^18",
78
- "sanity": "dev-preview || 3.0.0-rc.0",
87
+ "sanity": "dev-preview || 3.0.0-rc.2",
79
88
  "styled-components": "^5.2"
80
89
  },
81
- "repository": {
82
- "type": "git",
83
- "url": "https://github.com/sanity-io/sanity-plugin-markdown.git"
84
- },
85
- "bugs": {
86
- "url": "https://github.com/sanity-io/sanity-plugin-markdown/issues"
87
- },
88
- "homepage": "https://github.com/sanity-io/sanity-plugin-markdown#readme",
89
- "sanityExchangeUrl": "https://www.sanity.io/plugins/sanity-plugin-markdown",
90
90
  "engines": {
91
- "node": ">=14.0.0"
92
- }
91
+ "node": ">=14"
92
+ },
93
+ "sanityExchangeUrl": "https://www.sanity.io/plugins/sanity-plugin-markdown"
93
94
  }
@@ -1,7 +1,16 @@
1
1
  import MDEditor from '@uiw/react-md-editor'
2
2
  import useDebounce from '../hooks/useDebounce'
3
- import {StringInputProps, PatchEvent, set, unset} from 'sanity'
4
- import React, {forwardRef, Ref, useEffect, useState} from 'react'
3
+ import {PatchEvent, SanityClient, set, StringInputProps, unset, useClient} from 'sanity'
4
+ import React, {
5
+ ClipboardEvent,
6
+ forwardRef,
7
+ Ref,
8
+ SetStateAction,
9
+ useCallback,
10
+ useEffect,
11
+ useState,
12
+ DragEvent,
13
+ } from 'react'
5
14
  import {Card, useTheme} from '@sanity/ui'
6
15
  import rehypeSanitize from 'rehype-sanitize'
7
16
 
@@ -18,7 +27,7 @@ export const MarkdownEditor = forwardRef(function MarkdownEditor(
18
27
  const [editedValue, setEditedValue] = useState<string | undefined>(value)
19
28
  const debouncedValue = useDebounce(editedValue, 100)
20
29
  // const client = useClient({apiVersion: '2021-03-25'})
21
-
30
+ const client = useClient({apiVersion: '2022-01-01'})
22
31
  useEffect(() => {
23
32
  setEditedValue(value)
24
33
  }, [value])
@@ -32,22 +41,25 @@ export const MarkdownEditor = forwardRef(function MarkdownEditor(
32
41
  // eslint-disable-next-line react-hooks/exhaustive-deps
33
42
  }, [debouncedValue, onChange])
34
43
 
35
- /* const saveImage = async function* (data: any) {
36
-
37
- let success = true
38
- const result = await client.assets
39
- .upload('image', data)
40
- .then((doc) => `${doc.url}?w=450`)
41
- .catch(() => {
42
- success = false
43
- return `Error: Could not upload file. Only images are supported.`
44
- })
44
+ const {sanity: studioTheme} = useTheme()
45
+ const onPaste = useCallback(
46
+ async (event: ClipboardEvent<HTMLDivElement>) => {
47
+ await onImagePasted(event.clipboardData, setEditedValue, client)
48
+ },
49
+ [setEditedValue, client]
50
+ )
45
51
 
46
- yield result
47
- return success
48
- }*/
52
+ const onDrop = useCallback(
53
+ async (event: DragEvent<HTMLDivElement>) => {
54
+ event.preventDefault()
55
+ event.stopPropagation()
56
+ if (event.dataTransfer) {
57
+ await onImagePasted(event.dataTransfer, setEditedValue, client)
58
+ }
59
+ },
60
+ [setEditedValue, client]
61
+ )
49
62
 
50
- const {sanity: studioTheme} = useTheme()
51
63
  return (
52
64
  <div ref={ref} data-color-mode={studioTheme.color.dark ? 'dark' : 'light'}>
53
65
  {readOnly ? (
@@ -64,8 +76,59 @@ export const MarkdownEditor = forwardRef(function MarkdownEditor(
64
76
  rehypePlugins: [[rehypeSanitize]],
65
77
  }}
66
78
  preview="edit"
79
+ onPaste={onPaste}
80
+ onDrop={onDrop}
67
81
  />
68
82
  )}
69
83
  </div>
70
84
  )
71
85
  })
86
+
87
+ // https://github.com/uiwjs/react-md-editor/issues/83#issuecomment-1185471844
88
+ async function onImagePasted(
89
+ dataTransfer: DataTransfer,
90
+ setMarkdown: (value: SetStateAction<string | undefined>) => void,
91
+ client: SanityClient
92
+ ) {
93
+ const files: File[] = []
94
+ for (let index = 0; index < dataTransfer.items.length; index += 1) {
95
+ const file = dataTransfer.files.item(index)
96
+
97
+ if (file) {
98
+ files.push(file)
99
+ }
100
+ }
101
+
102
+ await Promise.all(
103
+ files.map(async (file) => {
104
+ const url = await client.assets.upload('image', file).then((doc) => `${doc.url}?w=450`)
105
+ const insertedMarkdown = insertToTextArea(`![](${url})`)
106
+ if (!insertedMarkdown) {
107
+ return
108
+ }
109
+ setMarkdown(insertedMarkdown)
110
+ })
111
+ )
112
+ }
113
+
114
+ function insertToTextArea(insertString: string) {
115
+ const textarea = document.querySelector('textarea')
116
+ if (!textarea) {
117
+ return null
118
+ }
119
+
120
+ let sentence = textarea.value
121
+ const len = sentence.length
122
+ const pos = textarea.selectionStart
123
+ const end = textarea.selectionEnd
124
+
125
+ const front = sentence.slice(0, pos)
126
+ const back = sentence.slice(pos, len)
127
+
128
+ sentence = front + insertString + back
129
+
130
+ textarea.value = sentence
131
+ textarea.selectionEnd = end + insertString.length
132
+
133
+ return sentence
134
+ }