@sanity/dashboard 3.1.6 → 4.1.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.
package/lib/index.esm.js CHANGED
@@ -1,464 +1,344 @@
1
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import { forwardRef, createContext, useContext, useMemo, createElement, useState, useEffect, useCallback } from 'react';
3
- import { Card, Box, Heading, Button, Stack, Label, Grid, Text, Code, Spinner, Flex, Container } from '@sanity/ui';
4
- import styled, { css } from 'styled-components';
5
- import { useClient, useUserStore, DefaultPreview, definePlugin } from 'sanity';
6
- import { from } from 'rxjs';
7
- import { switchMap, map } from 'rxjs/operators';
8
- import { RobotIcon, PlayIcon } from '@sanity/icons';
9
- import imageUrlBuilder from '@sanity/image-url';
10
- var __freeze$3 = Object.freeze;
11
- var __defProp$3 = Object.defineProperty;
12
- var __template$3 = (cooked, raw) => __freeze$3(__defProp$3(cooked, "raw", {
13
- value: __freeze$3(raw || cooked.slice())
14
- }));
15
- var _a$3, _b$2, _c$2, _d$2;
16
- const Root$2 = styled(Card)(_a$3 || (_a$3 = __template$3(["\n display: flex;\n flex-direction: column;\n justify-content: stretch;\n height: 100%;\n box-sizing: border-box;\n position: relative;\n"])));
17
- const Header = styled(Card)(_b$2 || (_b$2 = __template$3(["\n position: sticky;\n top: 0;\n z-index: 2;\n border-top-left-radius: inherit;\n border-top-right-radius: inherit;\n"])));
18
- const Footer = styled(Card)(_c$2 || (_c$2 = __template$3(["\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"])));
19
- const Content = styled(Box)(_d$2 || (_d$2 = __template$3(["\n position: relative;\n z-index: 1;\n height: stretch;\n min-height: 21.5em;\n\n @media (min-width: ", "px) {\n overflow-y: auto;\n outline: none;\n }\n"])), _ref => {
20
- let {
21
- theme
22
- } = _ref;
23
- return theme.sanity.media[0];
24
- });
25
- const DashboardWidgetContainer = forwardRef(function DashboardWidgetContainer2(props, ref) {
26
- const {
27
- header,
28
- children,
29
- footer
30
- } = props;
31
- return /* @__PURE__ */jsxs(Root$2, {
32
- radius: 3,
33
- display: "flex",
34
- ref,
35
- children: [header && /* @__PURE__ */jsx(Header, {
36
- borderBottom: true,
37
- paddingX: 3,
38
- paddingY: 4,
39
- children: /* @__PURE__ */jsx(Heading, {
40
- size: 1,
41
- textOverflow: "ellipsis",
42
- children: header
43
- })
44
- }), children && /* @__PURE__ */jsx(Content, {
45
- children
46
- }), footer && /* @__PURE__ */jsx(Footer, {
47
- borderTop: true,
48
- children: footer
49
- })]
50
- });
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import { forwardRef, createContext, useContext, useMemo, createElement, useState, useEffect, useCallback } from "react";
3
+ import { Card, Box, Heading, Button, Stack, Label, Grid, Text, Code, Flex, rem, Spinner, Container } from "@sanity/ui";
4
+ import { styled, css } from "styled-components";
5
+ import { useClient, useListFormat, UserAvatar, useUserStore, definePlugin } from "sanity";
6
+ import { from } from "rxjs";
7
+ import { switchMap, map } from "rxjs/operators";
8
+ import { RobotIcon, PlayIcon } from "@sanity/icons";
9
+ import imageUrlBuilder from "@sanity/image-url";
10
+ const Root$3 = styled(Card)`
11
+ display: flex;
12
+ flex-direction: column;
13
+ justify-content: stretch;
14
+ height: 100%;
15
+ box-sizing: border-box;
16
+ position: relative;
17
+ `, Header = styled(Card)`
18
+ position: sticky;
19
+ top: 0;
20
+ z-index: 2;
21
+ border-top-left-radius: inherit;
22
+ border-top-right-radius: inherit;
23
+ `, Footer = styled(Card)`
24
+ position: sticky;
25
+ overflow: hidden;
26
+ bottom: 0;
27
+ z-index: 2;
28
+ border-bottom-right-radius: inherit;
29
+ border-bottom-left-radius: inherit;
30
+ margin-top: auto;
31
+ `, Content = styled(Box)`
32
+ position: relative;
33
+ z-index: 1;
34
+ height: stretch;
35
+ min-height: 21.5em;
36
+
37
+ @media (min-width: ${({ theme }) => theme.sanity.media[0]}px) {
38
+ overflow-y: auto;
39
+ outline: none;
40
+ }
41
+ `, DashboardWidgetContainer = forwardRef(function(props, ref) {
42
+ const { header, children, footer } = props;
43
+ return /* @__PURE__ */ jsxs(Root$3, { radius: 3, display: "flex", ref, children: [
44
+ header && /* @__PURE__ */ jsx(Header, { borderBottom: !0, paddingX: 3, paddingY: 4, children: /* @__PURE__ */ jsx(Heading, { size: 1, textOverflow: "ellipsis", children: header }) }),
45
+ children && /* @__PURE__ */ jsx(Content, { children }),
46
+ footer && /* @__PURE__ */ jsx(Footer, { borderTop: !0, children: footer })
47
+ ] });
51
48
  });
52
49
  function useVersionedClient() {
53
- return useClient({
54
- apiVersion: "1"
55
- });
50
+ return useClient({ apiVersion: "2024-08-01" });
56
51
  }
57
- const DashboardContext = createContext({
58
- widgets: []
59
- });
52
+ const DashboardContext = createContext({ widgets: [] });
60
53
  function useDashboardConfig() {
61
54
  return useContext(DashboardContext);
62
55
  }
63
56
  function WidgetContainer(props) {
64
- const config = useDashboardConfig();
65
- const layout = useMemo(() => ({
66
- ...(props.layout || {}),
67
- ...(config.layout || {})
68
- }), [props.layout, config.layout]);
69
- return /* @__PURE__ */jsx(Card, {
70
- shadow: 1,
71
- "data-width": layout.width,
72
- "data-height": layout.height,
73
- children: createElement(props.component, {})
74
- });
57
+ const config = useDashboardConfig(), layout = useMemo(
58
+ () => ({
59
+ ...props.layout || {},
60
+ ...config.layout || {}
61
+ }),
62
+ [props.layout, config.layout]
63
+ );
64
+ return /* @__PURE__ */ jsx(Card, { shadow: 1, "data-width": layout.width, "data-height": layout.height, children: createElement(props.component, {}) });
75
65
  }
76
66
  function isUrl(url) {
77
- return url && /^https?:\/\//.test("".concat(url));
67
+ return url && /^https?:\/\//.test(`${url}`);
78
68
  }
79
- function getGraphQlUrl(projectId, dataset) {
80
- return "https://".concat(projectId, ".api.sanity.io/v1/graphql/").concat(dataset, "/default");
69
+ function getGraphQLUrl(projectId, dataset) {
70
+ return `https://${projectId}.api.sanity.io/v1/graphql/${dataset}/default`;
81
71
  }
82
72
  function getGroqUrl(projectId, dataset) {
83
- return "https://".concat(projectId, ".api.sanity.io/v1/groq/").concat(dataset);
73
+ return `https://${projectId}.api.sanity.io/v1/groq/${dataset}`;
84
74
  }
85
75
  function getManageUrl(projectId) {
86
- return "https://manage.sanity.io/projects/".concat(projectId);
76
+ return `https://manage.sanity.io/projects/${projectId}`;
87
77
  }
88
- const NO_EXPERIMENTAL = [];
89
- const NO_DATA = [];
78
+ const NO_EXPERIMENTAL = [], NO_DATA = [];
90
79
  function ProjectInfo(props) {
91
- const {
92
- __experimental_before = NO_EXPERIMENTAL,
93
- data = NO_DATA
94
- } = props;
95
- const [studioHost, setStudioHost] = useState();
96
- const [graphqlApi, setGraphQlApi] = useState();
97
- const versionedClient = useVersionedClient();
98
- const {
99
- projectId = "unknown",
100
- dataset = "unknown"
101
- } = versionedClient.config();
80
+ const { __experimental_before = NO_EXPERIMENTAL, data = NO_DATA } = props, [studioApps, setStudioApps] = useState(), [graphQLApi, setGraphQLApi] = useState(), versionedClient = useVersionedClient(), { projectId = "unknown", dataset = "unknown" } = versionedClient.config();
102
81
  useEffect(() => {
103
82
  const subscriptions = [];
104
- subscriptions.push(versionedClient.observable.request({
105
- uri: "/projects/".concat(projectId)
106
- }).subscribe({
107
- next: result => {
108
- const {
109
- studioHost: host
110
- } = result;
111
- setStudioHost(host ? "https://".concat(host, ".sanity.studio") : void 0);
112
- },
113
- error: error => {
114
- console.error("Error while looking for studioHost", error);
115
- setStudioHost({
116
- error: "Something went wrong while looking up studioHost. See console."
117
- });
118
- }
119
- }));
120
- subscriptions.push(versionedClient.observable.request({
121
- method: "HEAD",
122
- uri: "/graphql/".concat(dataset, "/default")
123
- }).subscribe({
124
- next: () => setGraphQlApi(getGraphQlUrl(projectId, dataset)),
125
- error: error => {
126
- if (error.statusCode === 404) {
127
- setGraphQlApi(void 0);
128
- } else {
129
- console.error("Error while looking for graphqlApi", error);
130
- setGraphQlApi({
131
- error: "Something went wrong while looking up graphqlApi. See console."
83
+ return subscriptions.push(
84
+ versionedClient.observable.request({ uri: "/user-applications", tag: "dashboard.project-info" }).subscribe({
85
+ next: (result) => setStudioApps(result.filter((app) => app.type === "studio")),
86
+ error: (error) => {
87
+ console.error("Error while resolving user applications", error), setStudioApps({
88
+ error: "Something went wrong while resolving user applications. See console."
132
89
  });
133
90
  }
134
- }
135
- }));
136
- return () => {
137
- subscriptions.forEach(s => s.unsubscribe());
91
+ })
92
+ ), subscriptions.push(
93
+ versionedClient.observable.request({
94
+ method: "HEAD",
95
+ uri: `/graphql/${dataset}/default`,
96
+ tag: "dashboard.project-info.graphql-api"
97
+ }).subscribe({
98
+ next: () => setGraphQLApi(getGraphQLUrl(projectId, dataset)),
99
+ error: (error) => {
100
+ error.statusCode === 404 ? setGraphQLApi(void 0) : (console.error("Error while looking for graphQLApi", error), setGraphQLApi({
101
+ error: "Something went wrong while looking up graphQLApi. See console."
102
+ }));
103
+ }
104
+ })
105
+ ), () => {
106
+ subscriptions.forEach((s) => s.unsubscribe());
138
107
  };
139
- }, [dataset, projectId, versionedClient, setGraphQlApi, setStudioHost]);
108
+ }, [dataset, projectId, versionedClient, setGraphQLApi]);
140
109
  const assembleTableRows = useMemo(() => {
141
- var _a;
142
- let result = [{
143
- title: "Sanity project",
144
- rows: [{
145
- title: "Project ID",
146
- value: projectId
147
- }, {
148
- title: "Dataset",
149
- value: dataset
150
- }]
151
- }];
152
- const apps = [studioHost ? {
153
- title: "Studio",
154
- value: studioHost
155
- } : null, ...data.filter(item => item.category === "apps")].filter(a => !!a);
156
- if (apps.length > 0) {
157
- result = result.concat([{
158
- title: "Apps",
159
- rows: apps
160
- }]);
161
- }
162
- result = result.concat([{
163
- title: "APIs",
164
- rows: [{
165
- title: "GROQ",
166
- value: getGroqUrl(projectId, dataset)
167
- }, {
168
- title: "GraphQL",
169
- value: (_a = typeof graphqlApi === "object" ? "Error" : graphqlApi) != null ? _a : "Not deployed"
170
- }]
171
- }], data.filter(item => item.category === "apis"));
172
- const otherStuff = {};
173
- data.forEach(item => {
174
- if (item.category && item.category !== "apps" && item.category !== "apis") {
175
- if (!otherStuff[item.category]) {
176
- otherStuff[item.category] = [];
177
- }
178
- otherStuff[item.category].push(item);
110
+ let result = [
111
+ {
112
+ title: "Sanity project",
113
+ rows: [
114
+ { title: "Project ID", value: projectId },
115
+ { title: "Dataset", value: dataset }
116
+ ]
179
117
  }
180
- });
181
- Object.keys(otherStuff).forEach(category => {
182
- result.push({
183
- title: category,
184
- rows: otherStuff[category]
118
+ ];
119
+ const apps = data.filter((item) => item.category === "apps");
120
+ (Array.isArray(studioApps) ? studioApps : []).forEach((app) => {
121
+ apps.push({
122
+ title: app.title || "Studio",
123
+ value: app.urlType === "internal" ? `https://${app.appHost}.sanity.studio` : app.appHost
185
124
  });
186
- });
187
- return result;
188
- }, [graphqlApi, studioHost, projectId, dataset, data]);
189
- return /* @__PURE__ */jsxs(Fragment, {
190
- children: [__experimental_before.map((widgetConfig, idx) => /* @__PURE__ */jsx(WidgetContainer, {
191
- ...widgetConfig
192
- }, idx)), /* @__PURE__ */jsx(Box, {
193
- height: "fill",
194
- marginTop: (__experimental_before == null ? void 0 : __experimental_before.length) > 0 ? 4 : 0,
195
- children: /* @__PURE__ */jsx(DashboardWidgetContainer, {
196
- footer: /* @__PURE__ */jsx(Button, {
197
- style: {
198
- width: "100%"
199
- },
200
- paddingX: 2,
201
- paddingY: 4,
202
- mode: "bleed",
203
- tone: "primary",
204
- text: "Manage project",
205
- as: "a",
206
- href: getManageUrl(projectId)
207
- }),
208
- children: /* @__PURE__ */jsx(Card, {
209
- paddingY: 4,
210
- radius: 2,
211
- role: "table",
212
- "aria-label": "Project info",
213
- "aria-describedby": "project_info_table",
214
- children: /* @__PURE__ */jsxs(Stack, {
215
- space: 4,
216
- children: [/* @__PURE__ */jsx(Box, {
217
- paddingX: 3,
218
- as: "header",
219
- children: /* @__PURE__ */jsx(Heading, {
220
- size: 1,
221
- as: "h2",
222
- id: "project_info_table",
223
- children: "Project info"
224
- })
225
- }), assembleTableRows.map(item => {
226
- if (!item || !item.rows) {
227
- return null;
228
- }
229
- return /* @__PURE__ */jsxs(Stack, {
230
- space: 3,
231
- children: [/* @__PURE__ */jsx(Card, {
232
- borderBottom: true,
233
- padding: 3,
234
- children: /* @__PURE__ */jsx(Label, {
235
- size: 0,
236
- muted: true,
237
- role: "columnheader",
238
- children: item.title
239
- })
240
- }), /* @__PURE__ */jsx(Stack, {
241
- space: 4,
242
- paddingX: 3,
243
- role: "rowgroup",
244
- children: item.rows.map(row => {
245
- var _a;
246
- return /* @__PURE__ */jsxs(Grid, {
247
- columns: 2,
248
- role: "row",
249
- children: [/* @__PURE__ */jsx(Text, {
250
- weight: "medium",
251
- role: "rowheader",
252
- children: row.title
253
- }), typeof row.value === "object" && /* @__PURE__ */jsx(Text, {
254
- size: 1,
255
- children: (_a = row.value) == null ? void 0 : _a.error
256
- }), typeof row.value === "string" && /* @__PURE__ */jsx(Fragment, {
257
- children: isUrl(row.value) ? /* @__PURE__ */jsx(Text, {
258
- size: 1,
259
- role: "cell",
260
- style: {
261
- wordBreak: "break-word"
262
- },
263
- children: /* @__PURE__ */jsx("a", {
264
- href: row.value,
265
- children: row.value
266
- })
267
- }) : /* @__PURE__ */jsx(Code, {
268
- size: 1,
269
- role: "cell",
270
- style: {
271
- wordBreak: "break-word"
272
- },
273
- children: row.value
274
- })
275
- })]
276
- }, row.title);
277
- })
278
- })]
279
- }, item.title);
280
- })]
281
- })
282
- })
283
- })
284
- })]
285
- });
125
+ }), apps.length > 0 && (result = result.concat([{ title: "Apps", rows: apps }])), result = result.concat(
126
+ [
127
+ {
128
+ title: "APIs",
129
+ rows: [
130
+ { title: "GROQ", value: getGroqUrl(projectId, dataset) },
131
+ {
132
+ title: "GraphQL",
133
+ value: (typeof graphQLApi == "object" ? "Error" : graphQLApi) ?? "Not deployed"
134
+ }
135
+ ]
136
+ }
137
+ ],
138
+ data.filter((item) => item.category === "apis")
139
+ );
140
+ const otherStuff = {};
141
+ return data.forEach((item) => {
142
+ item.category && item.category !== "apps" && item.category !== "apis" && (otherStuff[item.category] || (otherStuff[item.category] = []), otherStuff[item.category].push(item));
143
+ }), Object.keys(otherStuff).forEach((category) => {
144
+ result.push({ title: category, rows: otherStuff[category] });
145
+ }), result;
146
+ }, [graphQLApi, studioApps, projectId, dataset, data]);
147
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
148
+ __experimental_before.map((widgetConfig, idx) => /* @__PURE__ */ jsx(WidgetContainer, { ...widgetConfig }, idx)),
149
+ /* @__PURE__ */ jsx(Box, { height: "fill", marginTop: __experimental_before?.length > 0 ? 4 : 0, children: /* @__PURE__ */ jsx(
150
+ DashboardWidgetContainer,
151
+ {
152
+ footer: /* @__PURE__ */ jsx(
153
+ Button,
154
+ {
155
+ style: { width: "100%" },
156
+ paddingX: 2,
157
+ paddingY: 4,
158
+ mode: "bleed",
159
+ tone: "primary",
160
+ text: "Manage project",
161
+ as: "a",
162
+ href: getManageUrl(projectId)
163
+ }
164
+ ),
165
+ children: /* @__PURE__ */ jsx(
166
+ Card,
167
+ {
168
+ paddingY: 4,
169
+ radius: 2,
170
+ role: "table",
171
+ "aria-label": "Project info",
172
+ "aria-describedby": "project_info_table",
173
+ children: /* @__PURE__ */ jsxs(Stack, { space: 4, children: [
174
+ /* @__PURE__ */ jsx(Box, { paddingX: 3, as: "header", children: /* @__PURE__ */ jsx(Heading, { size: 1, as: "h2", id: "project_info_table", children: "Project info" }) }),
175
+ assembleTableRows.map((item) => !item || !item.rows ? null : /* @__PURE__ */ jsxs(Stack, { space: 3, children: [
176
+ /* @__PURE__ */ jsx(Card, { borderBottom: !0, padding: 3, children: /* @__PURE__ */ jsx(Label, { size: 0, muted: !0, role: "columnheader", children: item.title }) }),
177
+ /* @__PURE__ */ jsx(Stack, { space: 4, paddingX: 3, role: "rowgroup", children: item.rows.map((row) => /* @__PURE__ */ jsxs(Grid, { columns: 2, role: "row", children: [
178
+ /* @__PURE__ */ jsx(Text, { weight: "medium", role: "rowheader", children: row.title }),
179
+ typeof row.value == "object" && /* @__PURE__ */ jsx(Text, { size: 1, children: row.value?.error }),
180
+ typeof row.value == "string" && /* @__PURE__ */ jsx(Fragment, { children: isUrl(row.value) ? /* @__PURE__ */ jsx(Text, { size: 1, role: "cell", style: { wordBreak: "break-word" }, children: /* @__PURE__ */ jsx("a", { href: row.value, children: row.value }) }) : /* @__PURE__ */ jsx(Code, { size: 1, role: "cell", style: { wordBreak: "break-word" }, children: row.value }) })
181
+ ] }, `${row.value}-${row.title}`)) })
182
+ ] }, item.title))
183
+ ] })
184
+ }
185
+ )
186
+ }
187
+ ) })
188
+ ] });
286
189
  }
287
190
  function projectInfoWidget(config) {
288
- var _a;
289
191
  return {
290
192
  name: "project-info",
291
193
  component: ProjectInfo,
292
- layout: (_a = config == null ? void 0 : config.layout) != null ? _a : {
293
- width: "medium"
294
- }
194
+ layout: config?.layout ?? { width: "medium" }
295
195
  };
296
196
  }
297
- var __freeze$2 = Object.freeze;
298
- var __defProp$2 = Object.defineProperty;
299
- var __template$2 = (cooked, raw) => __freeze$2(__defProp$2(cooked, "raw", {
300
- value: __freeze$2(raw || cooked.slice())
301
- }));
302
- var _a$2;
303
- const AvatarWrapper = styled(Card)(_a$2 || (_a$2 = __template$2(["\n box-sizing: border-box;\n border-radius: 50%;\n border-color: transparent;\n overflow: hidden;\n width: 100%;\n height: 100%;\n\n & > img {\n width: 100%;\n height: auto;\n }\n"])));
197
+ const Root$2 = styled(Flex)`
198
+ height: ${rem(33)}; // 33 = PREVIEW_SIZES.default.media.height
199
+ box-sizing: content-box;
200
+ `;
201
+ function ProjectUser({ user, isRobot, roles }) {
202
+ const listFormat = useListFormat({ style: "narrow" });
203
+ return /* @__PURE__ */ jsx(Root$2, { align: "center", children: /* @__PURE__ */ jsxs(Flex, { align: "center", flex: 1, gap: 2, children: [
204
+ /* @__PURE__ */ jsx(Box, { flex: "none", children: isRobot ? /* @__PURE__ */ jsx(Text, { size: 2, children: /* @__PURE__ */ jsx(RobotIcon, {}) }) : /* @__PURE__ */ jsx(UserAvatar, { user }) }),
205
+ /* @__PURE__ */ jsxs(Stack, { flex: 1, space: 2, children: [
206
+ /* @__PURE__ */ jsx(Text, { size: 1, style: { color: "inherit" }, textOverflow: "ellipsis", weight: "medium", children: user.displayName }),
207
+ /* @__PURE__ */ jsx(Text, { muted: !0, size: 1, textOverflow: "ellipsis", children: listFormat.format(roles) })
208
+ ] })
209
+ ] }) });
210
+ }
304
211
  function getInviteUrl(projectId) {
305
- return "https://manage.sanity.io/projects/".concat(projectId, "/team/invite");
212
+ return `https://manage.sanity.io/projects/${projectId}/members`;
306
213
  }
307
214
  function ProjectUsers() {
308
- const [project, setProject] = useState();
309
- const [users, setUsers] = useState();
310
- const [error, setError] = useState();
311
- const userStore = useUserStore();
312
- const versionedClient = useVersionedClient();
313
- const fetchData = useCallback(() => {
314
- const {
315
- projectId
316
- } = versionedClient.config();
317
- const subscription = versionedClient.observable.request({
318
- uri: "/projects/".concat(projectId)
319
- }).pipe(switchMap(_project => from(userStore.getUsers(_project.members.map(mem => mem.id))).pipe(map(_users => ({
320
- project: _project,
321
- users: _users
322
- }))))).subscribe({
323
- next: _ref2 => {
324
- let {
325
- users: _users,
326
- project: _project
327
- } = _ref2;
328
- setProject(_project);
329
- setUsers((Array.isArray(_users) ? _users : [_users]).sort((userA, userB) => sortUsersByRobotStatus(userA, userB, _project)));
215
+ const [project, setProject] = useState(), [users, setUsers] = useState(), [error, setError] = useState(), userStore = useUserStore(), versionedClient = useVersionedClient(), fetchData = useCallback(() => {
216
+ const { projectId } = versionedClient.config(), subscription = versionedClient.observable.request({
217
+ uri: `/projects/${projectId}`,
218
+ tag: "dashboard.project-users"
219
+ }).pipe(
220
+ switchMap(
221
+ (_project) => from(userStore.getUsers(_project.members.map((mem) => mem.id))).pipe(
222
+ map((_users) => ({ project: _project, users: _users }))
223
+ )
224
+ )
225
+ ).subscribe({
226
+ next: ({ users: _users, project: _project }) => {
227
+ setProject(_project), setUsers(
228
+ (Array.isArray(_users) ? _users : [_users]).sort(
229
+ (userA, userB) => sortUsersByRobotStatus(userA, userB, _project)
230
+ )
231
+ );
330
232
  },
331
- error: e => setError(e)
233
+ error: (e) => setError(e)
332
234
  });
333
235
  return () => subscription.unsubscribe();
334
236
  }, [userStore, versionedClient]);
335
237
  useEffect(() => fetchData(), [fetchData]);
336
- const handleRetryFetch = useCallback(() => fetchData(), [fetchData]);
337
- const isLoading = !users || !project;
338
- if (error) {
339
- return /* @__PURE__ */jsx(DashboardWidgetContainer, {
238
+ const handleRetryFetch = useCallback(() => fetchData(), [fetchData]), isLoading = !users || !project;
239
+ return error ? /* @__PURE__ */ jsx(DashboardWidgetContainer, { header: "Project users", children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsxs(Text, { children: [
240
+ "Something went wrong while fetching data. You could",
241
+ " ",
242
+ /* @__PURE__ */ jsx("a", { onClick: handleRetryFetch, title: "Retry users fetch", style: { cursor: "pointer" }, children: "retry" }),
243
+ "..?"
244
+ ] }) }) }) : /* @__PURE__ */ jsxs(
245
+ DashboardWidgetContainer,
246
+ {
340
247
  header: "Project users",
341
- children: /* @__PURE__ */jsx(Box, {
342
- padding: 4,
343
- children: /* @__PURE__ */jsxs(Text, {
344
- children: ["Something went wrong while fetching data. You could", " ", /* @__PURE__ */jsx("a", {
345
- onClick: handleRetryFetch,
346
- title: "Retry users fetch",
347
- style: {
348
- cursor: "pointer"
248
+ footer: /* @__PURE__ */ jsx(
249
+ Button,
250
+ {
251
+ style: { width: "100%" },
252
+ paddingX: 2,
253
+ paddingY: 4,
254
+ mode: "bleed",
255
+ tone: "primary",
256
+ text: "Manage members",
257
+ as: "a",
258
+ loading: isLoading,
259
+ href: isLoading ? void 0 : getInviteUrl(project.id)
260
+ }
261
+ ),
262
+ children: [
263
+ isLoading && /* @__PURE__ */ jsx(Box, { paddingY: 5, paddingX: 2, children: /* @__PURE__ */ jsxs(Stack, { space: 4, children: [
264
+ /* @__PURE__ */ jsx(Text, { align: "center", muted: !0, size: 1, children: /* @__PURE__ */ jsx(Spinner, {}) }),
265
+ /* @__PURE__ */ jsx(Text, { align: "center", size: 1, muted: !0, children: "Loading items\u2026" })
266
+ ] }) }),
267
+ !isLoading && /* @__PURE__ */ jsx(Stack, { space: 3, padding: 3, children: users?.map((user) => {
268
+ const membership = project.members.find((member) => member.id === user.id);
269
+ return /* @__PURE__ */ jsx(
270
+ ProjectUser,
271
+ {
272
+ user,
273
+ isRobot: membership?.isRobot ?? !1,
274
+ roles: membership?.roles.map((role) => role.title) || []
349
275
  },
350
- children: "retry"
351
- }), "..?"]
352
- })
353
- })
354
- });
355
- }
356
- return /* @__PURE__ */jsxs(DashboardWidgetContainer, {
357
- header: "Project users",
358
- footer: /* @__PURE__ */jsx(Button, {
359
- style: {
360
- width: "100%"
361
- },
362
- paddingX: 2,
363
- paddingY: 4,
364
- mode: "bleed",
365
- tone: "primary",
366
- text: "Invite members",
367
- as: "a",
368
- loading: isLoading,
369
- href: isLoading ? void 0 : getInviteUrl(project.id)
370
- }),
371
- children: [isLoading && /* @__PURE__ */jsx(Box, {
372
- paddingY: 5,
373
- paddingX: 2,
374
- children: /* @__PURE__ */jsxs(Stack, {
375
- space: 4,
376
- children: [/* @__PURE__ */jsx(Text, {
377
- align: "center",
378
- muted: true,
379
- size: 1,
380
- children: /* @__PURE__ */jsx(Spinner, {})
381
- }), /* @__PURE__ */jsx(Text, {
382
- align: "center",
383
- size: 1,
384
- muted: true,
385
- children: "Loading items..."
386
- })]
387
- })
388
- }), !isLoading && /* @__PURE__ */jsx(Stack, {
389
- space: 3,
390
- padding: 3,
391
- children: users == null ? void 0 : users.map(user => {
392
- const membership = project.members.find(member => member.id === user.id);
393
- const media = (membership == null ? void 0 : membership.isRobot) ? /* @__PURE__ */jsx(Text, {
394
- size: 3,
395
- children: /* @__PURE__ */jsx(RobotIcon, {})
396
- }) : /* @__PURE__ */jsx(AvatarWrapper, {
397
- tone: "transparent",
398
- children: (user == null ? void 0 : user.imageUrl) && /* @__PURE__ */jsx("img", {
399
- src: user.imageUrl,
400
- alt: user == null ? void 0 : user.displayName
401
- })
402
- });
403
- return /* @__PURE__ */jsx(Box, {
404
- children: /* @__PURE__ */jsx(DefaultPreview, {
405
- title: user.displayName,
406
- subtitle: membership == null ? void 0 : membership.role,
407
- media
408
- })
409
- }, user.id);
410
- })
411
- })]
412
- });
276
+ user.id
277
+ );
278
+ }) })
279
+ ]
280
+ }
281
+ );
413
282
  }
414
283
  function sortUsersByRobotStatus(userA, userB, project) {
415
- const {
416
- members
417
- } = project;
418
- const membershipA = members.find(member => member.id === (userA == null ? void 0 : userA.id));
419
- const membershipB = members.find(member => member.id === (userB == null ? void 0 : userB.id));
420
- if (membershipA == null ? void 0 : membershipA.isRobot) {
421
- return 1;
422
- }
423
- if (membershipB == null ? void 0 : membershipB.isRobot) {
424
- return -1;
425
- }
426
- return 0;
284
+ const { members } = project, membershipA = members.find((member) => member.id === userA?.id), membershipB = members.find((member) => member.id === userB?.id);
285
+ return membershipA?.isRobot === membershipB?.isRobot ? (membershipA?.createdAt || "") > (membershipB?.createdAt || "") ? 1 : -1 : membershipA?.isRobot ? 1 : -1;
427
286
  }
428
287
  function projectUsersWidget(config) {
429
288
  return {
430
289
  name: "project-info",
431
290
  component: ProjectUsers,
432
- layout: config == null ? void 0 : config.layout
291
+ layout: config?.layout
433
292
  };
434
293
  }
435
- var __freeze$1 = Object.freeze;
436
- var __defProp$1 = Object.defineProperty;
437
- var __template$1 = (cooked, raw) => __freeze$1(__defProp$1(cooked, "raw", {
438
- value: __freeze$1(raw || cooked.slice())
439
- }));
440
- var _a$1, _b$1, _c$1, _d$1;
441
- const PlayIconBox = styled(Box)(_a$1 || (_a$1 = __template$1(["\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n\n &:before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 2.75em;\n height: 2.75em;\n border-radius: 50%;\n background: ", ";\n opacity: 0.75;\n }\n"])), _ref3 => {
442
- let {
443
- theme
444
- } = _ref3;
445
- return theme.sanity.color.card.enabled.bg;
446
- });
447
- const Root$1 = styled(Flex)(_b$1 || (_b$1 = __template$1(["\n &:hover {\n ", " {\n &:before {\n opacity: 1;\n }\n }\n }\n"])), PlayIconBox);
448
- const PosterCard = styled(Card)(_c$1 || (_c$1 = __template$1(["\n width: 100%;\n padding-bottom: calc(9 / 16 * 100%);\n position: relative;\n"])));
449
- const Poster = styled.img(_d$1 || (_d$1 = __template$1(["\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"])));
294
+ const PlayIconBox = styled(Box)`
295
+ position: absolute;
296
+ top: 50%;
297
+ left: 50%;
298
+ transform: translate(-50%, -50%);
299
+
300
+ &:before {
301
+ content: '';
302
+ position: absolute;
303
+ top: 50%;
304
+ left: 50%;
305
+ transform: translate(-50%, -50%);
306
+ width: 2.75em;
307
+ height: 2.75em;
308
+ border-radius: 50%;
309
+ background: ${({ theme }) => theme.sanity.color.card.enabled.bg};
310
+ opacity: 0.75;
311
+ }
312
+ `, Root$1 = styled(Flex)`
313
+ &:hover {
314
+ ${PlayIconBox} {
315
+ &:before {
316
+ opacity: 1;
317
+ }
318
+ }
319
+ }
320
+ `, PosterCard = styled(Card)`
321
+ width: 100%;
322
+ padding-bottom: calc(9 / 16 * 100%);
323
+ position: relative;
324
+ `, Poster = styled.img`
325
+ position: absolute;
326
+ top: 0;
327
+ left: 0;
328
+ height: 100%;
329
+ width: 100%;
330
+ object-fit: cover;
331
+ display: block;
332
+
333
+ &:not([src]) {
334
+ display: none;
335
+ }
336
+ `;
450
337
  function Tutorial(props) {
451
- const {
452
- title,
453
- posterURL,
454
- showPlayIcon,
455
- href,
456
- presenterName,
457
- presenterSubtitle
458
- } = props;
459
- return /* @__PURE__ */jsx(Root$1, {
460
- flex: 1,
461
- children: /* @__PURE__ */jsx(Card, {
338
+ const { title, posterURL, showPlayIcon, href, presenterName, presenterSubtitle } = props;
339
+ return /* @__PURE__ */ jsx(Root$1, { flex: 1, children: /* @__PURE__ */ jsx(
340
+ Card,
341
+ {
462
342
  sizing: "border",
463
343
  flex: 1,
464
344
  padding: 2,
@@ -467,55 +347,22 @@ function Tutorial(props) {
467
347
  href,
468
348
  target: "_blank",
469
349
  rel: "noopener noreferrer",
470
- style: {
471
- position: "relative"
472
- },
473
- children: /* @__PURE__ */jsxs(Flex, {
474
- direction: "column",
475
- style: {
476
- height: "100%"
477
- },
478
- children: [posterURL && /* @__PURE__ */jsxs(PosterCard, {
479
- marginBottom: 1,
480
- children: [/* @__PURE__ */jsx(Poster, {
481
- src: posterURL
482
- }), showPlayIcon && /* @__PURE__ */jsx(PlayIconBox, {
483
- display: "flex",
484
- children: /* @__PURE__ */jsx(Text, {
485
- align: "center",
486
- children: /* @__PURE__ */jsx(PlayIcon, {})
487
- })
488
- })]
489
- }), /* @__PURE__ */jsxs(Flex, {
490
- direction: "column",
491
- justify: "space-between",
492
- paddingY: 2,
493
- flex: 1,
494
- children: [/* @__PURE__ */jsx(Heading, {
495
- as: "h3",
496
- size: 1,
497
- children: title
498
- }), /* @__PURE__ */jsx(Box, {
499
- marginTop: 4,
500
- children: /* @__PURE__ */jsxs(Stack, {
501
- space: 2,
502
- flex: 1,
503
- children: [/* @__PURE__ */jsx(Text, {
504
- size: 1,
505
- children: presenterName
506
- }), /* @__PURE__ */jsx(Text, {
507
- size: 0,
508
- style: {
509
- opacity: 0.7
510
- },
511
- children: presenterSubtitle
512
- })]
513
- })
514
- })]
515
- })]
516
- })
517
- })
518
- });
350
+ style: { position: "relative" },
351
+ children: /* @__PURE__ */ jsxs(Flex, { direction: "column", style: { height: "100%" }, children: [
352
+ posterURL && /* @__PURE__ */ jsxs(PosterCard, { marginBottom: 1, children: [
353
+ /* @__PURE__ */ jsx(Poster, { src: posterURL }),
354
+ showPlayIcon && /* @__PURE__ */ jsx(PlayIconBox, { display: "flex", children: /* @__PURE__ */ jsx(Text, { align: "center", children: /* @__PURE__ */ jsx(PlayIcon, {}) }) })
355
+ ] }),
356
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", justify: "space-between", paddingY: 2, flex: 1, children: [
357
+ /* @__PURE__ */ jsx(Heading, { as: "h3", size: 1, children: title }),
358
+ /* @__PURE__ */ jsx(Box, { marginTop: 4, children: /* @__PURE__ */ jsxs(Stack, { space: 2, flex: 1, children: [
359
+ /* @__PURE__ */ jsx(Text, { size: 1, children: presenterName }),
360
+ /* @__PURE__ */ jsx(Text, { size: 0, style: { opacity: 0.7 }, children: presenterSubtitle })
361
+ ] }) })
362
+ ] })
363
+ ] })
364
+ }
365
+ ) });
519
366
  }
520
367
  const tutorialsProjectConfig = {
521
368
  projectId: "3do82whm",
@@ -523,231 +370,199 @@ const tutorialsProjectConfig = {
523
370
  };
524
371
  function useDataAdapter() {
525
372
  const versionedClient = useVersionedClient();
526
- return useMemo(() => ({
527
- getFeed: templateRepoId => {
528
- const uri = templateRepoId ? "/addons/dashboard?templateRepoId=".concat(templateRepoId) : "/addons/dashboard";
529
- return versionedClient.observable.request({
530
- uri,
531
- withCredentials: false
532
- });
533
- },
534
- urlBuilder: imageUrlBuilder(tutorialsProjectConfig)
535
- }), [versionedClient]);
373
+ return useMemo(
374
+ () => ({
375
+ getFeed: (templateRepoId) => {
376
+ const uri = templateRepoId ? `/addons/dashboard?templateRepoId=${templateRepoId}` : "/addons/dashboard";
377
+ return versionedClient.observable.request({
378
+ uri,
379
+ tag: "dashboard.sanity-tutorials",
380
+ withCredentials: !1
381
+ });
382
+ },
383
+ urlBuilder: imageUrlBuilder(tutorialsProjectConfig)
384
+ }),
385
+ [versionedClient]
386
+ );
536
387
  }
537
388
  function createUrl(slug, type) {
538
- if (type === "tutorial") {
539
- return "https://www.sanity.io/docs/tutorials/".concat(slug.current);
540
- } else if (type === "guide") {
541
- return "https://www.sanity.io/docs/guides/".concat(slug.current);
542
- }
543
- return false;
389
+ return type === "tutorial" ? `https://www.sanity.io/docs/tutorials/${slug.current}` : type === "guide" ? `https://www.sanity.io/docs/guides/${slug.current}` : !1;
544
390
  }
545
391
  function SanityTutorials(props) {
546
- const {
547
- templateRepoId
548
- } = props;
549
- const [feedItems, setFeedItems] = useState([]);
550
- const {
551
- getFeed,
552
- urlBuilder
553
- } = useDataAdapter();
554
- useEffect(() => {
555
- const subscription = getFeed(templateRepoId).subscribe(response => {
392
+ const { templateRepoId } = props, [feedItems, setFeedItems] = useState([]), { getFeed, urlBuilder } = useDataAdapter();
393
+ return useEffect(() => {
394
+ const subscription = getFeed(templateRepoId).subscribe((response) => {
556
395
  setFeedItems(response.items);
557
396
  });
558
397
  return () => {
559
398
  subscription.unsubscribe();
560
399
  };
561
- }, [setFeedItems, getFeed, templateRepoId]);
562
- const title = "Learn about Sanity";
563
- return /* @__PURE__ */jsx(DashboardWidgetContainer, {
564
- header: title,
565
- children: /* @__PURE__ */jsx(Flex, {
566
- as: "ul",
567
- overflow: "auto",
568
- align: "stretch",
569
- paddingY: 2,
570
- children: feedItems == null ? void 0 : feedItems.map((feedItem, index) => {
571
- var _a;
572
- if (!feedItem.title || !feedItem.guideOrTutorial && !feedItem.externalLink) {
573
- return null;
574
- }
575
- const presenter = feedItem.presenter || ((_a = feedItem.guideOrTutorial) == null ? void 0 : _a.presenter) || {};
576
- const subtitle = feedItem.category;
577
- const {
578
- guideOrTutorial = {}
579
- } = feedItem;
580
- const href = (guideOrTutorial.slug ? createUrl(guideOrTutorial.slug, guideOrTutorial._type) : feedItem.externalLink) || feedItem.externalLink;
581
- return /* @__PURE__ */jsx(Flex, {
582
- as: "li",
583
- paddingRight: index < (feedItems == null ? void 0 : feedItems.length) - 1 ? 1 : 3,
584
- paddingLeft: index === 0 ? 3 : 0,
585
- align: "stretch",
586
- style: {
587
- minWidth: 272,
588
- width: "30%"
589
- },
590
- children: /* @__PURE__ */jsx(Tutorial, {
400
+ }, [setFeedItems, getFeed, templateRepoId]), /* @__PURE__ */ jsx(DashboardWidgetContainer, { header: "Learn about Sanity", children: /* @__PURE__ */ jsx(Flex, { as: "ul", overflow: "auto", align: "stretch", paddingY: 2, children: feedItems?.map((feedItem, index) => {
401
+ if (!feedItem.title || !feedItem.guideOrTutorial && !feedItem.externalLink)
402
+ return null;
403
+ const presenter = feedItem.presenter || feedItem.guideOrTutorial?.presenter || {}, subtitle = feedItem.category, { guideOrTutorial = {} } = feedItem, href = (guideOrTutorial.slug ? createUrl(guideOrTutorial.slug, guideOrTutorial._type) : feedItem.externalLink) || feedItem.externalLink;
404
+ return /* @__PURE__ */ jsx(
405
+ Flex,
406
+ {
407
+ as: "li",
408
+ paddingRight: index < feedItems?.length - 1 ? 1 : 3,
409
+ paddingLeft: index === 0 ? 3 : 0,
410
+ align: "stretch",
411
+ style: { minWidth: 272, width: "30%" },
412
+ children: /* @__PURE__ */ jsx(
413
+ Tutorial,
414
+ {
591
415
  title: feedItem.title,
592
- href: href != null ? href : "",
416
+ href: href ?? "",
593
417
  presenterName: presenter.name,
594
418
  presenterSubtitle: subtitle,
595
419
  showPlayIcon: feedItem.hasVideo,
596
420
  posterURL: feedItem.poster ? urlBuilder.image(feedItem.poster).height(360).url() : void 0
597
- })
598
- }, feedItem._id);
599
- })
600
- })
601
- });
421
+ }
422
+ )
423
+ },
424
+ feedItem._id
425
+ );
426
+ }) }) });
602
427
  }
603
428
  function sanityTutorialsWidget(config) {
604
- var _a;
605
429
  return {
606
430
  name: "sanity-tutorials",
607
431
  component: SanityTutorials,
608
- layout: (_a = config == null ? void 0 : config.layout) != null ? _a : {
609
- width: "full"
610
- }
432
+ layout: config?.layout ?? { width: "full" }
611
433
  };
612
434
  }
613
435
  function DashboardLayout(props) {
614
- return /* @__PURE__ */jsx(Container, {
615
- width: 4,
616
- padding: 4,
617
- sizing: "border",
618
- style: {
619
- height: "100%",
620
- overflowY: "auto"
621
- },
622
- children: props.children
623
- });
436
+ return /* @__PURE__ */ jsx(Container, { width: 4, padding: 4, sizing: "border", style: { height: "100%", overflowY: "auto" }, children: props.children });
624
437
  }
625
- var __freeze = Object.freeze;
626
- var __defProp = Object.defineProperty;
627
- var __template = (cooked, raw) => __freeze(__defProp(cooked, "raw", {
628
- value: __freeze(raw || cooked.slice())
629
- }));
630
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
631
438
  const media = {
632
- small: function () {
633
- return css(_a || (_a = __template(["\n @media (min-width: ", "px) {\n ", "\n }\n "])), _ref4 => {
634
- let {
635
- theme
636
- } = _ref4;
637
- return theme.sanity.media[0];
638
- }, css(...arguments));
639
- },
640
- medium: function () {
641
- return css(_b || (_b = __template(["\n @media (min-width: ", "px) {\n ", "\n }\n "])), _ref5 => {
642
- let {
643
- theme
644
- } = _ref5;
645
- return theme.sanity.media[2];
646
- }, css(...arguments));
439
+ small: (...args) => css`
440
+ @media (min-width: ${({ theme }) => theme.sanity.media[0]}px) {
441
+ ${css(...args)}
442
+ }
443
+ `,
444
+ medium: (...args) => css`
445
+ @media (min-width: ${({ theme }) => theme.sanity.media[2]}px) {
446
+ ${css(...args)}
447
+ }
448
+ `
449
+ }, Root = styled(Grid)`
450
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
451
+
452
+ & > div {
453
+ overflow: hidden;
647
454
  }
648
- };
649
- const Root = styled(Grid)(_k || (_k = __template(["\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n\n & > div {\n overflow: hidden;\n }\n\n & > div[data-width='medium'] {\n ", "\n }\n\n & > div[data-width='large'] {\n ", "\n\n ", "\n }\n\n & > div[data-width='full'] {\n ", "\n }\n\n & > div[data-height='medium'] {\n ", "\n }\n\n & > div[data-height='large'] {\n ", "\n\n ", "\n }\n\n & > div[data-height='full'] {\n ", "\n }\n"])), media.small(_c || (_c = __template(["\n grid-column: span 2;\n "]))), media.small(_d || (_d = __template(["\n grid-column: span 2;\n "]))), media.medium(_e || (_e = __template(["\n grid-column: span 3;\n "]))), media.small(_f || (_f = __template(["\n grid-column: 1 / -1;\n "]))), media.small(_g || (_g = __template(["\n grid-row: span 2;\n "]))), media.small(_h || (_h = __template(["\n grid-row: span 2;\n "]))), media.medium(_i || (_i = __template(["\n grid-row: span 3;\n "]))), media.medium(_j || (_j = __template(["\n grid-row: 1 / -1;\n "]))));
650
- const NO_WIDGETS = [];
651
- const NO_LAYOUT = {};
455
+
456
+ & > div[data-width='medium'] {
457
+ ${media.small`
458
+ grid-column: span 2;
459
+ `}
460
+ }
461
+
462
+ & > div[data-width='large'] {
463
+ ${media.small`
464
+ grid-column: span 2;
465
+ `}
466
+
467
+ ${media.medium`
468
+ grid-column: span 3;
469
+ `}
470
+ }
471
+
472
+ & > div[data-width='full'] {
473
+ ${media.small`
474
+ grid-column: 1 / -1;
475
+ `}
476
+ }
477
+
478
+ & > div[data-height='medium'] {
479
+ ${media.small`
480
+ grid-row: span 2;
481
+ `}
482
+ }
483
+
484
+ & > div[data-height='large'] {
485
+ ${media.small`
486
+ grid-row: span 2;
487
+ `}
488
+
489
+ ${media.medium`
490
+ grid-row: span 3;
491
+ `}
492
+ }
493
+
494
+ & > div[data-height='full'] {
495
+ ${media.medium`
496
+ grid-row: 1 / -1;
497
+ `}
498
+ }
499
+ `, NO_WIDGETS = [], NO_LAYOUT = {};
652
500
  function WidgetGroup(props) {
653
501
  const {
654
- config: {
655
- layout = NO_LAYOUT,
656
- widgets = NO_WIDGETS
657
- }
502
+ config: { layout = NO_LAYOUT, widgets = NO_WIDGETS }
658
503
  } = props;
659
- return /* @__PURE__ */jsxs(Root, {
660
- autoFlow: "row dense",
661
- "data-width": layout.width || "auto",
662
- "data-height": layout.height || "auto",
663
- gap: 4,
664
- children: [widgets.length ? null : /* @__PURE__ */jsx(Card, {
665
- padding: 4,
666
- shadow: 1,
667
- tone: "primary",
668
- children: /* @__PURE__ */jsx(Text, {
669
- align: "center",
670
- children: "Add some widgets to populate this space."
671
- })
672
- }), widgets.map((widgetConfig, index) => {
673
- if (widgetConfig.type === "__experimental_group") {
674
- return /* @__PURE__ */jsx(WidgetGroup, {
675
- config: widgetConfig
676
- }, index);
677
- }
678
- if (widgetConfig.component) {
679
- return /* @__PURE__ */jsx(WidgetContainer, {
680
- ...widgetConfig
681
- }, index);
682
- }
683
- return /* @__PURE__ */jsxs(Box, {
684
- children: [widgetConfig.name, " is missing widget component"]
685
- }, index);
686
- })]
687
- });
504
+ return /* @__PURE__ */ jsxs(
505
+ Root,
506
+ {
507
+ autoFlow: "row dense",
508
+ "data-width": layout.width || "auto",
509
+ "data-height": layout.height || "auto",
510
+ gap: 4,
511
+ children: [
512
+ 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." }) }),
513
+ widgets.map((widgetConfig, index) => widgetConfig.type === "__experimental_group" ? /* @__PURE__ */ jsx(WidgetGroup, { config: widgetConfig }, index) : widgetConfig.component ? /* @__PURE__ */ jsx(WidgetContainer, { ...widgetConfig }, index) : /* @__PURE__ */ jsxs(Box, { children: [
514
+ widgetConfig.name,
515
+ " is missing widget component"
516
+ ] }, index))
517
+ ]
518
+ }
519
+ );
688
520
  }
689
- function Dashboard(_ref6) {
690
- let {
691
- config
692
- } = _ref6;
693
- if (!config) {
694
- return null;
695
- }
696
- return /* @__PURE__ */jsx(DashboardContext.Provider, {
697
- value: config,
698
- children: /* @__PURE__ */jsx(DashboardLayout, {
699
- children: /* @__PURE__ */jsx(WidgetGroup, {
700
- config
701
- })
702
- })
703
- });
521
+ function Dashboard({ config }) {
522
+ return config ? /* @__PURE__ */ jsx(DashboardContext.Provider, { value: config, children: /* @__PURE__ */ jsx(DashboardLayout, { children: /* @__PURE__ */ jsx(WidgetGroup, { config }) }) }) : null;
704
523
  }
705
524
  const strokeStyle = {
706
525
  stroke: "currentColor",
707
526
  strokeWidth: 1.2
708
- };
709
- const DashboardIcon = () => /* @__PURE__ */jsxs("svg", {
710
- "data-sanity-icon": true,
711
- viewBox: "0 0 25 25",
712
- fill: "none",
713
- xmlns: "http://www.w3.org/2000/svg",
714
- preserveAspectRatio: "xMidYMid",
715
- width: "1em",
716
- height: "1em",
717
- children: [/* @__PURE__ */jsx("path", {
718
- d: "M19.5 19.5H5.5V5.5H19.5V19.5Z",
719
- style: strokeStyle
720
- }), /* @__PURE__ */jsx("path", {
721
- d: "M5.5 12.5H19.5",
722
- style: strokeStyle
723
- }), /* @__PURE__ */jsx("path", {
724
- d: "M14.5 19.5V12.5M10.5 12.5V5.5",
725
- style: strokeStyle
726
- })]
727
- });
728
- const dashboardTool = definePlugin(function () {
729
- let config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
730
- var _a, _b, _c, _d, _e;
527
+ }, DashboardIcon = () => /* @__PURE__ */ jsxs(
528
+ "svg",
529
+ {
530
+ "data-sanity-icon": !0,
531
+ viewBox: "0 0 25 25",
532
+ fill: "none",
533
+ xmlns: "http://www.w3.org/2000/svg",
534
+ preserveAspectRatio: "xMidYMid",
535
+ width: "1em",
536
+ height: "1em",
537
+ children: [
538
+ /* @__PURE__ */ jsx("path", { d: "M19.5 19.5H5.5V5.5H19.5V19.5Z", style: strokeStyle }),
539
+ /* @__PURE__ */ jsx("path", { d: "M5.5 12.5H19.5", style: strokeStyle }),
540
+ /* @__PURE__ */ jsx("path", { d: "M14.5 19.5V12.5M10.5 12.5V5.5", style: strokeStyle })
541
+ ]
542
+ }
543
+ ), dashboardTool = definePlugin((config = {}) => {
731
544
  const pluginConfig = {
732
- layout: (_a = config.defaultLayout) != null ? _a : {},
733
- widgets: (_b = config.widgets) != null ? _b : []
734
- };
735
- const title = (_c = config.title) != null ? _c : "Dashboard";
736
- const name = (_d = config.name) != null ? _d : "dashboard";
737
- const icon = (_e = config.icon) != null ? _e : DashboardIcon;
545
+ layout: config.defaultLayout ?? {},
546
+ widgets: config.widgets ?? []
547
+ }, title = config.title ?? "Dashboard", name = config.name ?? "dashboard", icon = config.icon ?? DashboardIcon;
738
548
  return {
739
549
  name: "dashboard",
740
- tools: (prev, context) => {
741
- return [...prev, {
550
+ tools: (prev, context) => [
551
+ ...prev,
552
+ {
742
553
  title,
743
554
  name,
744
555
  icon,
745
- component: () => /* @__PURE__ */jsx(Dashboard, {
746
- config: pluginConfig
747
- })
748
- }];
749
- }
556
+ component: () => /* @__PURE__ */ jsx(Dashboard, { config: pluginConfig })
557
+ }
558
+ ]
750
559
  };
751
560
  });
752
- export { DashboardWidgetContainer, dashboardTool, projectInfoWidget, projectUsersWidget, sanityTutorialsWidget };
561
+ export {
562
+ DashboardWidgetContainer,
563
+ dashboardTool,
564
+ projectInfoWidget,
565
+ projectUsersWidget,
566
+ sanityTutorialsWidget
567
+ };
753
568
  //# sourceMappingURL=index.esm.js.map