@sanity/dashboard

6.0.186.0.19
~

Modified (2 files)

Index: package/package.json
===================================================================
--- package/package.json
+++ package/package.json
@@ -1,7 +1,7 @@
 {
   "name": "@sanity/dashboard",
-  "version": "6.0.18",
+  "version": "6.0.19",
   "description": "Tool for rendering dashboard widgets",
   "keywords": [
     "cms",
     "content",
@@ -32,22 +32,22 @@
     ".": "./dist/index.js",
     "./package.json": "./package.json"
   },
   "dependencies": {
-    "@sanity/icons": "^5.2.1",
+    "@sanity/icons": "^5.2.2",
     "@sanity/image-url": "^2.1.1",
-    "@sanity/ui": "^4.0.4",
+    "@sanity/ui": "^4.2.7",
     "rxjs": "^7.8.2"
   },
   "devDependencies": {
     "@sanity/tsconfig": "^2.2.1",
-    "@sanity/tsdown-config": "^0.26.0",
-    "@types/react": "^19.2.18",
-    "@types/react-dom": "^19.2.4",
-    "oxc-transform-react": "^0.145.0",
-    "react": "^19.2.8",
-    "react-dom": "^19.2.8",
-    "sanity": "^6.10.1",
+    "@sanity/tsdown-config": "^0.27.1",
+    "@types/react": "^19.3.0",
+    "@types/react-dom": "^19.3.0",
+    "oxc-transform-react": "^0.147.0",
+    "react": "^19.3.0",
+    "react-dom": "^19.3.0",
+    "sanity": "^6.16.0",
     "styled-components": "^6.5.3",
     "tsdown": "^0.22.14"
   },
   "peerDependencies": {
Index: package/dist/index.js.map
===================================================================
--- package/dist/index.js.map
+++ package/dist/index.js.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"index.js","names":["header && (\n        <Header borderBottom paddingX={3} paddingY={4}>\n          <Heading size={1} textOverflow=\"ellipsis\">\n            {header}\n          </Heading>\n        </Header>\n      )","children && <Content>{children}</Content>","footer && <Footer borderTop>{footer}</Footer>","<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      ...props.layout,\n      ...config.layout,\n    }","layout","useMemo(\n    () => ({\n      ...props.layout,\n      ...config.layout,\n    }),\n    [props.layout, config.layout],\n  )","<Widget />","<Card shadow={1} data-width={layout.width} data-height={layout.height}>\n      <Widget />\n    </Card>","height","width","{apiVersion: '2024-08-01'}","__experimental_before = NO_EXPERIMENTAL","data = NO_DATA","versionedClient.config()","projectId = 'unknown'","dataset = 'unknown'","() => {\n    const subscriptions: Subscription[] = []\n\n    subscriptions.push(\n      versionedClient.observable\n        .request<UserApplication[]>({url: '/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          url: `/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  }","observable","(app) => app.type === 'studio'","error","(s) => s.unsubscribe()","[dataset, projectId, versionedClient, setGraphQLApi]","result","(item) => item.category === 'apps'","app","(item) => item.category === 'apis'","item","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        const group = otherStuff[item.category] ?? []\n        group.push(item)\n        otherStuff[item.category] = group\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])","__experimental_before.map((widgetConfig, idx) => (\n        // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n        <WidgetContainer key={idx} {...widgetConfig} />\n      ))","(widgetConfig, idx) => (\n        // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n        <WidgetContainer key={idx} {...widgetConfig} />\n      )","{width: '100%'}","getManageUrl(projectId)","<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            />","<Box paddingX={3} as=\"header\">\n                <Heading size={1} as=\"h2\" id=\"project_info_table\">\n                  Project info\n                </Heading>\n              </Box>","assembleTableRows.map((item) => {\n                if (!item || !item.rows) {\n                  return null\n                }\n\n                return (\n                  <Stack key={item.title} gap={3}>\n                    <Card borderBottom padding={3}>\n                      <Label size={0} muted>\n                        {item.title}\n                      </Label>\n                    </Card>\n                    <Stack gap={4} paddingX={3}>\n                      {item.rows.map((row) => {\n                        const rowValue = typeof row.value === 'object' ? row.value.error : row.value\n                        return (\n                          <Grid key={`${rowValue ?? ''}-${row.title}`} gridTemplateColumns={2}>\n                            <Text weight=\"medium\">{row.title}</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} style={{wordBreak: 'break-word'}}>\n                                    <a href={row.value}>{row.value}</a>\n                                  </Text>\n                                ) : (\n                                  <Code size={1} style={{wordBreak: 'break-word'}}>\n                                    {row.value}\n                                  </Code>\n                                )}\n                              </>\n                            )}\n                          </Grid>\n                        )\n                      })}\n                    </Stack>\n                  </Stack>\n                )\n              })","(item) => {\n                if (!item || !item.rows) {\n                  return null\n                }\n\n                return (\n                  <Stack key={item.title} gap={3}>\n                    <Card borderBottom padding={3}>\n                      <Label size={0} muted>\n                        {item.title}\n                      </Label>\n                    </Card>\n                    <Stack gap={4} paddingX={3}>\n                      {item.rows.map((row) => {\n                        const rowValue = typeof row.value === 'object' ? row.value.error : row.value\n                        return (\n                          <Grid key={`${rowValue ?? ''}-${row.title}`} gridTemplateColumns={2}>\n                            <Text weight=\"medium\">{row.title}</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} style={{wordBreak: 'break-word'}}>\n                                    <a href={row.value}>{row.value}</a>\n                                  </Text>\n                                ) : (\n                                  <Code size={1} style={{wordBreak: 'break-word'}}>\n                                    {row.value}\n                                  </Code>\n                                )}\n                              </>\n                            )}\n                          </Grid>\n                        )\n                      })}\n                    </Stack>\n                  </Stack>\n                )\n              }","<Card paddingY={4} radius={2} aria-label=\"Project info\">\n            <Stack gap={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} gap={3}>\n                    <Card borderBottom padding={3}>\n                      <Label size={0} muted>\n                        {item.title}\n                      </Label>\n                    </Card>\n                    <Stack gap={4} paddingX={3}>\n                      {item.rows.map((row) => {\n                        const rowValue = typeof row.value === 'object' ? row.value.error : row.value\n                        return (\n                          <Grid key={`${rowValue ?? ''}-${row.title}`} gridTemplateColumns={2}>\n                            <Text weight=\"medium\">{row.title}</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} style={{wordBreak: 'break-word'}}>\n                                    <a href={row.value}>{row.value}</a>\n                                  </Text>\n                                ) : (\n                                  <Code size={1} 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>","<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 paddingY={4} radius={2} aria-label=\"Project info\">\n            <Stack gap={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} gap={3}>\n                    <Card borderBottom padding={3}>\n                      <Label size={0} muted>\n                        {item.title}\n                      </Label>\n                    </Card>\n                    <Stack gap={4} paddingX={3}>\n                      {item.rows.map((row) => {\n                        const rowValue = typeof row.value === 'object' ? row.value.error : row.value\n                        return (\n                          <Grid key={`${rowValue ?? ''}-${row.title}`} gridTemplateColumns={2}>\n                            <Text weight=\"medium\">{row.title}</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} style={{wordBreak: 'break-word'}}>\n                                    <a href={row.value}>{row.value}</a>\n                                  </Text>\n                                ) : (\n                                  <Code size={1} 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>","<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 paddingY={4} radius={2} aria-label=\"Project info\">\n            <Stack gap={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} gap={3}>\n                    <Card borderBottom padding={3}>\n                      <Label size={0} muted>\n                        {item.title}\n                      </Label>\n                    </Card>\n                    <Stack gap={4} paddingX={3}>\n                      {item.rows.map((row) => {\n                        const rowValue = typeof row.value === 'object' ? row.value.error : row.value\n                        return (\n                          <Grid key={`${rowValue ?? ''}-${row.title}`} gridTemplateColumns={2}>\n                            <Text weight=\"medium\">{row.title}</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} style={{wordBreak: 'break-word'}}>\n                                    <a href={row.value}>{row.value}</a>\n                                  </Text>\n                                ) : (\n                                  <Code size={1} 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>","__experimental_before?.length > 0 ? 4 : 0","<>\n      {__experimental_before.map((widgetConfig, idx) => (\n        // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\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 paddingY={4} radius={2} aria-label=\"Project info\">\n            <Stack gap={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} gap={3}>\n                    <Card borderBottom padding={3}>\n                      <Label size={0} muted>\n                        {item.title}\n                      </Label>\n                    </Card>\n                    <Stack gap={4} paddingX={3}>\n                      {item.rows.map((row) => {\n                        const rowValue = typeof row.value === 'object' ? row.value.error : row.value\n                        return (\n                          <Grid key={`${rowValue ?? ''}-${row.title}`} gridTemplateColumns={2}>\n                            <Text weight=\"medium\">{row.title}</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} style={{wordBreak: 'break-word'}}>\n                                    <a href={row.value}>{row.value}</a>\n                                  </Text>\n                                ) : (\n                                  <Code size={1} 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    </>","(row) => {\n                        const rowValue = typeof row.value === 'object' ? row.value.error : row.value\n                        return (\n                          <Grid key={`${rowValue ?? ''}-${row.title}`} gridTemplateColumns={2}>\n                            <Text weight=\"medium\">{row.title}</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} style={{wordBreak: 'break-word'}}>\n                                    <a href={row.value}>{row.value}</a>\n                                  </Text>\n                                ) : (\n                                  <Code size={1} style={{wordBreak: 'break-word'}}>\n                                    {row.value}\n                                  </Code>\n                                )}\n                              </>\n                            )}\n                          </Grid>\n                        )\n                      }","{user, isRobot, roles}: ProjectUserProps","{style: 'narrow'}","<Box flex=\"none\">\n          {isRobot ? (\n            <Text size={2}>\n              <RobotIcon />\n            </Text>\n          ) : (\n            <UserAvatar user={user} />\n          )}\n        </Box>","{color: 'inherit'}","<Text size={1} style={{color: 'inherit'}} textOverflow=\"ellipsis\" weight=\"medium\">\n            {user.displayName}\n          </Text>","displayName","listFormat.format(roles)","<Text muted size={1} textOverflow=\"ellipsis\">\n            {listFormat.format(roles)}\n          </Text>","<Stack flex={1} gap={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>","<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} gap={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    const {projectId} = versionedClient.config()\n    const subscription = versionedClient.observable\n      .request<Project>({\n        url: `/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  }","(mem) => mem.id","_users","_project","{users: _users, project: _project}","useCallback(() => {\n    const {projectId} = versionedClient.config()\n    const subscription = versionedClient.observable\n      .request<Project>({\n        url: `/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])","() => fetchData()","[fetchData]","useCallback(() => fetchData(), [fetchData])","<Text>Something went wrong while fetching data.</Text>","<DashboardWidgetContainer header=\"Project users\">\n        <Box padding={4}>\n          <Stack gap={3}>\n            <Text>Something went wrong while fetching data.</Text>\n            <Box>\n              <Button\n                mode=\"ghost\"\n                text=\"Retry\"\n                title=\"Retry users fetch\"\n                onClick={handleRetryFetch}\n              />\n            </Box>\n          </Stack>\n        </Box>\n      </DashboardWidgetContainer>","{width: '100%'}","isLoading ? undefined : getInviteUrl(project.id)","project.id","<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        />","isLoading && (\n        <Box paddingY={5} paddingX={2}>\n          <Stack gap={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      )","!isLoading && (\n        <Stack gap={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      )","project.members","users?.map","(role) => role.title","<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 gap={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 gap={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>","(templateRepoId: string) => {\n        const url = templateRepoId\n          ? `/addons/dashboard?templateRepoId=${templateRepoId}`\n          : '/addons/dashboard'\n        return versionedClient.observable.request<{items: FeedItem[]}>({\n          url,\n          tag: 'dashboard.sanity-tutorials',\n          withCredentials: false,\n        })\n      }","versionedClient.observable","createImageUrlBuilder(tutorialsProjectConfig)","{\n      getFeed: (templateRepoId: string) => {\n        const url = templateRepoId\n          ? `/addons/dashboard?templateRepoId=${templateRepoId}`\n          : '/addons/dashboard'\n        return versionedClient.observable.request<{items: FeedItem[]}>({\n          url,\n          tag: 'dashboard.sanity-tutorials',\n          withCredentials: false,\n        })\n      },\n      urlBuilder: createImageUrlBuilder(tutorialsProjectConfig),\n    }","useMemo(\n    () => ({\n      getFeed: (templateRepoId: string) => {\n        const url = templateRepoId\n          ? `/addons/dashboard?templateRepoId=${templateRepoId}`\n          : '/addons/dashboard'\n        return versionedClient.observable.request<{items: FeedItem[]}>({\n          url,\n          tag: 'dashboard.sanity-tutorials',\n          withCredentials: false,\n        })\n      },\n      urlBuilder: createImageUrlBuilder(tutorialsProjectConfig),\n    }),\n    [versionedClient],\n  )","{position: 'relative'}","{height: '100%'}","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          )","<Heading as=\"h3\" size={1}>\n              {title}\n            </Heading>","<Text size={1}>{presenterName}</Text>","{opacity: 0.7}","<Text size={0} style={{opacity: 0.7}}>\n                  {presenterSubtitle}\n                </Text>","<Box marginTop={4}>\n              <Stack gap={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>","<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 gap={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>","<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 gap={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>","<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 gap={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    const subscription = getFeed(templateRepoId).subscribe((response) => {\n      setFeedItems(response.items)\n    })\n    return () => {\n      subscription.unsubscribe()\n    }\n  }","[setFeedItems, getFeed, templateRepoId]","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 = {}} = 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        })","guideOrTutorial = {}","feedItems?.map","<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 = {}} = 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>","{children}: {children: React.ReactNode}","{height: '100%', overflowY: 'auto'}","<Container width={4} padding={4} sizing=\"border\" style={{height: '100%', overflowY: 'auto'}}>\n      {children}\n    </Container>","{layout = NO_LAYOUT, widgets = NO_WIDGETS}","layout = NO_LAYOUT","widgets = NO_WIDGETS","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      )","length","widgets.map((widgetConfig, index) => {\n        if (widgetConfig.type === '__experimental_group') {\n          // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n          return <WidgetGroup key={index} config={widgetConfig} />\n        }\n        if (widgetConfig.component) {\n          // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n          return <WidgetContainer key={index} {...widgetConfig} />\n        }\n        // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n        return <Box key={index}>{widgetConfig.name} is missing widget component</Box>\n      })","(widgetConfig, index) => {\n        if (widgetConfig.type === '__experimental_group') {\n          // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n          return <WidgetGroup key={index} config={widgetConfig} />\n        }\n        if (widgetConfig.component) {\n          // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n          return <WidgetContainer key={index} {...widgetConfig} />\n        }\n        // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n        return <Box key={index}>{widgetConfig.name} is missing widget component</Box>\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          // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n          return <WidgetGroup key={index} config={widgetConfig} />\n        }\n        if (widgetConfig.component) {\n          // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n          return <WidgetContainer key={index} {...widgetConfig} />\n        }\n        // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n        return <Box key={index}>{widgetConfig.name} is missing widget component</Box>\n      })}\n    </Root>","layout.width || 'auto'","layout.height || 'auto'","{config}: {config: DashboardConfig}","<DashboardLayout>\n        <WidgetGroup config={config} />\n      </DashboardLayout>","<DashboardContext.Provider value={config}>\n      <DashboardLayout>\n        <WidgetGroup config={config} />\n      </DashboardLayout>\n    </DashboardContext.Provider>","DashboardContext.Provider","<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>"],"sources":["../src/components/DashboardWidgetContainer.tsx","../src/containers/DashboardContext.tsx","../src/containers/WidgetContainer.tsx","../src/versionedClient.ts","../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/dataAdapter.ts","../src/widgets/sanityTutorials/Tutorial.tsx","../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 {Card, Box, Heading} from '@sanity/ui'\nimport {getTheme_v2} from '@sanity/ui/theme'\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}) => getTheme_v2(theme).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  ref?: React.Ref<HTMLDivElement>\n}\n\nexport function DashboardWidgetContainer(props: DashboardWidgetProps) {\n  const {header, children, footer, ref} = 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 {createContext, useContext} from 'react'\n\nimport {type DashboardConfig} from '../types'\n\nexport const DashboardContext = createContext<DashboardConfig>({widgets: []})\n\nexport function useDashboardConfig(): DashboardConfig {\n  return useContext(DashboardContext)\n}\n","import {Card} from '@sanity/ui'\nimport {useMemo} from 'react'\n\nimport {type DashboardWidget} from '../types'\nimport {useDashboardConfig} from './DashboardContext'\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  const Widget = props.component\n\n  return (\n    <Card shadow={1} data-width={layout.width} data-height={layout.height}>\n      <Widget />\n    </Card>\n  )\n}\n","import {useClient} from 'sanity'\n\nexport function useVersionedClient() {\n  return useClient({apiVersion: '2024-08-01'})\n}\n","import {Box, Card, Stack, Heading, Grid, Label, Text, Button} from '@sanity/ui'\nimport {Code} from '@sanity/ui/code'\nimport {useEffect, useMemo, useState} from 'react'\nimport {type Subscription} from 'rxjs'\n\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\nimport {WidgetContainer} from '../../containers/WidgetContainer'\nimport {type DashboardWidget} from '../../types'\nimport {useVersionedClient} from '../../versionedClient'\nimport {type App, type ProjectInfoProps, type ProjectData, type 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[]>({url: '/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          url: `/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        const group = otherStuff[item.category] ?? []\n        group.push(item)\n        otherStuff[item.category] = group\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        // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\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 paddingY={4} radius={2} aria-label=\"Project info\">\n            <Stack gap={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} gap={3}>\n                    <Card borderBottom padding={3}>\n                      <Label size={0} muted>\n                        {item.title}\n                      </Label>\n                    </Card>\n                    <Stack gap={4} paddingX={3}>\n                      {item.rows.map((row) => {\n                        const rowValue = typeof row.value === 'object' ? row.value.error : row.value\n                        return (\n                          <Grid key={`${rowValue ?? ''}-${row.title}`} gridTemplateColumns={2}>\n                            <Text weight=\"medium\">{row.title}</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} style={{wordBreak: 'break-word'}}>\n                                    <a href={row.value}>{row.value}</a>\n                                  </Text>\n                                ) : (\n                                  <Code size={1} 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 {type LayoutConfig, type DashboardWidget} from '../../types'\nimport {ProjectInfo} from './ProjectInfo'\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 {RobotIcon} from '@sanity/icons/Robot'\nimport {Box, Flex, rem, Stack, Text} from '@sanity/ui'\nimport {useListFormat, type User, UserAvatar} from 'sanity'\nimport {styled} from 'styled-components'\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} gap={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 {Stack, Spinner, Box, Text, Button} from '@sanity/ui'\nimport {useCallback, useEffect, useState} from 'react'\nimport {from} from 'rxjs'\nimport {map, switchMap} from 'rxjs/operators'\nimport {type Role, type User, useUserStore} from 'sanity'\n\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\nimport {useVersionedClient} from '../../versionedClient'\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        url: `/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          <Stack gap={3}>\n            <Text>Something went wrong while fetching data.</Text>\n            <Box>\n              <Button\n                mode=\"ghost\"\n                text=\"Retry\"\n                title=\"Retry users fetch\"\n                onClick={handleRetryFetch}\n              />\n            </Box>\n          </Stack>\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 gap={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 gap={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 {type LayoutConfig, type DashboardWidget} from '../../types'\nimport {ProjectUsers} from './ProjectUsers'\n\nexport function projectUsersWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n  return {\n    name: 'project-users',\n    component: ProjectUsers,\n    layout: config?.layout,\n  }\n}\n","import {createImageUrlBuilder} from '@sanity/image-url'\nimport {useMemo} from 'react'\n\nimport {useVersionedClient} from '../../versionedClient'\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 url = templateRepoId\n          ? `/addons/dashboard?templateRepoId=${templateRepoId}`\n          : '/addons/dashboard'\n        return versionedClient.observable.request<{items: FeedItem[]}>({\n          url,\n          tag: 'dashboard.sanity-tutorials',\n          withCredentials: false,\n        })\n      },\n      urlBuilder: createImageUrlBuilder(tutorialsProjectConfig),\n    }),\n    [versionedClient],\n  )\n}\n","import {PlayIcon} from '@sanity/icons/Play'\nimport {Card, Box, Heading, Flex, Text, Stack} from '@sanity/ui'\nimport {getTheme_v2} from '@sanity/ui/theme'\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}) => getTheme_v2(theme).color.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 gap={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 {Flex} from '@sanity/ui'\nimport {useEffect, useState} from 'react'\n\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\nimport {type FeedItem, useDataAdapter} from './dataAdapter'\nimport {Tutorial} from './Tutorial'\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 = {}} = 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 {type LayoutConfig, type DashboardWidget} from '../../types'\nimport {SanityTutorials} from './SanityTutorials'\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 {Container} from '@sanity/ui'\n\nexport function DashboardLayout({children}: {children: React.ReactNode}) {\n  return (\n    <Container width={4} padding={4} sizing=\"border\" style={{height: '100%', overflowY: 'auto'}}>\n      {children}\n    </Container>\n  )\n}\n","import {Box, Card, Grid, Text} from '@sanity/ui'\nimport {getTheme_v2} from '@sanity/ui/theme'\nimport {styled, css} from 'styled-components'\n\nimport {WidgetContainer} from '../containers/WidgetContainer'\nimport {type DashboardConfig, type LayoutConfig, type DashboardWidget} from '../types'\n\nconst media = {\n  small: (...args: Parameters<typeof css>) => css`\n    @media (min-width: ${({theme}) => getTheme_v2(theme).media[0]}px) {\n      ${css(...args)}\n    }\n  `,\n  medium: (...args: Parameters<typeof css>) => css`\n    @media (min-width: ${({theme}) => getTheme_v2(theme).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          // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n          return <WidgetGroup key={index} config={widgetConfig} />\n        }\n        if (widgetConfig.component) {\n          // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n          return <WidgetContainer key={index} {...widgetConfig} />\n        }\n        // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n        return <Box key={index}>{widgetConfig.name} is missing widget component</Box>\n      })}\n    </Root>\n  )\n}\n","import {DashboardLayout} from '../components/DashboardLayout'\nimport {WidgetGroup} from '../components/WidgetGroup'\nimport {type DashboardConfig} from '../types'\nimport {DashboardContext} from './DashboardContext'\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 {type ComponentType, type CSSProperties} from 'react'\nimport {definePlugin} from 'sanity'\n\nimport {Dashboard} from './containers/Dashboard'\nimport {type DashboardConfig, type DashboardWidget, type 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: [\n      {\n        title,\n        name,\n        icon,\n        component: () => <Dashboard config={pluginConfig} />,\n      },\n    ],\n  }\n})\n"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"index.js","names":["header && (\n        <Header borderBottom paddingX={3} paddingY={4}>\n          <Heading size={1} textOverflow=\"ellipsis\">\n            {header}\n          </Heading>\n        </Header>\n      )","children && <Content>{children}</Content>","footer && <Footer borderTop>{footer}</Footer>","<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>","Root","_c","{\n      ...props.layout,\n      ...config.layout,\n    }","layout","useMemo(\n    () => ({\n      ...props.layout,\n      ...config.layout,\n    }),\n    [props.layout, config.layout],\n  )","<Widget />","<Card shadow={1} data-width={layout.width} data-height={layout.height}>\n      <Widget />\n    </Card>","height","width","_c","{apiVersion: '2024-08-01'}","_c","__experimental_before = NO_EXPERIMENTAL","data = NO_DATA","versionedClient.config()","projectId = 'unknown'","dataset = 'unknown'","() => {\n    const subscriptions: Subscription[] = []\n\n    subscriptions.push(\n      versionedClient.observable\n        .request<UserApplication[]>({url: '/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          url: `/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  }","observable","(app) => app.type === 'studio'","error","(s) => s.unsubscribe()","[dataset, projectId, versionedClient, setGraphQLApi]","result","(item) => item.category === 'apps'","app","(item) => item.category === 'apis'","item","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        const group = otherStuff[item.category] ?? []\n        group.push(item)\n        otherStuff[item.category] = group\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])","__experimental_before.map((widgetConfig, idx) => (\n        // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n        <WidgetContainer key={idx} {...widgetConfig} />\n      ))","(widgetConfig, idx) => (\n        // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n        <WidgetContainer key={idx} {...widgetConfig} />\n      )","{width: '100%'}","getManageUrl(projectId)","<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            />","<Box paddingX={3} as=\"header\">\n                <Heading size={1} as=\"h2\" id=\"project_info_table\">\n                  Project info\n                </Heading>\n              </Box>","assembleTableRows.map((item) => {\n                if (!item || !item.rows) {\n                  return null\n                }\n\n                return (\n                  <Stack key={item.title} gap={3}>\n                    <Card borderBottom padding={3}>\n                      <Label size={0} muted>\n                        {item.title}\n                      </Label>\n                    </Card>\n                    <Stack gap={4} paddingX={3}>\n                      {item.rows.map((row) => {\n                        const rowValue = typeof row.value === 'object' ? row.value.error : row.value\n                        return (\n                          <Grid key={`${rowValue ?? ''}-${row.title}`} gridTemplateColumns={2}>\n                            <Text weight=\"medium\">{row.title}</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} style={{wordBreak: 'break-word'}}>\n                                    <a href={row.value}>{row.value}</a>\n                                  </Text>\n                                ) : (\n                                  <Code size={1} style={{wordBreak: 'break-word'}}>\n                                    {row.value}\n                                  </Code>\n                                )}\n                              </>\n                            )}\n                          </Grid>\n                        )\n                      })}\n                    </Stack>\n                  </Stack>\n                )\n              })","(item) => {\n                if (!item || !item.rows) {\n                  return null\n                }\n\n                return (\n                  <Stack key={item.title} gap={3}>\n                    <Card borderBottom padding={3}>\n                      <Label size={0} muted>\n                        {item.title}\n                      </Label>\n                    </Card>\n                    <Stack gap={4} paddingX={3}>\n                      {item.rows.map((row) => {\n                        const rowValue = typeof row.value === 'object' ? row.value.error : row.value\n                        return (\n                          <Grid key={`${rowValue ?? ''}-${row.title}`} gridTemplateColumns={2}>\n                            <Text weight=\"medium\">{row.title}</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} style={{wordBreak: 'break-word'}}>\n                                    <a href={row.value}>{row.value}</a>\n                                  </Text>\n                                ) : (\n                                  <Code size={1} style={{wordBreak: 'break-word'}}>\n                                    {row.value}\n                                  </Code>\n                                )}\n                              </>\n                            )}\n                          </Grid>\n                        )\n                      })}\n                    </Stack>\n                  </Stack>\n                )\n              }","<Card paddingY={4} radius={2} aria-label=\"Project info\">\n            <Stack gap={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} gap={3}>\n                    <Card borderBottom padding={3}>\n                      <Label size={0} muted>\n                        {item.title}\n                      </Label>\n                    </Card>\n                    <Stack gap={4} paddingX={3}>\n                      {item.rows.map((row) => {\n                        const rowValue = typeof row.value === 'object' ? row.value.error : row.value\n                        return (\n                          <Grid key={`${rowValue ?? ''}-${row.title}`} gridTemplateColumns={2}>\n                            <Text weight=\"medium\">{row.title}</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} style={{wordBreak: 'break-word'}}>\n                                    <a href={row.value}>{row.value}</a>\n                                  </Text>\n                                ) : (\n                                  <Code size={1} 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>","<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 paddingY={4} radius={2} aria-label=\"Project info\">\n            <Stack gap={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} gap={3}>\n                    <Card borderBottom padding={3}>\n                      <Label size={0} muted>\n                        {item.title}\n                      </Label>\n                    </Card>\n                    <Stack gap={4} paddingX={3}>\n                      {item.rows.map((row) => {\n                        const rowValue = typeof row.value === 'object' ? row.value.error : row.value\n                        return (\n                          <Grid key={`${rowValue ?? ''}-${row.title}`} gridTemplateColumns={2}>\n                            <Text weight=\"medium\">{row.title}</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} style={{wordBreak: 'break-word'}}>\n                                    <a href={row.value}>{row.value}</a>\n                                  </Text>\n                                ) : (\n                                  <Code size={1} 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>","<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 paddingY={4} radius={2} aria-label=\"Project info\">\n            <Stack gap={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} gap={3}>\n                    <Card borderBottom padding={3}>\n                      <Label size={0} muted>\n                        {item.title}\n                      </Label>\n                    </Card>\n                    <Stack gap={4} paddingX={3}>\n                      {item.rows.map((row) => {\n                        const rowValue = typeof row.value === 'object' ? row.value.error : row.value\n                        return (\n                          <Grid key={`${rowValue ?? ''}-${row.title}`} gridTemplateColumns={2}>\n                            <Text weight=\"medium\">{row.title}</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} style={{wordBreak: 'break-word'}}>\n                                    <a href={row.value}>{row.value}</a>\n                                  </Text>\n                                ) : (\n                                  <Code size={1} 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>","__experimental_before?.length > 0 ? 4 : 0","<>\n      {__experimental_before.map((widgetConfig, idx) => (\n        // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\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 paddingY={4} radius={2} aria-label=\"Project info\">\n            <Stack gap={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} gap={3}>\n                    <Card borderBottom padding={3}>\n                      <Label size={0} muted>\n                        {item.title}\n                      </Label>\n                    </Card>\n                    <Stack gap={4} paddingX={3}>\n                      {item.rows.map((row) => {\n                        const rowValue = typeof row.value === 'object' ? row.value.error : row.value\n                        return (\n                          <Grid key={`${rowValue ?? ''}-${row.title}`} gridTemplateColumns={2}>\n                            <Text weight=\"medium\">{row.title}</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} style={{wordBreak: 'break-word'}}>\n                                    <a href={row.value}>{row.value}</a>\n                                  </Text>\n                                ) : (\n                                  <Code size={1} 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    </>","(row) => {\n                        const rowValue = typeof row.value === 'object' ? row.value.error : row.value\n                        return (\n                          <Grid key={`${rowValue ?? ''}-${row.title}`} gridTemplateColumns={2}>\n                            <Text weight=\"medium\">{row.title}</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} style={{wordBreak: 'break-word'}}>\n                                    <a href={row.value}>{row.value}</a>\n                                  </Text>\n                                ) : (\n                                  <Code size={1} style={{wordBreak: 'break-word'}}>\n                                    {row.value}\n                                  </Code>\n                                )}\n                              </>\n                            )}\n                          </Grid>\n                        )\n                      }","_c","_temp","_temp2","_Fragment","{user, isRobot, roles}: ProjectUserProps","{style: 'narrow'}","<Box flex=\"none\">\n          {isRobot ? (\n            <Text size={2}>\n              <RobotIcon />\n            </Text>\n          ) : (\n            <UserAvatar user={user} />\n          )}\n        </Box>","{color: 'inherit'}","<Text size={1} style={{color: 'inherit'}} textOverflow=\"ellipsis\" weight=\"medium\">\n            {user.displayName}\n          </Text>","displayName","listFormat.format(roles)","<Text muted size={1} textOverflow=\"ellipsis\">\n            {listFormat.format(roles)}\n          </Text>","<Stack flex={1} gap={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>","<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} gap={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>","Root","_c","() => {\n    const {projectId} = versionedClient.config()\n    const subscription = versionedClient.observable\n      .request<Project>({\n        url: `/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  }","(mem) => mem.id","_users","_project","{users: _users, project: _project}","useCallback(() => {\n    const {projectId} = versionedClient.config()\n    const subscription = versionedClient.observable\n      .request<Project>({\n        url: `/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])","() => fetchData()","[fetchData]","useCallback(() => fetchData(), [fetchData])","<Text>Something went wrong while fetching data.</Text>","<DashboardWidgetContainer header=\"Project users\">\n        <Box padding={4}>\n          <Stack gap={3}>\n            <Text>Something went wrong while fetching data.</Text>\n            <Box>\n              <Button\n                mode=\"ghost\"\n                text=\"Retry\"\n                title=\"Retry users fetch\"\n                onClick={handleRetryFetch}\n              />\n            </Box>\n          </Stack>\n        </Box>\n      </DashboardWidgetContainer>","{width: '100%'}","isLoading ? undefined : getInviteUrl(project.id)","project.id","<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        />","isLoading && (\n        <Box paddingY={5} paddingX={2}>\n          <Stack gap={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      )","!isLoading && (\n        <Stack gap={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      )","project.members","users?.map","(role) => role.title","<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 gap={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 gap={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>","_c","_temp","(templateRepoId: string) => {\n        const url = templateRepoId\n          ? `/addons/dashboard?templateRepoId=${templateRepoId}`\n          : '/addons/dashboard'\n        return versionedClient.observable.request<{items: FeedItem[]}>({\n          url,\n          tag: 'dashboard.sanity-tutorials',\n          withCredentials: false,\n        })\n      }","versionedClient.observable","createImageUrlBuilder(tutorialsProjectConfig)","{\n      getFeed: (templateRepoId: string) => {\n        const url = templateRepoId\n          ? `/addons/dashboard?templateRepoId=${templateRepoId}`\n          : '/addons/dashboard'\n        return versionedClient.observable.request<{items: FeedItem[]}>({\n          url,\n          tag: 'dashboard.sanity-tutorials',\n          withCredentials: false,\n        })\n      },\n      urlBuilder: createImageUrlBuilder(tutorialsProjectConfig),\n    }","useMemo(\n    () => ({\n      getFeed: (templateRepoId: string) => {\n        const url = templateRepoId\n          ? `/addons/dashboard?templateRepoId=${templateRepoId}`\n          : '/addons/dashboard'\n        return versionedClient.observable.request<{items: FeedItem[]}>({\n          url,\n          tag: 'dashboard.sanity-tutorials',\n          withCredentials: false,\n        })\n      },\n      urlBuilder: createImageUrlBuilder(tutorialsProjectConfig),\n    }),\n    [versionedClient],\n  )","_c","{position: 'relative'}","{height: '100%'}","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          )","<Heading as=\"h3\" size={1}>\n              {title}\n            </Heading>","<Text size={1}>{presenterName}</Text>","{opacity: 0.7}","<Text size={0} style={{opacity: 0.7}}>\n                  {presenterSubtitle}\n                </Text>","<Box marginTop={4}>\n              <Stack gap={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>","<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 gap={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>","<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 gap={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>","<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 gap={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>","Root","_c","[]","() => {\n    const subscription = getFeed(templateRepoId).subscribe((response) => {\n      setFeedItems(response.items)\n    })\n    return () => {\n      subscription.unsubscribe()\n    }\n  }","[setFeedItems, getFeed, templateRepoId]","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 = {}} = 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        })","guideOrTutorial = {}","feedItems?.map","<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 = {}} = 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>","_c","{children}: {children: React.ReactNode}","{height: '100%', overflowY: 'auto'}","<Container width={4} padding={4} sizing=\"border\" style={{height: '100%', overflowY: 'auto'}}>\n      {children}\n    </Container>","_c","{layout = NO_LAYOUT, widgets = NO_WIDGETS}","layout = NO_LAYOUT","widgets = NO_WIDGETS","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      )","length","widgets.map((widgetConfig, index) => {\n        if (widgetConfig.type === '__experimental_group') {\n          // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n          return <WidgetGroup key={index} config={widgetConfig} />\n        }\n        if (widgetConfig.component) {\n          // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n          return <WidgetContainer key={index} {...widgetConfig} />\n        }\n        // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n        return <Box key={index}>{widgetConfig.name} is missing widget component</Box>\n      })","(widgetConfig, index) => {\n        if (widgetConfig.type === '__experimental_group') {\n          // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n          return <WidgetGroup key={index} config={widgetConfig} />\n        }\n        if (widgetConfig.component) {\n          // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n          return <WidgetContainer key={index} {...widgetConfig} />\n        }\n        // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n        return <Box key={index}>{widgetConfig.name} is missing widget component</Box>\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          // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n          return <WidgetGroup key={index} config={widgetConfig} />\n        }\n        if (widgetConfig.component) {\n          // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n          return <WidgetContainer key={index} {...widgetConfig} />\n        }\n        // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n        return <Box key={index}>{widgetConfig.name} is missing widget component</Box>\n      })}\n    </Root>","layout.width || 'auto'","layout.height || 'auto'","_c","{config}: {config: DashboardConfig}","<DashboardLayout>\n        <WidgetGroup config={config} />\n      </DashboardLayout>","<DashboardContext.Provider value={config}>\n      <DashboardLayout>\n        <WidgetGroup config={config} />\n      </DashboardLayout>\n    </DashboardContext.Provider>","DashboardContext.Provider","_c","<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>","_c"],"sources":["../src/components/DashboardWidgetContainer.tsx","../src/containers/DashboardContext.tsx","../src/containers/WidgetContainer.tsx","../src/versionedClient.ts","../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/dataAdapter.ts","../src/widgets/sanityTutorials/Tutorial.tsx","../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 {Card, Box, Heading} from '@sanity/ui'\nimport {getTheme_v2} from '@sanity/ui/theme'\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}) => getTheme_v2(theme).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  ref?: React.Ref<HTMLDivElement>\n}\n\nexport function DashboardWidgetContainer(props: DashboardWidgetProps) {\n  const {header, children, footer, ref} = 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 {createContext, useContext} from 'react'\n\nimport {type DashboardConfig} from '../types'\n\nexport const DashboardContext = createContext<DashboardConfig>({widgets: []})\n\nexport function useDashboardConfig(): DashboardConfig {\n  return useContext(DashboardContext)\n}\n","import {Card} from '@sanity/ui'\nimport {useMemo} from 'react'\n\nimport {type DashboardWidget} from '../types'\nimport {useDashboardConfig} from './DashboardContext'\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  const Widget = props.component\n\n  return (\n    <Card shadow={1} data-width={layout.width} data-height={layout.height}>\n      <Widget />\n    </Card>\n  )\n}\n","import {useClient} from 'sanity'\n\nexport function useVersionedClient() {\n  return useClient({apiVersion: '2024-08-01'})\n}\n","import {Box, Card, Stack, Heading, Grid, Label, Text, Button} from '@sanity/ui'\nimport {Code} from '@sanity/ui/code'\nimport {useEffect, useMemo, useState} from 'react'\nimport {type Subscription} from 'rxjs'\n\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\nimport {WidgetContainer} from '../../containers/WidgetContainer'\nimport {type DashboardWidget} from '../../types'\nimport {useVersionedClient} from '../../versionedClient'\nimport {type App, type ProjectInfoProps, type ProjectData, type 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[]>({url: '/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          url: `/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        const group = otherStuff[item.category] ?? []\n        group.push(item)\n        otherStuff[item.category] = group\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        // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\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 paddingY={4} radius={2} aria-label=\"Project info\">\n            <Stack gap={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} gap={3}>\n                    <Card borderBottom padding={3}>\n                      <Label size={0} muted>\n                        {item.title}\n                      </Label>\n                    </Card>\n                    <Stack gap={4} paddingX={3}>\n                      {item.rows.map((row) => {\n                        const rowValue = typeof row.value === 'object' ? row.value.error : row.value\n                        return (\n                          <Grid key={`${rowValue ?? ''}-${row.title}`} gridTemplateColumns={2}>\n                            <Text weight=\"medium\">{row.title}</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} style={{wordBreak: 'break-word'}}>\n                                    <a href={row.value}>{row.value}</a>\n                                  </Text>\n                                ) : (\n                                  <Code size={1} 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 {type LayoutConfig, type DashboardWidget} from '../../types'\nimport {ProjectInfo} from './ProjectInfo'\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 {RobotIcon} from '@sanity/icons/Robot'\nimport {Box, Flex, rem, Stack, Text} from '@sanity/ui'\nimport {useListFormat, type User, UserAvatar} from 'sanity'\nimport {styled} from 'styled-components'\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} gap={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 {Stack, Spinner, Box, Text, Button} from '@sanity/ui'\nimport {useCallback, useEffect, useState} from 'react'\nimport {from} from 'rxjs'\nimport {map, switchMap} from 'rxjs/operators'\nimport {type Role, type User, useUserStore} from 'sanity'\n\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\nimport {useVersionedClient} from '../../versionedClient'\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        url: `/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          <Stack gap={3}>\n            <Text>Something went wrong while fetching data.</Text>\n            <Box>\n              <Button\n                mode=\"ghost\"\n                text=\"Retry\"\n                title=\"Retry users fetch\"\n                onClick={handleRetryFetch}\n              />\n            </Box>\n          </Stack>\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 gap={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 gap={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 {type LayoutConfig, type DashboardWidget} from '../../types'\nimport {ProjectUsers} from './ProjectUsers'\n\nexport function projectUsersWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n  return {\n    name: 'project-users',\n    component: ProjectUsers,\n    layout: config?.layout,\n  }\n}\n","import {createImageUrlBuilder} from '@sanity/image-url'\nimport {useMemo} from 'react'\n\nimport {useVersionedClient} from '../../versionedClient'\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 url = templateRepoId\n          ? `/addons/dashboard?templateRepoId=${templateRepoId}`\n          : '/addons/dashboard'\n        return versionedClient.observable.request<{items: FeedItem[]}>({\n          url,\n          tag: 'dashboard.sanity-tutorials',\n          withCredentials: false,\n        })\n      },\n      urlBuilder: createImageUrlBuilder(tutorialsProjectConfig),\n    }),\n    [versionedClient],\n  )\n}\n","import {PlayIcon} from '@sanity/icons/Play'\nimport {Card, Box, Heading, Flex, Text, Stack} from '@sanity/ui'\nimport {getTheme_v2} from '@sanity/ui/theme'\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}) => getTheme_v2(theme).color.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 gap={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 {Flex} from '@sanity/ui'\nimport {useEffect, useState} from 'react'\n\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\nimport {type FeedItem, useDataAdapter} from './dataAdapter'\nimport {Tutorial} from './Tutorial'\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 = {}} = 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 {type LayoutConfig, type DashboardWidget} from '../../types'\nimport {SanityTutorials} from './SanityTutorials'\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 {Container} from '@sanity/ui'\n\nexport function DashboardLayout({children}: {children: React.ReactNode}) {\n  return (\n    <Container width={4} padding={4} sizing=\"border\" style={{height: '100%', overflowY: 'auto'}}>\n      {children}\n    </Container>\n  )\n}\n","import {Box, Card, Grid, Text} from '@sanity/ui'\nimport {getTheme_v2} from '@sanity/ui/theme'\nimport {styled, css} from 'styled-components'\n\nimport {WidgetContainer} from '../containers/WidgetContainer'\nimport {type DashboardConfig, type LayoutConfig, type DashboardWidget} from '../types'\n\nconst media = {\n  small: (...args: Parameters<typeof css>) => css`\n    @media (min-width: ${({theme}) => getTheme_v2(theme).media[0]}px) {\n      ${css(...args)}\n    }\n  `,\n  medium: (...args: Parameters<typeof css>) => css`\n    @media (min-width: ${({theme}) => getTheme_v2(theme).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          // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n          return <WidgetGroup key={index} config={widgetConfig} />\n        }\n        if (widgetConfig.component) {\n          // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n          return <WidgetContainer key={index} {...widgetConfig} />\n        }\n        // eslint-disable-next-line react/no-array-index-key -- static widget config never reorders\n        return <Box key={index}>{widgetConfig.name} is missing widget component</Box>\n      })}\n    </Root>\n  )\n}\n","import {DashboardLayout} from '../components/DashboardLayout'\nimport {WidgetGroup} from '../components/WidgetGroup'\nimport {type DashboardConfig} from '../types'\nimport {DashboardContext} from './DashboardContext'\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 {type ComponentType, type CSSProperties} from 'react'\nimport {definePlugin} from 'sanity'\n\nimport {Dashboard} from './containers/Dashboard'\nimport {type DashboardConfig, type DashboardWidget, type 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: [\n      {\n        title,\n        name,\n        icon,\n        component: () => <Dashboard config={pluginConfig} />,\n      },\n    ],\n  }\n})\n"],"mappings":"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"}
\ No newline at end of file