@sanity/dashboard 5.0.1 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +4 -50
  3. package/dist/index.d.ts +54 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +605 -0
  6. package/dist/index.js.map +1 -0
  7. package/package.json +37 -79
  8. package/lib/index.d.mts +0 -65
  9. package/lib/index.d.ts +0 -65
  10. package/lib/index.esm.js +0 -568
  11. package/lib/index.esm.js.map +0 -1
  12. package/lib/index.js +0 -564
  13. package/lib/index.js.map +0 -1
  14. package/lib/index.mjs +0 -568
  15. package/lib/index.mjs.map +0 -1
  16. package/sanity.json +0 -8
  17. package/src/components/DashboardLayout.tsx +0 -10
  18. package/src/components/DashboardWidgetContainer.tsx +0 -69
  19. package/src/components/NotFoundWidget.tsx +0 -30
  20. package/src/components/WidgetGroup.tsx +0 -106
  21. package/src/containers/Dashboard.tsx +0 -19
  22. package/src/containers/DashboardContext.tsx +0 -8
  23. package/src/containers/WidgetContainer.tsx +0 -21
  24. package/src/index.ts +0 -7
  25. package/src/plugin.tsx +0 -72
  26. package/src/types.ts +0 -21
  27. package/src/versionedClient.ts +0 -5
  28. package/src/widgets/projectInfo/ProjectInfo.tsx +0 -221
  29. package/src/widgets/projectInfo/index.ts +0 -10
  30. package/src/widgets/projectInfo/types.ts +0 -28
  31. package/src/widgets/projectUsers/ProjectUser.tsx +0 -45
  32. package/src/widgets/projectUsers/ProjectUsers.tsx +0 -148
  33. package/src/widgets/projectUsers/index.ts +0 -10
  34. package/src/widgets/sanityTutorials/SanityTutorials.tsx +0 -77
  35. package/src/widgets/sanityTutorials/Tutorial.tsx +0 -111
  36. package/src/widgets/sanityTutorials/dataAdapter.ts +0 -49
  37. package/src/widgets/sanityTutorials/index.ts +0 -10
  38. package/v2-incompatible.js +0 -11
package/dist/index.js ADDED
@@ -0,0 +1,605 @@
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import { c } from "react/compiler-runtime";
3
+ import { Card, Box, Heading, Stack, Label, Grid, Text, Code, Button, rem, Flex, Spinner, Container } from "@sanity/ui";
4
+ import { getTheme_v2 } from "@sanity/ui/theme";
5
+ import { forwardRef, createContext, useContext, useState, useEffect } from "react";
6
+ import { styled, css } from "styled-components";
7
+ import { useClient, useListFormat, UserAvatar, useUserStore, definePlugin } from "sanity";
8
+ import { from } from "rxjs";
9
+ import { switchMap, map } from "rxjs/operators";
10
+ import { RobotIcon, PlayIcon } from "@sanity/icons";
11
+ import imageUrlBuilder from "@sanity/image-url";
12
+ const Root$3 = styled(Card).withConfig({
13
+ displayName: "Root",
14
+ componentId: "sc-stlwez-0"
15
+ })`display:flex;flex-direction:column;justify-content:stretch;height:100%;box-sizing:border-box;position:relative;`, Header = styled(Card).withConfig({
16
+ displayName: "Header",
17
+ componentId: "sc-stlwez-1"
18
+ })`position:sticky;top:0;z-index:2;border-top-left-radius:inherit;border-top-right-radius:inherit;`, Footer = styled(Card).withConfig({
19
+ displayName: "Footer",
20
+ componentId: "sc-stlwez-2"
21
+ })`position:sticky;overflow:hidden;bottom:0;z-index:2;border-bottom-right-radius:inherit;border-bottom-left-radius:inherit;margin-top:auto;`, Content = styled(Box).withConfig({
22
+ displayName: "Content",
23
+ componentId: "sc-stlwez-3"
24
+ })`position:relative;z-index:1;height:stretch;min-height:21.5em;@media (min-width:${({
25
+ theme
26
+ }) => getTheme_v2(theme).media[0]}px){overflow-y:auto;outline:none;}`, DashboardWidgetContainer = forwardRef(function(props, ref) {
27
+ const $ = c(11), {
28
+ header,
29
+ children,
30
+ footer
31
+ } = props;
32
+ let t0;
33
+ $[0] !== header ? (t0 = header && /* @__PURE__ */ jsx(Header, { borderBottom: !0, paddingX: 3, paddingY: 4, children: /* @__PURE__ */ jsx(Heading, { size: 1, textOverflow: "ellipsis", children: header }) }), $[0] = header, $[1] = t0) : t0 = $[1];
34
+ let t1;
35
+ $[2] !== children ? (t1 = children && /* @__PURE__ */ jsx(Content, { children }), $[2] = children, $[3] = t1) : t1 = $[3];
36
+ let t2;
37
+ $[4] !== footer ? (t2 = footer && /* @__PURE__ */ jsx(Footer, { borderTop: !0, children: footer }), $[4] = footer, $[5] = t2) : t2 = $[5];
38
+ let t3;
39
+ return $[6] !== ref || $[7] !== t0 || $[8] !== t1 || $[9] !== t2 ? (t3 = /* @__PURE__ */ jsxs(Root$3, { radius: 3, display: "flex", ref, children: [
40
+ t0,
41
+ t1,
42
+ t2
43
+ ] }), $[6] = ref, $[7] = t0, $[8] = t1, $[9] = t2, $[10] = t3) : t3 = $[10], t3;
44
+ }), DashboardContext = createContext({
45
+ widgets: []
46
+ });
47
+ function useDashboardConfig() {
48
+ return useContext(DashboardContext);
49
+ }
50
+ function WidgetContainer(props) {
51
+ const $ = c(9), config = useDashboardConfig();
52
+ let t0;
53
+ $[0] !== config.layout || $[1] !== props.layout ? (t0 = {
54
+ ...props.layout,
55
+ ...config.layout
56
+ }, $[0] = config.layout, $[1] = props.layout, $[2] = t0) : t0 = $[2];
57
+ const layout = t0, Widget = props.component;
58
+ let t1;
59
+ $[3] !== Widget ? (t1 = /* @__PURE__ */ jsx(Widget, {}), $[3] = Widget, $[4] = t1) : t1 = $[4];
60
+ let t2;
61
+ return $[5] !== layout.height || $[6] !== layout.width || $[7] !== t1 ? (t2 = /* @__PURE__ */ jsx(Card, { shadow: 1, "data-width": layout.width, "data-height": layout.height, children: t1 }), $[5] = layout.height, $[6] = layout.width, $[7] = t1, $[8] = t2) : t2 = $[8], t2;
62
+ }
63
+ function useVersionedClient() {
64
+ const $ = c(1);
65
+ let t0;
66
+ return $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t0 = {
67
+ apiVersion: "2024-08-01"
68
+ }, $[0] = t0) : t0 = $[0], useClient(t0);
69
+ }
70
+ function isUrl(url) {
71
+ return url && /^https?:\/\//.test(url);
72
+ }
73
+ function getGraphQLUrl(projectId, dataset) {
74
+ return `https://${projectId}.api.sanity.io/v1/graphql/${dataset}/default`;
75
+ }
76
+ function getGroqUrl(projectId, dataset) {
77
+ return `https://${projectId}.api.sanity.io/v1/groq/${dataset}`;
78
+ }
79
+ function getManageUrl(projectId) {
80
+ return `https://manage.sanity.io/projects/${projectId}`;
81
+ }
82
+ const NO_EXPERIMENTAL = [], NO_DATA = [];
83
+ function ProjectInfo(props) {
84
+ const $ = c(37), {
85
+ __experimental_before: t0,
86
+ data: t1
87
+ } = props, __experimental_before = t0 === void 0 ? NO_EXPERIMENTAL : t0, data = t1 === void 0 ? NO_DATA : t1, [studioApps, setStudioApps] = useState(), [graphQLApi, setGraphQLApi] = useState(), versionedClient = useVersionedClient();
88
+ let t2;
89
+ $[0] !== versionedClient ? (t2 = versionedClient.config(), $[0] = versionedClient, $[1] = t2) : t2 = $[1];
90
+ const {
91
+ projectId: t3,
92
+ dataset: t4
93
+ } = t2, projectId = t3 === void 0 ? "unknown" : t3, dataset = t4 === void 0 ? "unknown" : t4;
94
+ let t5;
95
+ $[2] !== dataset || $[3] !== projectId || $[4] !== versionedClient.observable ? (t5 = () => {
96
+ const subscriptions = [];
97
+ return subscriptions.push(versionedClient.observable.request({
98
+ uri: "/user-applications",
99
+ tag: "dashboard.project-info"
100
+ }).subscribe({
101
+ next: (result) => setStudioApps(result.filter(_temp$2)),
102
+ error: (error) => {
103
+ console.error("Error while resolving user applications", error), setStudioApps({
104
+ error: "Something went wrong while resolving user applications. See console."
105
+ });
106
+ }
107
+ })), subscriptions.push(versionedClient.observable.request({
108
+ method: "HEAD",
109
+ uri: `/graphql/${dataset}/default`,
110
+ tag: "dashboard.project-info.graphql-api"
111
+ }).subscribe({
112
+ next: () => setGraphQLApi(getGraphQLUrl(projectId, dataset)),
113
+ error: (error_0) => {
114
+ error_0.statusCode === 404 ? setGraphQLApi(void 0) : (console.error("Error while looking for graphQLApi", error_0), setGraphQLApi({
115
+ error: "Something went wrong while looking up graphQLApi. See console."
116
+ }));
117
+ }
118
+ })), () => {
119
+ subscriptions.forEach(_temp2$1);
120
+ };
121
+ }, $[2] = dataset, $[3] = projectId, $[4] = versionedClient.observable, $[5] = t5) : t5 = $[5];
122
+ let t6;
123
+ $[6] !== dataset || $[7] !== projectId || $[8] !== versionedClient ? (t6 = [dataset, projectId, versionedClient, setGraphQLApi], $[6] = dataset, $[7] = projectId, $[8] = versionedClient, $[9] = t6) : t6 = $[9], useEffect(t5, t6);
124
+ let result_0;
125
+ if ($[10] !== data || $[11] !== dataset || $[12] !== graphQLApi || $[13] !== projectId || $[14] !== studioApps) {
126
+ result_0 = [{
127
+ title: "Sanity project",
128
+ rows: [{
129
+ title: "Project ID",
130
+ value: projectId
131
+ }, {
132
+ title: "Dataset",
133
+ value: dataset
134
+ }]
135
+ }];
136
+ const apps = data.filter(_temp3);
137
+ (Array.isArray(studioApps) ? studioApps : []).forEach((app_0) => {
138
+ apps.push({
139
+ title: app_0.title || "Studio",
140
+ value: app_0.urlType === "internal" ? `https://${app_0.appHost}.sanity.studio` : app_0.appHost
141
+ });
142
+ }), apps.length > 0 && (result_0 = result_0.concat([{
143
+ title: "Apps",
144
+ rows: apps
145
+ }])), result_0 = result_0.concat([{
146
+ title: "APIs",
147
+ rows: [{
148
+ title: "GROQ",
149
+ value: getGroqUrl(projectId, dataset)
150
+ }, {
151
+ title: "GraphQL",
152
+ value: (typeof graphQLApi == "object" ? "Error" : graphQLApi) ?? "Not deployed"
153
+ }]
154
+ }], data.filter(_temp4));
155
+ const otherStuff = {};
156
+ data.forEach((item_1) => {
157
+ if (item_1.category && item_1.category !== "apps" && item_1.category !== "apis") {
158
+ const group = otherStuff[item_1.category] ?? [];
159
+ group.push(item_1), otherStuff[item_1.category] = group;
160
+ }
161
+ }), Object.keys(otherStuff).forEach((category) => {
162
+ result_0.push({
163
+ title: category,
164
+ rows: otherStuff[category]
165
+ });
166
+ }), $[10] = data, $[11] = dataset, $[12] = graphQLApi, $[13] = projectId, $[14] = studioApps, $[15] = result_0;
167
+ } else
168
+ result_0 = $[15];
169
+ const assembleTableRows = result_0;
170
+ let t7;
171
+ $[16] !== __experimental_before ? (t7 = __experimental_before.map(_temp5), $[16] = __experimental_before, $[17] = t7) : t7 = $[17];
172
+ const t8 = __experimental_before?.length > 0 ? 4 : 0;
173
+ let t9;
174
+ $[18] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t9 = {
175
+ width: "100%"
176
+ }, $[18] = t9) : t9 = $[18];
177
+ let t10;
178
+ $[19] !== projectId ? (t10 = getManageUrl(projectId), $[19] = projectId, $[20] = t10) : t10 = $[20];
179
+ let t11;
180
+ $[21] !== t10 ? (t11 = /* @__PURE__ */ jsx(Button, { style: t9, paddingX: 2, paddingY: 4, mode: "bleed", tone: "primary", text: "Manage project", as: "a", href: t10 }), $[21] = t10, $[22] = t11) : t11 = $[22];
181
+ let t12;
182
+ $[23] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t12 = /* @__PURE__ */ jsx(Box, { paddingX: 3, as: "header", children: /* @__PURE__ */ jsx(Heading, { size: 1, as: "h2", id: "project_info_table", children: "Project info" }) }), $[23] = t12) : t12 = $[23];
183
+ let t13;
184
+ $[24] !== assembleTableRows ? (t13 = assembleTableRows.map(_temp7), $[24] = assembleTableRows, $[25] = t13) : t13 = $[25];
185
+ let t14;
186
+ $[26] !== t13 ? (t14 = /* @__PURE__ */ jsx(Card, { paddingY: 4, radius: 2, "aria-label": "Project info", children: /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
187
+ t12,
188
+ t13
189
+ ] }) }), $[26] = t13, $[27] = t14) : t14 = $[27];
190
+ let t15;
191
+ $[28] !== t11 || $[29] !== t14 ? (t15 = /* @__PURE__ */ jsx(DashboardWidgetContainer, { footer: t11, children: t14 }), $[28] = t11, $[29] = t14, $[30] = t15) : t15 = $[30];
192
+ let t16;
193
+ $[31] !== t15 || $[32] !== t8 ? (t16 = /* @__PURE__ */ jsx(Box, { height: "fill", marginTop: t8, children: t15 }), $[31] = t15, $[32] = t8, $[33] = t16) : t16 = $[33];
194
+ let t17;
195
+ return $[34] !== t16 || $[35] !== t7 ? (t17 = /* @__PURE__ */ jsxs(Fragment, { children: [
196
+ t7,
197
+ t16
198
+ ] }), $[34] = t16, $[35] = t7, $[36] = t17) : t17 = $[36], t17;
199
+ }
200
+ function _temp7(item_2) {
201
+ return !item_2 || !item_2.rows ? null : /* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
202
+ /* @__PURE__ */ jsx(Card, { borderBottom: !0, padding: 3, children: /* @__PURE__ */ jsx(Label, { size: 0, muted: !0, children: item_2.title }) }),
203
+ /* @__PURE__ */ jsx(Stack, { gap: 4, paddingX: 3, children: item_2.rows.map(_temp6) })
204
+ ] }, item_2.title);
205
+ }
206
+ function _temp6(row) {
207
+ const rowValue = typeof row.value == "object" ? row.value.error : row.value;
208
+ return /* @__PURE__ */ jsxs(Grid, { gridTemplateColumns: 2, children: [
209
+ /* @__PURE__ */ jsx(Text, { weight: "medium", children: row.title }),
210
+ typeof row.value == "object" && /* @__PURE__ */ jsx(Text, { size: 1, children: row.value?.error }),
211
+ typeof row.value == "string" && /* @__PURE__ */ jsx(Fragment, { children: isUrl(row.value) ? /* @__PURE__ */ jsx(Text, { size: 1, style: {
212
+ wordBreak: "break-word"
213
+ }, children: /* @__PURE__ */ jsx("a", { href: row.value, children: row.value }) }) : /* @__PURE__ */ jsx(Code, { size: 1, style: {
214
+ wordBreak: "break-word"
215
+ }, children: row.value }) })
216
+ ] }, `${rowValue ?? ""}-${row.title}`);
217
+ }
218
+ function _temp5(widgetConfig, idx) {
219
+ return /* @__PURE__ */ jsx(WidgetContainer, { ...widgetConfig }, idx);
220
+ }
221
+ function _temp4(item_0) {
222
+ return item_0.category === "apis";
223
+ }
224
+ function _temp3(item) {
225
+ return item.category === "apps";
226
+ }
227
+ function _temp2$1(s) {
228
+ return s.unsubscribe();
229
+ }
230
+ function _temp$2(app) {
231
+ return app.type === "studio";
232
+ }
233
+ function projectInfoWidget(config) {
234
+ return {
235
+ name: "project-info",
236
+ component: ProjectInfo,
237
+ layout: config?.layout ?? {
238
+ width: "medium"
239
+ }
240
+ };
241
+ }
242
+ const Root$2 = styled(Flex).withConfig({
243
+ displayName: "Root",
244
+ componentId: "sc-63c5lb-0"
245
+ })`height:${rem(33)};box-sizing:content-box;`;
246
+ function ProjectUser(t0) {
247
+ const $ = c(18), {
248
+ user,
249
+ isRobot,
250
+ roles
251
+ } = t0;
252
+ let t1;
253
+ $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t1 = {
254
+ style: "narrow"
255
+ }, $[0] = t1) : t1 = $[0];
256
+ const listFormat = useListFormat(t1);
257
+ let t2;
258
+ $[1] !== isRobot || $[2] !== user ? (t2 = /* @__PURE__ */ jsx(Box, { flex: "none", children: isRobot ? /* @__PURE__ */ jsx(Text, { size: 2, children: /* @__PURE__ */ jsx(RobotIcon, {}) }) : /* @__PURE__ */ jsx(UserAvatar, { user }) }), $[1] = isRobot, $[2] = user, $[3] = t2) : t2 = $[3];
259
+ let t3;
260
+ $[4] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t3 = {
261
+ color: "inherit"
262
+ }, $[4] = t3) : t3 = $[4];
263
+ let t4;
264
+ $[5] !== user.displayName ? (t4 = /* @__PURE__ */ jsx(Text, { size: 1, style: t3, textOverflow: "ellipsis", weight: "medium", children: user.displayName }), $[5] = user.displayName, $[6] = t4) : t4 = $[6];
265
+ let t5;
266
+ $[7] !== listFormat || $[8] !== roles ? (t5 = listFormat.format(roles), $[7] = listFormat, $[8] = roles, $[9] = t5) : t5 = $[9];
267
+ let t6;
268
+ $[10] !== t5 ? (t6 = /* @__PURE__ */ jsx(Text, { muted: !0, size: 1, textOverflow: "ellipsis", children: t5 }), $[10] = t5, $[11] = t6) : t6 = $[11];
269
+ let t7;
270
+ $[12] !== t4 || $[13] !== t6 ? (t7 = /* @__PURE__ */ jsxs(Stack, { flex: 1, gap: 2, children: [
271
+ t4,
272
+ t6
273
+ ] }), $[12] = t4, $[13] = t6, $[14] = t7) : t7 = $[14];
274
+ let t8;
275
+ return $[15] !== t2 || $[16] !== t7 ? (t8 = /* @__PURE__ */ jsx(Root$2, { align: "center", children: /* @__PURE__ */ jsxs(Flex, { align: "center", flex: 1, gap: 2, children: [
276
+ t2,
277
+ t7
278
+ ] }) }), $[15] = t2, $[16] = t7, $[17] = t8) : t8 = $[17], t8;
279
+ }
280
+ function getInviteUrl(projectId) {
281
+ return `https://manage.sanity.io/projects/${projectId}/members`;
282
+ }
283
+ function ProjectUsers() {
284
+ const $ = c(28), [project, setProject] = useState(), [users, setUsers] = useState(), [error, setError] = useState(), userStore = useUserStore(), versionedClient = useVersionedClient();
285
+ let t0;
286
+ $[0] !== userStore || $[1] !== versionedClient ? (t0 = () => {
287
+ const {
288
+ projectId
289
+ } = versionedClient.config(), subscription = versionedClient.observable.request({
290
+ uri: `/projects/${projectId}`,
291
+ tag: "dashboard.project-users"
292
+ }).pipe(switchMap((_project) => from(userStore.getUsers(_project.members.map(_temp$1))).pipe(map((_users) => ({
293
+ project: _project,
294
+ users: _users
295
+ }))))).subscribe({
296
+ next: (t12) => {
297
+ const {
298
+ users: _users_0,
299
+ project: _project_0
300
+ } = t12;
301
+ setProject(_project_0), setUsers((Array.isArray(_users_0) ? _users_0 : [_users_0]).sort((userA, userB) => sortUsersByRobotStatus(userA, userB, _project_0)));
302
+ },
303
+ error: (e) => setError(e)
304
+ });
305
+ return () => subscription.unsubscribe();
306
+ }, $[0] = userStore, $[1] = versionedClient, $[2] = t0) : t0 = $[2];
307
+ const fetchData = t0;
308
+ let t1, t2;
309
+ $[3] !== fetchData ? (t1 = () => fetchData(), t2 = [fetchData], $[3] = fetchData, $[4] = t1, $[5] = t2) : (t1 = $[4], t2 = $[5]), useEffect(t1, t2);
310
+ let t3;
311
+ $[6] !== fetchData ? (t3 = () => fetchData(), $[6] = fetchData, $[7] = t3) : t3 = $[7];
312
+ const handleRetryFetch = t3, isLoading = !users || !project;
313
+ if (error) {
314
+ let t42;
315
+ $[8] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t42 = /* @__PURE__ */ jsx(Text, { children: "Something went wrong while fetching data." }), $[8] = t42) : t42 = $[8];
316
+ let t52;
317
+ return $[9] !== handleRetryFetch ? (t52 = /* @__PURE__ */ jsx(DashboardWidgetContainer, { header: "Project users", children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsxs(Stack, { gap: 3, children: [
318
+ t42,
319
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Button, { mode: "ghost", text: "Retry", title: "Retry users fetch", onClick: handleRetryFetch }) })
320
+ ] }) }) }), $[9] = handleRetryFetch, $[10] = t52) : t52 = $[10], t52;
321
+ }
322
+ let t4;
323
+ $[11] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t4 = {
324
+ width: "100%"
325
+ }, $[11] = t4) : t4 = $[11];
326
+ let t5;
327
+ $[12] !== isLoading || $[13] !== project ? (t5 = isLoading ? void 0 : getInviteUrl(project.id), $[12] = isLoading, $[13] = project, $[14] = t5) : t5 = $[14];
328
+ let t6;
329
+ $[15] !== isLoading || $[16] !== t5 ? (t6 = /* @__PURE__ */ jsx(Button, { style: t4, paddingX: 2, paddingY: 4, mode: "bleed", tone: "primary", text: "Manage members", as: "a", loading: isLoading, href: t5 }), $[15] = isLoading, $[16] = t5, $[17] = t6) : t6 = $[17];
330
+ let t7;
331
+ $[18] !== isLoading ? (t7 = isLoading && /* @__PURE__ */ jsx(Box, { paddingY: 5, paddingX: 2, children: /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
332
+ /* @__PURE__ */ jsx(Text, { align: "center", muted: !0, size: 1, children: /* @__PURE__ */ jsx(Spinner, {}) }),
333
+ /* @__PURE__ */ jsx(Text, { align: "center", size: 1, muted: !0, children: "Loading items\u2026" })
334
+ ] }) }), $[18] = isLoading, $[19] = t7) : t7 = $[19];
335
+ let t8;
336
+ $[20] !== isLoading || $[21] !== project || $[22] !== users ? (t8 = !isLoading && /* @__PURE__ */ jsx(Stack, { gap: 3, padding: 3, children: users?.map((user) => {
337
+ const membership = project.members.find((member) => member.id === user.id);
338
+ return /* @__PURE__ */ jsx(ProjectUser, { user, isRobot: membership?.isRobot ?? !1, roles: membership?.roles.map(_temp2) || [] }, user.id);
339
+ }) }), $[20] = isLoading, $[21] = project, $[22] = users, $[23] = t8) : t8 = $[23];
340
+ let t9;
341
+ return $[24] !== t6 || $[25] !== t7 || $[26] !== t8 ? (t9 = /* @__PURE__ */ jsxs(DashboardWidgetContainer, { header: "Project users", footer: t6, children: [
342
+ t7,
343
+ t8
344
+ ] }), $[24] = t6, $[25] = t7, $[26] = t8, $[27] = t9) : t9 = $[27], t9;
345
+ }
346
+ function _temp2(role) {
347
+ return role.title;
348
+ }
349
+ function _temp$1(mem) {
350
+ return mem.id;
351
+ }
352
+ function sortUsersByRobotStatus(userA, userB, project) {
353
+ const {
354
+ members
355
+ } = project, membershipA = members.find((member) => member.id === userA?.id), membershipB = members.find((member) => member.id === userB?.id);
356
+ return membershipA?.isRobot === membershipB?.isRobot ? (membershipA?.createdAt || "") > (membershipB?.createdAt || "") ? 1 : -1 : membershipA?.isRobot ? 1 : -1;
357
+ }
358
+ function projectUsersWidget(config) {
359
+ return {
360
+ name: "project-info",
361
+ component: ProjectUsers,
362
+ layout: config?.layout
363
+ };
364
+ }
365
+ const tutorialsProjectConfig = {
366
+ projectId: "3do82whm",
367
+ dataset: "next"
368
+ };
369
+ function useDataAdapter() {
370
+ const $ = c(5), versionedClient = useVersionedClient();
371
+ let t0;
372
+ $[0] !== versionedClient ? (t0 = (templateRepoId) => {
373
+ const uri = templateRepoId ? `/addons/dashboard?templateRepoId=${templateRepoId}` : "/addons/dashboard";
374
+ return versionedClient.observable.request({
375
+ uri,
376
+ tag: "dashboard.sanity-tutorials",
377
+ withCredentials: !1
378
+ });
379
+ }, $[0] = versionedClient, $[1] = t0) : t0 = $[1];
380
+ let t1;
381
+ $[2] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t1 = imageUrlBuilder(tutorialsProjectConfig), $[2] = t1) : t1 = $[2];
382
+ let t2;
383
+ return $[3] !== t0 ? (t2 = {
384
+ getFeed: t0,
385
+ urlBuilder: t1
386
+ }, $[3] = t0, $[4] = t2) : t2 = $[4], t2;
387
+ }
388
+ const PlayIconBox = styled(Box).withConfig({
389
+ displayName: "PlayIconBox",
390
+ componentId: "sc-15gyucb-0"
391
+ })`position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);&:before{content:'';position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:2.75em;height:2.75em;border-radius:50%;background:${({
392
+ theme
393
+ }) => getTheme_v2(theme).color.bg};opacity:0.75;}`, Root$1 = styled(Flex).withConfig({
394
+ displayName: "Root",
395
+ componentId: "sc-15gyucb-1"
396
+ })`&:hover{${PlayIconBox}{&:before{opacity:1;}}}`, PosterCard = styled(Card).withConfig({
397
+ displayName: "PosterCard",
398
+ componentId: "sc-15gyucb-2"
399
+ })`width:100%;padding-bottom:calc(9 / 16 * 100%);position:relative;`, Poster = styled.img.withConfig({
400
+ displayName: "Poster",
401
+ componentId: "sc-15gyucb-3"
402
+ })`position:absolute;top:0;left:0;height:100%;width:100%;object-fit:cover;display:block;&:not([src]){display:none;}`;
403
+ function Tutorial(props) {
404
+ const $ = c(24), {
405
+ title,
406
+ posterURL,
407
+ showPlayIcon,
408
+ href,
409
+ presenterName,
410
+ presenterSubtitle
411
+ } = props;
412
+ let t0;
413
+ $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t0 = {
414
+ position: "relative"
415
+ }, $[0] = t0) : t0 = $[0];
416
+ let t1;
417
+ $[1] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t1 = {
418
+ height: "100%"
419
+ }, $[1] = t1) : t1 = $[1];
420
+ let t2;
421
+ $[2] !== posterURL || $[3] !== showPlayIcon ? (t2 = posterURL && /* @__PURE__ */ jsxs(PosterCard, { marginBottom: 1, children: [
422
+ /* @__PURE__ */ jsx(Poster, { src: posterURL }),
423
+ showPlayIcon && /* @__PURE__ */ jsx(PlayIconBox, { display: "flex", children: /* @__PURE__ */ jsx(Text, { align: "center", children: /* @__PURE__ */ jsx(PlayIcon, {}) }) })
424
+ ] }), $[2] = posterURL, $[3] = showPlayIcon, $[4] = t2) : t2 = $[4];
425
+ let t3;
426
+ $[5] !== title ? (t3 = /* @__PURE__ */ jsx(Heading, { as: "h3", size: 1, children: title }), $[5] = title, $[6] = t3) : t3 = $[6];
427
+ let t4;
428
+ $[7] !== presenterName ? (t4 = /* @__PURE__ */ jsx(Text, { size: 1, children: presenterName }), $[7] = presenterName, $[8] = t4) : t4 = $[8];
429
+ let t5;
430
+ $[9] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t5 = {
431
+ opacity: 0.7
432
+ }, $[9] = t5) : t5 = $[9];
433
+ let t6;
434
+ $[10] !== presenterSubtitle ? (t6 = /* @__PURE__ */ jsx(Text, { size: 0, style: t5, children: presenterSubtitle }), $[10] = presenterSubtitle, $[11] = t6) : t6 = $[11];
435
+ let t7;
436
+ $[12] !== t4 || $[13] !== t6 ? (t7 = /* @__PURE__ */ jsx(Box, { marginTop: 4, children: /* @__PURE__ */ jsxs(Stack, { gap: 2, flex: 1, children: [
437
+ t4,
438
+ t6
439
+ ] }) }), $[12] = t4, $[13] = t6, $[14] = t7) : t7 = $[14];
440
+ let t8;
441
+ $[15] !== t3 || $[16] !== t7 ? (t8 = /* @__PURE__ */ jsxs(Flex, { direction: "column", justify: "space-between", paddingY: 2, flex: 1, children: [
442
+ t3,
443
+ t7
444
+ ] }), $[15] = t3, $[16] = t7, $[17] = t8) : t8 = $[17];
445
+ let t9;
446
+ $[18] !== t2 || $[19] !== t8 ? (t9 = /* @__PURE__ */ jsxs(Flex, { direction: "column", style: t1, children: [
447
+ t2,
448
+ t8
449
+ ] }), $[18] = t2, $[19] = t8, $[20] = t9) : t9 = $[20];
450
+ let t10;
451
+ return $[21] !== href || $[22] !== t9 ? (t10 = /* @__PURE__ */ jsx(Root$1, { flex: 1, children: /* @__PURE__ */ jsx(Card, { sizing: "border", flex: 1, padding: 2, radius: 2, as: "a", href, target: "_blank", rel: "noopener noreferrer", style: t0, children: t9 }) }), $[21] = href, $[22] = t9, $[23] = t10) : t10 = $[23], t10;
452
+ }
453
+ function createUrl(slug, type) {
454
+ return type === "tutorial" ? `https://www.sanity.io/docs/tutorials/${slug.current}` : type === "guide" ? `https://www.sanity.io/docs/guides/${slug.current}` : !1;
455
+ }
456
+ function SanityTutorials(props) {
457
+ const $ = c(10), {
458
+ templateRepoId
459
+ } = props;
460
+ let t0;
461
+ $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t0 = [], $[0] = t0) : t0 = $[0];
462
+ const [feedItems, setFeedItems] = useState(t0), {
463
+ getFeed,
464
+ urlBuilder
465
+ } = useDataAdapter();
466
+ let t1, t2;
467
+ $[1] !== getFeed || $[2] !== templateRepoId ? (t1 = () => {
468
+ const subscription = getFeed(templateRepoId).subscribe((response) => {
469
+ setFeedItems(response.items);
470
+ });
471
+ return () => {
472
+ subscription.unsubscribe();
473
+ };
474
+ }, t2 = [setFeedItems, getFeed, templateRepoId], $[1] = getFeed, $[2] = templateRepoId, $[3] = t1, $[4] = t2) : (t1 = $[3], t2 = $[4]), useEffect(t1, t2);
475
+ let t3;
476
+ $[5] !== feedItems || $[6] !== urlBuilder ? (t3 = feedItems?.map((feedItem, index) => {
477
+ if (!feedItem.title || !feedItem.guideOrTutorial && !feedItem.externalLink)
478
+ return null;
479
+ const presenter = feedItem.presenter || feedItem.guideOrTutorial?.presenter || {}, subtitle = feedItem.category, {
480
+ guideOrTutorial: t42
481
+ } = feedItem, guideOrTutorial = t42 === void 0 ? {} : t42, href = (guideOrTutorial.slug ? createUrl(guideOrTutorial.slug, guideOrTutorial._type) : feedItem.externalLink) || feedItem.externalLink;
482
+ return /* @__PURE__ */ jsx(Flex, { as: "li", paddingRight: index < feedItems?.length - 1 ? 1 : 3, paddingLeft: index === 0 ? 3 : 0, align: "stretch", style: {
483
+ minWidth: 272,
484
+ width: "30%"
485
+ }, children: /* @__PURE__ */ jsx(Tutorial, { title: feedItem.title, href: href ?? "", presenterName: presenter.name, presenterSubtitle: subtitle, showPlayIcon: feedItem.hasVideo, posterURL: feedItem.poster ? urlBuilder.image(feedItem.poster).height(360).url() : void 0 }) }, feedItem._id);
486
+ }), $[5] = feedItems, $[6] = urlBuilder, $[7] = t3) : t3 = $[7];
487
+ let t4;
488
+ return $[8] !== t3 ? (t4 = /* @__PURE__ */ jsx(DashboardWidgetContainer, { header: "Learn about Sanity", children: /* @__PURE__ */ jsx(Flex, { as: "ul", overflow: "auto", align: "stretch", paddingY: 2, children: t3 }) }), $[8] = t3, $[9] = t4) : t4 = $[9], t4;
489
+ }
490
+ function sanityTutorialsWidget(config) {
491
+ return {
492
+ name: "sanity-tutorials",
493
+ component: SanityTutorials,
494
+ layout: config?.layout ?? {
495
+ width: "full"
496
+ }
497
+ };
498
+ }
499
+ function DashboardLayout(t0) {
500
+ const $ = c(3), {
501
+ children
502
+ } = t0;
503
+ let t1;
504
+ $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t1 = {
505
+ height: "100%",
506
+ overflowY: "auto"
507
+ }, $[0] = t1) : t1 = $[0];
508
+ let t2;
509
+ return $[1] !== children ? (t2 = /* @__PURE__ */ jsx(Container, { width: 4, padding: 4, sizing: "border", style: t1, children }), $[1] = children, $[2] = t2) : t2 = $[2], t2;
510
+ }
511
+ const media = {
512
+ small: (...args) => css`@media (min-width:${({
513
+ theme
514
+ }) => getTheme_v2(theme).media[0]}px){${css(...args)}}`,
515
+ medium: (...args) => css`@media (min-width:${({
516
+ theme
517
+ }) => getTheme_v2(theme).media[2]}px){${css(...args)}}`
518
+ }, Root = styled(Grid).withConfig({
519
+ displayName: "Root",
520
+ componentId: "sc-1av8yx9-0"
521
+ })`grid-template-columns:repeat(auto-fit,minmax(250px,1fr));& > div{overflow:hidden;}& > div[data-width='medium']{${media.small`
522
+ grid-column: span 2;
523
+ `}}& > div[data-width='large']{${media.small`
524
+ grid-column: span 2;
525
+ `} ${media.medium`
526
+ grid-column: span 3;
527
+ `}}& > div[data-width='full']{${media.small`
528
+ grid-column: 1 / -1;
529
+ `}}& > div[data-height='medium']{${media.small`
530
+ grid-row: span 2;
531
+ `}}& > div[data-height='large']{${media.small`
532
+ grid-row: span 2;
533
+ `} ${media.medium`
534
+ grid-row: span 3;
535
+ `}}& > div[data-height='full']{${media.medium`
536
+ grid-row: 1 / -1;
537
+ `}}`, NO_WIDGETS = [], NO_LAYOUT = {};
538
+ function WidgetGroup(props) {
539
+ const $ = c(9), {
540
+ config: t0
541
+ } = props, {
542
+ layout: t1,
543
+ widgets: t2
544
+ } = t0, layout = t1 === void 0 ? NO_LAYOUT : t1, widgets = t2 === void 0 ? NO_WIDGETS : t2, t3 = layout.width || "auto", t4 = layout.height || "auto";
545
+ let t5;
546
+ $[0] !== widgets.length ? (t5 = widgets.length ? null : /* @__PURE__ */ jsx(Card, { padding: 4, shadow: 1, tone: "primary", children: /* @__PURE__ */ jsx(Text, { align: "center", children: "Add some widgets to populate this space." }) }), $[0] = widgets.length, $[1] = t5) : t5 = $[1];
547
+ let t6;
548
+ $[2] !== widgets ? (t6 = widgets.map(_temp), $[2] = widgets, $[3] = t6) : t6 = $[3];
549
+ let t7;
550
+ return $[4] !== t3 || $[5] !== t4 || $[6] !== t5 || $[7] !== t6 ? (t7 = /* @__PURE__ */ jsxs(Root, { autoFlow: "row dense", "data-width": t3, "data-height": t4, gap: 4, children: [
551
+ t5,
552
+ t6
553
+ ] }), $[4] = t3, $[5] = t4, $[6] = t5, $[7] = t6, $[8] = t7) : t7 = $[8], t7;
554
+ }
555
+ function _temp(widgetConfig, index) {
556
+ return widgetConfig.type === "__experimental_group" ? /* @__PURE__ */ jsx(WidgetGroup, { config: widgetConfig }, index) : widgetConfig.component ? /* @__PURE__ */ jsx(WidgetContainer, { ...widgetConfig }, index) : /* @__PURE__ */ jsxs(Box, { children: [
557
+ widgetConfig.name,
558
+ " is missing widget component"
559
+ ] }, index);
560
+ }
561
+ function Dashboard(t0) {
562
+ const $ = c(5), {
563
+ config
564
+ } = t0;
565
+ if (!config)
566
+ return null;
567
+ let t1;
568
+ $[0] !== config ? (t1 = /* @__PURE__ */ jsx(DashboardLayout, { children: /* @__PURE__ */ jsx(WidgetGroup, { config }) }), $[0] = config, $[1] = t1) : t1 = $[1];
569
+ let t2;
570
+ return $[2] !== config || $[3] !== t1 ? (t2 = /* @__PURE__ */ jsx(DashboardContext.Provider, { value: config, children: t1 }), $[2] = config, $[3] = t1, $[4] = t2) : t2 = $[4], t2;
571
+ }
572
+ const strokeStyle = {
573
+ stroke: "currentColor",
574
+ strokeWidth: 1.2
575
+ }, DashboardIcon = () => {
576
+ const $ = c(1);
577
+ let t0;
578
+ return $[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsxs("svg", { "data-sanity-icon": !0, viewBox: "0 0 25 25", fill: "none", xmlns: "http://www.w3.org/2000/svg", preserveAspectRatio: "xMidYMid", width: "1em", height: "1em", children: [
579
+ /* @__PURE__ */ jsx("path", { d: "M19.5 19.5H5.5V5.5H19.5V19.5Z", style: strokeStyle }),
580
+ /* @__PURE__ */ jsx("path", { d: "M5.5 12.5H19.5", style: strokeStyle }),
581
+ /* @__PURE__ */ jsx("path", { d: "M14.5 19.5V12.5M10.5 12.5V5.5", style: strokeStyle })
582
+ ] }), $[0] = t0) : t0 = $[0], t0;
583
+ }, dashboardTool = definePlugin((config = {}) => {
584
+ const pluginConfig = {
585
+ layout: config.defaultLayout ?? {},
586
+ widgets: config.widgets ?? []
587
+ }, title = config.title ?? "Dashboard", name = config.name ?? "dashboard", icon = config.icon ?? DashboardIcon;
588
+ return {
589
+ name: "dashboard",
590
+ tools: [{
591
+ title,
592
+ name,
593
+ icon,
594
+ component: () => /* @__PURE__ */ jsx(Dashboard, { config: pluginConfig })
595
+ }]
596
+ };
597
+ });
598
+ export {
599
+ DashboardWidgetContainer,
600
+ dashboardTool,
601
+ projectInfoWidget,
602
+ projectUsersWidget,
603
+ sanityTutorialsWidget
604
+ };
605
+ //# sourceMappingURL=index.js.map