{"version":3,"file":"index.mjs","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/ProjectUser.tsx","../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: '2024-08-01'})\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 {type DashboardWidget} from '../../types'\nimport {type App, type ProjectInfoProps, type ProjectData, UserApplication} from './types'\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 [studioApps, setStudioApps] = useState<UserApplication[] | {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<UserApplication[]>({uri: '/user-applications', tag: 'dashboard.project-info'})\n        .subscribe({\n          next: (result) => setStudioApps(result.filter((app) => app.type === 'studio')),\n          error: (error) => {\n            console.error('Error while resolving user applications', error)\n            setStudioApps({\n              error: 'Something went wrong while resolving user applications. 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          tag: 'dashboard.project-info.graphql-api',\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])\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    const apps: App[] = data.filter((item) => item.category === 'apps')\n\n    // Handle studios\n    ;(Array.isArray(studioApps) ? studioApps : []).forEach((app) => {\n      apps.push({\n        title: app.title || 'Studio',\n        value: app.urlType === 'internal' ? `https://${app.appHost}.sanity.studio` : app.appHost,\n      })\n    })\n\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, studioApps, 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.value}-${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 {type LayoutConfig, type 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 from 'react'\nimport {Box, Flex, rem, Stack, Text} from '@sanity/ui'\nimport {styled} from 'styled-components'\nimport {useListFormat, type User, UserAvatar} from 'sanity'\nimport {RobotIcon} from '@sanity/icons'\n\nconst Root = styled(Flex)`\n  height: ${rem(33)}; // 33 = PREVIEW_SIZES.default.media.height\n  box-sizing: content-box;\n`\n\nexport interface ProjectUserProps {\n  user: User\n  isRobot: boolean\n  roles: string[]\n}\n\nexport function ProjectUser({user, isRobot, roles}: ProjectUserProps) {\n  const listFormat = useListFormat({style: 'narrow'})\n  return (\n    <Root align=\"center\">\n      <Flex align=\"center\" flex={1} gap={2}>\n        <Box flex=\"none\">\n          {isRobot ? (\n            <Text size={2}>\n              <RobotIcon />\n            </Text>\n          ) : (\n            <UserAvatar user={user} />\n          )}\n        </Box>\n\n        <Stack flex={1} space={2}>\n          <Text size={1} style={{color: 'inherit'}} textOverflow=\"ellipsis\" weight=\"medium\">\n            {user.displayName}\n          </Text>\n\n          <Text muted size={1} textOverflow=\"ellipsis\">\n            {listFormat.format(roles)}\n          </Text>\n        </Stack>\n      </Flex>\n    </Root>\n  )\n}\n","import React, {useCallback, useEffect, useState} from 'react'\nimport {from} from 'rxjs'\nimport {map, switchMap} from 'rxjs/operators'\nimport {Stack, Spinner, Box, Text, Button} from '@sanity/ui'\nimport {Role, useUserStore} from 'sanity'\nimport {useVersionedClient} from '../../versionedClient'\nimport {User} from 'sanity'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\nimport {ProjectUser} from './ProjectUser'\n\nfunction getInviteUrl(projectId: string) {\n  return `https://manage.sanity.io/projects/${projectId}/members`\n}\n\ninterface Member {\n  id: string\n  roles: Role[]\n  isRobot: boolean\n  isCurrentUser: boolean\n  createdAt: string\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        tag: 'dashboard.project-users',\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=\"Manage 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            return (\n              <ProjectUser\n                key={user.id}\n                user={user}\n                isRobot={membership?.isRobot ?? false}\n                roles={membership?.roles.map((role) => role.title) || []}\n              />\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\n  // On ties, sort by when the user was added\n  if (membershipA?.isRobot === membershipB?.isRobot) {\n    return (membershipA?.createdAt || '') > (membershipB?.createdAt || '') ? 1 : -1\n  }\n\n  // Robots go to the bottom\n  return membershipA?.isRobot ? 1 : -1\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          tag: 'dashboard.sanity-tutorials',\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={{height: '100%', overflowY: 'auto'}}>\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>) => css`\n    @media (min-width: ${({theme}) => theme.sanity.media[0]}px) {\n      ${css(...args)}\n    }\n  `,\n  medium: (...args: Parameters<typeof css>) => 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, {ComponentType, 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  /**\n   * Dashboard tool title\n   */\n  title?: string\n  /**\n   * Dashboard tool name (used in url path)\n   */\n  name?: string\n  /**\n   * Dashboard tool icon\n   */\n  icon?: ComponentType\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  const title = config.title ?? 'Dashboard'\n  const name = config.name ?? 'dashboard'\n  const icon = config.icon ?? DashboardIcon\n\n  return {\n    name: 'dashboard',\n    tools: (prev, context) => {\n      return [\n        ...prev,\n        {\n          title,\n          name,\n          icon,\n          component: () => <Dashboard config={pluginConfig} />,\n        },\n      ]\n    },\n  }\n})\n"],"names":["Root"],"mappings":"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"}