sanity-plugin-utils 0.0.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Simeon Griggs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,154 @@
1
+ # sanity-plugin-utils
2
+
3
+ ## Installation
4
+
5
+ ```
6
+ npm install --save sanity-plugin-utils
7
+ ```
8
+
9
+ or
10
+
11
+ ```
12
+ yarn add sanity-plugin-utils
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ Handy hooks and clever components for Sanity Studio v3
18
+
19
+ ### useListeningQuery()
20
+
21
+ Sanity's real-time APIs power excellent editorial experiences. Your plugins should respond to other users collaborating on documents in real time. This hook is a convenient way to perform a GROQ query that responds to changes, along with built-in `loading` and `error` states.
22
+
23
+ The `data` variable will be constantly updated as changes are made to the data returned by your query. You can also pass in initial data so that it is set in the first render.
24
+
25
+ ```jsx
26
+ import {useListeningQuery} from 'sanity-plugin-utils'
27
+
28
+ export default function DocumentList() {
29
+ const {data, loading, error} = useListeningQuery(`*[_type == $type]`, {
30
+ params: {type: 'pet'},
31
+ initialData: [],
32
+ })
33
+
34
+ if (loading) {
35
+ return <Spinner />
36
+ }
37
+
38
+ if (error) {
39
+ return <Feedback tone="critical">{error}</Feedback>
40
+ }
41
+
42
+ return (
43
+ <Stack>
44
+ {data?.length > 0 ? (
45
+ data.map((pet) => <Card key={pet._id}>{pet.title}</Card>)
46
+ ) : (
47
+ <Feedback>No Pets found</Feedback>
48
+ )}
49
+ </Stack>
50
+ )
51
+ }
52
+ ```
53
+
54
+ ### useProjectUsers()
55
+
56
+ Hook for getting extended details on all Users in the project. Such as name.
57
+
58
+ ```jsx
59
+ import {useProjectUsers} from 'sanity-plugin-utils'
60
+
61
+ export default function DocumentList() {
62
+ const users = useProjectUsers()
63
+
64
+ return (
65
+ <Stack>
66
+ {users?.length > 0 ? (
67
+ users.map((user) => <Profile key={user.id} {...user}>)
68
+ ) : (
69
+ <Spinner>
70
+ )}
71
+ </Stack>
72
+ )
73
+ }
74
+ ```
75
+
76
+ ### Feedback
77
+
78
+ Component for consistently displaying feedback in a card with a title, text and an icon.
79
+
80
+ ```jsx
81
+ import {Feedback, useListeningQuery} from 'sanity-plugin-utils'
82
+
83
+ export default function DocumentList() {
84
+ const {data, loading, error} = useListeningQuery(`*[_type == "task" && !complete]`)
85
+
86
+ if (loading) {
87
+ return <Feedback tone="primary" title="Please hold" description="Fetching tasks..." />
88
+ }
89
+
90
+ if (error) {
91
+ return (
92
+ <Feedback tone="critical" title="There was an error" description="Please try again later" />
93
+ )
94
+ }
95
+
96
+ return data?.length > 0 ? (
97
+ <Feedback tone="caution" title="There are unfinished tasks" description="Please get to work" />
98
+ ) : (
99
+ <Feedback tone="success" title="You're all done" description="You should feel accomplished" />
100
+ )
101
+ }
102
+ ```
103
+
104
+ ### Table, Row and Cell
105
+
106
+ These components are all @sanity/ui Card's but with their HTML DOM elements and CSS updated to output and behave like tables.
107
+
108
+ ```jsx
109
+ import {Table, Row, Cell} from 'sanity-plugin-utils'
110
+
111
+ export default function Report(documents) {
112
+ return (
113
+ <Table>
114
+ <thead>
115
+ <Row>
116
+ <Cell>
117
+ <Text>Name</Text>
118
+ </Cell>
119
+ <Cell>
120
+ <Text>Price</Text>
121
+ </Cell>
122
+ </Row>
123
+ </thead>
124
+ <tbody>
125
+ {documents.map((doc) => (
126
+ <Row key={doc._id}>
127
+ <Cell>
128
+ <Text>{doc.title}</Text>
129
+ </Cell>
130
+ <Cell tone={doc.inStock ? `caution` : `primary`}>
131
+ <Text>{doc.price}</Text>
132
+ </Cell>
133
+ </Row>
134
+ ))}
135
+ </tbody>
136
+ </Table>
137
+ )
138
+ }
139
+ ```
140
+
141
+ ### UserSelectMenu
142
+
143
+ A Menu component for searching and interacting with users. Requires Users to be passed into the component. Will return an array of user `id`s.
144
+
145
+ ```jsx
146
+ import {UserSelectMenu} from 'sanity-plugin-utils'
147
+
148
+ // TODO: Example
149
+ ```
150
+
151
+ ## License
152
+
153
+ MIT © Simeon Griggs
154
+ See LICENSE
@@ -0,0 +1,331 @@
1
+ var $k7rGe$react = require("react");
2
+ var $k7rGe$rxjsoperators = require("rxjs/operators");
3
+ var $k7rGe$reactfastcompare = require("react-fast-compare");
4
+ var $k7rGe$sanity_unstable = require("sanity/_unstable");
5
+ var $k7rGe$sanity = require("sanity");
6
+ var $k7rGe$reactjsxruntime = require("react/jsx-runtime");
7
+ var $k7rGe$sanityui = require("@sanity/ui");
8
+ var $k7rGe$styledcomponents = require("styled-components");
9
+ var $k7rGe$sanityicons = require("@sanity/icons");
10
+
11
+ function $parcel$export(e, n, v, s) {
12
+ Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
13
+ }
14
+ function $parcel$interopDefault(a) {
15
+ return a && a.__esModule ? a.default : a;
16
+ }
17
+
18
+ $parcel$export(module.exports, "useListeningQuery", () => $38e62e17b2ecf1ab$export$3a1bc984843df335);
19
+ $parcel$export(module.exports, "useProjectUsers", () => $9be8b8b7af8d7d37$export$a38963ede7c2ac91);
20
+ $parcel$export(module.exports, "Feedback", () => $aaf4d804384afd00$export$175e500a48a60fd2);
21
+ $parcel$export(module.exports, "Table", () => $acfbfc6ee2363807$export$54ec01a60f47d33d);
22
+ $parcel$export(module.exports, "Row", () => $acfbfc6ee2363807$export$b59bdbef9ce70de2);
23
+ $parcel$export(module.exports, "Cell", () => $acfbfc6ee2363807$export$f6f0c3fe4ec306ea);
24
+ $parcel$export(module.exports, "UserSelectMenu", () => $cce1a432d06a385f$export$4a7d9e0c70b27556);
25
+
26
+
27
+
28
+
29
+ const $38e62e17b2ecf1ab$var$DEFAULT_PARAMS = {};
30
+ const $38e62e17b2ecf1ab$var$DEFAULT_OPTIONS = {
31
+ apiVersion: `v2022-05-09`
32
+ };
33
+ const $38e62e17b2ecf1ab$var$DEFAULT_INITIAL_VALUE = null;
34
+ function $38e62e17b2ecf1ab$export$3a1bc984843df335(query, { params: params = $38e62e17b2ecf1ab$var$DEFAULT_PARAMS , options: options = $38e62e17b2ecf1ab$var$DEFAULT_OPTIONS , initialValue: initialValue = $38e62e17b2ecf1ab$var$DEFAULT_INITIAL_VALUE }) {
35
+ const [loading, setLoading] = (0, $k7rGe$react.useState)(true);
36
+ const [error, setError] = (0, $k7rGe$react.useState)(false);
37
+ const [data, setData] = (0, $k7rGe$react.useState)(initialValue);
38
+ const subscription = (0, $k7rGe$react.useRef)(null);
39
+ const documentStore = (0, $k7rGe$sanity_unstable.useDocumentStore)();
40
+ (0, $k7rGe$react.useEffect)(()=>{
41
+ if (query) subscription.current = documentStore.listenQuery(query, params, options).pipe((0, $k7rGe$rxjsoperators.distinctUntilChanged)((0, ($parcel$interopDefault($k7rGe$reactfastcompare)))), (0, $k7rGe$rxjsoperators.catchError)((err)=>{
42
+ console.error(err);
43
+ setError(err);
44
+ setLoading(false);
45
+ setData(null);
46
+ return err;
47
+ })).subscribe((documents)=>{
48
+ setData((current)=>(0, ($parcel$interopDefault($k7rGe$reactfastcompare)))(current, documents) ? current : documents);
49
+ setLoading(false);
50
+ setError(false);
51
+ });
52
+ return ()=>subscription?.current?.unsubscribe();
53
+ }, [
54
+ query,
55
+ params,
56
+ options,
57
+ documentStore
58
+ ]);
59
+ return {
60
+ data: data,
61
+ loading: loading,
62
+ error: error
63
+ };
64
+ }
65
+
66
+
67
+
68
+
69
+ function $9be8b8b7af8d7d37$export$a38963ede7c2ac91() {
70
+ const { currentUser: currentUser } = (0, $k7rGe$sanity.useWorkspace)();
71
+ const client = (0, $k7rGe$sanity.useClient)();
72
+ const [users, setUsers] = (0, $k7rGe$react.useState)([]);
73
+ (0, $k7rGe$react.useEffect)(()=>{
74
+ const { projectId: projectId } = client.config();
75
+ async function getUser(id) {
76
+ const userDetails = await client.request({
77
+ url: `/projects/${projectId}/users/${id}`
78
+ });
79
+ return userDetails;
80
+ }
81
+ async function getUsersWithRoles() {
82
+ const userRoles = await client.request({
83
+ url: `/projects/${projectId}/acl`
84
+ }).then(async (res)=>Promise.all(res.map(async (user)=>({
85
+ isCurrentUser: user.projectUserId === currentUser?.id,
86
+ ...await getUser(user.projectUserId)
87
+ })))).catch((err)=>err);
88
+ setUsers(userRoles);
89
+ }
90
+ if (!users.length) getUsersWithRoles();
91
+ }, [
92
+ client,
93
+ currentUser?.id,
94
+ users.length
95
+ ]);
96
+ return users;
97
+ }
98
+
99
+
100
+
101
+
102
+
103
+ const $aaf4d804384afd00$var$DEFAULT_PROPS = {
104
+ tone: "primary"
105
+ };
106
+ function $aaf4d804384afd00$export$175e500a48a60fd2(props) {
107
+ const { title: title , description: description , icon: icon , tone: tone , children: children } = {
108
+ ...$aaf4d804384afd00$var$DEFAULT_PROPS,
109
+ ...props
110
+ };
111
+ return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Card), {
112
+ tone: tone,
113
+ padding: 4,
114
+ radius: 3,
115
+ border: true,
116
+ children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsxs)((0, $k7rGe$sanityui.Flex), {
117
+ children: [
118
+ icon ? `display icon` : null,
119
+ children ? children : /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Box), {
120
+ flex: 1,
121
+ children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsxs)((0, $k7rGe$sanityui.Stack), {
122
+ space: 4,
123
+ children: [
124
+ title ? /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Text), {
125
+ weight: "semibold",
126
+ children: title
127
+ }) : null,
128
+ description ? /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Text), {
129
+ size: 2,
130
+ children: description
131
+ }) : null
132
+ ]
133
+ })
134
+ })
135
+ ]
136
+ })
137
+ });
138
+ }
139
+
140
+
141
+
142
+
143
+
144
+
145
+ // Wrappers required because of bug with passing down "as" prop
146
+ // https://github.com/styled-components/styled-components/issues/2449
147
+ // Table
148
+ const $acfbfc6ee2363807$var$TableWrapper = (props = {})=>{
149
+ return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Card), {
150
+ as: "table",
151
+ ...props
152
+ });
153
+ };
154
+ const $acfbfc6ee2363807$var$StyledTable = (0, ($parcel$interopDefault($k7rGe$styledcomponents)))($acfbfc6ee2363807$var$TableWrapper)(()=>(0, $k7rGe$styledcomponents.css)`
155
+ display: table;
156
+ width: 100%;
157
+
158
+ &:not([hidden]) {
159
+ display: table;
160
+ }
161
+ `);
162
+ function $acfbfc6ee2363807$export$54ec01a60f47d33d(props) {
163
+ const { children: children , ...rest } = props;
164
+ return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)($acfbfc6ee2363807$var$StyledTable, {
165
+ ...rest,
166
+ children: children
167
+ });
168
+ }
169
+ // Row
170
+ const $acfbfc6ee2363807$var$RowWrapper = (props = {})=>{
171
+ return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Card), {
172
+ as: "tr",
173
+ ...props
174
+ });
175
+ };
176
+ const $acfbfc6ee2363807$var$StyledRow = (0, ($parcel$interopDefault($k7rGe$styledcomponents)))($acfbfc6ee2363807$var$RowWrapper)(()=>(0, $k7rGe$styledcomponents.css)`
177
+ display: table-row;
178
+
179
+ &:not([hidden]) {
180
+ display: table-row;
181
+ }
182
+ `);
183
+ function $acfbfc6ee2363807$export$b59bdbef9ce70de2(props) {
184
+ const { children: children , ...rest } = props;
185
+ return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)($acfbfc6ee2363807$var$StyledRow, {
186
+ ...rest,
187
+ children: children
188
+ });
189
+ }
190
+ // Cell
191
+ const $acfbfc6ee2363807$var$CellWrapper = (props = {})=>{
192
+ return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Card), {
193
+ as: "td",
194
+ ...props
195
+ });
196
+ };
197
+ const $acfbfc6ee2363807$var$StyledCell = (0, ($parcel$interopDefault($k7rGe$styledcomponents)))($acfbfc6ee2363807$var$CellWrapper)(()=>(0, $k7rGe$styledcomponents.css)`
198
+ display: table-cell;
199
+
200
+ &:not([hidden]) {
201
+ display: table-cell;
202
+ }
203
+ `);
204
+ function $acfbfc6ee2363807$export$f6f0c3fe4ec306ea(props) {
205
+ const { children: children , ...rest } = props;
206
+ return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)($acfbfc6ee2363807$var$StyledCell, {
207
+ ...rest,
208
+ children: children
209
+ });
210
+ }
211
+
212
+
213
+
214
+
215
+
216
+
217
+
218
+ function $cce1a432d06a385f$var$searchUsers(users, searchString) {
219
+ return users.filter((user)=>{
220
+ const displayName = (user.displayName || "").toLowerCase();
221
+ if (displayName.startsWith(searchString)) return true;
222
+ const givenName = (user.givenName || "").toLowerCase();
223
+ if (givenName.startsWith(searchString)) return true;
224
+ const middleName = (user.middleName || "").toLowerCase();
225
+ if (middleName.startsWith(searchString)) return true;
226
+ const familyName = (user.familyName || "").toLowerCase();
227
+ if (familyName.startsWith(searchString)) return true;
228
+ return false;
229
+ });
230
+ }
231
+ function $cce1a432d06a385f$export$4a7d9e0c70b27556(props) {
232
+ const { value: value = [] , userList: userList = [] , onAdd: onAdd , onRemove: onRemove , onClear: onClear , style: style = {} } = props;
233
+ const [searchString, setSearchString] = (0, ($parcel$interopDefault($k7rGe$react))).useState("");
234
+ const searchResults = $cce1a432d06a385f$var$searchUsers(userList || [], searchString);
235
+ const me = userList.find((u)=>u.isCurrentUser);
236
+ const meAssigned = me && value.includes(me.id);
237
+ // Focus input on open
238
+ // TODO: Fix focus, it gets immediately taken away
239
+ const input = (0, $k7rGe$react.useRef)();
240
+ // useEffect(() => {
241
+ // if (open && input?.current) {
242
+ // input.current.focus()
243
+ // }
244
+ // }, [open])
245
+ const handleSearchChange = (event)=>{
246
+ setSearchString(event.target.value);
247
+ };
248
+ const handleSelect = (isChecked, user)=>{
249
+ if (!isChecked) {
250
+ if (onAdd) onAdd(user.id);
251
+ } else if (onRemove) onRemove(user.id);
252
+ };
253
+ const handleAssignMyself = ()=>{
254
+ if (me && onAdd) onAdd(me.id);
255
+ };
256
+ const handleUnassignMyself = ()=>{
257
+ if (me && onRemove) onRemove(me.id);
258
+ };
259
+ const handleClearAssigneesClick = ()=>{
260
+ if (onClear) onClear();
261
+ };
262
+ return /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsxs)((0, $k7rGe$sanityui.Menu), {
263
+ style: style,
264
+ children: [
265
+ meAssigned ? /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.MenuItem), {
266
+ tone: "caution",
267
+ disabled: !me,
268
+ onClick: handleUnassignMyself,
269
+ icon: (0, $k7rGe$sanityicons.RemoveCircleIcon),
270
+ text: "Unassign myself"
271
+ }) : /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.MenuItem), {
272
+ tone: "positive",
273
+ onClick: handleAssignMyself,
274
+ icon: (0, $k7rGe$sanityicons.AddCircleIcon),
275
+ text: "Assign myself"
276
+ }),
277
+ /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.MenuItem), {
278
+ tone: "critical",
279
+ disabled: value.length === 0,
280
+ onClick: handleClearAssigneesClick,
281
+ icon: (0, $k7rGe$sanityicons.RestoreIcon),
282
+ text: "Clear assignees"
283
+ }),
284
+ /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Box), {
285
+ padding: 1,
286
+ children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.TextInput), {
287
+ // @ts-ignore TODO: Satisfy ref
288
+ ref: input,
289
+ onChange: handleSearchChange,
290
+ placeholder: "Search members",
291
+ value: searchString
292
+ })
293
+ }),
294
+ searchString && searchResults?.length === 0 && /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.MenuItem), {
295
+ disabled: true,
296
+ text: "No matches"
297
+ }),
298
+ searchResults && searchResults.map((user)=>/*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.MenuItem), {
299
+ pressed: value.includes(user.id),
300
+ onClick: ()=>handleSelect(value.indexOf(user.id) > -1, user),
301
+ children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsxs)((0, $k7rGe$sanityui.Flex), {
302
+ align: "center",
303
+ children: [
304
+ /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanity_unstable.UserAvatar), {
305
+ user: user,
306
+ size: 1
307
+ }),
308
+ /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Box), {
309
+ paddingX: 2,
310
+ flex: 1,
311
+ children: /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Text), {
312
+ children: user.displayName
313
+ })
314
+ }),
315
+ user.isCurrentUser && /*#__PURE__*/ (0, $k7rGe$reactjsxruntime.jsx)((0, $k7rGe$sanityui.Badge), {
316
+ fontSize: 1,
317
+ tone: "positive",
318
+ mode: "outline",
319
+ children: "Me"
320
+ })
321
+ ]
322
+ })
323
+ }, user.id))
324
+ ]
325
+ });
326
+ }
327
+
328
+
329
+
330
+
331
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"mappings":"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","sources":["src/index.ts","src/hooks/useListeningQuery.tsx","src/hooks/useProjectUsers.tsx","src/components/Feedback.tsx","src/components/Table.tsx","src/components/UserSelectMenu/index.tsx"],"sourcesContent":["export {useListeningQuery} from './hooks/useListeningQuery'\nexport {useProjectUsers} from './hooks/useProjectUsers'\n\nexport {Feedback} from './components/Feedback'\nexport {Table, Row, Cell} from './components/Table'\nexport {UserSelectMenu} from './components/UserSelectMenu/index'\n","import {useEffect, useState, useRef} from 'react'\nimport {catchError, distinctUntilChanged} from 'rxjs/operators'\nimport isEqual from 'react-fast-compare'\nimport {useDocumentStore} from 'sanity/_unstable'\nimport {Subscription} from 'rxjs'\n\ntype Params = Record<string, string | number | boolean | string[]>\n\ninterface ListenQueryOptions {\n tag?: string\n apiVersion?: string\n}\n\ntype Value = any\n\ninterface Config<V> {\n params: Params\n options?: ListenQueryOptions\n initialValue?: null | V\n}\n\ninterface Return<V> {\n loading: boolean\n error: boolean\n data: null | V\n initialValue?: Value\n}\n\nconst DEFAULT_PARAMS = {}\nconst DEFAULT_OPTIONS = {apiVersion: `v2022-05-09`}\nconst DEFAULT_INITIAL_VALUE = null\n\nexport function useListeningQuery<V>(\n query: string | {fetch: string; listen: string},\n {\n params = DEFAULT_PARAMS,\n options = DEFAULT_OPTIONS,\n initialValue = DEFAULT_INITIAL_VALUE,\n }: Config<V>\n): Return<V> {\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState(false)\n const [data, setData] = useState(initialValue)\n const subscription = useRef<null | Subscription>(null)\n const documentStore = useDocumentStore()\n\n useEffect(() => {\n if (query) {\n subscription.current = documentStore\n .listenQuery(query, params, options)\n .pipe(\n distinctUntilChanged(isEqual),\n catchError((err) => {\n console.error(err)\n setError(err)\n setLoading(false)\n setData(null)\n\n return err\n })\n )\n .subscribe((documents) => {\n setData((current: Value) => (isEqual(current, documents) ? current : documents))\n setLoading(false)\n setError(false)\n })\n }\n\n return () => subscription?.current?.unsubscribe()\n }, [query, params, options, documentStore])\n\n return {data, loading, error}\n}\n","import {useState, useEffect} from 'react'\nimport {useClient, useWorkspace} from 'sanity'\n\nexport type UserExtended = {\n createdAt: string\n displayName: string\n email: string\n familyName: string\n givenName: string\n id: string\n imageUrl: string\n isCurrentUser: boolean\n middleName: string\n projectId: string\n provider: string\n sanityUserId: string\n updatedAt: string\n}\n\ntype UserRole = {\n name: string\n title: string\n}\n\ntype UserResponse = {\n isRobot: boolean\n projectUserId: string\n roles: UserRole[]\n}\n\n// Custom hook to fetch user details\n// Built-in hook doesn't fetch all user details\nexport function useProjectUsers(): UserExtended[] {\n const {currentUser} = useWorkspace()\n const client = useClient()\n const [users, setUsers] = useState([])\n\n useEffect(() => {\n const {projectId} = client.config()\n\n async function getUser(id: string) {\n const userDetails = await client.request({\n url: `/projects/${projectId}/users/${id}`,\n })\n\n return userDetails\n }\n\n async function getUsersWithRoles() {\n const userRoles = await client\n .request({\n url: `/projects/${projectId}/acl`,\n })\n .then(async (res) =>\n Promise.all(\n res.map(async (user: UserResponse) => ({\n isCurrentUser: user.projectUserId === currentUser?.id,\n ...(await getUser(user.projectUserId)),\n }))\n )\n )\n .catch((err) => err)\n\n setUsers(userRoles)\n }\n\n if (!users.length) {\n getUsersWithRoles()\n }\n }, [client, currentUser?.id, users.length])\n\n return users\n}\n","import React from 'react'\nimport {Box, Card, CardTone, Flex, Stack, Text} from '@sanity/ui'\n\ntype FeedbackChildren = {\n children?: React.ReactNode\n title?: never\n description?: never\n}\n\ntype FeedbackTextProps = {\n title?: string\n description?: React.ReactNode\n children?: never\n}\n\ntype FeedbackProps = (FeedbackChildren | FeedbackTextProps) & {\n tone?: CardTone\n icon?: React.ReactNode\n}\n\nconst DEFAULT_PROPS: FeedbackProps = {\n tone: 'primary',\n}\n\nexport function Feedback(props: FeedbackProps) {\n const {title, description, icon, tone, children} = {...DEFAULT_PROPS, ...props}\n\n return (\n <Card tone={tone} padding={4} radius={3} border>\n <Flex>\n {icon ? `display icon` : null}\n {children ? (\n children\n ) : (\n <Box flex={1}>\n <Stack space={4}>\n {title ? <Text weight=\"semibold\">{title}</Text> : null}\n {description ? <Text size={2}>{description}</Text> : null}\n </Stack>\n </Box>\n )}\n </Flex>\n </Card>\n )\n}\n","import React, {PropsWithChildren} from 'react'\nimport styled, {css} from 'styled-components'\nimport {Card, CardProps} from '@sanity/ui'\n\n// Wrappers required because of bug with passing down \"as\" prop\n// https://github.com/styled-components/styled-components/issues/2449\n\n// Table\nconst TableWrapper = (props: CardProps = {}) => {\n return <Card as=\"table\" {...props} />\n}\n\nconst StyledTable = styled(TableWrapper)(\n () =>\n css`\n display: table;\n width: 100%;\n\n &:not([hidden]) {\n display: table;\n }\n `\n)\n\ntype TableProps = PropsWithChildren<CardProps>\n\nexport function Table(props: TableProps) {\n const {children, ...rest} = props\n\n return <StyledTable {...rest}>{children}</StyledTable>\n}\n\n// Row\nconst RowWrapper = (props: CardProps = {}) => {\n return <Card as=\"tr\" {...props} />\n}\n\nconst StyledRow = styled(RowWrapper)(\n () =>\n css`\n display: table-row;\n\n &:not([hidden]) {\n display: table-row;\n }\n `\n)\n\ntype TableRowProps = PropsWithChildren<CardProps>\n\nexport function Row(props: TableRowProps) {\n const {children, ...rest} = props\n\n return <StyledRow {...rest}>{children}</StyledRow>\n}\n\n// Cell\nconst CellWrapper = (props = {}) => {\n return <Card as=\"td\" {...props} />\n}\n\nconst StyledCell = styled(CellWrapper)(\n () =>\n css`\n display: table-cell;\n\n &:not([hidden]) {\n display: table-cell;\n }\n `\n)\n\ntype TableCellProps = PropsWithChildren<CardProps>\n\nexport function Cell(props: TableCellProps) {\n const {children, ...rest} = props\n\n return <StyledCell {...rest}>{children}</StyledCell>\n}\n","import React, {useEffect, useRef} from 'react'\nimport {Box, Text, Menu, MenuItem, TextInput, Flex, Badge} from '@sanity/ui'\nimport {AddCircleIcon, RemoveCircleIcon, RestoreIcon} from '@sanity/icons'\nimport {UserAvatar} from 'sanity/_unstable'\n\nimport {UserExtended} from '../../hooks/useProjectUsers'\n\nfunction searchUsers(users: UserExtended[], searchString: string): UserExtended[] {\n return users.filter((user) => {\n const displayName = (user.displayName || '').toLowerCase()\n if (displayName.startsWith(searchString)) return true\n const givenName = (user.givenName || '').toLowerCase()\n if (givenName.startsWith(searchString)) return true\n const middleName = (user.middleName || '').toLowerCase()\n if (middleName.startsWith(searchString)) return true\n const familyName = (user.familyName || '').toLowerCase()\n if (familyName.startsWith(searchString)) return true\n\n return false\n })\n}\n\ntype UserSelectMenuProps = {\n value: string[]\n userList: UserExtended[]\n onAdd: any\n onRemove: any\n onClear: any\n open: boolean\n style?: React.CSSProperties\n}\n\nexport function UserSelectMenu(props: UserSelectMenuProps) {\n const {value = [], userList = [], onAdd, onRemove, onClear, style = {}} = props\n const [searchString, setSearchString] = React.useState('')\n const searchResults = searchUsers(userList || [], searchString)\n\n const me = userList.find((u) => u.isCurrentUser)\n const meAssigned = me && value.includes(me.id)\n\n // Focus input on open\n // TODO: Fix focus, it gets immediately taken away\n const input = useRef<HTMLInputElement>()\n // useEffect(() => {\n // if (open && input?.current) {\n // input.current.focus()\n // }\n // }, [open])\n\n const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setSearchString(event.target.value)\n }\n\n const handleSelect = (isChecked: boolean, user: UserExtended) => {\n if (!isChecked) {\n if (onAdd) onAdd(user.id)\n } else if (onRemove) onRemove(user.id)\n }\n\n const handleAssignMyself = () => {\n if (me && onAdd) onAdd(me.id)\n }\n\n const handleUnassignMyself = () => {\n if (me && onRemove) onRemove(me.id)\n }\n\n const handleClearAssigneesClick = () => {\n if (onClear) onClear()\n }\n\n return (\n <Menu style={style}>\n {meAssigned ? (\n <MenuItem\n tone=\"caution\"\n disabled={!me}\n onClick={handleUnassignMyself}\n icon={RemoveCircleIcon}\n text=\"Unassign myself\"\n />\n ) : (\n <MenuItem\n tone=\"positive\"\n onClick={handleAssignMyself}\n icon={AddCircleIcon}\n text=\"Assign myself\"\n />\n )}\n\n <MenuItem\n tone=\"critical\"\n disabled={value.length === 0}\n onClick={handleClearAssigneesClick}\n icon={RestoreIcon}\n text=\"Clear assignees\"\n />\n\n <Box padding={1}>\n <TextInput\n // @ts-ignore TODO: Satisfy ref\n ref={input}\n onChange={handleSearchChange}\n placeholder=\"Search members\"\n value={searchString}\n />\n </Box>\n\n {searchString && searchResults?.length === 0 && <MenuItem disabled text=\"No matches\" />}\n\n {searchResults &&\n searchResults.map((user) => (\n <MenuItem\n key={user.id}\n pressed={value.includes(user.id)}\n onClick={() => handleSelect(value.indexOf(user.id) > -1, user)}\n >\n <Flex align=\"center\">\n <UserAvatar user={user} size={1} />\n <Box paddingX={2} flex={1}>\n <Text>{user.displayName}</Text>\n </Box>\n {user.isCurrentUser && (\n <Badge fontSize={1} tone=\"positive\" mode=\"outline\">\n Me\n </Badge>\n )}\n </Flex>\n </MenuItem>\n ))}\n </Menu>\n )\n}\n"],"names":[],"version":3,"file":"index.js.map","sourceRoot":"../../"}