@sanity/dashboard 3.0.0-v3-studio.5 → 3.0.0-v3-studio.7

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2022 - 2022 Sanity.io
3
+ Copyright (c) 2022 Sanity.io
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## Installation
2
+
3
+ ```
4
+ npm install --save @sanity/dashboard@studio-v3
5
+ ```
6
+
7
+ or
8
+
9
+ ```
10
+ yarn add @sanity/dashboard@studio-v3
11
+ ```
12
+
13
+ ## Usage
14
+
1
15
  # Sanity Dashboard
2
16
 
3
17
  > **NOTE**
@@ -27,12 +41,12 @@ or
27
41
  `yarn add @sanity/dashboard@studio-v3`
28
42
 
29
43
  ## Basic usage
30
- In `sanity.config.js` (or .ts), add the dashboard tool to the createConfig plugins array:
44
+ In `sanity.config.js` (or .ts), add the dashboard tool to the defineConfig plugins array:
31
45
 
32
46
  ```ts
33
- import { createConfig } from "sanity";
47
+ import { defineConfig } from "sanity";
34
48
  import { dashboardTool } from "@sanity/dashboard";
35
- export default createConfig({
49
+ export default defineConfig({
36
50
  /* ... */
37
51
  plugins: [
38
52
  dashboardTool({ widgets: []})
@@ -48,7 +62,7 @@ It should show an empty dashboard, with a message encouraging you to add some wi
48
62
  Now, add any widgets you might want. The dashboard plugin provides three widgets out-of-the-box:
49
63
 
50
64
  ```ts
51
- import { createConfig } from "sanity";
65
+ import { defineConfig } from "sanity";
52
66
  import {
53
67
  dashboardTool,
54
68
  sanityTutorialsWidget,
@@ -188,3 +202,23 @@ Make sure to select the main branch and check "Release new version".
188
202
 
189
203
  Semantic release will only release on configured branches, so it is safe to run release on any branch.
190
204
 
205
+
206
+
207
+ ## License
208
+
209
+ MIT-licensed. See LICENSE.
210
+
211
+ ## Develop & test
212
+
213
+ This plugin uses [@sanity/plugin-kit](https://github.com/sanity-io/plugin-kit)
214
+ with default configuration for build & watch scripts.
215
+
216
+ See [Testing a plugin in Sanity Studio](https://github.com/sanity-io/plugin-kit#testing-a-plugin-in-sanity-studio)
217
+ on how to run this plugin with hotreload in the studio.
218
+
219
+ ### Release new version
220
+
221
+ Run ["CI & Release" workflow](https://github.com/sanity-io/dashboard/actions/workflows/main.yml).
222
+ Make sure to select the main branch and check "Release new version".
223
+
224
+ Semantic release will only release on configured branches, so it is safe to run release on any branch.
@@ -0,0 +1,2 @@
1
+ var e,n,t,r,i,o,a,l,d,s,c,u,h,p,g,m,f,b,y,w;function v(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function j(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?v(Object(t),!0).forEach((function(n){x(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):v(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function x(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function O(e,n){return n||(n=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(n)}}))}import{jsxs as k,jsx as z,Fragment as P}from"react/jsx-runtime";import{forwardRef as _,createContext as S,useContext as R,useMemo as I,createElement as L,useState as q,useEffect as A,useCallback as E}from"react";import{Card as Y,Box as B,Heading as D,Button as H,Stack as M,Label as T,Grid as V,Text as X,Code as N,Spinner as U,Flex as C,Container as F}from"@sanity/ui";import G,{css as Q}from"styled-components";import{useClient as W,useUserStore as Z,DefaultPreview as J,definePlugin as K}from"sanity";import{from as $}from"rxjs";import{switchMap as ee,map as ne}from"rxjs/operators";import{RobotIcon as te,PlayIcon as re}from"@sanity/icons";import ie from"@sanity/image-url";const oe=G(Y)(e||(e=O(["\n display: flex;\n flex-direction: column;\n justify-content: stretch;\n height: 100%;\n box-sizing: border-box;\n position: relative;\n"]))),ae=G(Y)(n||(n=O(["\n position: sticky;\n top: 0;\n z-index: 2;\n border-top-left-radius: inherit;\n border-top-right-radius: inherit;\n"]))),le=G(Y)(t||(t=O(["\n position: sticky;\n overflow: hidden;\n bottom: 0;\n z-index: 2;\n border-bottom-right-radius: inherit;\n border-bottom-left-radius: inherit;\n margin-top: auto;\n"]))),de=G(B)(r||(r=O(["\n position: relative;\n z-index: 1;\n height: stretch;\n min-height: 21.5em;\n\n @media (min-width: ","px) {\n overflow-y: auto;\n outline: none;\n }\n"])),(e=>{let{theme:n}=e;return n.sanity.media[0]})),se=_((function(e,n){const{header:t,children:r,footer:i}=e;return k(oe,{radius:3,display:"flex",ref:n,children:[t&&z(ae,{borderBottom:!0,paddingX:3,paddingY:4,children:z(D,{size:1,textOverflow:"ellipsis",children:t})}),r&&z(de,{children:r}),i&&z(le,{borderTop:!0,children:i})]})}));function ce(){return W({apiVersion:"1"})}const ue=S({widgets:[]});function he(e){const n=R(ue),t=I((()=>j(j({},e.layout||{}),n.layout||{})),[e.layout,n.layout]);return z(Y,{shadow:1,"data-width":t.width,"data-height":t.height,children:L(e.component,{})})}function pe(e,n){return"https://".concat(e,".api.sanity.io/v1/groq/").concat(n)}function ge(e){return"https://manage.sanity.io/projects/".concat(e)}const me=[],fe=[];function be(e){const{__experimental_before:n=me,data:t=fe}=e,[r,i]=q(),[o,a]=q(),l=ce(),{projectId:d="unknown",dataset:s="unknown"}=l.config();A((()=>{const e=[];return e.push(l.observable.request({uri:"/projects/".concat(d)}).subscribe({next:e=>{const{studioHost:n}=e;i(n?"https://".concat(n,".sanity.studio"):void 0)},error:e=>{console.error("Error while looking for studioHost",e),i({error:"Something went wrong while looking up studioHost. See console."})}})),e.push(l.observable.request({method:"HEAD",uri:"/graphql/".concat(s,"/default")}).subscribe({next:()=>a(function(e,n){return"https://".concat(e,".api.sanity.io/v1/graphql/").concat(n,"/default")}(d,s)),error:e=>{404===e.statusCode?a(void 0):(console.error("Error while looking for graphqlApi",e),a({error:"Something went wrong while looking up graphqlApi. See console."}))}})),()=>{e.forEach((e=>e.unsubscribe()))}}),[s,d,l,a,i]);const c=I((()=>{var e;let n=[{title:"Sanity project",rows:[{title:"Project ID",value:d},{title:"Dataset",value:s}]}];const i=[r?{title:"Studio",value:r}:null,...t.filter((e=>"apps"===e.category))].filter((e=>!!e));i.length>0&&(n=n.concat([{title:"Apps",rows:i}])),n=n.concat([{title:"APIs",rows:[{title:"GROQ",value:pe(d,s)},{title:"GraphQL",value:null!=(e="object"==typeof o?"Error":o)?e:"Not deployed"}]}],t.filter((e=>"apis"===e.category)));const a={};return t.forEach((e=>{e.category&&"apps"!==e.category&&"apis"!==e.category&&(a[e.category]||(a[e.category]=[]),a[e.category].push(e))})),Object.keys(a).forEach((e=>{n.push({title:e,rows:a[e]})})),n}),[o,r,d,s,t]);return k(P,{children:[n.map(((e,n)=>z(he,j({},e),n))),z(B,{height:"fill",marginTop:(null==n?void 0:n.length)>0?4:0,children:z(se,{footer:z(H,{style:{width:"100%"},paddingX:2,paddingY:4,mode:"bleed",tone:"primary",text:"Manage project",as:"a",href:ge(d)}),children:z(Y,{paddingY:4,radius:2,role:"table","aria-label":"Project info","aria-describedby":"project_info_table",children:k(M,{space:4,children:[z(B,{paddingX:3,as:"header",children:z(D,{size:1,as:"h2",id:"project_info_table",children:"Project info"})}),c.map((e=>e&&e.rows?k(M,{space:3,children:[z(Y,{borderBottom:!0,padding:3,children:z(T,{size:0,muted:!0,role:"columnheader",children:e.title})}),z(M,{space:4,paddingX:3,role:"rowgroup",children:e.rows.map((e=>{var n,t;return k(V,{columns:2,role:"row",children:[z(X,{weight:"medium",role:"rowheader",children:e.title}),"object"==typeof e.value&&z(X,{size:1,children:null==(n=e.value)?void 0:n.error}),"string"==typeof e.value&&z(P,{children:(t=e.value,t&&/^https?:\/\//.test("".concat(t))?z(X,{size:1,role:"cell",style:{wordBreak:"break-word"},children:z("a",{href:e.value,children:e.value})}):z(N,{size:1,role:"cell",style:{wordBreak:"break-word"},children:e.value}))})]},e.title)}))})]},e.title):null))]})})})})]})}function ye(e){var n;return{name:"project-info",component:be,layout:null!=(n=null==e?void 0:e.layout)?n:{width:"medium"}}}const we=G(Y)(i||(i=O(["\n box-sizing: border-box;\n border-radius: 50%;\n border-color: transparent;\n overflow: hidden;\n width: 100%;\n height: 100%;\n\n & > img {\n width: 100%;\n height: auto;\n }\n"])));function ve(){const[e,n]=q(),[t,r]=q(),[i,o]=q(),a=Z(),l=ce(),d=E((()=>{const{projectId:e}=l.config(),t=l.observable.request({uri:"/projects/".concat(e)}).pipe(ee((e=>$(a.getUsers(e.members.map((e=>e.id)))).pipe(ne((n=>({project:e,users:n}))))))).subscribe({next:e=>{let{users:t,project:i}=e;n(i),r((Array.isArray(t)?t:[t]).sort(((e,n)=>function(e,n,t){const{members:r}=t,i=r.find((n=>n.id===(null==e?void 0:e.id))),o=r.find((e=>e.id===(null==n?void 0:n.id)));if(null==i?void 0:i.isRobot)return 1;if(null==o?void 0:o.isRobot)return-1;return 0}(e,n,i))))},error:e=>o(e)});return()=>t.unsubscribe()}),[a,l]);A((()=>d()),[d]);const s=E((()=>d()),[d]),c=!t||!e;return i?z(se,{header:"Project users",children:z(B,{padding:4,children:k(X,{children:["Something went wrong while fetching data. You could"," ",z("a",{onClick:s,title:"Retry users fetch",style:{cursor:"pointer"},children:"retry"}),"..?"]})})}):k(se,{header:"Project users",footer:z(H,{style:{width:"100%"},paddingX:2,paddingY:4,mode:"bleed",tone:"primary",text:"Invite members",as:"a",loading:c,href:c?void 0:(u=e.id,"https://manage.sanity.io/projects/".concat(u,"/team/invite"))}),children:[c&&z(B,{paddingY:5,paddingX:2,children:k(M,{space:4,children:[z(X,{align:"center",muted:!0,size:1,children:z(U,{})}),z(X,{align:"center",size:1,muted:!0,children:"Loading items..."})]})}),!c&&z(M,{space:3,padding:3,children:null==t?void 0:t.map((n=>{const t=e.members.find((e=>e.id===n.id)),r=(null==t?void 0:t.isRobot)?z(X,{size:3,children:z(te,{})}):z(we,{tone:"transparent",children:(null==n?void 0:n.imageUrl)&&z("img",{src:n.imageUrl,alt:null==n?void 0:n.displayName})});return z(B,{children:z(J,{title:n.displayName,subtitle:null==t?void 0:t.role,media:r})},n.id)}))})]});var u}function je(e){return{name:"project-info",component:ve,layout:null==e?void 0:e.layout}}const xe=G(B)(o||(o=O(["\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n\n &:before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 2.75em;\n height: 2.75em;\n border-radius: 50%;\n background: ",";\n opacity: 0.75;\n }\n"])),(e=>{let{theme:n}=e;return n.sanity.color.card.enabled.bg})),Oe=G(C)(a||(a=O(["\n &:hover {\n "," {\n &:before {\n opacity: 1;\n }\n }\n }\n"])),xe),ke=G(Y)(l||(l=O(["\n width: 100%;\n padding-bottom: calc(9 / 16 * 100%);\n position: relative;\n"]))),ze=G.img(d||(d=O(["\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n width: 100%;\n object-fit: cover;\n display: block;\n\n &:not([src]) {\n display: none;\n }\n"])));function Pe(e){const{title:n,posterURL:t,showPlayIcon:r,href:i,presenterName:o,presenterSubtitle:a}=e;return z(Oe,{flex:1,children:z(Y,{sizing:"border",flex:1,padding:2,radius:2,as:"a",href:i,target:"_blank",rel:"noopener noreferrer",style:{position:"relative"},children:k(C,{direction:"column",style:{height:"100%"},children:[t&&k(ke,{marginBottom:1,children:[z(ze,{src:t}),r&&z(xe,{display:"flex",children:z(X,{align:"center",children:z(re,{})})})]}),k(C,{direction:"column",justify:"space-between",paddingY:2,flex:1,children:[z(D,{as:"h3",size:1,children:n}),z(B,{marginTop:4,children:k(M,{space:2,flex:1,children:[z(X,{size:1,children:o}),z(X,{size:0,style:{opacity:.7},children:a})]})})]})]})})})}const _e={projectId:"3do82whm",dataset:"next"};function Se(e){const{templateRepoId:n}=e,[t,r]=q([]),{getFeed:i,urlBuilder:o}=function(){const e=ce();return I((()=>({getFeed:n=>{const t=n?"/addons/dashboard?templateRepoId=".concat(n):"/addons/dashboard";return e.observable.request({uri:t,withCredentials:!1})},urlBuilder:ie(_e)})),[e])}();A((()=>{const e=i(n).subscribe((e=>{r(e.items)}));return()=>{e.unsubscribe()}}),[r,i,n]);return z(se,{header:"Learn about Sanity",children:z(C,{as:"ul",overflow:"auto",align:"stretch",paddingY:2,children:null==t?void 0:t.map(((e,n)=>{var r;if(!e.title||!e.guideOrTutorial&&!e.externalLink)return null;const i=e.presenter||(null==(r=e.guideOrTutorial)?void 0:r.presenter)||{},a=e.category,{guideOrTutorial:l={}}=e,d=(l.slug?(s=l.slug,"tutorial"===(c=l._type)?"https://www.sanity.io/docs/tutorials/".concat(s.current):"guide"===c&&"https://www.sanity.io/docs/guides/".concat(s.current)):e.externalLink)||e.externalLink;var s,c;return z(C,{as:"li",paddingRight:n<(null==t?void 0:t.length)-1?1:3,paddingLeft:0===n?3:0,align:"stretch",style:{minWidth:272,width:"30%"},children:z(Pe,{title:e.title,href:null!=d?d:"",presenterName:i.name,presenterSubtitle:a,showPlayIcon:e.hasVideo,posterURL:e.poster?o.image(e.poster).height(360).url():void 0})},e._id)}))})})}function Re(e){var n;return{name:"sanity-tutorials",component:Se,layout:null!=(n=null==e?void 0:e.layout)?n:{width:"full"}}}function Ie(e){return z(F,{width:4,padding:4,sizing:"border",style:{minHeight:"100%"},children:e.children})}const Le=function(){return Q(s||(s=O(["\n @media (min-width: ","px) {\n ","\n }\n "])),(e=>{let{theme:n}=e;return n.sanity.media[0]}),Q(...arguments))},qe=function(){return Q(c||(c=O(["\n @media (min-width: ","px) {\n ","\n }\n "])),(e=>{let{theme:n}=e;return n.sanity.media[2]}),Q(...arguments))},Ae=G(V)(u||(u=O(["\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n\n & > div {\n overflow: hidden;\n }\n\n & > div[data-width='medium'] {\n ","\n }\n\n & > div[data-width='large'] {\n ","\n\n ","\n }\n\n & > div[data-width='full'] {\n ","\n }\n\n & > div[data-height='medium'] {\n ","\n }\n\n & > div[data-height='large'] {\n ","\n\n ","\n }\n\n & > div[data-height='full'] {\n ","\n }\n"])),Le(h||(h=O(["\n grid-column: span 2;\n "]))),Le(p||(p=O(["\n grid-column: span 2;\n "]))),qe(g||(g=O(["\n grid-column: span 3;\n "]))),Le(m||(m=O(["\n grid-column: 1 / -1;\n "]))),Le(f||(f=O(["\n grid-row: span 2;\n "]))),Le(b||(b=O(["\n grid-row: span 2;\n "]))),qe(y||(y=O(["\n grid-row: span 3;\n "]))),qe(w||(w=O(["\n grid-row: 1 / -1;\n "])))),Ee=[],Ye={};function Be(e){const{config:{layout:n=Ye,widgets:t=Ee}}=e;return k(Ae,{autoFlow:"row dense","data-width":n.width||"auto","data-height":n.height||"auto",gap:4,children:[t.length?null:z(Y,{padding:4,shadow:1,tone:"primary",children:z(X,{align:"center",children:"Add some widgets to populate this space."})}),t.map(((e,n)=>"__experimental_group"===e.type?z(Be,{config:e},n):e.component?z(he,j({},e),n):k(B,{children:[e.name," is missing widget component"]},n)))]})}function De(e){let{config:n}=e;return n?z(ue.Provider,{value:n,children:z(Ie,{children:z(Be,{config:n})})}):null}const He={stroke:"currentColor",strokeWidth:1.2},Me=()=>k("svg",{"data-sanity-icon":!0,viewBox:"0 0 25 25",fill:"none",xmlns:"http://www.w3.org/2000/svg",preserveAspectRatio:"xMidYMid",width:"1em",height:"1em",children:[z("path",{d:"M19.5 19.5H5.5V5.5H19.5V19.5Z",style:He}),z("path",{d:"M5.5 12.5H19.5",style:He}),z("path",{d:"M14.5 19.5V12.5M10.5 12.5V5.5",style:He})]}),Te=K((function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};var n,t;const r={layout:null!=(n=e.defaultLayout)?n:{},widgets:null!=(t=e.widgets)?t:[]};return{name:"dashboard",tools:(e,n)=>[...e,{title:"Dashboard",name:"dashboard",icon:Me,component:()=>z(De,{config:r})}]}}));export{se as DashboardWidgetContainer,Te as dashboardTool,ye as projectInfoWidget,je as projectUsersWidget,Re as sanityTutorialsWidget};
2
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../src/components/DashboardWidgetContainer.tsx","../src/versionedClient.ts","../src/containers/DashboardContext.tsx","../src/containers/WidgetContainer.tsx","../src/widgets/projectInfo/ProjectInfo.tsx","../src/widgets/projectInfo/index.ts","../src/widgets/projectUsers/ProjectUsers.tsx","../src/widgets/projectUsers/index.ts","../src/widgets/sanityTutorials/Tutorial.tsx","../src/widgets/sanityTutorials/dataAdapter.ts","../src/widgets/sanityTutorials/SanityTutorials.tsx","../src/widgets/sanityTutorials/index.ts","../src/components/DashboardLayout.tsx","../src/components/WidgetGroup.tsx","../src/containers/Dashboard.tsx","../src/plugin.tsx"],"sourcesContent":["import React, {forwardRef} from 'react'\nimport {Card, Box, Heading} from '@sanity/ui'\nimport styled from 'styled-components'\n\nconst Root = styled(Card)`\n display: flex;\n flex-direction: column;\n justify-content: stretch;\n height: 100%;\n box-sizing: border-box;\n position: relative;\n`\n\nconst Header = styled(Card)`\n position: sticky;\n top: 0;\n z-index: 2;\n border-top-left-radius: inherit;\n border-top-right-radius: inherit;\n`\n\nconst Footer = styled(Card)`\n position: sticky;\n overflow: hidden;\n bottom: 0;\n z-index: 2;\n border-bottom-right-radius: inherit;\n border-bottom-left-radius: inherit;\n margin-top: auto;\n`\n\nconst Content = styled(Box)`\n position: relative;\n z-index: 1;\n height: stretch;\n min-height: 21.5em;\n\n @media (min-width: ${({theme}) => theme.sanity.media[0]}px) {\n overflow-y: auto;\n outline: none;\n }\n`\n\ninterface DashboardWidgetProps {\n header?: string\n children: React.ReactNode\n footer?: React.ReactNode\n}\n\nexport const DashboardWidgetContainer = forwardRef(function DashboardWidgetContainer(\n props: DashboardWidgetProps,\n ref: React.Ref<HTMLDivElement>\n) {\n const {header, children, footer} = props\n\n return (\n <Root radius={3} display=\"flex\" ref={ref}>\n {header && (\n <Header borderBottom paddingX={3} paddingY={4}>\n <Heading size={1} textOverflow=\"ellipsis\">\n {header}\n </Heading>\n </Header>\n )}\n {children && <Content>{children}</Content>}\n {footer && <Footer borderTop>{footer}</Footer>}\n </Root>\n )\n})\n","import {useClient} from 'sanity'\n\nexport function useVersionedClient() {\n return useClient({apiVersion: '1'})\n}\n","import {createContext, useContext} from 'react'\nimport {DashboardConfig} from '../types'\n\nexport const DashboardContext = createContext<DashboardConfig>({widgets: []})\n\nexport function useDashboardConfig(): DashboardConfig {\n return useContext(DashboardContext)\n}\n","import React, {createElement, useMemo} from 'react'\nimport {useDashboardConfig} from './DashboardContext'\nimport {Card} from '@sanity/ui'\nimport {DashboardWidget} from '../types'\n\nexport function WidgetContainer(props: DashboardWidget) {\n const config = useDashboardConfig()\n const layout = useMemo(\n () => ({\n ...(props.layout || {}),\n ...(config.layout || {}),\n }),\n [props.layout, config.layout]\n )\n\n return (\n <Card shadow={1} data-width={layout.width} data-height={layout.height}>\n {createElement(props.component, {})}\n </Card>\n )\n}\n","import React, {useEffect, useMemo, useState} from 'react'\nimport {Box, Card, Stack, Heading, Grid, Label, Text, Code, Button} from '@sanity/ui'\nimport {useVersionedClient} from '../../versionedClient'\nimport {Subscription} from 'rxjs'\nimport {WidgetContainer} from '../../containers/WidgetContainer'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\nimport {DashboardWidget} from '../../types'\n\nexport interface ProjectInfoProps {\n __experimental_before?: DashboardWidget[]\n data: ProjectData[]\n}\n\ninterface App {\n title: string\n rows?: App[]\n value?: string | {error: string}\n}\n\ninterface ProjectData {\n title: string\n category?: string\n}\n\nfunction isUrl(url?: string) {\n return url && /^https?:\\/\\//.test(`${url}`)\n}\n\nfunction getGraphQlUrl(projectId: string, dataset: string) {\n return `https://${projectId}.api.sanity.io/v1/graphql/${dataset}/default`\n}\n\nfunction getGroqUrl(projectId: string, dataset: string) {\n return `https://${projectId}.api.sanity.io/v1/groq/${dataset}`\n}\n\nfunction getManageUrl(projectId: string) {\n return `https://manage.sanity.io/projects/${projectId}`\n}\n\nconst NO_EXPERIMENTAL: DashboardWidget[] = []\nconst NO_DATA: ProjectData[] = []\n\nexport function ProjectInfo(props: ProjectInfoProps) {\n const {__experimental_before = NO_EXPERIMENTAL, data = NO_DATA} = props\n const [studioHost, setStudioHost] = useState<string | {error: string} | undefined>()\n const [graphqlApi, setGraphQlApi] = useState<string | {error: string} | undefined>()\n const versionedClient = useVersionedClient()\n const {projectId = 'unknown', dataset = 'unknown'} = versionedClient.config()\n\n useEffect(() => {\n const subscriptions: Subscription[] = []\n\n subscriptions.push(\n versionedClient.observable\n .request<{studioHost: string}>({uri: `/projects/${projectId}`})\n .subscribe({\n next: (result) => {\n const {studioHost: host} = result\n setStudioHost(host ? `https://${host}.sanity.studio` : undefined)\n },\n error: (error) => {\n console.error('Error while looking for studioHost', error)\n setStudioHost({\n error: 'Something went wrong while looking up studioHost. See console.',\n })\n },\n })\n )\n\n // ping assumed graphql endpoint\n subscriptions.push(\n versionedClient.observable\n .request({\n method: 'HEAD',\n uri: `/graphql/${dataset}/default`,\n })\n .subscribe({\n next: () => setGraphQlApi(getGraphQlUrl(projectId, dataset)),\n error: (error) => {\n if (error.statusCode === 404) {\n setGraphQlApi(undefined)\n } else {\n console.error('Error while looking for graphqlApi', error)\n setGraphQlApi({\n error: 'Something went wrong while looking up graphqlApi. See console.',\n })\n }\n },\n })\n )\n\n return () => {\n subscriptions.forEach((s) => s.unsubscribe())\n }\n }, [dataset, projectId, versionedClient, setGraphQlApi, setStudioHost])\n\n const assembleTableRows = useMemo(() => {\n let result: App[] = [\n {\n title: 'Sanity project',\n rows: [\n {title: 'Project ID', value: projectId},\n {title: 'Dataset', value: dataset},\n ],\n },\n ]\n\n // Handle any apps\n const apps: App[] = [\n studioHost ? {title: 'Studio', value: studioHost} : null,\n ...data.filter((item) => item.category === 'apps'),\n ].filter((a): a is App => !!a)\n if (apps.length > 0) {\n result = result.concat([{title: 'Apps', rows: apps}])\n }\n\n // Handle APIs\n result = result.concat(\n [\n {\n title: 'APIs',\n rows: [\n {title: 'GROQ', value: getGroqUrl(projectId, dataset)},\n {\n title: 'GraphQL',\n value: (typeof graphqlApi === 'object' ? 'Error' : graphqlApi) ?? 'Not deployed',\n },\n ],\n },\n ],\n data.filter((item) => item.category === 'apis')\n )\n\n // Handle whatever else there might be\n const otherStuff: Record<string, ProjectData[]> = {}\n data.forEach((item) => {\n if (item.category && item.category !== 'apps' && item.category !== 'apis') {\n if (!otherStuff[item.category]) {\n otherStuff[item.category] = []\n }\n otherStuff[item.category].push(item)\n }\n })\n Object.keys(otherStuff).forEach((category) => {\n result.push({title: category, rows: otherStuff[category]})\n })\n\n return result\n }, [graphqlApi, studioHost, projectId, dataset, data])\n\n return (\n <>\n {__experimental_before.map((widgetConfig, idx) => (\n <WidgetContainer key={idx} {...widgetConfig} />\n ))}\n <Box height=\"fill\" marginTop={__experimental_before?.length > 0 ? 4 : 0}>\n <DashboardWidgetContainer\n footer={\n <Button\n style={{width: '100%'}}\n paddingX={2}\n paddingY={4}\n mode=\"bleed\"\n tone=\"primary\"\n text=\"Manage project\"\n as=\"a\"\n href={getManageUrl(projectId)}\n />\n }\n >\n <Card\n paddingY={4}\n radius={2}\n role=\"table\"\n aria-label=\"Project info\"\n aria-describedby=\"project_info_table\"\n >\n <Stack space={4}>\n <Box paddingX={3} as=\"header\">\n <Heading size={1} as=\"h2\" id=\"project_info_table\">\n Project info\n </Heading>\n </Box>\n {assembleTableRows.map((item) => {\n if (!item || !item.rows) {\n return null\n }\n\n return (\n <Stack key={item.title} space={3}>\n <Card borderBottom padding={3}>\n <Label size={0} muted role=\"columnheader\">\n {item.title}\n </Label>\n </Card>\n <Stack space={4} paddingX={3} role=\"rowgroup\">\n {item.rows.map((row) => {\n return (\n <Grid key={row.title} columns={2} role=\"row\">\n <Text weight=\"medium\" role=\"rowheader\">\n {row.title}\n </Text>\n {typeof row.value === 'object' && (\n <Text size={1}>{row.value?.error}</Text>\n )}\n {typeof row.value === 'string' && (\n <>\n {isUrl(row.value) ? (\n <Text size={1} role=\"cell\" style={{wordBreak: 'break-word'}}>\n <a href={row.value}>{row.value}</a>\n </Text>\n ) : (\n <Code size={1} role=\"cell\" style={{wordBreak: 'break-word'}}>\n {row.value}\n </Code>\n )}\n </>\n )}\n </Grid>\n )\n })}\n </Stack>\n </Stack>\n )\n })}\n </Stack>\n </Card>\n </DashboardWidgetContainer>\n </Box>\n </>\n )\n}\n","import {ProjectInfo} from './ProjectInfo'\nimport {LayoutConfig, DashboardWidget} from '../../types'\n\nexport function projectInfoWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'project-info',\n component: ProjectInfo,\n layout: config?.layout ?? {width: 'medium'},\n }\n}\n","import React, {useCallback, useEffect, useState} from 'react'\nimport {from} from 'rxjs'\nimport {map, switchMap} from 'rxjs/operators'\nimport {Stack, Spinner, Card, Box, Text, Button} from '@sanity/ui'\nimport {RobotIcon} from '@sanity/icons'\nimport styled from 'styled-components'\nimport {DefaultPreview, useUserStore} from 'sanity'\nimport {useVersionedClient} from '../../versionedClient'\nimport {User} from 'sanity'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\n\nconst AvatarWrapper = styled(Card)`\n box-sizing: border-box;\n border-radius: 50%;\n border-color: transparent;\n overflow: hidden;\n width: 100%;\n height: 100%;\n\n & > img {\n width: 100%;\n height: auto;\n }\n`\n\nfunction getInviteUrl(projectId: string) {\n return `https://manage.sanity.io/projects/${projectId}/team/invite`\n}\n\ninterface Member {\n id: string\n role: string\n isRobot: boolean\n}\n\ninterface Project {\n id: string\n members: Member[]\n}\n\nexport function ProjectUsers() {\n const [project, setProject] = useState<Project | undefined>()\n const [users, setUsers] = useState<User[] | undefined>()\n const [error, setError] = useState<Error | undefined>()\n\n const userStore = useUserStore()\n const versionedClient = useVersionedClient()\n\n const fetchData = useCallback(() => {\n const {projectId} = versionedClient.config()\n const subscription = versionedClient.observable\n .request<Project>({\n uri: `/projects/${projectId}`,\n })\n .pipe(\n switchMap((_project) =>\n from(userStore.getUsers(_project.members.map((mem) => mem.id))).pipe(\n map((_users) => ({project: _project, users: _users}))\n )\n )\n )\n .subscribe({\n next: ({users: _users, project: _project}) => {\n setProject(_project)\n setUsers(\n (Array.isArray(_users) ? _users : [_users]).sort((userA, userB) =>\n sortUsersByRobotStatus(userA, userB, _project)\n )\n )\n },\n error: (e: Error) => setError(e),\n })\n\n return () => subscription.unsubscribe()\n }, [userStore, versionedClient])\n\n useEffect(() => fetchData(), [fetchData])\n\n const handleRetryFetch = useCallback(() => fetchData(), [fetchData])\n\n const isLoading = !users || !project\n\n if (error) {\n return (\n <DashboardWidgetContainer header=\"Project users\">\n <Box padding={4}>\n <Text>\n Something went wrong while fetching data. You could{' '}\n <a onClick={handleRetryFetch} title=\"Retry users fetch\" style={{cursor: 'pointer'}}>\n retry\n </a>\n ..?\n </Text>\n </Box>\n </DashboardWidgetContainer>\n )\n }\n\n return (\n <DashboardWidgetContainer\n header=\"Project users\"\n footer={\n <Button\n style={{width: '100%'}}\n paddingX={2}\n paddingY={4}\n mode=\"bleed\"\n tone=\"primary\"\n text=\"Invite members\"\n as=\"a\"\n loading={isLoading}\n href={isLoading ? undefined : getInviteUrl(project.id)}\n />\n }\n >\n {isLoading && (\n <Box paddingY={5} paddingX={2}>\n <Stack space={4}>\n <Text align=\"center\" muted size={1}>\n <Spinner />\n </Text>\n <Text align=\"center\" size={1} muted>\n Loading items...\n </Text>\n </Stack>\n </Box>\n )}\n\n {!isLoading && (\n <Stack space={3} padding={3}>\n {users?.map((user) => {\n const membership = project.members.find((member) => member.id === user.id)\n const media = membership?.isRobot ? (\n <Text size={3}>\n <RobotIcon />\n </Text>\n ) : (\n <AvatarWrapper tone=\"transparent\">\n {user?.imageUrl && <img src={user.imageUrl} alt={user?.displayName} />}\n </AvatarWrapper>\n )\n return (\n <Box key={user.id}>\n <DefaultPreview\n title={user.displayName}\n subtitle={membership?.role}\n media={media}\n />\n </Box>\n )\n })}\n </Stack>\n )}\n </DashboardWidgetContainer>\n )\n}\n\nfunction sortUsersByRobotStatus(userA: User, userB: User, project: Project) {\n const {members} = project\n const membershipA = members.find((member) => member.id === userA?.id)\n const membershipB = members.find((member) => member.id === userB?.id)\n if (membershipA?.isRobot) {\n return 1\n }\n if (membershipB?.isRobot) {\n return -1\n }\n return 0\n}\n","import {ProjectUsers} from './ProjectUsers'\nimport {LayoutConfig, DashboardWidget} from '../../types'\n\nexport function projectUsersWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'project-info',\n component: ProjectUsers,\n layout: config?.layout,\n }\n}\n","import React from 'react'\nimport {Card, Box, Heading, Flex, Text, Stack} from '@sanity/ui'\nimport {PlayIcon} from '@sanity/icons'\nimport styled from 'styled-components'\n\nconst PlayIconBox = styled(Box)`\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n\n &:before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 2.75em;\n height: 2.75em;\n border-radius: 50%;\n background: ${({theme}) => theme.sanity.color.card.enabled.bg};\n opacity: 0.75;\n }\n`\n\nconst Root = styled(Flex)`\n &:hover {\n ${PlayIconBox} {\n &:before {\n opacity: 1;\n }\n }\n }\n`\n\nconst PosterCard = styled(Card)`\n width: 100%;\n padding-bottom: calc(9 / 16 * 100%);\n position: relative;\n`\n\nconst Poster = styled.img`\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n width: 100%;\n object-fit: cover;\n display: block;\n\n &:not([src]) {\n display: none;\n }\n`\n\nexport interface TutorialProps {\n title: string\n posterURL?: string\n href: string\n showPlayIcon?: boolean\n presenterName?: string\n presenterSubtitle?: string\n}\n\nexport function Tutorial(props: TutorialProps) {\n const {title, posterURL, showPlayIcon, href, presenterName, presenterSubtitle} = props\n\n return (\n <Root flex={1}>\n <Card\n sizing=\"border\"\n flex={1}\n padding={2}\n radius={2}\n as=\"a\"\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{position: 'relative'}}\n >\n <Flex direction=\"column\" style={{height: '100%'}}>\n {posterURL && (\n <PosterCard marginBottom={1}>\n <Poster src={posterURL} />\n {showPlayIcon && (\n <PlayIconBox display=\"flex\">\n <Text align=\"center\">\n <PlayIcon />\n </Text>\n </PlayIconBox>\n )}\n </PosterCard>\n )}\n <Flex direction=\"column\" justify=\"space-between\" paddingY={2} flex={1}>\n <Heading as=\"h3\" size={1}>\n {title}\n </Heading>\n <Box marginTop={4}>\n <Stack space={2} flex={1}>\n <Text size={1}>{presenterName}</Text>\n <Text size={0} style={{opacity: 0.7}}>\n {presenterSubtitle}\n </Text>\n </Stack>\n </Box>\n </Flex>\n </Flex>\n </Card>\n </Root>\n )\n}\n","import {useMemo} from 'react'\nimport {useVersionedClient} from '../../versionedClient'\nimport imageUrlBuilder from '@sanity/image-url'\n\nconst tutorialsProjectConfig = {\n projectId: '3do82whm',\n dataset: 'next',\n}\n\nexport interface Guide {\n _type?: string\n slug?: {current: string}\n presenter?: {\n name?: string\n }\n}\n\nexport interface FeedItem {\n _id: string\n title?: string\n poster?: string\n category?: string\n guideOrTutorial?: Guide\n externalLink?: string\n presenter?: {\n name?: string\n }\n hasVideo?: boolean\n}\n\nexport function useDataAdapter() {\n const versionedClient = useVersionedClient()\n return useMemo(\n () => ({\n getFeed: (templateRepoId: string) => {\n const uri = templateRepoId\n ? `/addons/dashboard?templateRepoId=${templateRepoId}`\n : '/addons/dashboard'\n return versionedClient.observable.request<{items: FeedItem[]}>({\n uri,\n withCredentials: false,\n })\n },\n urlBuilder: imageUrlBuilder(tutorialsProjectConfig),\n }),\n [versionedClient]\n )\n}\n","import React, {useEffect, useState} from 'react'\nimport {Flex} from '@sanity/ui'\nimport {Tutorial} from './Tutorial'\nimport {FeedItem, Guide, useDataAdapter} from './dataAdapter'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\n\nfunction createUrl(slug: {current: string}, type?: string) {\n if (type === 'tutorial') {\n return `https://www.sanity.io/docs/tutorials/${slug.current}`\n } else if (type === 'guide') {\n return `https://www.sanity.io/docs/guides/${slug.current}`\n }\n return false\n}\n\nexport interface SanityTutorialsProps {\n templateRepoId: string\n}\n\nexport function SanityTutorials(props: SanityTutorialsProps) {\n const {templateRepoId} = props\n const [feedItems, setFeedItems] = useState<FeedItem[]>([])\n\n const {getFeed, urlBuilder} = useDataAdapter()\n\n useEffect(() => {\n const subscription = getFeed(templateRepoId).subscribe((response) => {\n setFeedItems(response.items)\n })\n return () => {\n subscription.unsubscribe()\n }\n }, [setFeedItems, getFeed, templateRepoId])\n\n const title = 'Learn about Sanity'\n\n return (\n <DashboardWidgetContainer header={title}>\n <Flex as=\"ul\" overflow=\"auto\" align=\"stretch\" paddingY={2}>\n {feedItems?.map((feedItem, index) => {\n if (!feedItem.title || (!feedItem.guideOrTutorial && !feedItem.externalLink)) {\n return null\n }\n const presenter = feedItem.presenter || feedItem.guideOrTutorial?.presenter || {}\n const subtitle = feedItem.category\n const {guideOrTutorial = {} as Guide} = feedItem\n const href =\n (guideOrTutorial.slug\n ? createUrl(guideOrTutorial.slug, guideOrTutorial._type)\n : feedItem.externalLink) || feedItem.externalLink\n\n return (\n <Flex\n as=\"li\"\n key={feedItem._id}\n paddingRight={index < feedItems?.length - 1 ? 1 : 3}\n paddingLeft={index === 0 ? 3 : 0}\n align=\"stretch\"\n style={{minWidth: 272, width: '30%'}}\n >\n <Tutorial\n title={feedItem.title}\n href={href ?? ''}\n presenterName={presenter.name}\n presenterSubtitle={subtitle}\n showPlayIcon={feedItem.hasVideo}\n posterURL={\n feedItem.poster ? urlBuilder.image(feedItem.poster).height(360).url() : undefined\n }\n />\n </Flex>\n )\n })}\n </Flex>\n </DashboardWidgetContainer>\n )\n}\n","import {SanityTutorials} from './SanityTutorials'\nimport {LayoutConfig, DashboardWidget} from '../../types'\n\nexport function sanityTutorialsWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'sanity-tutorials',\n component: SanityTutorials,\n layout: config?.layout ?? {width: 'full'},\n }\n}\n","import React, {PropsWithChildren} from 'react'\nimport {Container} from '@sanity/ui'\n\nexport function DashboardLayout(props: PropsWithChildren<{}>) {\n return (\n <Container width={4} padding={4} sizing=\"border\" style={{minHeight: '100%'}}>\n {props.children}\n </Container>\n )\n}\n","import React from 'react'\nimport styled, {css} from 'styled-components'\nimport {Box, Card, Grid, Text} from '@sanity/ui'\nimport {WidgetContainer} from '../containers/WidgetContainer'\nimport {DashboardConfig, LayoutConfig, DashboardWidget} from '../types'\n\nconst media = {\n small: (...args: Parameters<typeof css>) =>\n css`\n @media (min-width: ${({theme}) => theme.sanity.media[0]}px) {\n ${css(...args)}\n }\n `,\n medium: (...args: Parameters<typeof css>) =>\n css`\n @media (min-width: ${({theme}) => theme.sanity.media[2]}px) {\n ${css(...args)}\n }\n `,\n}\n\nconst Root = styled(Grid)`\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n\n & > div {\n overflow: hidden;\n }\n\n & > div[data-width='medium'] {\n ${media.small`\n grid-column: span 2;\n `}\n }\n\n & > div[data-width='large'] {\n ${media.small`\n grid-column: span 2;\n `}\n\n ${media.medium`\n grid-column: span 3;\n `}\n }\n\n & > div[data-width='full'] {\n ${media.small`\n grid-column: 1 / -1;\n `}\n }\n\n & > div[data-height='medium'] {\n ${media.small`\n grid-row: span 2;\n `}\n }\n\n & > div[data-height='large'] {\n ${media.small`\n grid-row: span 2;\n `}\n\n ${media.medium`\n grid-row: span 3;\n `}\n }\n\n & > div[data-height='full'] {\n ${media.medium`\n grid-row: 1 / -1;\n `}\n }\n`\n\nexport interface WidgetGroupProps {\n config: Partial<DashboardConfig>\n}\n\nconst NO_WIDGETS: DashboardWidget[] = []\nconst NO_LAYOUT: LayoutConfig = {}\n\nexport function WidgetGroup(props: WidgetGroupProps) {\n const {\n config: {layout = NO_LAYOUT, widgets = NO_WIDGETS},\n } = props\n return (\n <Root\n autoFlow=\"row dense\"\n data-width={layout.width || 'auto'}\n data-height={layout.height || 'auto'}\n gap={4}\n >\n {widgets.length ? null : (\n <Card padding={4} shadow={1} tone=\"primary\">\n <Text align=\"center\">Add some widgets to populate this space.</Text>\n </Card>\n )}\n {widgets.map((widgetConfig, index) => {\n if (widgetConfig.type === '__experimental_group') {\n return <WidgetGroup key={index} config={widgetConfig} />\n }\n if (widgetConfig.component) {\n return <WidgetContainer key={index} {...widgetConfig} />\n }\n return <Box key={index}>{widgetConfig.name} is missing widget component</Box>\n })}\n </Root>\n )\n}\n","import React from 'react'\nimport {DashboardLayout} from '../components/DashboardLayout'\nimport {WidgetGroup} from '../components/WidgetGroup'\nimport {DashboardContext} from './DashboardContext'\nimport {DashboardConfig} from '../types'\n\nexport function Dashboard({config}: {config: DashboardConfig}) {\n if (!config) {\n return null\n }\n\n return (\n <DashboardContext.Provider value={config}>\n <DashboardLayout>\n <WidgetGroup config={config} />\n </DashboardLayout>\n </DashboardContext.Provider>\n )\n}\n","import React, {CSSProperties} from 'react'\nimport {Dashboard} from './containers/Dashboard'\nimport {definePlugin} from 'sanity'\nimport {DashboardConfig, DashboardWidget, LayoutConfig} from './types'\n\nconst strokeStyle: CSSProperties = {\n stroke: 'currentColor',\n strokeWidth: 1.2,\n}\n\nconst DashboardIcon = () => (\n <svg\n data-sanity-icon\n viewBox=\"0 0 25 25\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n preserveAspectRatio=\"xMidYMid\"\n width=\"1em\"\n height=\"1em\"\n >\n <path d=\"M19.5 19.5H5.5V5.5H19.5V19.5Z\" style={strokeStyle} />\n <path d=\"M5.5 12.5H19.5\" style={strokeStyle} />\n <path d=\"M14.5 19.5V12.5M10.5 12.5V5.5\" style={strokeStyle} />\n </svg>\n)\n\nexport interface DashboardPluginConfig {\n widgets?: DashboardWidget[]\n\n /**\n * Will be used for widgets that do not define a layout directly.\n */\n defaultLayout?: LayoutConfig\n}\n\nexport const dashboardTool = definePlugin<DashboardPluginConfig>((config = {}) => {\n const pluginConfig: DashboardConfig = {\n layout: config.defaultLayout ?? {},\n widgets: config.widgets ?? [],\n }\n\n return {\n name: 'dashboard',\n tools: (prev, context) => {\n return [\n ...prev,\n {\n title: 'Dashboard',\n name: 'dashboard',\n icon: DashboardIcon,\n component: () => <Dashboard config={pluginConfig} />,\n },\n ]\n },\n }\n})\n"],"names":["Root","styled","Card","_templateObject","_taggedTemplateLiteral","Header","_templateObject2","Footer","_templateObject3","Content","Box","_templateObject4","_ref","theme","sanity","media","DashboardWidgetContainer","forwardRef","props","ref","header","children","footer","jsxs","radius","display","jsx","borderBottom","paddingX","paddingY","Heading","size","textOverflow","borderTop","useVersionedClient","useClient","apiVersion","DashboardContext","createContext","widgets","WidgetContainer","config","useContext","layout","useMemo","shadow","width","height","createElement","component","getGroqUrl","projectId","dataset","getManageUrl","concat","NO_EXPERIMENTAL","NO_DATA","ProjectInfo","__experimental_before","data","studioHost","setStudioHost","useState","graphqlApi","setGraphQlApi","versionedClient","useEffect","subscriptions","push","observable","request","uri","subscribe","next","result","host","error","console","method","getGraphQlUrl","statusCode","forEach","s","unsubscribe","assembleTableRows","_a","title","rows","value","apps","filter","item","category","a","length","otherStuff","Object","keys","Fragment","map","widgetConfig","idx","_objectSpread","marginTop","Button","style","mode","tone","text","as","href","role","Stack","space","id","padding","Label","muted","row","url","Grid","columns","Text","weight","test","wordBreak","Code","projectInfoWidget","name","AvatarWrapper","_templateObject5","ProjectUsers","project","setProject","users","setUsers","setError","userStore","useUserStore","fetchData","useCallback","subscription","pipe","switchMap","_project","from","getUsers","members","mem","_users","_ref2","Array","isArray","sort","userA","userB","membershipA","find","member","membershipB","isRobot","sortUsersByRobotStatus","e","handleRetryFetch","isLoading","onClick","cursor","loading","align","Spinner","user","membership","RobotIcon","imageUrl","src","alt","displayName","DefaultPreview","subtitle","projectUsersWidget","PlayIconBox","_templateObject6","_ref3","color","card","enabled","bg","Flex","_templateObject7","PosterCard","_templateObject8","Poster","img","_templateObject9","Tutorial","posterURL","showPlayIcon","presenterName","presenterSubtitle","flex","sizing","target","rel","position","direction","marginBottom","PlayIcon","justify","opacity","tutorialsProjectConfig","SanityTutorials","templateRepoId","feedItems","setFeedItems","getFeed","urlBuilder","withCredentials","imageUrlBuilder","useDataAdapter","response","items","overflow","feedItem","index","guideOrTutorial","externalLink","presenter","slug","type","_type","current","paddingRight","paddingLeft","minWidth","hasVideo","poster","image","_id","sanityTutorialsWidget","DashboardLayout","Container","minHeight","css","_templateObject10","_ref4","arguments","_templateObject11","_ref5","_templateObject15","_templateObject18","_templateObject20","NO_WIDGETS","NO_LAYOUT","WidgetGroup","autoFlow","gap","Dashboard","_ref6","Provider","strokeStyle","stroke","strokeWidth","DashboardIcon","viewBox","fill","xmlns","preserveAspectRatio","d","dashboardTool","definePlugin","undefined","_b","pluginConfig","defaultLayout","tools","prev","context","icon"],"mappings":"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"}
package/lib/index.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var e,t,n,r,i,o,s,a,l,d,c,u,h,p,g,f,x,m,j,b;function y(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function w(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?y(Object(n),!0).forEach((function(t){v(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):y(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function v(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function k(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}Object.defineProperty(exports,"__esModule",{value:!0});var O=require("react/jsx-runtime"),S=require("react"),P=require("@sanity/ui"),C=require("styled-components"),z=require("sanity"),B=require("rxjs"),T=require("rxjs/operators"),q=require("@sanity/icons"),_=require("@sanity/image-url");function E(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var I=E(C),R=E(_);const M=I.default(P.Card)(e||(e=k(["\n display: flex;\n flex-direction: column;\n justify-content: stretch;\n height: 100%;\n box-sizing: border-box;\n position: relative;\n"]))),H=I.default(P.Card)(t||(t=k(["\n position: sticky;\n top: 0;\n z-index: 2;\n border-top-left-radius: inherit;\n border-top-right-radius: inherit;\n"]))),L=I.default(P.Card)(n||(n=k(["\n position: sticky;\n overflow: hidden;\n bottom: 0;\n z-index: 2;\n border-bottom-right-radius: inherit;\n border-bottom-left-radius: inherit;\n margin-top: auto;\n"]))),D=I.default(P.Box)(r||(r=k(["\n position: relative;\n z-index: 1;\n height: stretch;\n min-height: 21.5em;\n\n @media (min-width: ","px) {\n overflow-y: auto;\n outline: none;\n }\n"])),(e=>{let{theme:t}=e;return t.sanity.media[0]})),F=S.forwardRef((function(e,t){const{header:n,children:r,footer:i}=e;return O.jsxs(M,{radius:3,display:"flex",ref:t,children:[n&&O.jsx(H,{borderBottom:!0,paddingX:3,paddingY:4,children:O.jsx(P.Heading,{size:1,textOverflow:"ellipsis",children:n})}),r&&O.jsx(D,{children:r}),i&&O.jsx(L,{borderTop:!0,children:i})]})}));function A(){return z.useClient({apiVersion:"1"})}const Y=S.createContext({widgets:[]});function U(e){const t=S.useContext(Y),n=S.useMemo((()=>w(w({},e.layout||{}),t.layout||{})),[e.layout,t.layout]);return O.jsx(P.Card,{shadow:1,"data-width":n.width,"data-height":n.height,children:S.createElement(e.component,{})})}function V(e,t){return"https://".concat(e,".api.sanity.io/v1/groq/").concat(t)}function W(e){return"https://manage.sanity.io/projects/".concat(e)}const X=[],N=[];function G(e){const{__experimental_before:t=X,data:n=N}=e,[r,i]=S.useState(),[o,s]=S.useState(),a=A(),{projectId:l="unknown",dataset:d="unknown"}=a.config();S.useEffect((()=>{const e=[];return e.push(a.observable.request({uri:"/projects/".concat(l)}).subscribe({next:e=>{const{studioHost:t}=e;i(t?"https://".concat(t,".sanity.studio"):void 0)},error:e=>{console.error("Error while looking for studioHost",e),i({error:"Something went wrong while looking up studioHost. See console."})}})),e.push(a.observable.request({method:"HEAD",uri:"/graphql/".concat(d,"/default")}).subscribe({next:()=>s(function(e,t){return"https://".concat(e,".api.sanity.io/v1/graphql/").concat(t,"/default")}(l,d)),error:e=>{404===e.statusCode?s(void 0):(console.error("Error while looking for graphqlApi",e),s({error:"Something went wrong while looking up graphqlApi. See console."}))}})),()=>{e.forEach((e=>e.unsubscribe()))}}),[d,l,a,s,i]);const c=S.useMemo((()=>{var e;let t=[{title:"Sanity project",rows:[{title:"Project ID",value:l},{title:"Dataset",value:d}]}];const i=[r?{title:"Studio",value:r}:null,...n.filter((e=>"apps"===e.category))].filter((e=>!!e));i.length>0&&(t=t.concat([{title:"Apps",rows:i}])),t=t.concat([{title:"APIs",rows:[{title:"GROQ",value:V(l,d)},{title:"GraphQL",value:null!=(e="object"==typeof o?"Error":o)?e:"Not deployed"}]}],n.filter((e=>"apis"===e.category)));const s={};return n.forEach((e=>{e.category&&"apps"!==e.category&&"apis"!==e.category&&(s[e.category]||(s[e.category]=[]),s[e.category].push(e))})),Object.keys(s).forEach((e=>{t.push({title:e,rows:s[e]})})),t}),[o,r,l,d,n]);return O.jsxs(O.Fragment,{children:[t.map(((e,t)=>O.jsx(U,w({},e),t))),O.jsx(P.Box,{height:"fill",marginTop:(null==t?void 0:t.length)>0?4:0,children:O.jsx(F,{footer:O.jsx(P.Button,{style:{width:"100%"},paddingX:2,paddingY:4,mode:"bleed",tone:"primary",text:"Manage project",as:"a",href:W(l)}),children:O.jsx(P.Card,{paddingY:4,radius:2,role:"table","aria-label":"Project info","aria-describedby":"project_info_table",children:O.jsxs(P.Stack,{space:4,children:[O.jsx(P.Box,{paddingX:3,as:"header",children:O.jsx(P.Heading,{size:1,as:"h2",id:"project_info_table",children:"Project info"})}),c.map((e=>e&&e.rows?O.jsxs(P.Stack,{space:3,children:[O.jsx(P.Card,{borderBottom:!0,padding:3,children:O.jsx(P.Label,{size:0,muted:!0,role:"columnheader",children:e.title})}),O.jsx(P.Stack,{space:4,paddingX:3,role:"rowgroup",children:e.rows.map((e=>{var t,n;return O.jsxs(P.Grid,{columns:2,role:"row",children:[O.jsx(P.Text,{weight:"medium",role:"rowheader",children:e.title}),"object"==typeof e.value&&O.jsx(P.Text,{size:1,children:null==(t=e.value)?void 0:t.error}),"string"==typeof e.value&&O.jsx(O.Fragment,{children:(n=e.value,n&&/^https?:\/\//.test("".concat(n))?O.jsx(P.Text,{size:1,role:"cell",style:{wordBreak:"break-word"},children:O.jsx("a",{href:e.value,children:e.value})}):O.jsx(P.Code,{size:1,role:"cell",style:{wordBreak:"break-word"},children:e.value}))})]},e.title)}))})]},e.title):null))]})})})})]})}const Q=I.default(P.Card)(i||(i=k(["\n box-sizing: border-box;\n border-radius: 50%;\n border-color: transparent;\n overflow: hidden;\n width: 100%;\n height: 100%;\n\n & > img {\n width: 100%;\n height: auto;\n }\n"])));function Z(){const[e,t]=S.useState(),[n,r]=S.useState(),[i,o]=S.useState(),s=z.useUserStore(),a=A(),l=S.useCallback((()=>{const{projectId:e}=a.config(),n=a.observable.request({uri:"/projects/".concat(e)}).pipe(T.switchMap((e=>B.from(s.getUsers(e.members.map((e=>e.id)))).pipe(T.map((t=>({project:e,users:t}))))))).subscribe({next:e=>{let{users:n,project:i}=e;t(i),r((Array.isArray(n)?n:[n]).sort(((e,t)=>function(e,t,n){const{members:r}=n,i=r.find((t=>t.id===(null==e?void 0:e.id))),o=r.find((e=>e.id===(null==t?void 0:t.id)));if(null==i?void 0:i.isRobot)return 1;if(null==o?void 0:o.isRobot)return-1;return 0}(e,t,i))))},error:e=>o(e)});return()=>n.unsubscribe()}),[s,a]);S.useEffect((()=>l()),[l]);const d=S.useCallback((()=>l()),[l]),c=!n||!e;return i?O.jsx(F,{header:"Project users",children:O.jsx(P.Box,{padding:4,children:O.jsxs(P.Text,{children:["Something went wrong while fetching data. You could"," ",O.jsx("a",{onClick:d,title:"Retry users fetch",style:{cursor:"pointer"},children:"retry"}),"..?"]})})}):O.jsxs(F,{header:"Project users",footer:O.jsx(P.Button,{style:{width:"100%"},paddingX:2,paddingY:4,mode:"bleed",tone:"primary",text:"Invite members",as:"a",loading:c,href:c?void 0:(u=e.id,"https://manage.sanity.io/projects/".concat(u,"/team/invite"))}),children:[c&&O.jsx(P.Box,{paddingY:5,paddingX:2,children:O.jsxs(P.Stack,{space:4,children:[O.jsx(P.Text,{align:"center",muted:!0,size:1,children:O.jsx(P.Spinner,{})}),O.jsx(P.Text,{align:"center",size:1,muted:!0,children:"Loading items..."})]})}),!c&&O.jsx(P.Stack,{space:3,padding:3,children:null==n?void 0:n.map((t=>{const n=e.members.find((e=>e.id===t.id)),r=(null==n?void 0:n.isRobot)?O.jsx(P.Text,{size:3,children:O.jsx(q.RobotIcon,{})}):O.jsx(Q,{tone:"transparent",children:(null==t?void 0:t.imageUrl)&&O.jsx("img",{src:t.imageUrl,alt:null==t?void 0:t.displayName})});return O.jsx(P.Box,{children:O.jsx(z.DefaultPreview,{title:t.displayName,subtitle:null==n?void 0:n.role,media:r})},t.id)}))})]});var u}const J=I.default(P.Box)(o||(o=k(["\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n\n &:before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 2.75em;\n height: 2.75em;\n border-radius: 50%;\n background: ",";\n opacity: 0.75;\n }\n"])),(e=>{let{theme:t}=e;return t.sanity.color.card.enabled.bg})),K=I.default(P.Flex)(s||(s=k(["\n &:hover {\n "," {\n &:before {\n opacity: 1;\n }\n }\n }\n"])),J),$=I.default(P.Card)(a||(a=k(["\n width: 100%;\n padding-bottom: calc(9 / 16 * 100%);\n position: relative;\n"]))),ee=I.default.img(l||(l=k(["\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n width: 100%;\n object-fit: cover;\n display: block;\n\n &:not([src]) {\n display: none;\n }\n"])));function te(e){const{title:t,posterURL:n,showPlayIcon:r,href:i,presenterName:o,presenterSubtitle:s}=e;return O.jsx(K,{flex:1,children:O.jsx(P.Card,{sizing:"border",flex:1,padding:2,radius:2,as:"a",href:i,target:"_blank",rel:"noopener noreferrer",style:{position:"relative"},children:O.jsxs(P.Flex,{direction:"column",style:{height:"100%"},children:[n&&O.jsxs($,{marginBottom:1,children:[O.jsx(ee,{src:n}),r&&O.jsx(J,{display:"flex",children:O.jsx(P.Text,{align:"center",children:O.jsx(q.PlayIcon,{})})})]}),O.jsxs(P.Flex,{direction:"column",justify:"space-between",paddingY:2,flex:1,children:[O.jsx(P.Heading,{as:"h3",size:1,children:t}),O.jsx(P.Box,{marginTop:4,children:O.jsxs(P.Stack,{space:2,flex:1,children:[O.jsx(P.Text,{size:1,children:o}),O.jsx(P.Text,{size:0,style:{opacity:.7},children:s})]})})]})]})})})}const ne={projectId:"3do82whm",dataset:"next"};function re(e){const{templateRepoId:t}=e,[n,r]=S.useState([]),{getFeed:i,urlBuilder:o}=function(){const e=A();return S.useMemo((()=>({getFeed:t=>{const n=t?"/addons/dashboard?templateRepoId=".concat(t):"/addons/dashboard";return e.observable.request({uri:n,withCredentials:!1})},urlBuilder:R.default(ne)})),[e])}();S.useEffect((()=>{const e=i(t).subscribe((e=>{r(e.items)}));return()=>{e.unsubscribe()}}),[r,i,t]);return O.jsx(F,{header:"Learn about Sanity",children:O.jsx(P.Flex,{as:"ul",overflow:"auto",align:"stretch",paddingY:2,children:null==n?void 0:n.map(((e,t)=>{var r;if(!e.title||!e.guideOrTutorial&&!e.externalLink)return null;const i=e.presenter||(null==(r=e.guideOrTutorial)?void 0:r.presenter)||{},s=e.category,{guideOrTutorial:a={}}=e,l=(a.slug?(d=a.slug,"tutorial"===(c=a._type)?"https://www.sanity.io/docs/tutorials/".concat(d.current):"guide"===c&&"https://www.sanity.io/docs/guides/".concat(d.current)):e.externalLink)||e.externalLink;var d,c;return O.jsx(P.Flex,{as:"li",paddingRight:t<(null==n?void 0:n.length)-1?1:3,paddingLeft:0===t?3:0,align:"stretch",style:{minWidth:272,width:"30%"},children:O.jsx(te,{title:e.title,href:null!=l?l:"",presenterName:i.name,presenterSubtitle:s,showPlayIcon:e.hasVideo,posterURL:e.poster?o.image(e.poster).height(360).url():void 0})},e._id)}))})})}function ie(e){return O.jsx(P.Container,{width:4,padding:4,sizing:"border",style:{minHeight:"100%"},children:e.children})}const oe=function(){return C.css(d||(d=k(["\n @media (min-width: ","px) {\n ","\n }\n "])),(e=>{let{theme:t}=e;return t.sanity.media[0]}),C.css(...arguments))},se=function(){return C.css(c||(c=k(["\n @media (min-width: ","px) {\n ","\n }\n "])),(e=>{let{theme:t}=e;return t.sanity.media[2]}),C.css(...arguments))},ae=I.default(P.Grid)(u||(u=k(["\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n\n & > div {\n overflow: hidden;\n }\n\n & > div[data-width='medium'] {\n ","\n }\n\n & > div[data-width='large'] {\n ","\n\n ","\n }\n\n & > div[data-width='full'] {\n ","\n }\n\n & > div[data-height='medium'] {\n ","\n }\n\n & > div[data-height='large'] {\n ","\n\n ","\n }\n\n & > div[data-height='full'] {\n ","\n }\n"])),oe(h||(h=k(["\n grid-column: span 2;\n "]))),oe(p||(p=k(["\n grid-column: span 2;\n "]))),se(g||(g=k(["\n grid-column: span 3;\n "]))),oe(f||(f=k(["\n grid-column: 1 / -1;\n "]))),oe(x||(x=k(["\n grid-row: span 2;\n "]))),oe(m||(m=k(["\n grid-row: span 2;\n "]))),se(j||(j=k(["\n grid-row: span 3;\n "]))),se(b||(b=k(["\n grid-row: 1 / -1;\n "])))),le=[],de={};function ce(e){const{config:{layout:t=de,widgets:n=le}}=e;return O.jsxs(ae,{autoFlow:"row dense","data-width":t.width||"auto","data-height":t.height||"auto",gap:4,children:[n.length?null:O.jsx(P.Card,{padding:4,shadow:1,tone:"primary",children:O.jsx(P.Text,{align:"center",children:"Add some widgets to populate this space."})}),n.map(((e,t)=>"__experimental_group"===e.type?O.jsx(ce,{config:e},t):e.component?O.jsx(U,w({},e),t):O.jsxs(P.Box,{children:[e.name," is missing widget component"]},t)))]})}function ue(e){let{config:t}=e;return t?O.jsx(Y.Provider,{value:t,children:O.jsx(ie,{children:O.jsx(ce,{config:t})})}):null}const he={stroke:"currentColor",strokeWidth:1.2},pe=()=>O.jsxs("svg",{"data-sanity-icon":!0,viewBox:"0 0 25 25",fill:"none",xmlns:"http://www.w3.org/2000/svg",preserveAspectRatio:"xMidYMid",width:"1em",height:"1em",children:[O.jsx("path",{d:"M19.5 19.5H5.5V5.5H19.5V19.5Z",style:he}),O.jsx("path",{d:"M5.5 12.5H19.5",style:he}),O.jsx("path",{d:"M14.5 19.5V12.5M10.5 12.5V5.5",style:he})]}),ge=z.definePlugin((function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};var t,n;const r={layout:null!=(t=e.defaultLayout)?t:{},widgets:null!=(n=e.widgets)?n:[]};return{name:"dashboard",tools:(e,t)=>[...e,{title:"Dashboard",name:"dashboard",icon:pe,component:()=>O.jsx(ue,{config:r})}]}}));exports.DashboardWidgetContainer=F,exports.dashboardTool=ge,exports.projectInfoWidget=function(e){var t;return{name:"project-info",component:G,layout:null!=(t=null==e?void 0:e.layout)?t:{width:"medium"}}},exports.projectUsersWidget=function(e){return{name:"project-info",component:Z,layout:null==e?void 0:e.layout}},exports.sanityTutorialsWidget=function(e){var t;return{name:"sanity-tutorials",component:re,layout:null!=(t=null==e?void 0:e.layout)?t:{width:"full"}}};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/components/DashboardWidgetContainer.tsx","../src/versionedClient.ts","../src/containers/DashboardContext.tsx","../src/containers/WidgetContainer.tsx","../src/widgets/projectInfo/ProjectInfo.tsx","../src/widgets/projectUsers/ProjectUsers.tsx","../src/widgets/sanityTutorials/Tutorial.tsx","../src/widgets/sanityTutorials/dataAdapter.ts","../src/widgets/sanityTutorials/SanityTutorials.tsx","../src/components/DashboardLayout.tsx","../src/components/WidgetGroup.tsx","../src/containers/Dashboard.tsx","../src/plugin.tsx","../src/widgets/projectInfo/index.ts","../src/widgets/projectUsers/index.ts","../src/widgets/sanityTutorials/index.ts"],"sourcesContent":["import React, {forwardRef} from 'react'\nimport {Card, Box, Heading} from '@sanity/ui'\nimport styled from 'styled-components'\n\nconst Root = styled(Card)`\n display: flex;\n flex-direction: column;\n justify-content: stretch;\n height: 100%;\n box-sizing: border-box;\n position: relative;\n`\n\nconst Header = styled(Card)`\n position: sticky;\n top: 0;\n z-index: 2;\n border-top-left-radius: inherit;\n border-top-right-radius: inherit;\n`\n\nconst Footer = styled(Card)`\n position: sticky;\n overflow: hidden;\n bottom: 0;\n z-index: 2;\n border-bottom-right-radius: inherit;\n border-bottom-left-radius: inherit;\n margin-top: auto;\n`\n\nconst Content = styled(Box)`\n position: relative;\n z-index: 1;\n height: stretch;\n min-height: 21.5em;\n\n @media (min-width: ${({theme}) => theme.sanity.media[0]}px) {\n overflow-y: auto;\n outline: none;\n }\n`\n\ninterface DashboardWidgetProps {\n header?: string\n children: React.ReactNode\n footer?: React.ReactNode\n}\n\nexport const DashboardWidgetContainer = forwardRef(function DashboardWidgetContainer(\n props: DashboardWidgetProps,\n ref: React.Ref<HTMLDivElement>\n) {\n const {header, children, footer} = props\n\n return (\n <Root radius={3} display=\"flex\" ref={ref}>\n {header && (\n <Header borderBottom paddingX={3} paddingY={4}>\n <Heading size={1} textOverflow=\"ellipsis\">\n {header}\n </Heading>\n </Header>\n )}\n {children && <Content>{children}</Content>}\n {footer && <Footer borderTop>{footer}</Footer>}\n </Root>\n )\n})\n","import {useClient} from 'sanity'\n\nexport function useVersionedClient() {\n return useClient({apiVersion: '1'})\n}\n","import {createContext, useContext} from 'react'\nimport {DashboardConfig} from '../types'\n\nexport const DashboardContext = createContext<DashboardConfig>({widgets: []})\n\nexport function useDashboardConfig(): DashboardConfig {\n return useContext(DashboardContext)\n}\n","import React, {createElement, useMemo} from 'react'\nimport {useDashboardConfig} from './DashboardContext'\nimport {Card} from '@sanity/ui'\nimport {DashboardWidget} from '../types'\n\nexport function WidgetContainer(props: DashboardWidget) {\n const config = useDashboardConfig()\n const layout = useMemo(\n () => ({\n ...(props.layout || {}),\n ...(config.layout || {}),\n }),\n [props.layout, config.layout]\n )\n\n return (\n <Card shadow={1} data-width={layout.width} data-height={layout.height}>\n {createElement(props.component, {})}\n </Card>\n )\n}\n","import React, {useEffect, useMemo, useState} from 'react'\nimport {Box, Card, Stack, Heading, Grid, Label, Text, Code, Button} from '@sanity/ui'\nimport {useVersionedClient} from '../../versionedClient'\nimport {Subscription} from 'rxjs'\nimport {WidgetContainer} from '../../containers/WidgetContainer'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\nimport {DashboardWidget} from '../../types'\n\nexport interface ProjectInfoProps {\n __experimental_before?: DashboardWidget[]\n data: ProjectData[]\n}\n\ninterface App {\n title: string\n rows?: App[]\n value?: string | {error: string}\n}\n\ninterface ProjectData {\n title: string\n category?: string\n}\n\nfunction isUrl(url?: string) {\n return url && /^https?:\\/\\//.test(`${url}`)\n}\n\nfunction getGraphQlUrl(projectId: string, dataset: string) {\n return `https://${projectId}.api.sanity.io/v1/graphql/${dataset}/default`\n}\n\nfunction getGroqUrl(projectId: string, dataset: string) {\n return `https://${projectId}.api.sanity.io/v1/groq/${dataset}`\n}\n\nfunction getManageUrl(projectId: string) {\n return `https://manage.sanity.io/projects/${projectId}`\n}\n\nconst NO_EXPERIMENTAL: DashboardWidget[] = []\nconst NO_DATA: ProjectData[] = []\n\nexport function ProjectInfo(props: ProjectInfoProps) {\n const {__experimental_before = NO_EXPERIMENTAL, data = NO_DATA} = props\n const [studioHost, setStudioHost] = useState<string | {error: string} | undefined>()\n const [graphqlApi, setGraphQlApi] = useState<string | {error: string} | undefined>()\n const versionedClient = useVersionedClient()\n const {projectId = 'unknown', dataset = 'unknown'} = versionedClient.config()\n\n useEffect(() => {\n const subscriptions: Subscription[] = []\n\n subscriptions.push(\n versionedClient.observable\n .request<{studioHost: string}>({uri: `/projects/${projectId}`})\n .subscribe({\n next: (result) => {\n const {studioHost: host} = result\n setStudioHost(host ? `https://${host}.sanity.studio` : undefined)\n },\n error: (error) => {\n console.error('Error while looking for studioHost', error)\n setStudioHost({\n error: 'Something went wrong while looking up studioHost. See console.',\n })\n },\n })\n )\n\n // ping assumed graphql endpoint\n subscriptions.push(\n versionedClient.observable\n .request({\n method: 'HEAD',\n uri: `/graphql/${dataset}/default`,\n })\n .subscribe({\n next: () => setGraphQlApi(getGraphQlUrl(projectId, dataset)),\n error: (error) => {\n if (error.statusCode === 404) {\n setGraphQlApi(undefined)\n } else {\n console.error('Error while looking for graphqlApi', error)\n setGraphQlApi({\n error: 'Something went wrong while looking up graphqlApi. See console.',\n })\n }\n },\n })\n )\n\n return () => {\n subscriptions.forEach((s) => s.unsubscribe())\n }\n }, [dataset, projectId, versionedClient, setGraphQlApi, setStudioHost])\n\n const assembleTableRows = useMemo(() => {\n let result: App[] = [\n {\n title: 'Sanity project',\n rows: [\n {title: 'Project ID', value: projectId},\n {title: 'Dataset', value: dataset},\n ],\n },\n ]\n\n // Handle any apps\n const apps: App[] = [\n studioHost ? {title: 'Studio', value: studioHost} : null,\n ...data.filter((item) => item.category === 'apps'),\n ].filter((a): a is App => !!a)\n if (apps.length > 0) {\n result = result.concat([{title: 'Apps', rows: apps}])\n }\n\n // Handle APIs\n result = result.concat(\n [\n {\n title: 'APIs',\n rows: [\n {title: 'GROQ', value: getGroqUrl(projectId, dataset)},\n {\n title: 'GraphQL',\n value: (typeof graphqlApi === 'object' ? 'Error' : graphqlApi) ?? 'Not deployed',\n },\n ],\n },\n ],\n data.filter((item) => item.category === 'apis')\n )\n\n // Handle whatever else there might be\n const otherStuff: Record<string, ProjectData[]> = {}\n data.forEach((item) => {\n if (item.category && item.category !== 'apps' && item.category !== 'apis') {\n if (!otherStuff[item.category]) {\n otherStuff[item.category] = []\n }\n otherStuff[item.category].push(item)\n }\n })\n Object.keys(otherStuff).forEach((category) => {\n result.push({title: category, rows: otherStuff[category]})\n })\n\n return result\n }, [graphqlApi, studioHost, projectId, dataset, data])\n\n return (\n <>\n {__experimental_before.map((widgetConfig, idx) => (\n <WidgetContainer key={idx} {...widgetConfig} />\n ))}\n <Box height=\"fill\" marginTop={__experimental_before?.length > 0 ? 4 : 0}>\n <DashboardWidgetContainer\n footer={\n <Button\n style={{width: '100%'}}\n paddingX={2}\n paddingY={4}\n mode=\"bleed\"\n tone=\"primary\"\n text=\"Manage project\"\n as=\"a\"\n href={getManageUrl(projectId)}\n />\n }\n >\n <Card\n paddingY={4}\n radius={2}\n role=\"table\"\n aria-label=\"Project info\"\n aria-describedby=\"project_info_table\"\n >\n <Stack space={4}>\n <Box paddingX={3} as=\"header\">\n <Heading size={1} as=\"h2\" id=\"project_info_table\">\n Project info\n </Heading>\n </Box>\n {assembleTableRows.map((item) => {\n if (!item || !item.rows) {\n return null\n }\n\n return (\n <Stack key={item.title} space={3}>\n <Card borderBottom padding={3}>\n <Label size={0} muted role=\"columnheader\">\n {item.title}\n </Label>\n </Card>\n <Stack space={4} paddingX={3} role=\"rowgroup\">\n {item.rows.map((row) => {\n return (\n <Grid key={row.title} columns={2} role=\"row\">\n <Text weight=\"medium\" role=\"rowheader\">\n {row.title}\n </Text>\n {typeof row.value === 'object' && (\n <Text size={1}>{row.value?.error}</Text>\n )}\n {typeof row.value === 'string' && (\n <>\n {isUrl(row.value) ? (\n <Text size={1} role=\"cell\" style={{wordBreak: 'break-word'}}>\n <a href={row.value}>{row.value}</a>\n </Text>\n ) : (\n <Code size={1} role=\"cell\" style={{wordBreak: 'break-word'}}>\n {row.value}\n </Code>\n )}\n </>\n )}\n </Grid>\n )\n })}\n </Stack>\n </Stack>\n )\n })}\n </Stack>\n </Card>\n </DashboardWidgetContainer>\n </Box>\n </>\n )\n}\n","import React, {useCallback, useEffect, useState} from 'react'\nimport {from} from 'rxjs'\nimport {map, switchMap} from 'rxjs/operators'\nimport {Stack, Spinner, Card, Box, Text, Button} from '@sanity/ui'\nimport {RobotIcon} from '@sanity/icons'\nimport styled from 'styled-components'\nimport {DefaultPreview, useUserStore} from 'sanity'\nimport {useVersionedClient} from '../../versionedClient'\nimport {User} from 'sanity'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\n\nconst AvatarWrapper = styled(Card)`\n box-sizing: border-box;\n border-radius: 50%;\n border-color: transparent;\n overflow: hidden;\n width: 100%;\n height: 100%;\n\n & > img {\n width: 100%;\n height: auto;\n }\n`\n\nfunction getInviteUrl(projectId: string) {\n return `https://manage.sanity.io/projects/${projectId}/team/invite`\n}\n\ninterface Member {\n id: string\n role: string\n isRobot: boolean\n}\n\ninterface Project {\n id: string\n members: Member[]\n}\n\nexport function ProjectUsers() {\n const [project, setProject] = useState<Project | undefined>()\n const [users, setUsers] = useState<User[] | undefined>()\n const [error, setError] = useState<Error | undefined>()\n\n const userStore = useUserStore()\n const versionedClient = useVersionedClient()\n\n const fetchData = useCallback(() => {\n const {projectId} = versionedClient.config()\n const subscription = versionedClient.observable\n .request<Project>({\n uri: `/projects/${projectId}`,\n })\n .pipe(\n switchMap((_project) =>\n from(userStore.getUsers(_project.members.map((mem) => mem.id))).pipe(\n map((_users) => ({project: _project, users: _users}))\n )\n )\n )\n .subscribe({\n next: ({users: _users, project: _project}) => {\n setProject(_project)\n setUsers(\n (Array.isArray(_users) ? _users : [_users]).sort((userA, userB) =>\n sortUsersByRobotStatus(userA, userB, _project)\n )\n )\n },\n error: (e: Error) => setError(e),\n })\n\n return () => subscription.unsubscribe()\n }, [userStore, versionedClient])\n\n useEffect(() => fetchData(), [fetchData])\n\n const handleRetryFetch = useCallback(() => fetchData(), [fetchData])\n\n const isLoading = !users || !project\n\n if (error) {\n return (\n <DashboardWidgetContainer header=\"Project users\">\n <Box padding={4}>\n <Text>\n Something went wrong while fetching data. You could{' '}\n <a onClick={handleRetryFetch} title=\"Retry users fetch\" style={{cursor: 'pointer'}}>\n retry\n </a>\n ..?\n </Text>\n </Box>\n </DashboardWidgetContainer>\n )\n }\n\n return (\n <DashboardWidgetContainer\n header=\"Project users\"\n footer={\n <Button\n style={{width: '100%'}}\n paddingX={2}\n paddingY={4}\n mode=\"bleed\"\n tone=\"primary\"\n text=\"Invite members\"\n as=\"a\"\n loading={isLoading}\n href={isLoading ? undefined : getInviteUrl(project.id)}\n />\n }\n >\n {isLoading && (\n <Box paddingY={5} paddingX={2}>\n <Stack space={4}>\n <Text align=\"center\" muted size={1}>\n <Spinner />\n </Text>\n <Text align=\"center\" size={1} muted>\n Loading items...\n </Text>\n </Stack>\n </Box>\n )}\n\n {!isLoading && (\n <Stack space={3} padding={3}>\n {users?.map((user) => {\n const membership = project.members.find((member) => member.id === user.id)\n const media = membership?.isRobot ? (\n <Text size={3}>\n <RobotIcon />\n </Text>\n ) : (\n <AvatarWrapper tone=\"transparent\">\n {user?.imageUrl && <img src={user.imageUrl} alt={user?.displayName} />}\n </AvatarWrapper>\n )\n return (\n <Box key={user.id}>\n <DefaultPreview\n title={user.displayName}\n subtitle={membership?.role}\n media={media}\n />\n </Box>\n )\n })}\n </Stack>\n )}\n </DashboardWidgetContainer>\n )\n}\n\nfunction sortUsersByRobotStatus(userA: User, userB: User, project: Project) {\n const {members} = project\n const membershipA = members.find((member) => member.id === userA?.id)\n const membershipB = members.find((member) => member.id === userB?.id)\n if (membershipA?.isRobot) {\n return 1\n }\n if (membershipB?.isRobot) {\n return -1\n }\n return 0\n}\n","import React from 'react'\nimport {Card, Box, Heading, Flex, Text, Stack} from '@sanity/ui'\nimport {PlayIcon} from '@sanity/icons'\nimport styled from 'styled-components'\n\nconst PlayIconBox = styled(Box)`\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n\n &:before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 2.75em;\n height: 2.75em;\n border-radius: 50%;\n background: ${({theme}) => theme.sanity.color.card.enabled.bg};\n opacity: 0.75;\n }\n`\n\nconst Root = styled(Flex)`\n &:hover {\n ${PlayIconBox} {\n &:before {\n opacity: 1;\n }\n }\n }\n`\n\nconst PosterCard = styled(Card)`\n width: 100%;\n padding-bottom: calc(9 / 16 * 100%);\n position: relative;\n`\n\nconst Poster = styled.img`\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n width: 100%;\n object-fit: cover;\n display: block;\n\n &:not([src]) {\n display: none;\n }\n`\n\nexport interface TutorialProps {\n title: string\n posterURL?: string\n href: string\n showPlayIcon?: boolean\n presenterName?: string\n presenterSubtitle?: string\n}\n\nexport function Tutorial(props: TutorialProps) {\n const {title, posterURL, showPlayIcon, href, presenterName, presenterSubtitle} = props\n\n return (\n <Root flex={1}>\n <Card\n sizing=\"border\"\n flex={1}\n padding={2}\n radius={2}\n as=\"a\"\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{position: 'relative'}}\n >\n <Flex direction=\"column\" style={{height: '100%'}}>\n {posterURL && (\n <PosterCard marginBottom={1}>\n <Poster src={posterURL} />\n {showPlayIcon && (\n <PlayIconBox display=\"flex\">\n <Text align=\"center\">\n <PlayIcon />\n </Text>\n </PlayIconBox>\n )}\n </PosterCard>\n )}\n <Flex direction=\"column\" justify=\"space-between\" paddingY={2} flex={1}>\n <Heading as=\"h3\" size={1}>\n {title}\n </Heading>\n <Box marginTop={4}>\n <Stack space={2} flex={1}>\n <Text size={1}>{presenterName}</Text>\n <Text size={0} style={{opacity: 0.7}}>\n {presenterSubtitle}\n </Text>\n </Stack>\n </Box>\n </Flex>\n </Flex>\n </Card>\n </Root>\n )\n}\n","import {useMemo} from 'react'\nimport {useVersionedClient} from '../../versionedClient'\nimport imageUrlBuilder from '@sanity/image-url'\n\nconst tutorialsProjectConfig = {\n projectId: '3do82whm',\n dataset: 'next',\n}\n\nexport interface Guide {\n _type?: string\n slug?: {current: string}\n presenter?: {\n name?: string\n }\n}\n\nexport interface FeedItem {\n _id: string\n title?: string\n poster?: string\n category?: string\n guideOrTutorial?: Guide\n externalLink?: string\n presenter?: {\n name?: string\n }\n hasVideo?: boolean\n}\n\nexport function useDataAdapter() {\n const versionedClient = useVersionedClient()\n return useMemo(\n () => ({\n getFeed: (templateRepoId: string) => {\n const uri = templateRepoId\n ? `/addons/dashboard?templateRepoId=${templateRepoId}`\n : '/addons/dashboard'\n return versionedClient.observable.request<{items: FeedItem[]}>({\n uri,\n withCredentials: false,\n })\n },\n urlBuilder: imageUrlBuilder(tutorialsProjectConfig),\n }),\n [versionedClient]\n )\n}\n","import React, {useEffect, useState} from 'react'\nimport {Flex} from '@sanity/ui'\nimport {Tutorial} from './Tutorial'\nimport {FeedItem, Guide, useDataAdapter} from './dataAdapter'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\n\nfunction createUrl(slug: {current: string}, type?: string) {\n if (type === 'tutorial') {\n return `https://www.sanity.io/docs/tutorials/${slug.current}`\n } else if (type === 'guide') {\n return `https://www.sanity.io/docs/guides/${slug.current}`\n }\n return false\n}\n\nexport interface SanityTutorialsProps {\n templateRepoId: string\n}\n\nexport function SanityTutorials(props: SanityTutorialsProps) {\n const {templateRepoId} = props\n const [feedItems, setFeedItems] = useState<FeedItem[]>([])\n\n const {getFeed, urlBuilder} = useDataAdapter()\n\n useEffect(() => {\n const subscription = getFeed(templateRepoId).subscribe((response) => {\n setFeedItems(response.items)\n })\n return () => {\n subscription.unsubscribe()\n }\n }, [setFeedItems, getFeed, templateRepoId])\n\n const title = 'Learn about Sanity'\n\n return (\n <DashboardWidgetContainer header={title}>\n <Flex as=\"ul\" overflow=\"auto\" align=\"stretch\" paddingY={2}>\n {feedItems?.map((feedItem, index) => {\n if (!feedItem.title || (!feedItem.guideOrTutorial && !feedItem.externalLink)) {\n return null\n }\n const presenter = feedItem.presenter || feedItem.guideOrTutorial?.presenter || {}\n const subtitle = feedItem.category\n const {guideOrTutorial = {} as Guide} = feedItem\n const href =\n (guideOrTutorial.slug\n ? createUrl(guideOrTutorial.slug, guideOrTutorial._type)\n : feedItem.externalLink) || feedItem.externalLink\n\n return (\n <Flex\n as=\"li\"\n key={feedItem._id}\n paddingRight={index < feedItems?.length - 1 ? 1 : 3}\n paddingLeft={index === 0 ? 3 : 0}\n align=\"stretch\"\n style={{minWidth: 272, width: '30%'}}\n >\n <Tutorial\n title={feedItem.title}\n href={href ?? ''}\n presenterName={presenter.name}\n presenterSubtitle={subtitle}\n showPlayIcon={feedItem.hasVideo}\n posterURL={\n feedItem.poster ? urlBuilder.image(feedItem.poster).height(360).url() : undefined\n }\n />\n </Flex>\n )\n })}\n </Flex>\n </DashboardWidgetContainer>\n )\n}\n","import React, {PropsWithChildren} from 'react'\nimport {Container} from '@sanity/ui'\n\nexport function DashboardLayout(props: PropsWithChildren<{}>) {\n return (\n <Container width={4} padding={4} sizing=\"border\" style={{minHeight: '100%'}}>\n {props.children}\n </Container>\n )\n}\n","import React from 'react'\nimport styled, {css} from 'styled-components'\nimport {Box, Card, Grid, Text} from '@sanity/ui'\nimport {WidgetContainer} from '../containers/WidgetContainer'\nimport {DashboardConfig, LayoutConfig, DashboardWidget} from '../types'\n\nconst media = {\n small: (...args: Parameters<typeof css>) =>\n css`\n @media (min-width: ${({theme}) => theme.sanity.media[0]}px) {\n ${css(...args)}\n }\n `,\n medium: (...args: Parameters<typeof css>) =>\n css`\n @media (min-width: ${({theme}) => theme.sanity.media[2]}px) {\n ${css(...args)}\n }\n `,\n}\n\nconst Root = styled(Grid)`\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n\n & > div {\n overflow: hidden;\n }\n\n & > div[data-width='medium'] {\n ${media.small`\n grid-column: span 2;\n `}\n }\n\n & > div[data-width='large'] {\n ${media.small`\n grid-column: span 2;\n `}\n\n ${media.medium`\n grid-column: span 3;\n `}\n }\n\n & > div[data-width='full'] {\n ${media.small`\n grid-column: 1 / -1;\n `}\n }\n\n & > div[data-height='medium'] {\n ${media.small`\n grid-row: span 2;\n `}\n }\n\n & > div[data-height='large'] {\n ${media.small`\n grid-row: span 2;\n `}\n\n ${media.medium`\n grid-row: span 3;\n `}\n }\n\n & > div[data-height='full'] {\n ${media.medium`\n grid-row: 1 / -1;\n `}\n }\n`\n\nexport interface WidgetGroupProps {\n config: Partial<DashboardConfig>\n}\n\nconst NO_WIDGETS: DashboardWidget[] = []\nconst NO_LAYOUT: LayoutConfig = {}\n\nexport function WidgetGroup(props: WidgetGroupProps) {\n const {\n config: {layout = NO_LAYOUT, widgets = NO_WIDGETS},\n } = props\n return (\n <Root\n autoFlow=\"row dense\"\n data-width={layout.width || 'auto'}\n data-height={layout.height || 'auto'}\n gap={4}\n >\n {widgets.length ? null : (\n <Card padding={4} shadow={1} tone=\"primary\">\n <Text align=\"center\">Add some widgets to populate this space.</Text>\n </Card>\n )}\n {widgets.map((widgetConfig, index) => {\n if (widgetConfig.type === '__experimental_group') {\n return <WidgetGroup key={index} config={widgetConfig} />\n }\n if (widgetConfig.component) {\n return <WidgetContainer key={index} {...widgetConfig} />\n }\n return <Box key={index}>{widgetConfig.name} is missing widget component</Box>\n })}\n </Root>\n )\n}\n","import React from 'react'\nimport {DashboardLayout} from '../components/DashboardLayout'\nimport {WidgetGroup} from '../components/WidgetGroup'\nimport {DashboardContext} from './DashboardContext'\nimport {DashboardConfig} from '../types'\n\nexport function Dashboard({config}: {config: DashboardConfig}) {\n if (!config) {\n return null\n }\n\n return (\n <DashboardContext.Provider value={config}>\n <DashboardLayout>\n <WidgetGroup config={config} />\n </DashboardLayout>\n </DashboardContext.Provider>\n )\n}\n","import React, {CSSProperties} from 'react'\nimport {Dashboard} from './containers/Dashboard'\nimport {definePlugin} from 'sanity'\nimport {DashboardConfig, DashboardWidget, LayoutConfig} from './types'\n\nconst strokeStyle: CSSProperties = {\n stroke: 'currentColor',\n strokeWidth: 1.2,\n}\n\nconst DashboardIcon = () => (\n <svg\n data-sanity-icon\n viewBox=\"0 0 25 25\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n preserveAspectRatio=\"xMidYMid\"\n width=\"1em\"\n height=\"1em\"\n >\n <path d=\"M19.5 19.5H5.5V5.5H19.5V19.5Z\" style={strokeStyle} />\n <path d=\"M5.5 12.5H19.5\" style={strokeStyle} />\n <path d=\"M14.5 19.5V12.5M10.5 12.5V5.5\" style={strokeStyle} />\n </svg>\n)\n\nexport interface DashboardPluginConfig {\n widgets?: DashboardWidget[]\n\n /**\n * Will be used for widgets that do not define a layout directly.\n */\n defaultLayout?: LayoutConfig\n}\n\nexport const dashboardTool = definePlugin<DashboardPluginConfig>((config = {}) => {\n const pluginConfig: DashboardConfig = {\n layout: config.defaultLayout ?? {},\n widgets: config.widgets ?? [],\n }\n\n return {\n name: 'dashboard',\n tools: (prev, context) => {\n return [\n ...prev,\n {\n title: 'Dashboard',\n name: 'dashboard',\n icon: DashboardIcon,\n component: () => <Dashboard config={pluginConfig} />,\n },\n ]\n },\n }\n})\n","import {ProjectInfo} from './ProjectInfo'\nimport {LayoutConfig, DashboardWidget} from '../../types'\n\nexport function projectInfoWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'project-info',\n component: ProjectInfo,\n layout: config?.layout ?? {width: 'medium'},\n }\n}\n","import {ProjectUsers} from './ProjectUsers'\nimport {LayoutConfig, DashboardWidget} from '../../types'\n\nexport function projectUsersWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'project-info',\n component: ProjectUsers,\n layout: config?.layout,\n }\n}\n","import {SanityTutorials} from './SanityTutorials'\nimport {LayoutConfig, DashboardWidget} from '../../types'\n\nexport function sanityTutorialsWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'sanity-tutorials',\n component: SanityTutorials,\n layout: config?.layout ?? {width: 'full'},\n }\n}\n"],"names":["Root","styled","Card","_templateObject","_taggedTemplateLiteral","Header","_templateObject2","Footer","_templateObject3","Content","Box","_templateObject4","_ref","theme","sanity","media","DashboardWidgetContainer","forwardRef","props","ref","header","children","footer","jsxs","radius","display","jsx","borderBottom","paddingX","paddingY","Heading","size","textOverflow","borderTop","useVersionedClient","useClient","apiVersion","DashboardContext","createContext","widgets","WidgetContainer","config","useContext","layout","useMemo","shadow","width","height","createElement","component","getGroqUrl","projectId","dataset","getManageUrl","concat","NO_EXPERIMENTAL","NO_DATA","ProjectInfo","__experimental_before","data","studioHost","setStudioHost","useState","graphqlApi","setGraphQlApi","versionedClient","useEffect","subscriptions","push","observable","request","uri","subscribe","next","result","host","error","console","method","getGraphQlUrl","statusCode","forEach","s","unsubscribe","assembleTableRows","_a","title","rows","value","apps","filter","item","category","a","length","otherStuff","Object","keys","Fragment","map","widgetConfig","idx","_objectSpread","marginTop","Button","style","mode","tone","text","as","href","role","Stack","space","id","padding","Label","muted","row","url","Grid","columns","Text","weight","test","wordBreak","Code","AvatarWrapper","_templateObject5","ProjectUsers","project","setProject","users","setUsers","setError","userStore","useUserStore","fetchData","useCallback","subscription","pipe","switchMap","_project","from","getUsers","members","mem","_users","_ref2","Array","isArray","sort","userA","userB","membershipA","find","member","membershipB","isRobot","sortUsersByRobotStatus","e","handleRetryFetch","isLoading","onClick","cursor","loading","align","Spinner","user","membership","RobotIcon","imageUrl","src","alt","displayName","DefaultPreview","subtitle","PlayIconBox","_templateObject6","_ref3","color","card","enabled","bg","Flex","_templateObject7","PosterCard","_templateObject8","Poster","img","_templateObject9","Tutorial","posterURL","showPlayIcon","presenterName","presenterSubtitle","flex","sizing","target","rel","position","direction","marginBottom","PlayIcon","justify","opacity","tutorialsProjectConfig","SanityTutorials","templateRepoId","feedItems","setFeedItems","getFeed","urlBuilder","withCredentials","imageUrlBuilder","useDataAdapter","response","items","overflow","feedItem","index","guideOrTutorial","externalLink","presenter","slug","type","_type","current","paddingRight","paddingLeft","minWidth","name","hasVideo","poster","image","_id","DashboardLayout","Container","minHeight","css","_templateObject10","_ref4","_templateObject11","_ref5","_templateObject12","_templateObject15","_templateObject18","_templateObject20","NO_WIDGETS","NO_LAYOUT","WidgetGroup","autoFlow","gap","Dashboard","_ref6","Provider","strokeStyle","stroke","strokeWidth","DashboardIcon","viewBox","fill","xmlns","preserveAspectRatio","d","dashboardTool","definePlugin","arguments","undefined","_b","pluginConfig","defaultLayout","tools","prev","context","icon"],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import {ComponentClass} from 'react'
2
+ import {FunctionComponent} from 'react'
3
+ import {Plugin as Plugin_2} from 'sanity'
4
+ import {default as React_2} from 'react'
5
+
6
+ export declare interface DashboardConfig {
7
+ widgets: DashboardWidget[]
8
+ layout?: LayoutConfig
9
+ }
10
+
11
+ export declare interface DashboardPluginConfig {
12
+ widgets?: DashboardWidget[]
13
+ /**
14
+ * Will be used for widgets that do not define a layout directly.
15
+ */
16
+ defaultLayout?: LayoutConfig
17
+ }
18
+
19
+ export declare const dashboardTool: Plugin_2<DashboardPluginConfig>
20
+
21
+ export declare interface DashboardWidget {
22
+ name: string
23
+ type?: '__experimental_group'
24
+ component: FunctionComponent<any> | ComponentClass<any>
25
+ layout?: LayoutConfig
26
+ widgets?: DashboardWidget[]
27
+ }
28
+
29
+ export declare const DashboardWidgetContainer: React_2.ForwardRefExoticComponent<
30
+ DashboardWidgetProps & React_2.RefAttributes<HTMLDivElement>
31
+ >
32
+
33
+ declare interface DashboardWidgetProps {
34
+ header?: string
35
+ children: React_2.ReactNode
36
+ footer?: React_2.ReactNode
37
+ }
38
+
39
+ export declare interface LayoutConfig {
40
+ width?: LayoutSize
41
+ height?: LayoutSize
42
+ }
43
+
44
+ export declare type LayoutSize = 'auto' | 'small' | 'medium' | 'large' | 'full'
45
+
46
+ export declare function projectInfoWidget(config?: {layout?: LayoutConfig}): DashboardWidget
47
+
48
+ export declare function projectUsersWidget(config?: {layout?: LayoutConfig}): DashboardWidget
49
+
50
+ export declare function sanityTutorialsWidget(config?: {layout?: LayoutConfig}): DashboardWidget
51
+
52
+ export {}
package/package.json CHANGED
@@ -1,35 +1,39 @@
1
1
  {
2
2
  "name": "@sanity/dashboard",
3
- "version": "3.0.0-v3-studio.5",
3
+ "version": "3.0.0-v3-studio.7",
4
4
  "description": "Tool for rendering dashboard widgets",
5
- "source": "./src/index.tsx",
5
+ "author": "Sanity.io <hello@sanity.io>",
6
+ "license": "MIT",
7
+ "source": "./src/index.ts",
6
8
  "exports": {
7
9
  ".": {
8
- "require": "./lib/cjs/index.js",
9
- "default": "./lib/esm/index.js"
10
+ "types": "./lib/src/index.d.ts",
11
+ "source": "./src/index.ts",
12
+ "import": "./lib/index.esm.js",
13
+ "require": "./lib/index.js",
14
+ "default": "./lib/index.esm.js"
10
15
  }
11
16
  },
12
- "main": "./lib/cjs/index.js",
13
- "module": "./lib/esm/index.js",
14
- "types": "./lib/types/index.d.ts",
17
+ "main": "./lib/index.js",
18
+ "module": "./lib/index.esm.js",
19
+ "types": "./lib/src/index.d.ts",
15
20
  "files": [
16
21
  "src",
17
22
  "lib",
18
23
  "v2-incompatible.js",
19
24
  "sanity.json"
20
25
  ],
21
- "author": "Sanity.io <hello@sanity.io>",
22
- "license": "MIT",
23
26
  "scripts": {
24
27
  "clean": "rimraf lib",
25
- "prebuild": "npm run clean && plugin-kit verify-package --silent",
26
- "build": "parcel build --no-cache",
27
- "watch": "parcel watch",
28
+ "prebuild": "npm run clean && plugin-kit verify-package --silent && pkg-utils",
29
+ "build": "pkg-utils build",
30
+ "watch": "pkg-utils watch",
28
31
  "link-watch": "plugin-kit link-watch",
29
32
  "format": "prettier src -w",
30
33
  "prepare": "husky install",
31
34
  "compile": "tsc --noEmit",
32
- "prepublishOnly": "npm run build"
35
+ "prepublishOnly": "npm run build",
36
+ "lint": "eslint ."
33
37
  },
34
38
  "keywords": [
35
39
  "sanity",
@@ -42,54 +46,51 @@
42
46
  "sanity-tool"
43
47
  ],
44
48
  "dependencies": {
45
- "@sanity/icons": "^1.3.6",
49
+ "@sanity/icons": "1.3.9-beta.3",
46
50
  "@sanity/image-url": "^1.0.1",
47
51
  "@sanity/incompatible-plugin": "^1.0.4",
48
- "@sanity/ui": "^1.0.0-beta.31",
52
+ "@sanity/ui": "1.0.0-beta.32",
49
53
  "lodash": "^4.17.21",
50
- "rxjs": "^6.5.3"
54
+ "rxjs": "^6.6.7"
51
55
  },
52
56
  "devDependencies": {
53
- "@commitlint/cli": "^17.1.2",
54
- "@commitlint/config-conventional": "^17.1.0",
55
- "@parcel/packager-ts": "^2.7.0",
56
- "@parcel/transformer-typescript-types": "^2.7.0",
57
- "@sanity/plugin-kit": "^1.1.0-ecosystem-preset.5",
58
- "@sanity/semantic-release-preset": "^2.0.1",
59
- "@types/styled-components": "^5.1.25",
60
- "@typescript-eslint/eslint-plugin": "^5.12.0",
61
- "@typescript-eslint/parser": "^5.12.0",
62
- "eslint": "^8.7.0",
63
- "eslint-config-prettier": "^8.3.0",
64
- "eslint-config-sanity": "^5.1.0",
65
- "eslint-plugin-prettier": "4.0.0",
66
- "eslint-plugin-react": "^7.28.0",
67
- "eslint-plugin-react-hooks": "^4.5.0",
57
+ "@commitlint/cli": "^17.2.0",
58
+ "@commitlint/config-conventional": "^17.2.0",
59
+ "@sanity/pkg-utils": "^1.16.2",
60
+ "@sanity/plugin-kit": "^2.0.9",
61
+ "@sanity/semantic-release-preset": "^2.0.2",
62
+ "@types/styled-components": "^5.1.26",
63
+ "@typescript-eslint/eslint-plugin": "^5.42.0",
64
+ "@typescript-eslint/parser": "^5.42.0",
65
+ "eslint": "^8.26.0",
66
+ "eslint-config-prettier": "^8.5.0",
67
+ "eslint-config-sanity": "^6.0.0",
68
+ "eslint-plugin-prettier": "^4.2.1",
69
+ "eslint-plugin-react": "^7.31.10",
70
+ "eslint-plugin-react-hooks": "^4.6.0",
68
71
  "husky": "^8.0.1",
69
72
  "lint-staged": "^13.0.3",
70
- "parcel": "^2.7.0",
71
- "prettier": "^2.5.1",
72
- "react": "^18.0.0",
73
+ "prettier": "^2.7.1",
74
+ "react": "^18.2.0",
73
75
  "rimraf": "^3.0.2",
74
- "sanity": "3.0.0-dev-preview.22",
75
- "styled-components": "^5.3.5",
76
- "typescript": "4.7.3"
76
+ "sanity": "dev-preview || 3.0.0-rc.0",
77
+ "styled-components": "^5.3.6",
78
+ "typescript": "^4.8.4"
77
79
  },
78
80
  "peerDependencies": {
79
- "react": "^18.0.0",
80
- "sanity": "dev-preview || 3.0.0-dev-preview.22",
81
+ "react": "^18",
82
+ "sanity": "dev-preview || 3.0.0-rc.0",
81
83
  "styled-components": "^5.2.0"
82
84
  },
83
85
  "repository": {
84
86
  "type": "git",
85
- "url": "git+https://github.com/sanity-io/dashboard.git",
86
- "directory": "packages/@sanity/dashboard"
87
+ "url": "git@github.com:sanity-io/dashboard.git"
87
88
  },
88
89
  "sanityExchangeUrl": "https://www.sanity.io/exchange/dashboard",
89
90
  "bugs": {
90
91
  "url": "https://github.com/sanity-io/dashboard/issues"
91
92
  },
92
- "homepage": "https://www.sanity.io/",
93
+ "homepage": "https://github.com/sanity-io/dashboard#readme",
93
94
  "directories": {
94
95
  "lib": "lib"
95
96
  },
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ export * from './types'
2
+ export * from './components/DashboardWidgetContainer'
3
+ export * from './widgets/projectInfo'
4
+ export * from './widgets/projectUsers'
5
+ export * from './widgets/sanityTutorials'
6
+
7
+ export {type DashboardPluginConfig, dashboardTool} from './plugin'
@@ -1,6 +1,6 @@
1
1
  import React, {CSSProperties} from 'react'
2
2
  import {Dashboard} from './containers/Dashboard'
3
- import {createPlugin} from 'sanity'
3
+ import {definePlugin} from 'sanity'
4
4
  import {DashboardConfig, DashboardWidget, LayoutConfig} from './types'
5
5
 
6
6
  const strokeStyle: CSSProperties = {
@@ -24,12 +24,6 @@ const DashboardIcon = () => (
24
24
  </svg>
25
25
  )
26
26
 
27
- export * from './types'
28
- export * from './components/DashboardWidgetContainer'
29
- export * from './widgets/projectInfo'
30
- export * from './widgets/projectUsers'
31
- export * from './widgets/sanityTutorials'
32
-
33
27
  export interface DashboardPluginConfig {
34
28
  widgets?: DashboardWidget[]
35
29
 
@@ -39,7 +33,7 @@ export interface DashboardPluginConfig {
39
33
  defaultLayout?: LayoutConfig
40
34
  }
41
35
 
42
- export const dashboardTool = createPlugin<DashboardPluginConfig>((config = {}) => {
36
+ export const dashboardTool = definePlugin<DashboardPluginConfig>((config = {}) => {
43
37
  const pluginConfig: DashboardConfig = {
44
38
  layout: config.defaultLayout ?? {},
45
39
  widgets: config.widgets ?? [],