@sanity/dashboard 4.1.0 → 4.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -51,16 +51,29 @@ const DashboardContext = react.createContext({ widgets: [] });
51
51
  function useDashboardConfig() {
52
52
  return react.useContext(DashboardContext);
53
53
  }
54
+ var __defProp$2 = Object.defineProperty, __getOwnPropSymbols$2 = Object.getOwnPropertySymbols, __hasOwnProp$2 = Object.prototype.hasOwnProperty, __propIsEnum$2 = Object.prototype.propertyIsEnumerable, __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$2 = (a, b) => {
55
+ for (var prop in b || (b = {}))
56
+ __hasOwnProp$2.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
57
+ if (__getOwnPropSymbols$2)
58
+ for (var prop of __getOwnPropSymbols$2(b))
59
+ __propIsEnum$2.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
60
+ return a;
61
+ };
54
62
  function WidgetContainer(props) {
55
63
  const config = useDashboardConfig(), layout = react.useMemo(
56
- () => ({
57
- ...props.layout || {},
58
- ...config.layout || {}
59
- }),
64
+ () => __spreadValues$2(__spreadValues$2({}, props.layout || {}), config.layout || {}),
60
65
  [props.layout, config.layout]
61
66
  );
62
67
  return /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { shadow: 1, "data-width": layout.width, "data-height": layout.height, children: react.createElement(props.component, {}) });
63
68
  }
69
+ var __defProp$1 = Object.defineProperty, __getOwnPropSymbols$1 = Object.getOwnPropertySymbols, __hasOwnProp$1 = Object.prototype.hasOwnProperty, __propIsEnum$1 = Object.prototype.propertyIsEnumerable, __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$1 = (a, b) => {
70
+ for (var prop in b || (b = {}))
71
+ __hasOwnProp$1.call(b, prop) && __defNormalProp$1(a, prop, b[prop]);
72
+ if (__getOwnPropSymbols$1)
73
+ for (var prop of __getOwnPropSymbols$1(b))
74
+ __propIsEnum$1.call(b, prop) && __defNormalProp$1(a, prop, b[prop]);
75
+ return a;
76
+ };
64
77
  function isUrl(url) {
65
78
  return url && /^https?:\/\//.test(`${url}`);
66
79
  }
@@ -105,6 +118,7 @@ function ProjectInfo(props) {
105
118
  };
106
119
  }, [dataset, projectId, versionedClient, setGraphQLApi]);
107
120
  const assembleTableRows = react.useMemo(() => {
121
+ var _a;
108
122
  let result = [
109
123
  {
110
124
  title: "Sanity project",
@@ -128,7 +142,7 @@ function ProjectInfo(props) {
128
142
  { title: "GROQ", value: getGroqUrl(projectId, dataset) },
129
143
  {
130
144
  title: "GraphQL",
131
- value: (typeof graphQLApi == "object" ? "Error" : graphQLApi) ?? "Not deployed"
145
+ value: (_a = typeof graphQLApi == "object" ? "Error" : graphQLApi) != null ? _a : "Not deployed"
132
146
  }
133
147
  ]
134
148
  }
@@ -143,8 +157,8 @@ function ProjectInfo(props) {
143
157
  }), result;
144
158
  }, [graphQLApi, studioApps, projectId, dataset, data]);
145
159
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
146
- __experimental_before.map((widgetConfig, idx) => /* @__PURE__ */ jsxRuntime.jsx(WidgetContainer, { ...widgetConfig }, idx)),
147
- /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { height: "fill", marginTop: __experimental_before?.length > 0 ? 4 : 0, children: /* @__PURE__ */ jsxRuntime.jsx(
160
+ __experimental_before.map((widgetConfig, idx) => /* @__PURE__ */ jsxRuntime.jsx(WidgetContainer, __spreadValues$1({}, widgetConfig), idx)),
161
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { height: "fill", marginTop: (__experimental_before == null ? void 0 : __experimental_before.length) > 0 ? 4 : 0, children: /* @__PURE__ */ jsxRuntime.jsx(
148
162
  DashboardWidgetContainer,
149
163
  {
150
164
  footer: /* @__PURE__ */ jsxRuntime.jsx(
@@ -172,11 +186,14 @@ function ProjectInfo(props) {
172
186
  /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { paddingX: 3, as: "header", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { size: 1, as: "h2", id: "project_info_table", children: "Project info" }) }),
173
187
  assembleTableRows.map((item) => !item || !item.rows ? null : /* @__PURE__ */ jsxRuntime.jsxs(ui.Stack, { space: 3, children: [
174
188
  /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { borderBottom: !0, padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { size: 0, muted: !0, role: "columnheader", children: item.title }) }),
175
- /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 4, paddingX: 3, role: "rowgroup", children: item.rows.map((row) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Grid, { columns: 2, role: "row", children: [
176
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "medium", role: "rowheader", children: row.title }),
177
- typeof row.value == "object" && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: row.value?.error }),
178
- typeof row.value == "string" && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: isUrl(row.value) ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, role: "cell", style: { wordBreak: "break-word" }, children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: row.value, children: row.value }) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Code, { size: 1, role: "cell", style: { wordBreak: "break-word" }, children: row.value }) })
179
- ] }, `${row.value}-${row.title}`)) })
189
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 4, paddingX: 3, role: "rowgroup", children: item.rows.map((row) => {
190
+ var _a;
191
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Grid, { columns: 2, role: "row", children: [
192
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { weight: "medium", role: "rowheader", children: row.title }),
193
+ typeof row.value == "object" && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: (_a = row.value) == null ? void 0 : _a.error }),
194
+ typeof row.value == "string" && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: isUrl(row.value) ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, role: "cell", style: { wordBreak: "break-word" }, children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: row.value, children: row.value }) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Code, { size: 1, role: "cell", style: { wordBreak: "break-word" }, children: row.value }) })
195
+ ] }, `${row.value}-${row.title}`);
196
+ }) })
180
197
  ] }, item.title))
181
198
  ] })
182
199
  }
@@ -186,10 +203,11 @@ function ProjectInfo(props) {
186
203
  ] });
187
204
  }
188
205
  function projectInfoWidget(config) {
206
+ var _a;
189
207
  return {
190
208
  name: "project-info",
191
209
  component: ProjectInfo,
192
- layout: config?.layout ?? { width: "medium" }
210
+ layout: (_a = config == null ? void 0 : config.layout) != null ? _a : { width: "medium" }
193
211
  };
194
212
  }
195
213
  const Root$2 = styledComponents.styled(ui.Flex)`
@@ -262,14 +280,15 @@ function ProjectUsers() {
262
280
  /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { align: "center", muted: !0, size: 1, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Spinner, {}) }),
263
281
  /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { align: "center", size: 1, muted: !0, children: "Loading items\u2026" })
264
282
  ] }) }),
265
- !isLoading && /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 3, padding: 3, children: users?.map((user) => {
283
+ !isLoading && /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { space: 3, padding: 3, children: users == null ? void 0 : users.map((user) => {
284
+ var _a;
266
285
  const membership = project.members.find((member) => member.id === user.id);
267
286
  return /* @__PURE__ */ jsxRuntime.jsx(
268
287
  ProjectUser,
269
288
  {
270
289
  user,
271
- isRobot: membership?.isRobot ?? !1,
272
- roles: membership?.roles.map((role) => role.title) || []
290
+ isRobot: (_a = membership == null ? void 0 : membership.isRobot) != null ? _a : !1,
291
+ roles: (membership == null ? void 0 : membership.roles.map((role) => role.title)) || []
273
292
  },
274
293
  user.id
275
294
  );
@@ -279,14 +298,14 @@ function ProjectUsers() {
279
298
  );
280
299
  }
281
300
  function sortUsersByRobotStatus(userA, userB, project) {
282
- const { members } = project, membershipA = members.find((member) => member.id === userA?.id), membershipB = members.find((member) => member.id === userB?.id);
283
- return membershipA?.isRobot === membershipB?.isRobot ? (membershipA?.createdAt || "") > (membershipB?.createdAt || "") ? 1 : -1 : membershipA?.isRobot ? 1 : -1;
301
+ const { members } = project, membershipA = members.find((member) => member.id === (userA == null ? void 0 : userA.id)), membershipB = members.find((member) => member.id === (userB == null ? void 0 : userB.id));
302
+ return (membershipA == null ? void 0 : membershipA.isRobot) === (membershipB == null ? void 0 : membershipB.isRobot) ? ((membershipA == null ? void 0 : membershipA.createdAt) || "") > ((membershipB == null ? void 0 : membershipB.createdAt) || "") ? 1 : -1 : membershipA != null && membershipA.isRobot ? 1 : -1;
284
303
  }
285
304
  function projectUsersWidget(config) {
286
305
  return {
287
306
  name: "project-info",
288
307
  component: ProjectUsers,
289
- layout: config?.layout
308
+ layout: config == null ? void 0 : config.layout
290
309
  };
291
310
  }
292
311
  const PlayIconBox = styledComponents.styled(ui.Box)`
@@ -395,15 +414,16 @@ function SanityTutorials(props) {
395
414
  return () => {
396
415
  subscription.unsubscribe();
397
416
  };
398
- }, [setFeedItems, getFeed, templateRepoId]), /* @__PURE__ */ jsxRuntime.jsx(DashboardWidgetContainer, { header: "Learn about Sanity", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { as: "ul", overflow: "auto", align: "stretch", paddingY: 2, children: feedItems?.map((feedItem, index) => {
417
+ }, [setFeedItems, getFeed, templateRepoId]), /* @__PURE__ */ jsxRuntime.jsx(DashboardWidgetContainer, { header: "Learn about Sanity", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { as: "ul", overflow: "auto", align: "stretch", paddingY: 2, children: feedItems == null ? void 0 : feedItems.map((feedItem, index) => {
418
+ var _a;
399
419
  if (!feedItem.title || !feedItem.guideOrTutorial && !feedItem.externalLink)
400
420
  return null;
401
- const presenter = feedItem.presenter || feedItem.guideOrTutorial?.presenter || {}, subtitle = feedItem.category, { guideOrTutorial = {} } = feedItem, href = (guideOrTutorial.slug ? createUrl(guideOrTutorial.slug, guideOrTutorial._type) : feedItem.externalLink) || feedItem.externalLink;
421
+ const presenter = feedItem.presenter || ((_a = feedItem.guideOrTutorial) == null ? void 0 : _a.presenter) || {}, subtitle = feedItem.category, { guideOrTutorial = {} } = feedItem, href = (guideOrTutorial.slug ? createUrl(guideOrTutorial.slug, guideOrTutorial._type) : feedItem.externalLink) || feedItem.externalLink;
402
422
  return /* @__PURE__ */ jsxRuntime.jsx(
403
423
  ui.Flex,
404
424
  {
405
425
  as: "li",
406
- paddingRight: index < feedItems?.length - 1 ? 1 : 3,
426
+ paddingRight: index < (feedItems == null ? void 0 : feedItems.length) - 1 ? 1 : 3,
407
427
  paddingLeft: index === 0 ? 3 : 0,
408
428
  align: "stretch",
409
429
  style: { minWidth: 272, width: "30%" },
@@ -411,7 +431,7 @@ function SanityTutorials(props) {
411
431
  Tutorial,
412
432
  {
413
433
  title: feedItem.title,
414
- href: href ?? "",
434
+ href: href != null ? href : "",
415
435
  presenterName: presenter.name,
416
436
  presenterSubtitle: subtitle,
417
437
  showPlayIcon: feedItem.hasVideo,
@@ -424,15 +444,24 @@ function SanityTutorials(props) {
424
444
  }) }) });
425
445
  }
426
446
  function sanityTutorialsWidget(config) {
447
+ var _a;
427
448
  return {
428
449
  name: "sanity-tutorials",
429
450
  component: SanityTutorials,
430
- layout: config?.layout ?? { width: "full" }
451
+ layout: (_a = config == null ? void 0 : config.layout) != null ? _a : { width: "full" }
431
452
  };
432
453
  }
433
454
  function DashboardLayout(props) {
434
455
  return /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { width: 4, padding: 4, sizing: "border", style: { height: "100%", overflowY: "auto" }, children: props.children });
435
456
  }
457
+ var __defProp = Object.defineProperty, __getOwnPropSymbols = Object.getOwnPropertySymbols, __hasOwnProp = Object.prototype.hasOwnProperty, __propIsEnum = Object.prototype.propertyIsEnumerable, __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues = (a, b) => {
458
+ for (var prop in b || (b = {}))
459
+ __hasOwnProp.call(b, prop) && __defNormalProp(a, prop, b[prop]);
460
+ if (__getOwnPropSymbols)
461
+ for (var prop of __getOwnPropSymbols(b))
462
+ __propIsEnum.call(b, prop) && __defNormalProp(a, prop, b[prop]);
463
+ return a;
464
+ };
436
465
  const media = {
437
466
  small: (...args) => styledComponents.css`
438
467
  @media (min-width: ${({ theme }) => theme.sanity.media[0]}px) {
@@ -508,7 +537,7 @@ function WidgetGroup(props) {
508
537
  gap: 4,
509
538
  children: [
510
539
  widgets.length ? null : /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { padding: 4, shadow: 1, tone: "primary", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { align: "center", children: "Add some widgets to populate this space." }) }),
511
- widgets.map((widgetConfig, index) => widgetConfig.type === "__experimental_group" ? /* @__PURE__ */ jsxRuntime.jsx(WidgetGroup, { config: widgetConfig }, index) : widgetConfig.component ? /* @__PURE__ */ jsxRuntime.jsx(WidgetContainer, { ...widgetConfig }, index) : /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { children: [
540
+ widgets.map((widgetConfig, index) => widgetConfig.type === "__experimental_group" ? /* @__PURE__ */ jsxRuntime.jsx(WidgetGroup, { config: widgetConfig }, index) : widgetConfig.component ? /* @__PURE__ */ jsxRuntime.jsx(WidgetContainer, __spreadValues({}, widgetConfig), index) : /* @__PURE__ */ jsxRuntime.jsxs(ui.Box, { children: [
512
541
  widgetConfig.name,
513
542
  " is missing widget component"
514
543
  ] }, index))
@@ -539,10 +568,11 @@ const strokeStyle = {
539
568
  ]
540
569
  }
541
570
  ), dashboardTool = sanity.definePlugin((config = {}) => {
571
+ var _a, _b, _c, _d, _e;
542
572
  const pluginConfig = {
543
- layout: config.defaultLayout ?? {},
544
- widgets: config.widgets ?? []
545
- }, title = config.title ?? "Dashboard", name = config.name ?? "dashboard", icon = config.icon ?? DashboardIcon;
573
+ layout: (_a = config.defaultLayout) != null ? _a : {},
574
+ widgets: (_b = config.widgets) != null ? _b : []
575
+ }, title = (_c = config.title) != null ? _c : "Dashboard", name = (_d = config.name) != null ? _d : "dashboard", icon = (_e = config.icon) != null ? _e : DashboardIcon;
546
576
  return {
547
577
  name: "dashboard",
548
578
  tools: (prev, context) => [
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/components/DashboardWidgetContainer.tsx","../src/versionedClient.ts","../src/containers/DashboardContext.tsx","../src/containers/WidgetContainer.tsx","../src/widgets/projectInfo/ProjectInfo.tsx","../src/widgets/projectInfo/index.ts","../src/widgets/projectUsers/ProjectUser.tsx","../src/widgets/projectUsers/ProjectUsers.tsx","../src/widgets/projectUsers/index.ts","../src/widgets/sanityTutorials/Tutorial.tsx","../src/widgets/sanityTutorials/dataAdapter.ts","../src/widgets/sanityTutorials/SanityTutorials.tsx","../src/widgets/sanityTutorials/index.ts","../src/components/DashboardLayout.tsx","../src/components/WidgetGroup.tsx","../src/containers/Dashboard.tsx","../src/plugin.tsx"],"sourcesContent":["import React, {forwardRef} from 'react'\nimport {Card, Box, Heading} from '@sanity/ui'\nimport {styled} from 'styled-components'\n\nconst Root = styled(Card)`\n display: flex;\n flex-direction: column;\n justify-content: stretch;\n height: 100%;\n box-sizing: border-box;\n position: relative;\n`\n\nconst Header = styled(Card)`\n position: sticky;\n top: 0;\n z-index: 2;\n border-top-left-radius: inherit;\n border-top-right-radius: inherit;\n`\n\nconst Footer = styled(Card)`\n position: sticky;\n overflow: hidden;\n bottom: 0;\n z-index: 2;\n border-bottom-right-radius: inherit;\n border-bottom-left-radius: inherit;\n margin-top: auto;\n`\n\nconst Content = styled(Box)`\n position: relative;\n z-index: 1;\n height: stretch;\n min-height: 21.5em;\n\n @media (min-width: ${({theme}) => theme.sanity.media[0]}px) {\n overflow-y: auto;\n outline: none;\n }\n`\n\ninterface DashboardWidgetProps {\n header?: string\n children: React.ReactNode\n footer?: React.ReactNode\n}\n\nexport const DashboardWidgetContainer = forwardRef(function DashboardWidgetContainer(\n props: DashboardWidgetProps,\n ref: React.Ref<HTMLDivElement>,\n) {\n const {header, children, footer} = props\n\n return (\n <Root radius={3} display=\"flex\" ref={ref}>\n {header && (\n <Header borderBottom paddingX={3} paddingY={4}>\n <Heading size={1} textOverflow=\"ellipsis\">\n {header}\n </Heading>\n </Header>\n )}\n {children && <Content>{children}</Content>}\n {footer && <Footer borderTop>{footer}</Footer>}\n </Root>\n )\n})\n","import {useClient} from 'sanity'\n\nexport function useVersionedClient() {\n return useClient({apiVersion: '2024-08-01'})\n}\n","import {createContext, useContext} from 'react'\nimport {DashboardConfig} from '../types'\n\nexport const DashboardContext = createContext<DashboardConfig>({widgets: []})\n\nexport function useDashboardConfig(): DashboardConfig {\n return useContext(DashboardContext)\n}\n","import React, {createElement, useMemo} from 'react'\nimport {useDashboardConfig} from './DashboardContext'\nimport {Card} from '@sanity/ui'\nimport {DashboardWidget} from '../types'\n\nexport function WidgetContainer(props: DashboardWidget) {\n const config = useDashboardConfig()\n const layout = useMemo(\n () => ({\n ...(props.layout || {}),\n ...(config.layout || {}),\n }),\n [props.layout, config.layout],\n )\n\n return (\n <Card shadow={1} data-width={layout.width} data-height={layout.height}>\n {createElement(props.component, {})}\n </Card>\n )\n}\n","import React, {useEffect, useMemo, useState} from 'react'\nimport {Box, Card, Stack, Heading, Grid, Label, Text, Code, Button} from '@sanity/ui'\nimport {useVersionedClient} from '../../versionedClient'\nimport {Subscription} from 'rxjs'\nimport {WidgetContainer} from '../../containers/WidgetContainer'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\nimport {type DashboardWidget} from '../../types'\nimport {type App, type ProjectInfoProps, type ProjectData, UserApplication} from './types'\n\nfunction isUrl(url?: string) {\n return url && /^https?:\\/\\//.test(`${url}`)\n}\n\nfunction getGraphQLUrl(projectId: string, dataset: string) {\n return `https://${projectId}.api.sanity.io/v1/graphql/${dataset}/default`\n}\n\nfunction getGroqUrl(projectId: string, dataset: string) {\n return `https://${projectId}.api.sanity.io/v1/groq/${dataset}`\n}\n\nfunction getManageUrl(projectId: string) {\n return `https://manage.sanity.io/projects/${projectId}`\n}\n\nconst NO_EXPERIMENTAL: DashboardWidget[] = []\nconst NO_DATA: ProjectData[] = []\n\nexport function ProjectInfo(props: ProjectInfoProps) {\n const {__experimental_before = NO_EXPERIMENTAL, data = NO_DATA} = props\n const [studioApps, setStudioApps] = useState<UserApplication[] | {error: string} | undefined>()\n const [graphQLApi, setGraphQLApi] = useState<string | {error: string} | undefined>()\n const versionedClient = useVersionedClient()\n const {projectId = 'unknown', dataset = 'unknown'} = versionedClient.config()\n\n useEffect(() => {\n const subscriptions: Subscription[] = []\n\n subscriptions.push(\n versionedClient.observable\n .request<UserApplication[]>({uri: '/user-applications', tag: 'dashboard.project-info'})\n .subscribe({\n next: (result) => setStudioApps(result.filter((app) => app.type === 'studio')),\n error: (error) => {\n console.error('Error while resolving user applications', error)\n setStudioApps({\n error: 'Something went wrong while resolving user applications. See console.',\n })\n },\n }),\n )\n\n // ping assumed graphql endpoint\n subscriptions.push(\n versionedClient.observable\n .request({\n method: 'HEAD',\n uri: `/graphql/${dataset}/default`,\n tag: 'dashboard.project-info.graphql-api',\n })\n .subscribe({\n next: () => setGraphQLApi(getGraphQLUrl(projectId, dataset)),\n error: (error) => {\n if (error.statusCode === 404) {\n setGraphQLApi(undefined)\n } else {\n console.error('Error while looking for graphQLApi', error)\n setGraphQLApi({\n error: 'Something went wrong while looking up graphQLApi. See console.',\n })\n }\n },\n }),\n )\n\n return () => {\n subscriptions.forEach((s) => s.unsubscribe())\n }\n }, [dataset, projectId, versionedClient, setGraphQLApi])\n\n const assembleTableRows = useMemo(() => {\n let result: App[] = [\n {\n title: 'Sanity project',\n rows: [\n {title: 'Project ID', value: projectId},\n {title: 'Dataset', value: dataset},\n ],\n },\n ]\n\n const apps: App[] = data.filter((item) => item.category === 'apps')\n\n // Handle studios\n ;(Array.isArray(studioApps) ? studioApps : []).forEach((app) => {\n apps.push({\n title: app.title || 'Studio',\n value: app.urlType === 'internal' ? `https://${app.appHost}.sanity.studio` : app.appHost,\n })\n })\n\n if (apps.length > 0) {\n result = result.concat([{title: 'Apps', rows: apps}])\n }\n\n // Handle APIs\n result = result.concat(\n [\n {\n title: 'APIs',\n rows: [\n {title: 'GROQ', value: getGroqUrl(projectId, dataset)},\n {\n title: 'GraphQL',\n value: (typeof graphQLApi === 'object' ? 'Error' : graphQLApi) ?? 'Not deployed',\n },\n ],\n },\n ],\n data.filter((item) => item.category === 'apis'),\n )\n\n // Handle whatever else there might be\n const otherStuff: Record<string, ProjectData[]> = {}\n data.forEach((item) => {\n if (item.category && item.category !== 'apps' && item.category !== 'apis') {\n if (!otherStuff[item.category]) {\n otherStuff[item.category] = []\n }\n otherStuff[item.category].push(item)\n }\n })\n Object.keys(otherStuff).forEach((category) => {\n result.push({title: category, rows: otherStuff[category]})\n })\n\n return result\n }, [graphQLApi, studioApps, projectId, dataset, data])\n\n return (\n <>\n {__experimental_before.map((widgetConfig, idx) => (\n <WidgetContainer key={idx} {...widgetConfig} />\n ))}\n <Box height=\"fill\" marginTop={__experimental_before?.length > 0 ? 4 : 0}>\n <DashboardWidgetContainer\n footer={\n <Button\n style={{width: '100%'}}\n paddingX={2}\n paddingY={4}\n mode=\"bleed\"\n tone=\"primary\"\n text=\"Manage project\"\n as=\"a\"\n href={getManageUrl(projectId)}\n />\n }\n >\n <Card\n paddingY={4}\n radius={2}\n role=\"table\"\n aria-label=\"Project info\"\n aria-describedby=\"project_info_table\"\n >\n <Stack space={4}>\n <Box paddingX={3} as=\"header\">\n <Heading size={1} as=\"h2\" id=\"project_info_table\">\n Project info\n </Heading>\n </Box>\n {assembleTableRows.map((item) => {\n if (!item || !item.rows) {\n return null\n }\n\n return (\n <Stack key={item.title} space={3}>\n <Card borderBottom padding={3}>\n <Label size={0} muted role=\"columnheader\">\n {item.title}\n </Label>\n </Card>\n <Stack space={4} paddingX={3} role=\"rowgroup\">\n {item.rows.map((row) => {\n return (\n <Grid key={`${row.value}-${row.title}`} columns={2} role=\"row\">\n <Text weight=\"medium\" role=\"rowheader\">\n {row.title}\n </Text>\n {typeof row.value === 'object' && (\n <Text size={1}>{row.value?.error}</Text>\n )}\n {typeof row.value === 'string' && (\n <>\n {isUrl(row.value) ? (\n <Text size={1} role=\"cell\" style={{wordBreak: 'break-word'}}>\n <a href={row.value}>{row.value}</a>\n </Text>\n ) : (\n <Code size={1} role=\"cell\" style={{wordBreak: 'break-word'}}>\n {row.value}\n </Code>\n )}\n </>\n )}\n </Grid>\n )\n })}\n </Stack>\n </Stack>\n )\n })}\n </Stack>\n </Card>\n </DashboardWidgetContainer>\n </Box>\n </>\n )\n}\n","import {ProjectInfo} from './ProjectInfo'\nimport {type LayoutConfig, type DashboardWidget} from '../../types'\n\nexport function projectInfoWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'project-info',\n component: ProjectInfo,\n layout: config?.layout ?? {width: 'medium'},\n }\n}\n","import React from 'react'\nimport {Box, Flex, rem, Stack, Text} from '@sanity/ui'\nimport {styled} from 'styled-components'\nimport {useListFormat, type User, UserAvatar} from 'sanity'\nimport {RobotIcon} from '@sanity/icons'\n\nconst Root = styled(Flex)`\n height: ${rem(33)}; // 33 = PREVIEW_SIZES.default.media.height\n box-sizing: content-box;\n`\n\nexport interface ProjectUserProps {\n user: User\n isRobot: boolean\n roles: string[]\n}\n\nexport function ProjectUser({user, isRobot, roles}: ProjectUserProps) {\n const listFormat = useListFormat({style: 'narrow'})\n return (\n <Root align=\"center\">\n <Flex align=\"center\" flex={1} gap={2}>\n <Box flex=\"none\">\n {isRobot ? (\n <Text size={2}>\n <RobotIcon />\n </Text>\n ) : (\n <UserAvatar user={user} />\n )}\n </Box>\n\n <Stack flex={1} space={2}>\n <Text size={1} style={{color: 'inherit'}} textOverflow=\"ellipsis\" weight=\"medium\">\n {user.displayName}\n </Text>\n\n <Text muted size={1} textOverflow=\"ellipsis\">\n {listFormat.format(roles)}\n </Text>\n </Stack>\n </Flex>\n </Root>\n )\n}\n","import React, {useCallback, useEffect, useState} from 'react'\nimport {from} from 'rxjs'\nimport {map, switchMap} from 'rxjs/operators'\nimport {Stack, Spinner, Box, Text, Button} from '@sanity/ui'\nimport {Role, useUserStore} from 'sanity'\nimport {useVersionedClient} from '../../versionedClient'\nimport {User} from 'sanity'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\nimport {ProjectUser} from './ProjectUser'\n\nfunction getInviteUrl(projectId: string) {\n return `https://manage.sanity.io/projects/${projectId}/members`\n}\n\ninterface Member {\n id: string\n roles: Role[]\n isRobot: boolean\n isCurrentUser: boolean\n createdAt: string\n}\n\ninterface Project {\n id: string\n members: Member[]\n}\n\nexport function ProjectUsers() {\n const [project, setProject] = useState<Project | undefined>()\n const [users, setUsers] = useState<User[] | undefined>()\n const [error, setError] = useState<Error | undefined>()\n\n const userStore = useUserStore()\n const versionedClient = useVersionedClient()\n\n const fetchData = useCallback(() => {\n const {projectId} = versionedClient.config()\n const subscription = versionedClient.observable\n .request<Project>({\n uri: `/projects/${projectId}`,\n tag: 'dashboard.project-users',\n })\n .pipe(\n switchMap((_project) =>\n from(userStore.getUsers(_project.members.map((mem) => mem.id))).pipe(\n map((_users) => ({project: _project, users: _users})),\n ),\n ),\n )\n .subscribe({\n next: ({users: _users, project: _project}) => {\n setProject(_project)\n setUsers(\n (Array.isArray(_users) ? _users : [_users]).sort((userA, userB) =>\n sortUsersByRobotStatus(userA, userB, _project),\n ),\n )\n },\n error: (e: Error) => setError(e),\n })\n\n return () => subscription.unsubscribe()\n }, [userStore, versionedClient])\n\n useEffect(() => fetchData(), [fetchData])\n\n const handleRetryFetch = useCallback(() => fetchData(), [fetchData])\n\n const isLoading = !users || !project\n\n if (error) {\n return (\n <DashboardWidgetContainer header=\"Project users\">\n <Box padding={4}>\n <Text>\n Something went wrong while fetching data. You could{' '}\n <a onClick={handleRetryFetch} title=\"Retry users fetch\" style={{cursor: 'pointer'}}>\n retry\n </a>\n ..?\n </Text>\n </Box>\n </DashboardWidgetContainer>\n )\n }\n\n return (\n <DashboardWidgetContainer\n header=\"Project users\"\n footer={\n <Button\n style={{width: '100%'}}\n paddingX={2}\n paddingY={4}\n mode=\"bleed\"\n tone=\"primary\"\n text=\"Manage members\"\n as=\"a\"\n loading={isLoading}\n href={isLoading ? undefined : getInviteUrl(project.id)}\n />\n }\n >\n {isLoading && (\n <Box paddingY={5} paddingX={2}>\n <Stack space={4}>\n <Text align=\"center\" muted size={1}>\n <Spinner />\n </Text>\n <Text align=\"center\" size={1} muted>\n Loading items…\n </Text>\n </Stack>\n </Box>\n )}\n\n {!isLoading && (\n <Stack space={3} padding={3}>\n {users?.map((user) => {\n const membership = project.members.find((member) => member.id === user.id)\n return (\n <ProjectUser\n key={user.id}\n user={user}\n isRobot={membership?.isRobot ?? false}\n roles={membership?.roles.map((role) => role.title) || []}\n />\n )\n })}\n </Stack>\n )}\n </DashboardWidgetContainer>\n )\n}\n\nfunction sortUsersByRobotStatus(userA: User, userB: User, project: Project) {\n const {members} = project\n const membershipA = members.find((member) => member.id === userA?.id)\n const membershipB = members.find((member) => member.id === userB?.id)\n\n // On ties, sort by when the user was added\n if (membershipA?.isRobot === membershipB?.isRobot) {\n return (membershipA?.createdAt || '') > (membershipB?.createdAt || '') ? 1 : -1\n }\n\n // Robots go to the bottom\n return membershipA?.isRobot ? 1 : -1\n}\n","import {ProjectUsers} from './ProjectUsers'\nimport {LayoutConfig, DashboardWidget} from '../../types'\n\nexport function projectUsersWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'project-info',\n component: ProjectUsers,\n layout: config?.layout,\n }\n}\n","import React from 'react'\nimport {Card, Box, Heading, Flex, Text, Stack} from '@sanity/ui'\nimport {PlayIcon} from '@sanity/icons'\nimport {styled} from 'styled-components'\n\nconst PlayIconBox = styled(Box)`\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n\n &:before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 2.75em;\n height: 2.75em;\n border-radius: 50%;\n background: ${({theme}) => theme.sanity.color.card.enabled.bg};\n opacity: 0.75;\n }\n`\n\nconst Root = styled(Flex)`\n &:hover {\n ${PlayIconBox} {\n &:before {\n opacity: 1;\n }\n }\n }\n`\n\nconst PosterCard = styled(Card)`\n width: 100%;\n padding-bottom: calc(9 / 16 * 100%);\n position: relative;\n`\n\nconst Poster = styled.img`\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n width: 100%;\n object-fit: cover;\n display: block;\n\n &:not([src]) {\n display: none;\n }\n`\n\nexport interface TutorialProps {\n title: string\n posterURL?: string\n href: string\n showPlayIcon?: boolean\n presenterName?: string\n presenterSubtitle?: string\n}\n\nexport function Tutorial(props: TutorialProps) {\n const {title, posterURL, showPlayIcon, href, presenterName, presenterSubtitle} = props\n\n return (\n <Root flex={1}>\n <Card\n sizing=\"border\"\n flex={1}\n padding={2}\n radius={2}\n as=\"a\"\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{position: 'relative'}}\n >\n <Flex direction=\"column\" style={{height: '100%'}}>\n {posterURL && (\n <PosterCard marginBottom={1}>\n <Poster src={posterURL} />\n {showPlayIcon && (\n <PlayIconBox display=\"flex\">\n <Text align=\"center\">\n <PlayIcon />\n </Text>\n </PlayIconBox>\n )}\n </PosterCard>\n )}\n <Flex direction=\"column\" justify=\"space-between\" paddingY={2} flex={1}>\n <Heading as=\"h3\" size={1}>\n {title}\n </Heading>\n <Box marginTop={4}>\n <Stack space={2} flex={1}>\n <Text size={1}>{presenterName}</Text>\n <Text size={0} style={{opacity: 0.7}}>\n {presenterSubtitle}\n </Text>\n </Stack>\n </Box>\n </Flex>\n </Flex>\n </Card>\n </Root>\n )\n}\n","import {useMemo} from 'react'\nimport {useVersionedClient} from '../../versionedClient'\nimport imageUrlBuilder from '@sanity/image-url'\n\nconst tutorialsProjectConfig = {\n projectId: '3do82whm',\n dataset: 'next',\n}\n\nexport interface Guide {\n _type?: string\n slug?: {current: string}\n presenter?: {\n name?: string\n }\n}\n\nexport interface FeedItem {\n _id: string\n title?: string\n poster?: string\n category?: string\n guideOrTutorial?: Guide\n externalLink?: string\n presenter?: {\n name?: string\n }\n hasVideo?: boolean\n}\n\nexport function useDataAdapter() {\n const versionedClient = useVersionedClient()\n return useMemo(\n () => ({\n getFeed: (templateRepoId: string) => {\n const uri = templateRepoId\n ? `/addons/dashboard?templateRepoId=${templateRepoId}`\n : '/addons/dashboard'\n return versionedClient.observable.request<{items: FeedItem[]}>({\n uri,\n tag: 'dashboard.sanity-tutorials',\n withCredentials: false,\n })\n },\n urlBuilder: imageUrlBuilder(tutorialsProjectConfig),\n }),\n [versionedClient],\n )\n}\n","import React, {useEffect, useState} from 'react'\nimport {Flex} from '@sanity/ui'\nimport {Tutorial} from './Tutorial'\nimport {FeedItem, Guide, useDataAdapter} from './dataAdapter'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\n\nfunction createUrl(slug: {current: string}, type?: string) {\n if (type === 'tutorial') {\n return `https://www.sanity.io/docs/tutorials/${slug.current}`\n } else if (type === 'guide') {\n return `https://www.sanity.io/docs/guides/${slug.current}`\n }\n return false\n}\n\nexport interface SanityTutorialsProps {\n templateRepoId: string\n}\n\nexport function SanityTutorials(props: SanityTutorialsProps) {\n const {templateRepoId} = props\n const [feedItems, setFeedItems] = useState<FeedItem[]>([])\n\n const {getFeed, urlBuilder} = useDataAdapter()\n\n useEffect(() => {\n const subscription = getFeed(templateRepoId).subscribe((response) => {\n setFeedItems(response.items)\n })\n return () => {\n subscription.unsubscribe()\n }\n }, [setFeedItems, getFeed, templateRepoId])\n\n const title = 'Learn about Sanity'\n\n return (\n <DashboardWidgetContainer header={title}>\n <Flex as=\"ul\" overflow=\"auto\" align=\"stretch\" paddingY={2}>\n {feedItems?.map((feedItem, index) => {\n if (!feedItem.title || (!feedItem.guideOrTutorial && !feedItem.externalLink)) {\n return null\n }\n const presenter = feedItem.presenter || feedItem.guideOrTutorial?.presenter || {}\n const subtitle = feedItem.category\n const {guideOrTutorial = {} as Guide} = feedItem\n const href =\n (guideOrTutorial.slug\n ? createUrl(guideOrTutorial.slug, guideOrTutorial._type)\n : feedItem.externalLink) || feedItem.externalLink\n\n return (\n <Flex\n as=\"li\"\n key={feedItem._id}\n paddingRight={index < feedItems?.length - 1 ? 1 : 3}\n paddingLeft={index === 0 ? 3 : 0}\n align=\"stretch\"\n style={{minWidth: 272, width: '30%'}}\n >\n <Tutorial\n title={feedItem.title}\n href={href ?? ''}\n presenterName={presenter.name}\n presenterSubtitle={subtitle}\n showPlayIcon={feedItem.hasVideo}\n posterURL={\n feedItem.poster ? urlBuilder.image(feedItem.poster).height(360).url() : undefined\n }\n />\n </Flex>\n )\n })}\n </Flex>\n </DashboardWidgetContainer>\n )\n}\n","import {SanityTutorials} from './SanityTutorials'\nimport {LayoutConfig, DashboardWidget} from '../../types'\n\nexport function sanityTutorialsWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'sanity-tutorials',\n component: SanityTutorials,\n layout: config?.layout ?? {width: 'full'},\n }\n}\n","import React, {PropsWithChildren} from 'react'\nimport {Container} from '@sanity/ui'\n\nexport function DashboardLayout(props: PropsWithChildren<{}>) {\n return (\n <Container width={4} padding={4} sizing=\"border\" style={{height: '100%', overflowY: 'auto'}}>\n {props.children}\n </Container>\n )\n}\n","import React from 'react'\nimport {styled, css} from 'styled-components'\nimport {Box, Card, Grid, Text} from '@sanity/ui'\nimport {WidgetContainer} from '../containers/WidgetContainer'\nimport {DashboardConfig, LayoutConfig, DashboardWidget} from '../types'\n\nconst media = {\n small: (...args: Parameters<typeof css>) => css`\n @media (min-width: ${({theme}) => theme.sanity.media[0]}px) {\n ${css(...args)}\n }\n `,\n medium: (...args: Parameters<typeof css>) => css`\n @media (min-width: ${({theme}) => theme.sanity.media[2]}px) {\n ${css(...args)}\n }\n `,\n}\n\nconst Root = styled(Grid)`\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n\n & > div {\n overflow: hidden;\n }\n\n & > div[data-width='medium'] {\n ${media.small`\n grid-column: span 2;\n `}\n }\n\n & > div[data-width='large'] {\n ${media.small`\n grid-column: span 2;\n `}\n\n ${media.medium`\n grid-column: span 3;\n `}\n }\n\n & > div[data-width='full'] {\n ${media.small`\n grid-column: 1 / -1;\n `}\n }\n\n & > div[data-height='medium'] {\n ${media.small`\n grid-row: span 2;\n `}\n }\n\n & > div[data-height='large'] {\n ${media.small`\n grid-row: span 2;\n `}\n\n ${media.medium`\n grid-row: span 3;\n `}\n }\n\n & > div[data-height='full'] {\n ${media.medium`\n grid-row: 1 / -1;\n `}\n }\n`\n\nexport interface WidgetGroupProps {\n config: Partial<DashboardConfig>\n}\n\nconst NO_WIDGETS: DashboardWidget[] = []\nconst NO_LAYOUT: LayoutConfig = {}\n\nexport function WidgetGroup(props: WidgetGroupProps) {\n const {\n config: {layout = NO_LAYOUT, widgets = NO_WIDGETS},\n } = props\n return (\n <Root\n autoFlow=\"row dense\"\n data-width={layout.width || 'auto'}\n data-height={layout.height || 'auto'}\n gap={4}\n >\n {widgets.length ? null : (\n <Card padding={4} shadow={1} tone=\"primary\">\n <Text align=\"center\">Add some widgets to populate this space.</Text>\n </Card>\n )}\n {widgets.map((widgetConfig, index) => {\n if (widgetConfig.type === '__experimental_group') {\n return <WidgetGroup key={index} config={widgetConfig} />\n }\n if (widgetConfig.component) {\n return <WidgetContainer key={index} {...widgetConfig} />\n }\n return <Box key={index}>{widgetConfig.name} is missing widget component</Box>\n })}\n </Root>\n )\n}\n","import React from 'react'\nimport {DashboardLayout} from '../components/DashboardLayout'\nimport {WidgetGroup} from '../components/WidgetGroup'\nimport {DashboardContext} from './DashboardContext'\nimport {DashboardConfig} from '../types'\n\nexport function Dashboard({config}: {config: DashboardConfig}) {\n if (!config) {\n return null\n }\n\n return (\n <DashboardContext.Provider value={config}>\n <DashboardLayout>\n <WidgetGroup config={config} />\n </DashboardLayout>\n </DashboardContext.Provider>\n )\n}\n","import React, {ComponentType, CSSProperties} from 'react'\nimport {Dashboard} from './containers/Dashboard'\nimport {definePlugin} from 'sanity'\nimport {DashboardConfig, DashboardWidget, LayoutConfig} from './types'\n\nconst strokeStyle: CSSProperties = {\n stroke: 'currentColor',\n strokeWidth: 1.2,\n}\n\nconst DashboardIcon = () => (\n <svg\n data-sanity-icon\n viewBox=\"0 0 25 25\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n preserveAspectRatio=\"xMidYMid\"\n width=\"1em\"\n height=\"1em\"\n >\n <path d=\"M19.5 19.5H5.5V5.5H19.5V19.5Z\" style={strokeStyle} />\n <path d=\"M5.5 12.5H19.5\" style={strokeStyle} />\n <path d=\"M14.5 19.5V12.5M10.5 12.5V5.5\" style={strokeStyle} />\n </svg>\n)\n\nexport interface DashboardPluginConfig {\n /**\n * Dashboard tool title\n */\n title?: string\n /**\n * Dashboard tool name (used in url path)\n */\n name?: string\n /**\n * Dashboard tool icon\n */\n icon?: ComponentType\n widgets?: DashboardWidget[]\n\n /**\n * Will be used for widgets that do not define a layout directly.\n */\n defaultLayout?: LayoutConfig\n}\n\nexport const dashboardTool = definePlugin<DashboardPluginConfig>((config = {}) => {\n const pluginConfig: DashboardConfig = {\n layout: config.defaultLayout ?? {},\n widgets: config.widgets ?? [],\n }\n\n const title = config.title ?? 'Dashboard'\n const name = config.name ?? 'dashboard'\n const icon = config.icon ?? DashboardIcon\n\n return {\n name: 'dashboard',\n tools: (prev, context) => {\n return [\n ...prev,\n {\n title,\n name,\n icon,\n component: () => <Dashboard config={pluginConfig} />,\n },\n ]\n },\n }\n})\n"],"names":["Root","styled","Card","Box","forwardRef","jsx","Heading","useClient","createContext","useContext","useMemo","createElement","useState","useEffect","jsxs","Fragment","Button","Stack","Label","Grid","Text","Code","Flex","rem","useListFormat","RobotIcon","UserAvatar","useUserStore","useCallback","switchMap","from","map","Spinner","PlayIcon","imageUrlBuilder","Container","css","definePlugin"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/components/DashboardWidgetContainer.tsx","../src/versionedClient.ts","../src/containers/DashboardContext.tsx","../src/containers/WidgetContainer.tsx","../src/widgets/projectInfo/ProjectInfo.tsx","../src/widgets/projectInfo/index.ts","../src/widgets/projectUsers/ProjectUser.tsx","../src/widgets/projectUsers/ProjectUsers.tsx","../src/widgets/projectUsers/index.ts","../src/widgets/sanityTutorials/Tutorial.tsx","../src/widgets/sanityTutorials/dataAdapter.ts","../src/widgets/sanityTutorials/SanityTutorials.tsx","../src/widgets/sanityTutorials/index.ts","../src/components/DashboardLayout.tsx","../src/components/WidgetGroup.tsx","../src/containers/Dashboard.tsx","../src/plugin.tsx"],"sourcesContent":["import React, {forwardRef} from 'react'\nimport {Card, Box, Heading} from '@sanity/ui'\nimport {styled} from 'styled-components'\n\nconst Root = styled(Card)`\n display: flex;\n flex-direction: column;\n justify-content: stretch;\n height: 100%;\n box-sizing: border-box;\n position: relative;\n`\n\nconst Header = styled(Card)`\n position: sticky;\n top: 0;\n z-index: 2;\n border-top-left-radius: inherit;\n border-top-right-radius: inherit;\n`\n\nconst Footer = styled(Card)`\n position: sticky;\n overflow: hidden;\n bottom: 0;\n z-index: 2;\n border-bottom-right-radius: inherit;\n border-bottom-left-radius: inherit;\n margin-top: auto;\n`\n\nconst Content = styled(Box)`\n position: relative;\n z-index: 1;\n height: stretch;\n min-height: 21.5em;\n\n @media (min-width: ${({theme}) => theme.sanity.media[0]}px) {\n overflow-y: auto;\n outline: none;\n }\n`\n\ninterface DashboardWidgetProps {\n header?: string\n children: React.ReactNode\n footer?: React.ReactNode\n}\n\nexport const DashboardWidgetContainer = forwardRef(function DashboardWidgetContainer(\n props: DashboardWidgetProps,\n ref: React.Ref<HTMLDivElement>,\n) {\n const {header, children, footer} = props\n\n return (\n <Root radius={3} display=\"flex\" ref={ref}>\n {header && (\n <Header borderBottom paddingX={3} paddingY={4}>\n <Heading size={1} textOverflow=\"ellipsis\">\n {header}\n </Heading>\n </Header>\n )}\n {children && <Content>{children}</Content>}\n {footer && <Footer borderTop>{footer}</Footer>}\n </Root>\n )\n})\n","import {useClient} from 'sanity'\n\nexport function useVersionedClient() {\n return useClient({apiVersion: '2024-08-01'})\n}\n","import {createContext, useContext} from 'react'\nimport {DashboardConfig} from '../types'\n\nexport const DashboardContext = createContext<DashboardConfig>({widgets: []})\n\nexport function useDashboardConfig(): DashboardConfig {\n return useContext(DashboardContext)\n}\n","import React, {createElement, useMemo} from 'react'\nimport {useDashboardConfig} from './DashboardContext'\nimport {Card} from '@sanity/ui'\nimport {DashboardWidget} from '../types'\n\nexport function WidgetContainer(props: DashboardWidget) {\n const config = useDashboardConfig()\n const layout = useMemo(\n () => ({\n ...(props.layout || {}),\n ...(config.layout || {}),\n }),\n [props.layout, config.layout],\n )\n\n return (\n <Card shadow={1} data-width={layout.width} data-height={layout.height}>\n {createElement(props.component, {})}\n </Card>\n )\n}\n","import React, {useEffect, useMemo, useState} from 'react'\nimport {Box, Card, Stack, Heading, Grid, Label, Text, Code, Button} from '@sanity/ui'\nimport {useVersionedClient} from '../../versionedClient'\nimport {Subscription} from 'rxjs'\nimport {WidgetContainer} from '../../containers/WidgetContainer'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\nimport {type DashboardWidget} from '../../types'\nimport {type App, type ProjectInfoProps, type ProjectData, UserApplication} from './types'\n\nfunction isUrl(url?: string) {\n return url && /^https?:\\/\\//.test(`${url}`)\n}\n\nfunction getGraphQLUrl(projectId: string, dataset: string) {\n return `https://${projectId}.api.sanity.io/v1/graphql/${dataset}/default`\n}\n\nfunction getGroqUrl(projectId: string, dataset: string) {\n return `https://${projectId}.api.sanity.io/v1/groq/${dataset}`\n}\n\nfunction getManageUrl(projectId: string) {\n return `https://manage.sanity.io/projects/${projectId}`\n}\n\nconst NO_EXPERIMENTAL: DashboardWidget[] = []\nconst NO_DATA: ProjectData[] = []\n\nexport function ProjectInfo(props: ProjectInfoProps) {\n const {__experimental_before = NO_EXPERIMENTAL, data = NO_DATA} = props\n const [studioApps, setStudioApps] = useState<UserApplication[] | {error: string} | undefined>()\n const [graphQLApi, setGraphQLApi] = useState<string | {error: string} | undefined>()\n const versionedClient = useVersionedClient()\n const {projectId = 'unknown', dataset = 'unknown'} = versionedClient.config()\n\n useEffect(() => {\n const subscriptions: Subscription[] = []\n\n subscriptions.push(\n versionedClient.observable\n .request<UserApplication[]>({uri: '/user-applications', tag: 'dashboard.project-info'})\n .subscribe({\n next: (result) => setStudioApps(result.filter((app) => app.type === 'studio')),\n error: (error) => {\n console.error('Error while resolving user applications', error)\n setStudioApps({\n error: 'Something went wrong while resolving user applications. See console.',\n })\n },\n }),\n )\n\n // ping assumed graphql endpoint\n subscriptions.push(\n versionedClient.observable\n .request({\n method: 'HEAD',\n uri: `/graphql/${dataset}/default`,\n tag: 'dashboard.project-info.graphql-api',\n })\n .subscribe({\n next: () => setGraphQLApi(getGraphQLUrl(projectId, dataset)),\n error: (error) => {\n if (error.statusCode === 404) {\n setGraphQLApi(undefined)\n } else {\n console.error('Error while looking for graphQLApi', error)\n setGraphQLApi({\n error: 'Something went wrong while looking up graphQLApi. See console.',\n })\n }\n },\n }),\n )\n\n return () => {\n subscriptions.forEach((s) => s.unsubscribe())\n }\n }, [dataset, projectId, versionedClient, setGraphQLApi])\n\n const assembleTableRows = useMemo(() => {\n let result: App[] = [\n {\n title: 'Sanity project',\n rows: [\n {title: 'Project ID', value: projectId},\n {title: 'Dataset', value: dataset},\n ],\n },\n ]\n\n const apps: App[] = data.filter((item) => item.category === 'apps')\n\n // Handle studios\n ;(Array.isArray(studioApps) ? studioApps : []).forEach((app) => {\n apps.push({\n title: app.title || 'Studio',\n value: app.urlType === 'internal' ? `https://${app.appHost}.sanity.studio` : app.appHost,\n })\n })\n\n if (apps.length > 0) {\n result = result.concat([{title: 'Apps', rows: apps}])\n }\n\n // Handle APIs\n result = result.concat(\n [\n {\n title: 'APIs',\n rows: [\n {title: 'GROQ', value: getGroqUrl(projectId, dataset)},\n {\n title: 'GraphQL',\n value: (typeof graphQLApi === 'object' ? 'Error' : graphQLApi) ?? 'Not deployed',\n },\n ],\n },\n ],\n data.filter((item) => item.category === 'apis'),\n )\n\n // Handle whatever else there might be\n const otherStuff: Record<string, ProjectData[]> = {}\n data.forEach((item) => {\n if (item.category && item.category !== 'apps' && item.category !== 'apis') {\n if (!otherStuff[item.category]) {\n otherStuff[item.category] = []\n }\n otherStuff[item.category].push(item)\n }\n })\n Object.keys(otherStuff).forEach((category) => {\n result.push({title: category, rows: otherStuff[category]})\n })\n\n return result\n }, [graphQLApi, studioApps, projectId, dataset, data])\n\n return (\n <>\n {__experimental_before.map((widgetConfig, idx) => (\n <WidgetContainer key={idx} {...widgetConfig} />\n ))}\n <Box height=\"fill\" marginTop={__experimental_before?.length > 0 ? 4 : 0}>\n <DashboardWidgetContainer\n footer={\n <Button\n style={{width: '100%'}}\n paddingX={2}\n paddingY={4}\n mode=\"bleed\"\n tone=\"primary\"\n text=\"Manage project\"\n as=\"a\"\n href={getManageUrl(projectId)}\n />\n }\n >\n <Card\n paddingY={4}\n radius={2}\n role=\"table\"\n aria-label=\"Project info\"\n aria-describedby=\"project_info_table\"\n >\n <Stack space={4}>\n <Box paddingX={3} as=\"header\">\n <Heading size={1} as=\"h2\" id=\"project_info_table\">\n Project info\n </Heading>\n </Box>\n {assembleTableRows.map((item) => {\n if (!item || !item.rows) {\n return null\n }\n\n return (\n <Stack key={item.title} space={3}>\n <Card borderBottom padding={3}>\n <Label size={0} muted role=\"columnheader\">\n {item.title}\n </Label>\n </Card>\n <Stack space={4} paddingX={3} role=\"rowgroup\">\n {item.rows.map((row) => {\n return (\n <Grid key={`${row.value}-${row.title}`} columns={2} role=\"row\">\n <Text weight=\"medium\" role=\"rowheader\">\n {row.title}\n </Text>\n {typeof row.value === 'object' && (\n <Text size={1}>{row.value?.error}</Text>\n )}\n {typeof row.value === 'string' && (\n <>\n {isUrl(row.value) ? (\n <Text size={1} role=\"cell\" style={{wordBreak: 'break-word'}}>\n <a href={row.value}>{row.value}</a>\n </Text>\n ) : (\n <Code size={1} role=\"cell\" style={{wordBreak: 'break-word'}}>\n {row.value}\n </Code>\n )}\n </>\n )}\n </Grid>\n )\n })}\n </Stack>\n </Stack>\n )\n })}\n </Stack>\n </Card>\n </DashboardWidgetContainer>\n </Box>\n </>\n )\n}\n","import {ProjectInfo} from './ProjectInfo'\nimport {type LayoutConfig, type DashboardWidget} from '../../types'\n\nexport function projectInfoWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'project-info',\n component: ProjectInfo,\n layout: config?.layout ?? {width: 'medium'},\n }\n}\n","import React from 'react'\nimport {Box, Flex, rem, Stack, Text} from '@sanity/ui'\nimport {styled} from 'styled-components'\nimport {useListFormat, type User, UserAvatar} from 'sanity'\nimport {RobotIcon} from '@sanity/icons'\n\nconst Root = styled(Flex)`\n height: ${rem(33)}; // 33 = PREVIEW_SIZES.default.media.height\n box-sizing: content-box;\n`\n\nexport interface ProjectUserProps {\n user: User\n isRobot: boolean\n roles: string[]\n}\n\nexport function ProjectUser({user, isRobot, roles}: ProjectUserProps) {\n const listFormat = useListFormat({style: 'narrow'})\n return (\n <Root align=\"center\">\n <Flex align=\"center\" flex={1} gap={2}>\n <Box flex=\"none\">\n {isRobot ? (\n <Text size={2}>\n <RobotIcon />\n </Text>\n ) : (\n <UserAvatar user={user} />\n )}\n </Box>\n\n <Stack flex={1} space={2}>\n <Text size={1} style={{color: 'inherit'}} textOverflow=\"ellipsis\" weight=\"medium\">\n {user.displayName}\n </Text>\n\n <Text muted size={1} textOverflow=\"ellipsis\">\n {listFormat.format(roles)}\n </Text>\n </Stack>\n </Flex>\n </Root>\n )\n}\n","import React, {useCallback, useEffect, useState} from 'react'\nimport {from} from 'rxjs'\nimport {map, switchMap} from 'rxjs/operators'\nimport {Stack, Spinner, Box, Text, Button} from '@sanity/ui'\nimport {Role, useUserStore} from 'sanity'\nimport {useVersionedClient} from '../../versionedClient'\nimport {User} from 'sanity'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\nimport {ProjectUser} from './ProjectUser'\n\nfunction getInviteUrl(projectId: string) {\n return `https://manage.sanity.io/projects/${projectId}/members`\n}\n\ninterface Member {\n id: string\n roles: Role[]\n isRobot: boolean\n isCurrentUser: boolean\n createdAt: string\n}\n\ninterface Project {\n id: string\n members: Member[]\n}\n\nexport function ProjectUsers() {\n const [project, setProject] = useState<Project | undefined>()\n const [users, setUsers] = useState<User[] | undefined>()\n const [error, setError] = useState<Error | undefined>()\n\n const userStore = useUserStore()\n const versionedClient = useVersionedClient()\n\n const fetchData = useCallback(() => {\n const {projectId} = versionedClient.config()\n const subscription = versionedClient.observable\n .request<Project>({\n uri: `/projects/${projectId}`,\n tag: 'dashboard.project-users',\n })\n .pipe(\n switchMap((_project) =>\n from(userStore.getUsers(_project.members.map((mem) => mem.id))).pipe(\n map((_users) => ({project: _project, users: _users})),\n ),\n ),\n )\n .subscribe({\n next: ({users: _users, project: _project}) => {\n setProject(_project)\n setUsers(\n (Array.isArray(_users) ? _users : [_users]).sort((userA, userB) =>\n sortUsersByRobotStatus(userA, userB, _project),\n ),\n )\n },\n error: (e: Error) => setError(e),\n })\n\n return () => subscription.unsubscribe()\n }, [userStore, versionedClient])\n\n useEffect(() => fetchData(), [fetchData])\n\n const handleRetryFetch = useCallback(() => fetchData(), [fetchData])\n\n const isLoading = !users || !project\n\n if (error) {\n return (\n <DashboardWidgetContainer header=\"Project users\">\n <Box padding={4}>\n <Text>\n Something went wrong while fetching data. You could{' '}\n <a onClick={handleRetryFetch} title=\"Retry users fetch\" style={{cursor: 'pointer'}}>\n retry\n </a>\n ..?\n </Text>\n </Box>\n </DashboardWidgetContainer>\n )\n }\n\n return (\n <DashboardWidgetContainer\n header=\"Project users\"\n footer={\n <Button\n style={{width: '100%'}}\n paddingX={2}\n paddingY={4}\n mode=\"bleed\"\n tone=\"primary\"\n text=\"Manage members\"\n as=\"a\"\n loading={isLoading}\n href={isLoading ? undefined : getInviteUrl(project.id)}\n />\n }\n >\n {isLoading && (\n <Box paddingY={5} paddingX={2}>\n <Stack space={4}>\n <Text align=\"center\" muted size={1}>\n <Spinner />\n </Text>\n <Text align=\"center\" size={1} muted>\n Loading items…\n </Text>\n </Stack>\n </Box>\n )}\n\n {!isLoading && (\n <Stack space={3} padding={3}>\n {users?.map((user) => {\n const membership = project.members.find((member) => member.id === user.id)\n return (\n <ProjectUser\n key={user.id}\n user={user}\n isRobot={membership?.isRobot ?? false}\n roles={membership?.roles.map((role) => role.title) || []}\n />\n )\n })}\n </Stack>\n )}\n </DashboardWidgetContainer>\n )\n}\n\nfunction sortUsersByRobotStatus(userA: User, userB: User, project: Project) {\n const {members} = project\n const membershipA = members.find((member) => member.id === userA?.id)\n const membershipB = members.find((member) => member.id === userB?.id)\n\n // On ties, sort by when the user was added\n if (membershipA?.isRobot === membershipB?.isRobot) {\n return (membershipA?.createdAt || '') > (membershipB?.createdAt || '') ? 1 : -1\n }\n\n // Robots go to the bottom\n return membershipA?.isRobot ? 1 : -1\n}\n","import {ProjectUsers} from './ProjectUsers'\nimport {LayoutConfig, DashboardWidget} from '../../types'\n\nexport function projectUsersWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'project-info',\n component: ProjectUsers,\n layout: config?.layout,\n }\n}\n","import React from 'react'\nimport {Card, Box, Heading, Flex, Text, Stack} from '@sanity/ui'\nimport {PlayIcon} from '@sanity/icons'\nimport {styled} from 'styled-components'\n\nconst PlayIconBox = styled(Box)`\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n\n &:before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 2.75em;\n height: 2.75em;\n border-radius: 50%;\n background: ${({theme}) => theme.sanity.color.card.enabled.bg};\n opacity: 0.75;\n }\n`\n\nconst Root = styled(Flex)`\n &:hover {\n ${PlayIconBox} {\n &:before {\n opacity: 1;\n }\n }\n }\n`\n\nconst PosterCard = styled(Card)`\n width: 100%;\n padding-bottom: calc(9 / 16 * 100%);\n position: relative;\n`\n\nconst Poster = styled.img`\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n width: 100%;\n object-fit: cover;\n display: block;\n\n &:not([src]) {\n display: none;\n }\n`\n\nexport interface TutorialProps {\n title: string\n posterURL?: string\n href: string\n showPlayIcon?: boolean\n presenterName?: string\n presenterSubtitle?: string\n}\n\nexport function Tutorial(props: TutorialProps) {\n const {title, posterURL, showPlayIcon, href, presenterName, presenterSubtitle} = props\n\n return (\n <Root flex={1}>\n <Card\n sizing=\"border\"\n flex={1}\n padding={2}\n radius={2}\n as=\"a\"\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{position: 'relative'}}\n >\n <Flex direction=\"column\" style={{height: '100%'}}>\n {posterURL && (\n <PosterCard marginBottom={1}>\n <Poster src={posterURL} />\n {showPlayIcon && (\n <PlayIconBox display=\"flex\">\n <Text align=\"center\">\n <PlayIcon />\n </Text>\n </PlayIconBox>\n )}\n </PosterCard>\n )}\n <Flex direction=\"column\" justify=\"space-between\" paddingY={2} flex={1}>\n <Heading as=\"h3\" size={1}>\n {title}\n </Heading>\n <Box marginTop={4}>\n <Stack space={2} flex={1}>\n <Text size={1}>{presenterName}</Text>\n <Text size={0} style={{opacity: 0.7}}>\n {presenterSubtitle}\n </Text>\n </Stack>\n </Box>\n </Flex>\n </Flex>\n </Card>\n </Root>\n )\n}\n","import {useMemo} from 'react'\nimport {useVersionedClient} from '../../versionedClient'\nimport imageUrlBuilder from '@sanity/image-url'\n\nconst tutorialsProjectConfig = {\n projectId: '3do82whm',\n dataset: 'next',\n}\n\nexport interface Guide {\n _type?: string\n slug?: {current: string}\n presenter?: {\n name?: string\n }\n}\n\nexport interface FeedItem {\n _id: string\n title?: string\n poster?: string\n category?: string\n guideOrTutorial?: Guide\n externalLink?: string\n presenter?: {\n name?: string\n }\n hasVideo?: boolean\n}\n\nexport function useDataAdapter() {\n const versionedClient = useVersionedClient()\n return useMemo(\n () => ({\n getFeed: (templateRepoId: string) => {\n const uri = templateRepoId\n ? `/addons/dashboard?templateRepoId=${templateRepoId}`\n : '/addons/dashboard'\n return versionedClient.observable.request<{items: FeedItem[]}>({\n uri,\n tag: 'dashboard.sanity-tutorials',\n withCredentials: false,\n })\n },\n urlBuilder: imageUrlBuilder(tutorialsProjectConfig),\n }),\n [versionedClient],\n )\n}\n","import React, {useEffect, useState} from 'react'\nimport {Flex} from '@sanity/ui'\nimport {Tutorial} from './Tutorial'\nimport {FeedItem, Guide, useDataAdapter} from './dataAdapter'\nimport {DashboardWidgetContainer} from '../../components/DashboardWidgetContainer'\n\nfunction createUrl(slug: {current: string}, type?: string) {\n if (type === 'tutorial') {\n return `https://www.sanity.io/docs/tutorials/${slug.current}`\n } else if (type === 'guide') {\n return `https://www.sanity.io/docs/guides/${slug.current}`\n }\n return false\n}\n\nexport interface SanityTutorialsProps {\n templateRepoId: string\n}\n\nexport function SanityTutorials(props: SanityTutorialsProps) {\n const {templateRepoId} = props\n const [feedItems, setFeedItems] = useState<FeedItem[]>([])\n\n const {getFeed, urlBuilder} = useDataAdapter()\n\n useEffect(() => {\n const subscription = getFeed(templateRepoId).subscribe((response) => {\n setFeedItems(response.items)\n })\n return () => {\n subscription.unsubscribe()\n }\n }, [setFeedItems, getFeed, templateRepoId])\n\n const title = 'Learn about Sanity'\n\n return (\n <DashboardWidgetContainer header={title}>\n <Flex as=\"ul\" overflow=\"auto\" align=\"stretch\" paddingY={2}>\n {feedItems?.map((feedItem, index) => {\n if (!feedItem.title || (!feedItem.guideOrTutorial && !feedItem.externalLink)) {\n return null\n }\n const presenter = feedItem.presenter || feedItem.guideOrTutorial?.presenter || {}\n const subtitle = feedItem.category\n const {guideOrTutorial = {} as Guide} = feedItem\n const href =\n (guideOrTutorial.slug\n ? createUrl(guideOrTutorial.slug, guideOrTutorial._type)\n : feedItem.externalLink) || feedItem.externalLink\n\n return (\n <Flex\n as=\"li\"\n key={feedItem._id}\n paddingRight={index < feedItems?.length - 1 ? 1 : 3}\n paddingLeft={index === 0 ? 3 : 0}\n align=\"stretch\"\n style={{minWidth: 272, width: '30%'}}\n >\n <Tutorial\n title={feedItem.title}\n href={href ?? ''}\n presenterName={presenter.name}\n presenterSubtitle={subtitle}\n showPlayIcon={feedItem.hasVideo}\n posterURL={\n feedItem.poster ? urlBuilder.image(feedItem.poster).height(360).url() : undefined\n }\n />\n </Flex>\n )\n })}\n </Flex>\n </DashboardWidgetContainer>\n )\n}\n","import {SanityTutorials} from './SanityTutorials'\nimport {LayoutConfig, DashboardWidget} from '../../types'\n\nexport function sanityTutorialsWidget(config?: {layout?: LayoutConfig}): DashboardWidget {\n return {\n name: 'sanity-tutorials',\n component: SanityTutorials,\n layout: config?.layout ?? {width: 'full'},\n }\n}\n","import React, {PropsWithChildren} from 'react'\nimport {Container} from '@sanity/ui'\n\nexport function DashboardLayout(props: PropsWithChildren<{}>) {\n return (\n <Container width={4} padding={4} sizing=\"border\" style={{height: '100%', overflowY: 'auto'}}>\n {props.children}\n </Container>\n )\n}\n","import React from 'react'\nimport {styled, css} from 'styled-components'\nimport {Box, Card, Grid, Text} from '@sanity/ui'\nimport {WidgetContainer} from '../containers/WidgetContainer'\nimport {DashboardConfig, LayoutConfig, DashboardWidget} from '../types'\n\nconst media = {\n small: (...args: Parameters<typeof css>) => css`\n @media (min-width: ${({theme}) => theme.sanity.media[0]}px) {\n ${css(...args)}\n }\n `,\n medium: (...args: Parameters<typeof css>) => css`\n @media (min-width: ${({theme}) => theme.sanity.media[2]}px) {\n ${css(...args)}\n }\n `,\n}\n\nconst Root = styled(Grid)`\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n\n & > div {\n overflow: hidden;\n }\n\n & > div[data-width='medium'] {\n ${media.small`\n grid-column: span 2;\n `}\n }\n\n & > div[data-width='large'] {\n ${media.small`\n grid-column: span 2;\n `}\n\n ${media.medium`\n grid-column: span 3;\n `}\n }\n\n & > div[data-width='full'] {\n ${media.small`\n grid-column: 1 / -1;\n `}\n }\n\n & > div[data-height='medium'] {\n ${media.small`\n grid-row: span 2;\n `}\n }\n\n & > div[data-height='large'] {\n ${media.small`\n grid-row: span 2;\n `}\n\n ${media.medium`\n grid-row: span 3;\n `}\n }\n\n & > div[data-height='full'] {\n ${media.medium`\n grid-row: 1 / -1;\n `}\n }\n`\n\nexport interface WidgetGroupProps {\n config: Partial<DashboardConfig>\n}\n\nconst NO_WIDGETS: DashboardWidget[] = []\nconst NO_LAYOUT: LayoutConfig = {}\n\nexport function WidgetGroup(props: WidgetGroupProps) {\n const {\n config: {layout = NO_LAYOUT, widgets = NO_WIDGETS},\n } = props\n return (\n <Root\n autoFlow=\"row dense\"\n data-width={layout.width || 'auto'}\n data-height={layout.height || 'auto'}\n gap={4}\n >\n {widgets.length ? null : (\n <Card padding={4} shadow={1} tone=\"primary\">\n <Text align=\"center\">Add some widgets to populate this space.</Text>\n </Card>\n )}\n {widgets.map((widgetConfig, index) => {\n if (widgetConfig.type === '__experimental_group') {\n return <WidgetGroup key={index} config={widgetConfig} />\n }\n if (widgetConfig.component) {\n return <WidgetContainer key={index} {...widgetConfig} />\n }\n return <Box key={index}>{widgetConfig.name} is missing widget component</Box>\n })}\n </Root>\n )\n}\n","import React from 'react'\nimport {DashboardLayout} from '../components/DashboardLayout'\nimport {WidgetGroup} from '../components/WidgetGroup'\nimport {DashboardContext} from './DashboardContext'\nimport {DashboardConfig} from '../types'\n\nexport function Dashboard({config}: {config: DashboardConfig}) {\n if (!config) {\n return null\n }\n\n return (\n <DashboardContext.Provider value={config}>\n <DashboardLayout>\n <WidgetGroup config={config} />\n </DashboardLayout>\n </DashboardContext.Provider>\n )\n}\n","import React, {ComponentType, CSSProperties} from 'react'\nimport {Dashboard} from './containers/Dashboard'\nimport {definePlugin} from 'sanity'\nimport {DashboardConfig, DashboardWidget, LayoutConfig} from './types'\n\nconst strokeStyle: CSSProperties = {\n stroke: 'currentColor',\n strokeWidth: 1.2,\n}\n\nconst DashboardIcon = () => (\n <svg\n data-sanity-icon\n viewBox=\"0 0 25 25\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n preserveAspectRatio=\"xMidYMid\"\n width=\"1em\"\n height=\"1em\"\n >\n <path d=\"M19.5 19.5H5.5V5.5H19.5V19.5Z\" style={strokeStyle} />\n <path d=\"M5.5 12.5H19.5\" style={strokeStyle} />\n <path d=\"M14.5 19.5V12.5M10.5 12.5V5.5\" style={strokeStyle} />\n </svg>\n)\n\nexport interface DashboardPluginConfig {\n /**\n * Dashboard tool title\n */\n title?: string\n /**\n * Dashboard tool name (used in url path)\n */\n name?: string\n /**\n * Dashboard tool icon\n */\n icon?: ComponentType\n widgets?: DashboardWidget[]\n\n /**\n * Will be used for widgets that do not define a layout directly.\n */\n defaultLayout?: LayoutConfig\n}\n\nexport const dashboardTool = definePlugin<DashboardPluginConfig>((config = {}) => {\n const pluginConfig: DashboardConfig = {\n layout: config.defaultLayout ?? {},\n widgets: config.widgets ?? [],\n }\n\n const title = config.title ?? 'Dashboard'\n const name = config.name ?? 'dashboard'\n const icon = config.icon ?? DashboardIcon\n\n return {\n name: 'dashboard',\n tools: (prev, context) => {\n return [\n ...prev,\n {\n title,\n name,\n icon,\n component: () => <Dashboard config={pluginConfig} />,\n },\n ]\n },\n }\n})\n"],"names":["Root","styled","Card","Box","forwardRef","jsx","Heading","useClient","createContext","useContext","useMemo","__spreadValues","createElement","useState","useEffect","jsxs","Fragment","Button","Stack","Label","Grid","Text","Code","Flex","rem","useListFormat","RobotIcon","UserAvatar","useUserStore","useCallback","switchMap","from","map","Spinner","PlayIcon","imageUrlBuilder","Container","css","definePlugin"],"mappings":";;;;;;;AAIA,MAAMA,SAAOC,wBAAOC,OAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASlB,SAASD,wBAAOC,OAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAQpB,SAASD,wBAAOC,OAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAUpB,UAAUD,wBAAOE,MAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAMH,CAAC,EAAC,YAAW,MAAM,OAAO,MAAM,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA,GAY5C,2BAA2BC,MAAA,WAAW,SACjD,OACA,KACA;AACA,QAAM,EAAC,QAAQ,UAAU,OAAU,IAAA;AAEnC,yCACGJ,QAAK,EAAA,QAAQ,GAAG,SAAQ,QAAO,KAC7B,UAAA;AAAA,IAAA,UACEK,2BAAAA,IAAA,QAAA,EAAO,cAAY,IAAC,UAAU,GAAG,UAAU,GAC1C,UAAAA,+BAACC,GAAAA,WAAQ,MAAM,GAAG,cAAa,YAC5B,iBACH,CAAA,GACF;AAAA,IAED,YAAaD,2BAAA,IAAA,SAAA,EAAS,SAAS,CAAA;AAAA,IAC/B,UAAUA,2BAAA,IAAC,QAAO,EAAA,WAAS,IAAE,UAAO,OAAA,CAAA;AAAA,EAAA,GACvC;AAEJ,CAAC;AClEM,SAAS,qBAAqB;AACnC,SAAOE,iBAAU,EAAC,YAAY,cAAa;AAC7C;ACDO,MAAM,mBAAmBC,MAA+B,cAAA,EAAC,SAAS,IAAG;AAErE,SAAS,qBAAsC;AACpD,SAAOC,MAAAA,WAAW,gBAAgB;AACpC;;;;;;;;;ACFO,SAAS,gBAAgB,OAAwB;AAChD,QAAA,SAAS,sBACT,SAASC,MAAA;AAAA,IACb,MAAOC,sCACD,MAAM,UAAU,CAAA,CAChB,GAAA,OAAO,UAAU,EAAC;AAAA,IAExB,CAAC,MAAM,QAAQ,OAAO,MAAM;AAAA,EAC9B;AAEA,SACGN,2BAAAA,IAAAH,GAAAA,MAAA,EAAK,QAAQ,GAAG,cAAY,OAAO,OAAO,eAAa,OAAO,QAC5D,UAAcU,MAAAA,cAAA,MAAM,WAAW,CAAE,CAAA,GACpC;AAEJ;;;;;;;;;ACXA,SAAS,MAAM,KAAc;AAC3B,SAAO,OAAO,eAAe,KAAK,GAAG,GAAG,EAAE;AAC5C;AAEA,SAAS,cAAc,WAAmB,SAAiB;AAClD,SAAA,WAAW,SAAS,6BAA6B,OAAO;AACjE;AAEA,SAAS,WAAW,WAAmB,SAAiB;AAC/C,SAAA,WAAW,SAAS,0BAA0B,OAAO;AAC9D;AAEA,SAAS,aAAa,WAAmB;AACvC,SAAO,qCAAqC,SAAS;AACvD;AAEA,MAAM,kBAAqC,CAAA,GACrC,UAAyB,CAAC;AAEzB,SAAS,YAAY,OAAyB;AACnD,QAAM,EAAC,wBAAwB,iBAAiB,OAAO,QAAO,IAAI,OAC5D,CAAC,YAAY,aAAa,IAAIC,MAAAA,SAC9B,GAAA,CAAC,YAAY,aAAa,IAAIA,MAAA,SAAA,GAC9B,kBAAkB,mBAAmB,GACrC,EAAC,YAAY,WAAW,UAAU,cAAa,gBAAgB,OAAO;AAE5EC,QAAAA,UAAU,MAAM;AACd,UAAM,gBAAgC,CAAC;AAEzB,WAAA,cAAA;AAAA,MACZ,gBAAgB,WACb,QAA2B,EAAC,KAAK,sBAAsB,KAAK,0BAAyB,EACrF,UAAU;AAAA,QACT,MAAM,CAAC,WAAW,cAAc,OAAO,OAAO,CAAC,QAAQ,IAAI,SAAS,QAAQ,CAAC;AAAA,QAC7E,OAAO,CAAC,UAAU;AAChB,kBAAQ,MAAM,2CAA2C,KAAK,GAC9D,cAAc;AAAA,YACZ,OAAO;AAAA,UAAA,CACR;AAAA,QAAA;AAAA,MAEJ,CAAA;AAAA,OAIL,cAAc;AAAA,MACZ,gBAAgB,WACb,QAAQ;AAAA,QACP,QAAQ;AAAA,QACR,KAAK,YAAY,OAAO;AAAA,QACxB,KAAK;AAAA,MACN,CAAA,EACA,UAAU;AAAA,QACT,MAAM,MAAM,cAAc,cAAc,WAAW,OAAO,CAAC;AAAA,QAC3D,OAAO,CAAC,UAAU;AACZ,gBAAM,eAAe,MACvB,cAAc,MAAS,KAEvB,QAAQ,MAAM,sCAAsC,KAAK,GACzD,cAAc;AAAA,YACZ,OAAO;AAAA,UAAA,CACR;AAAA,QAAA;AAAA,MAGN,CAAA;AAAA,IAAA,GAGE,MAAM;AACX,oBAAc,QAAQ,CAAC,MAAM,EAAE,aAAa;AAAA,IAC9C;AAAA,KACC,CAAC,SAAS,WAAW,iBAAiB,aAAa,CAAC;AAEjD,QAAA,oBAAoBJ,MAAAA,QAAQ,MAAM;AAhF1C,QAAA;AAiFI,QAAI,SAAgB;AAAA,MAClB;AAAA,QACE,OAAO;AAAA,QACP,MAAM;AAAA,UACJ,EAAC,OAAO,cAAc,OAAO,UAAS;AAAA,UACtC,EAAC,OAAO,WAAW,OAAO,QAAO;AAAA,QAAA;AAAA,MACnC;AAAA,IAEJ;AAEA,UAAM,OAAc,KAAK,OAAO,CAAC,SAAS,KAAK,aAAa,MAAM;AAGhE,KAAA,MAAM,QAAQ,UAAU,IAAI,aAAa,IAAI,QAAQ,CAAC,QAAQ;AAC9D,WAAK,KAAK;AAAA,QACR,OAAO,IAAI,SAAS;AAAA,QACpB,OAAO,IAAI,YAAY,aAAa,WAAW,IAAI,OAAO,mBAAmB,IAAI;AAAA,MAAA,CAClF;AAAA,IAAA,CACF,GAEG,KAAK,SAAS,MAChB,SAAS,OAAO,OAAO,CAAC,EAAC,OAAO,QAAQ,MAAM,KAAK,CAAA,CAAC,IAItD,SAAS,OAAO;AAAA,MACd;AAAA,QACE;AAAA,UACE,OAAO;AAAA,UACP,MAAM;AAAA,YACJ,EAAC,OAAO,QAAQ,OAAO,WAAW,WAAW,OAAO,EAAC;AAAA,YACrD;AAAA,cACE,OAAO;AAAA,cACP,QAAQ,KAAO,OAAA,cAAe,WAAW,UAAU,eAA3C,OAA0D,KAAA;AAAA,YAAA;AAAA,UACpE;AAAA,QACF;AAAA,MAEJ;AAAA,MACA,KAAK,OAAO,CAAC,SAAS,KAAK,aAAa,MAAM;AAAA,IAChD;AAGA,UAAM,aAA4C,CAAC;AAC9C,WAAA,KAAA,QAAQ,CAAC,SAAS;AACjB,WAAK,YAAY,KAAK,aAAa,UAAU,KAAK,aAAa,WAC5D,WAAW,KAAK,QAAQ,MAC3B,WAAW,KAAK,QAAQ,IAAI,CAAA,IAE9B,WAAW,KAAK,QAAQ,EAAE,KAAK,IAAI;AAAA,IAAA,CAEtC,GACD,OAAO,KAAK,UAAU,EAAE,QAAQ,CAAC,aAAa;AACrC,aAAA,KAAK,EAAC,OAAO,UAAU,MAAM,WAAW,QAAQ,GAAE;AAAA,IAC1D,CAAA,GAEM;AAAA,EAAA,GACN,CAAC,YAAY,YAAY,WAAW,SAAS,IAAI,CAAC;AAErD,SAEKK,2BAAA,KAAAC,qBAAA,EAAA,UAAA;AAAA,IAAsB,sBAAA,IAAI,CAAC,cAAc,uCACvC,iBAA8BL,iBAAA,CAAA,GAAA,YAAA,GAAT,GAAuB,CAC9C;AAAA,IACDN,2BAAA,IAACF,UAAI,QAAO,QAAO,YAAW,yBAAuB,OAAA,SAAA,sBAAA,UAAS,IAAI,IAAI,GACpE,UAAAE,2BAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,QACEA,2BAAA;AAAA,UAACY,GAAA;AAAA,UAAA;AAAA,YACC,OAAO,EAAC,OAAO,OAAM;AAAA,YACrB,UAAU;AAAA,YACV,UAAU;AAAA,YACV,MAAK;AAAA,YACL,MAAK;AAAA,YACL,MAAK;AAAA,YACL,IAAG;AAAA,YACH,MAAM,aAAa,SAAS;AAAA,UAAA;AAAA,QAC9B;AAAA,QAGF,UAAAZ,2BAAA;AAAA,UAACH,GAAA;AAAA,UAAA;AAAA,YACC,UAAU;AAAA,YACV,QAAQ;AAAA,YACR,MAAK;AAAA,YACL,cAAW;AAAA,YACX,oBAAiB;AAAA,YAEjB,UAAAa,2BAAA,KAACG,GAAM,OAAA,EAAA,OAAO,GACZ,UAAA;AAAA,cAAAb,+BAACF,GAAAA,KAAI,EAAA,UAAU,GAAG,IAAG,UACnB,UAACE,2BAAAA,IAAAC,GAAA,SAAA,EAAQ,MAAM,GAAG,IAAG,MAAK,IAAG,sBAAqB,yBAElD,CAAA,GACF;AAAA,cACC,kBAAkB,IAAI,CAAC,SAClB,CAAC,QAAQ,CAAC,KAAK,OACV,OAINS,2BAAA,KAAAG,GAAA,OAAA,EAAuB,OAAO,GAC7B,UAAA;AAAA,gBAAAb,+BAACH,GAAAA,MAAK,EAAA,cAAY,IAAC,SAAS,GAC1B,UAACG,2BAAA,IAAAc,UAAA,EAAM,MAAM,GAAG,OAAK,IAAC,MAAK,gBACxB,UAAA,KAAK,MACR,CAAA,GACF;AAAA,gBACCd,2BAAAA,IAAAa,GAAAA,OAAA,EAAM,OAAO,GAAG,UAAU,GAAG,MAAK,YAChC,UAAK,KAAA,KAAK,IAAI,CAAC,QAAQ;AAzL9C,sBAAA;AA0LwB,yBACGH,2BAAAA,KAAAK,GAAAA,MAAA,EAAuC,SAAS,GAAG,MAAK,OACvD,UAAA;AAAA,oBAAAf,+BAACgB,GAAAA,QAAK,QAAO,UAAS,MAAK,aACxB,cAAI,OACP;AAAA,oBACC,OAAO,IAAI,SAAU,YACpBhB,2BAAA,IAACgB,SAAK,EAAA,MAAM,GAAI,WAAA,KAAA,IAAI,UAAJ,OAAA,SAAA,GAAW,OAAM;AAAA,oBAElC,OAAO,IAAI,SAAU,YAEjBhB,+BAAAW,WAAAA,UAAA,EAAA,UAAA,MAAM,IAAI,KAAK,mCACbK,GAAK,MAAA,EAAA,MAAM,GAAG,MAAK,QAAO,OAAO,EAAC,WAAW,gBAC5C,UAAAhB,2BAAA,IAAC,KAAE,EAAA,MAAM,IAAI,OAAQ,UAAA,IAAI,OAAM,EACjC,CAAA,mCAECiB,SAAK,EAAA,MAAM,GAAG,MAAK,QAAO,OAAO,EAAC,WAAW,gBAC3C,UAAA,IAAI,MACP,CAAA,EAEJ,CAAA;AAAA,kBAAA,EAAA,GAlBO,GAAG,IAAI,KAAK,IAAI,IAAI,KAAK,EAoBpC;AAAA,gBAAA,CAEH,EACH,CAAA;AAAA,cAAA,EAhCU,GAAA,KAAK,KAiCjB,CAEH;AAAA,YAAA,EACH,CAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MACF;AAAA,IAAA,EAEJ,CAAA;AAAA,EAAA,GACF;AAEJ;ACzNO,SAAS,kBAAkB,QAAmD;AAHrF,MAAA;AAIS,SAAA;AAAA,IACL,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAQ,KAAQ,UAAA,OAAA,SAAA,OAAA,WAAR,OAAkB,KAAA,EAAC,OAAO,SAAQ;AAAA,EAC5C;AACF;ACHA,MAAMtB,SAAOC,wBAAOsB,OAAI;AAAA,YACZC,GAAAA,IAAI,EAAE,CAAC;AAAA;AAAA;AAUZ,SAAS,YAAY,EAAC,MAAM,SAAS,SAA0B;AACpE,QAAM,aAAaC,OAAA,cAAc,EAAC,OAAO,UAAS;AAEhD,SAAApB,2BAAAA,IAACL,QAAK,EAAA,OAAM,UACV,UAAAe,gCAACQ,GAAAA,MAAK,EAAA,OAAM,UAAS,MAAM,GAAG,KAAK,GACjC,UAAA;AAAA,IAAAlB,+BAACF,GAAAA,KAAI,EAAA,MAAK,QACP,UAAA,yCACEkB,SAAK,EAAA,MAAM,GACV,UAAAhB,2BAAA,IAACqB,mBAAU,EACb,CAAA,IAECrB,2BAAA,IAAAsB,mBAAA,EAAW,KAAY,CAAA,GAE5B;AAAA,IAECZ,2BAAA,KAAAG,GAAA,OAAA,EAAM,MAAM,GAAG,OAAO,GACrB,UAAA;AAAA,MAAAb,2BAAA,IAACgB,GAAK,MAAA,EAAA,MAAM,GAAG,OAAO,EAAC,OAAO,UAAS,GAAG,cAAa,YAAW,QAAO,UACtE,eAAK,aACR;AAAA,MAEAhB,2BAAAA,IAACgB,GAAAA,MAAK,EAAA,OAAK,IAAC,MAAM,GAAG,cAAa,YAC/B,UAAA,WAAW,OAAO,KAAK,EAC1B,CAAA;AAAA,IAAA,EACF,CAAA;AAAA,EAAA,EAAA,CACF,EACF,CAAA;AAEJ;AClCA,SAAS,aAAa,WAAmB;AACvC,SAAO,qCAAqC,SAAS;AACvD;AAeO,SAAS,eAAe;AACvB,QAAA,CAAC,SAAS,UAAU,IAAIR,MAAA,SAAA,GACxB,CAAC,OAAO,QAAQ,IAAIA,MAAA,SAAA,GACpB,CAAC,OAAO,QAAQ,IAAIA,MAAAA,YAEpB,YAAYe,OAAA,aAAA,GACZ,kBAAkB,mBAAmB,GAErC,YAAYC,MAAAA,YAAY,MAAM;AAC5B,UAAA,EAAC,UAAa,IAAA,gBAAgB,OAC9B,GAAA,eAAe,gBAAgB,WAClC,QAAiB;AAAA,MAChB,KAAK,aAAa,SAAS;AAAA,MAC3B,KAAK;AAAA,IACN,CAAA,EACA;AAAA,MACCC,UAAA;AAAA,QAAU,CAAC,aACTC,KAAK,KAAA,UAAU,SAAS,SAAS,QAAQ,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,EAAE;AAAA,UAC9DC,UAAA,IAAI,CAAC,YAAY,EAAC,SAAS,UAAU,OAAO,SAAQ;AAAA,QAAA;AAAA,MACtD;AAAA,MAGH,UAAU;AAAA,MACT,MAAM,CAAC,EAAC,OAAO,QAAQ,SAAS,eAAc;AAC5C,mBAAW,QAAQ,GACnB;AAAA,WACG,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM,GAAG;AAAA,YAAK,CAAC,OAAO,UACvD,uBAAuB,OAAO,OAAO,QAAQ;AAAA,UAAA;AAAA,QAEjD;AAAA,MACF;AAAA,MACA,OAAO,CAAC,MAAa,SAAS,CAAC;AAAA,IAAA,CAChC;AAEI,WAAA,MAAM,aAAa,YAAY;AAAA,EAAA,GACrC,CAAC,WAAW,eAAe,CAAC;AAE/BlB,QAAAA,UAAU,MAAM,aAAa,CAAC,SAAS,CAAC;AAExC,QAAM,mBAAmBe,MAAAA,YAAY,MAAM,aAAa,CAAC,SAAS,CAAC,GAE7D,YAAY,CAAC,SAAS,CAAC;AAEzB,SAAA,QAECxB,2BAAAA,IAAA,0BAAA,EAAyB,QAAO,iBAC/B,yCAACF,GAAAA,KAAI,EAAA,SAAS,GACZ,UAAAY,2BAAAA,KAACM,GAAAA,MAAK,EAAA,UAAA;AAAA,IAAA;AAAA,IACgD;AAAA,IACpDhB,2BAAAA,IAAC,KAAE,EAAA,SAAS,kBAAkB,OAAM,qBAAoB,OAAO,EAAC,QAAQ,UAAS,GAAG,UAEpF,QAAA,CAAA;AAAA,IAAI;AAAA,EAAA,GAEN,EAAA,CACF,EACF,CAAA,IAKFU,2BAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,QAAO;AAAA,MACP,QACEV,2BAAA;AAAA,QAACY,GAAA;AAAA,QAAA;AAAA,UACC,OAAO,EAAC,OAAO,OAAM;AAAA,UACrB,UAAU;AAAA,UACV,UAAU;AAAA,UACV,MAAK;AAAA,UACL,MAAK;AAAA,UACL,MAAK;AAAA,UACL,IAAG;AAAA,UACH,SAAS;AAAA,UACT,MAAM,YAAY,SAAY,aAAa,QAAQ,EAAE;AAAA,QAAA;AAAA,MACvD;AAAA,MAGD,UAAA;AAAA,QACC,aAAAZ,2BAAAA,IAACF,GAAAA,OAAI,UAAU,GAAG,UAAU,GAC1B,UAAAY,2BAAA,KAACG,GAAM,OAAA,EAAA,OAAO,GACZ,UAAA;AAAA,UAACb,2BAAAA,IAAAgB,GAAAA,MAAA,EAAK,OAAM,UAAS,OAAK,IAAC,MAAM,GAC/B,UAAChB,2BAAAA,IAAA4B,GAAAA,SAAA,CAAA,CAAQ,EACX,CAAA;AAAA,UACA5B,2BAAAA,IAACgB,WAAK,OAAM,UAAS,MAAM,GAAG,OAAK,IAAC,UAEpC,sBAAA,CAAA;AAAA,QAAA,EAAA,CACF,EACF,CAAA;AAAA,QAGD,CAAC,aACAhB,2BAAAA,IAACa,GAAAA,OAAM,EAAA,OAAO,GAAG,SAAS,GACvB,UAAA,SAAA,OAAA,SAAA,MAAO,IAAI,CAAC,SAAS;AAtHhC,cAAA;AAuHkB,gBAAA,aAAa,QAAQ,QAAQ,KAAK,CAAC,WAAW,OAAO,OAAO,KAAK,EAAE;AAEvE,iBAAAb,2BAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC;AAAA,cACA,UAAS,KAAY,cAAA,OAAA,SAAA,WAAA,YAAZ,OAAuB,KAAA;AAAA,cAChC,QAAO,yCAAY,MAAM,IAAI,CAAC,SAAS,KAAK,WAAU,CAAA;AAAA,YAAC;AAAA,YAHlD,KAAK;AAAA,UAIZ;AAAA,QAAA,CAGN,EAAA,CAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAEJ;AAEJ;AAEA,SAAS,uBAAuB,OAAa,OAAa,SAAkB;AACpE,QAAA,EAAC,QAAW,IAAA,SACZ,cAAc,QAAQ,KAAK,CAAC,WAAW,OAAO,QAAO,+BAAO,GAAE,GAC9D,cAAc,QAAQ,KAAK,CAAC,WAAW,OAAO,QAAO,SAAA,OAAA,SAAA,MAAO,GAAE;AAGpE,UAAI,eAAa,OAAA,SAAA,YAAA,cAAY,eAAa,OAAA,SAAA,YAAA,aAChC,2CAAa,cAAa,QAAO,eAAa,OAAA,SAAA,YAAA,cAAa,MAAM,IAAI,KAIxE,eAAA,QAAA,YAAa,UAAU,IAAI;AACpC;AChJO,SAAS,mBAAmB,QAAmD;AAC7E,SAAA;AAAA,IACL,MAAM;AAAA,IACN,WAAW;AAAA,IACX,QAAQ,UAAQ,OAAA,SAAA,OAAA;AAAA,EAClB;AACF;ACJA,MAAM,cAAcJ,wBAAOE,MAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAeZ,CAAC,EAAC,MAAK,MAAM,MAAM,OAAO,MAAM,KAAK,QAAQ,EAAE;AAAA;AAAA;AAAA,GAK3DH,SAAOC,wBAAOsB,OAAI;AAAA;AAAA,MAElB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAQX,aAAatB,wBAAOC,OAAI;AAAA;AAAA;AAAA;AAAA,GAMxB,SAASD,iBAAAA,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuBf,SAAS,SAAS,OAAsB;AAC7C,QAAM,EAAC,OAAO,WAAW,cAAc,MAAM,eAAe,sBAAqB;AAG/E,SAAAI,2BAAAA,IAACL,QAAK,EAAA,MAAM,GACV,UAAAK,2BAAA;AAAA,IAACH,GAAA;AAAA,IAAA;AAAA,MACC,QAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,IAAG;AAAA,MACH;AAAA,MACA,QAAO;AAAA,MACP,KAAI;AAAA,MACJ,OAAO,EAAC,UAAU,WAAU;AAAA,MAE5B,UAAAa,2BAAA,KAACQ,WAAK,WAAU,UAAS,OAAO,EAAC,QAAQ,OACtC,GAAA,UAAA;AAAA,QACC,aAAAR,2BAAA,KAAC,YAAW,EAAA,cAAc,GACxB,UAAA;AAAA,UAACV,2BAAAA,IAAA,QAAA,EAAO,KAAK,UAAW,CAAA;AAAA,UACvB,gBACCA,2BAAA,IAAC,aAAY,EAAA,SAAQ,QACnB,UAAAA,+BAACgB,GAAAA,MAAK,EAAA,OAAM,UACV,UAAAhB,2BAAAA,IAAC6B,MAAAA,UAAS,CAAA,CAAA,EAAA,CACZ,EACF,CAAA;AAAA,QAAA,GAEJ;AAAA,QAEFnB,2BAAAA,KAACQ,WAAK,WAAU,UAAS,SAAQ,iBAAgB,UAAU,GAAG,MAAM,GAClE,UAAA;AAAA,UAAAlB,+BAACC,GAAAA,SAAQ,EAAA,IAAG,MAAK,MAAM,GACpB,UACH,OAAA;AAAA,UACAD,2BAAAA,IAACF,GAAAA,OAAI,WAAW,GACd,0CAACe,GAAM,OAAA,EAAA,OAAO,GAAG,MAAM,GACrB,UAAA;AAAA,YAACb,2BAAA,IAAAgB,GAAA,MAAA,EAAK,MAAM,GAAI,UAAc,eAAA;AAAA,YAC9BhB,2BAAAA,IAACgB,WAAK,MAAM,GAAG,OAAO,EAAC,SAAS,IAAG,GAChC,UACH,kBAAA,CAAA;AAAA,UAAA,EAAA,CACF,EACF,CAAA;AAAA,QAAA,EACF,CAAA;AAAA,MAAA,EACF,CAAA;AAAA,IAAA;AAAA,EAAA,GAEJ;AAEJ;AC1GA,MAAM,yBAAyB;AAAA,EAC7B,WAAW;AAAA,EACX,SAAS;AACX;AAuBO,SAAS,iBAAiB;AAC/B,QAAM,kBAAkB,mBAAmB;AACpC,SAAAX,MAAA;AAAA,IACL,OAAO;AAAA,MACL,SAAS,CAAC,mBAA2B;AACnC,cAAM,MAAM,iBACR,oCAAoC,cAAc,KAClD;AACG,eAAA,gBAAgB,WAAW,QAA6B;AAAA,UAC7D;AAAA,UACA,KAAK;AAAA,UACL,iBAAiB;AAAA,QAAA,CAClB;AAAA,MACH;AAAA,MACA,YAAYyB,iCAAgB,sBAAsB;AAAA,IAAA;AAAA,IAEpD,CAAC,eAAe;AAAA,EAClB;AACF;AC1CA,SAAS,UAAU,MAAyB,MAAe;AACrD,SAAA,SAAS,aACJ,wCAAwC,KAAK,OAAO,KAClD,SAAS,UACX,qCAAqC,KAAK,OAAO,KAEnD;AACT;AAMO,SAAS,gBAAgB,OAA6B;AAC3D,QAAM,EAAC,eAAc,IAAI,OACnB,CAAC,WAAW,YAAY,IAAItB,MAAqB,SAAA,CAAE,CAAA,GAEnD,EAAC,SAAS,WAAA,IAAc,eAAe;AAE7C,SAAAC,MAAA,UAAU,MAAM;AACd,UAAM,eAAe,QAAQ,cAAc,EAAE,UAAU,CAAC,aAAa;AACnE,mBAAa,SAAS,KAAK;AAAA,IAAA,CAC5B;AACD,WAAO,MAAM;AACX,mBAAa,YAAY;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,cAAc,SAAS,cAAc,CAAC,GAKxCT,2BAAAA,IAAC,0BAAyB,EAAA,QAHd,sBAIV,UAAAA,2BAAA,IAACkB,WAAK,IAAG,MAAK,UAAS,QAAO,OAAM,WAAU,UAAU,GACrD,UAAW,aAAA,OAAA,SAAA,UAAA,IAAI,CAAC,UAAU,UAAU;AAvC7C,QAAA;AAwCU,QAAI,CAAC,SAAS,SAAU,CAAC,SAAS,mBAAmB,CAAC,SAAS;AACtD,aAAA;AAET,UAAM,YAAY,SAAS,eAAa,KAAA,SAAS,oBAAT,OAAA,SAAA,GAA0B,cAAa,CAAA,GACzE,WAAW,SAAS,UACpB,EAAC,kBAAkB,CAAA,EAAe,IAAA,UAClC,QACH,gBAAgB,OACb,UAAU,gBAAgB,MAAM,gBAAgB,KAAK,IACrD,SAAS,iBAAiB,SAAS;AAGvC,WAAAlB,2BAAA;AAAA,MAACkB,GAAA;AAAA,MAAA;AAAA,QACC,IAAG;AAAA,QAEH,cAAc,SAAQ,aAAW,OAAA,SAAA,UAAA,UAAS,IAAI,IAAI;AAAA,QAClD,aAAa,UAAU,IAAI,IAAI;AAAA,QAC/B,OAAM;AAAA,QACN,OAAO,EAAC,UAAU,KAAK,OAAO,MAAK;AAAA,QAEnC,UAAAlB,2BAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,OAAO,SAAS;AAAA,YAChB,MAAM,QAAQ,OAAA,OAAA;AAAA,YACd,eAAe,UAAU;AAAA,YACzB,mBAAmB;AAAA,YACnB,cAAc,SAAS;AAAA,YACvB,WACE,SAAS,SAAS,WAAW,MAAM,SAAS,MAAM,EAAE,OAAO,GAAG,EAAE,IAAQ,IAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAE5E;AAAA,MAfK,SAAS;AAAA,IAgBhB;AAAA,EAAA,IAGN,EACF,CAAA;AAEJ;ACzEO,SAAS,sBAAsB,QAAmD;AAHzF,MAAA;AAIS,SAAA;AAAA,IACL,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAQ,KAAQ,UAAA,OAAA,SAAA,OAAA,WAAR,OAAkB,KAAA,EAAC,OAAO,OAAM;AAAA,EAC1C;AACF;ACNO,SAAS,gBAAgB,OAA8B;AAC5D,wCACG+B,GAAU,WAAA,EAAA,OAAO,GAAG,SAAS,GAAG,QAAO,UAAS,OAAO,EAAC,QAAQ,QAAQ,WAAW,OAAM,GACvF,gBAAM,UACT;AAEJ;;;;;;;;;ACHA,MAAM,QAAQ;AAAA,EACZ,OAAO,IAAI,SAAiCC,iBAAA;AAAA,yBACrB,CAAC,EAAC,YAAW,MAAM,OAAO,MAAM,CAAC,CAAC;AAAA,QACnDA,iBAAAA,IAAI,GAAG,IAAI,CAAC;AAAA;AAAA;AAAA,EAGlB,QAAQ,IAAI,SAAiCA,iBAAA;AAAA,yBACtB,CAAC,EAAC,YAAW,MAAM,OAAO,MAAM,CAAC,CAAC;AAAA,QACnDA,iBAAAA,IAAI,GAAG,IAAI,CAAC;AAAA;AAAA;AAGpB,GAEM,OAAOpC,wBAAOmB,OAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQlB,MAAM;AAAA;AAAA,KAEP;AAAA;AAAA;AAAA;AAAA,MAIC,MAAM;AAAA;AAAA,KAEP;AAAA;AAAA,MAEC,MAAM;AAAA;AAAA,KAEP;AAAA;AAAA;AAAA;AAAA,MAIC,MAAM;AAAA;AAAA,KAEP;AAAA;AAAA;AAAA;AAAA,MAIC,MAAM;AAAA;AAAA,KAEP;AAAA;AAAA;AAAA;AAAA,MAIC,MAAM;AAAA;AAAA,KAEP;AAAA;AAAA,MAEC,MAAM;AAAA;AAAA,KAEP;AAAA;AAAA;AAAA;AAAA,MAIC,MAAM;AAAA;AAAA,KAEP;AAAA;AAAA,GAQC,aAAgC,IAChC,YAA0B,CAAC;AAE1B,SAAS,YAAY,OAAyB;AAC7C,QAAA;AAAA,IACJ,QAAQ,EAAC,SAAS,WAAW,UAAU,WAAU;AAAA,EAAA,IAC/C;AAEF,SAAAL,2BAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,UAAS;AAAA,MACT,cAAY,OAAO,SAAS;AAAA,MAC5B,eAAa,OAAO,UAAU;AAAA,MAC9B,KAAK;AAAA,MAEJ,UAAA;AAAA,QAAA,QAAQ,SAAS,OACfV,+BAAAH,GAAAA,MAAA,EAAK,SAAS,GAAG,QAAQ,GAAG,MAAK,WAChC,UAACG,+BAAAgB,GAAAA,MAAA,EAAK,OAAM,UAAS,qDAAwC,CAAA,GAC/D;AAAA,QAED,QAAQ,IAAI,CAAC,cAAc,UACtB,aAAa,SAAS,yBACjBhB,2BAAA,IAAC,aAAwB,EAAA,QAAQ,gBAAf,KAA6B,IAEpD,aAAa,YACRA,2BAAAA,IAAC,oCAAgC,YAAX,GAAA,KAAyB,IAEjDU,2BAAAA,KAACZ,GAAiB,KAAA,EAAA,UAAA;AAAA,UAAa,aAAA;AAAA,UAAK;AAAA,QAAA,EAAA,GAA1B,KAAsD,CACxE;AAAA,MAAA;AAAA,IAAA;AAAA,EACH;AAEJ;ACnGgB,SAAA,UAAU,EAAC,UAAoC;AAC7D,SAAK,SAKHE,2BAAA,IAAC,iBAAiB,UAAjB,EAA0B,OAAO,QAChC,UAACA,2BAAA,IAAA,iBAAA,EACC,UAACA,2BAAA,IAAA,aAAA,EAAY,OAAgB,CAAA,EAC/B,CAAA,EACF,CAAA,IARO;AAUX;ACbA,MAAM,cAA6B;AAAA,EACjC,QAAQ;AAAA,EACR,aAAa;AACf,GAEM,gBAAgB,MACpBU,2BAAA;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,oBAAgB;AAAA,IAChB,SAAQ;AAAA,IACR,MAAK;AAAA,IACL,OAAM;AAAA,IACN,qBAAoB;AAAA,IACpB,OAAM;AAAA,IACN,QAAO;AAAA,IAEP,UAAA;AAAA,MAAAV,2BAAA,IAAC,QAAK,EAAA,GAAE,iCAAgC,OAAO,aAAa;AAAA,MAC3DA,2BAAA,IAAA,QAAA,EAAK,GAAE,kBAAiB,OAAO,aAAa;AAAA,MAC5CA,2BAAA,IAAA,QAAA,EAAK,GAAE,iCAAgC,OAAO,YAAa,CAAA;AAAA,IAAA;AAAA,EAAA;AAC9D,GAwBW,gBAAgBiC,OAAA,aAAoC,CAAC,SAAS,OAAO;AA/ClF,MAAA,IAAA,IAAA,IAAA,IAAA;AAgDE,QAAM,eAAgC;AAAA,IACpC,SAAQ,KAAA,OAAO,kBAAP,OAAA,KAAwB,CAAC;AAAA,IACjC,UAAS,KAAA,OAAO,YAAP,OAAA,KAAkB,CAAA;AAAA,EAGvB,GAAA,SAAQ,KAAO,OAAA,UAAP,YAAgB,aACxB,QAAO,KAAO,OAAA,SAAP,OAAe,KAAA,aACtB,QAAO,KAAA,OAAO,SAAP,OAAe,KAAA;AAErB,SAAA;AAAA,IACL,MAAM;AAAA,IACN,OAAO,CAAC,MAAM,YACL;AAAA,MACL,GAAG;AAAA,MACH;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW,MAAOjC,2BAAA,IAAA,WAAA,EAAU,QAAQ,aAAc,CAAA;AAAA,MAAA;AAAA,IACpD;AAAA,EAGN;AACF,CAAC;;;;;;"}