@sanity/orderable-document-list 0.0.8 → 1.0.0-v3-studio.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.
Files changed (63) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +142 -48
  3. package/lib/index.d.ts +38 -0
  4. package/lib/index.d.ts.map +1 -0
  5. package/lib/index.js +849 -30
  6. package/lib/index.js.map +1 -1
  7. package/lib/index.modern.js +840 -0
  8. package/lib/index.modern.js.map +1 -0
  9. package/package.json +56 -22
  10. package/src/{Document.js → Document.tsx} +30 -27
  11. package/src/{DocumentListQuery.js → DocumentListQuery.tsx} +29 -18
  12. package/src/{DocumentListWrapper.js → DocumentListWrapper.tsx} +29 -21
  13. package/src/DraggableList.tsx +304 -0
  14. package/src/{Feedback.js → Feedback.tsx} +2 -7
  15. package/src/OrderableContext.ts +7 -0
  16. package/src/{OrderableDocumentList.js → OrderableDocumentList.tsx} +25 -10
  17. package/src/desk-structure/globalClientWorkaround.ts +33 -0
  18. package/src/desk-structure/{orderableDocumentListDeskItem.js → orderableDocumentListDeskItem.ts} +27 -11
  19. package/src/fields/orderRankField.ts +45 -0
  20. package/src/fields/{orderRankOrdering.js → orderRankOrdering.ts} +0 -0
  21. package/src/helpers/client.ts +13 -0
  22. package/src/helpers/constants.ts +1 -0
  23. package/src/helpers/{initialRank.js → initialRank.ts} +2 -2
  24. package/src/helpers/{reorderDocuments.js → reorderDocuments.ts} +33 -44
  25. package/src/helpers/{resetOrder.js → resetOrder.ts} +3 -8
  26. package/src/index.ts +9 -0
  27. package/.babelrc +0 -3
  28. package/.eslintignore +0 -1
  29. package/.eslintrc.js +0 -50
  30. package/lib/Document.js +0 -101
  31. package/lib/Document.js.map +0 -1
  32. package/lib/DocumentListQuery.js +0 -155
  33. package/lib/DocumentListQuery.js.map +0 -1
  34. package/lib/DocumentListWrapper.js +0 -97
  35. package/lib/DocumentListWrapper.js.map +0 -1
  36. package/lib/DraggableList.js +0 -314
  37. package/lib/DraggableList.js.map +0 -1
  38. package/lib/Feedback.js +0 -31
  39. package/lib/Feedback.js.map +0 -1
  40. package/lib/OrderableContext.js +0 -15
  41. package/lib/OrderableContext.js.map +0 -1
  42. package/lib/OrderableDocumentList.js +0 -99
  43. package/lib/OrderableDocumentList.js.map +0 -1
  44. package/lib/desk-structure/orderableDocumentListDeskItem.js +0 -52
  45. package/lib/desk-structure/orderableDocumentListDeskItem.js.map +0 -1
  46. package/lib/fields/orderRankField.js +0 -64
  47. package/lib/fields/orderRankField.js.map +0 -1
  48. package/lib/fields/orderRankOrdering.js +0 -19
  49. package/lib/fields/orderRankOrdering.js.map +0 -1
  50. package/lib/helpers/constants.js +0 -9
  51. package/lib/helpers/constants.js.map +0 -1
  52. package/lib/helpers/initialRank.js +0 -18
  53. package/lib/helpers/initialRank.js.map +0 -1
  54. package/lib/helpers/reorderDocuments.js +0 -133
  55. package/lib/helpers/reorderDocuments.js.map +0 -1
  56. package/lib/helpers/resetOrder.js +0 -62
  57. package/lib/helpers/resetOrder.js.map +0 -1
  58. package/sanity.json +0 -7
  59. package/src/DraggableList.js +0 -276
  60. package/src/OrderableContext.js +0 -3
  61. package/src/fields/orderRankField.js +0 -35
  62. package/src/helpers/constants.js +0 -1
  63. package/src/index.js +0 -5
package/lib/index.js CHANGED
@@ -1,30 +1,849 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- Object.defineProperty(exports, "orderRankField", {
7
- enumerable: true,
8
- get: function get() {
9
- return _orderRankField.orderRankField;
10
- }
11
- });
12
- Object.defineProperty(exports, "orderRankOrdering", {
13
- enumerable: true,
14
- get: function get() {
15
- return _orderRankOrdering.orderRankOrdering;
16
- }
17
- });
18
- Object.defineProperty(exports, "orderableDocumentListDeskItem", {
19
- enumerable: true,
20
- get: function get() {
21
- return _orderableDocumentListDeskItem.orderableDocumentListDeskItem;
22
- }
23
- });
24
-
25
- var _orderRankField = require("./fields/orderRankField");
26
-
27
- var _orderRankOrdering = require("./fields/orderRankOrdering");
28
-
29
- var _orderableDocumentListDeskItem = require("./desk-structure/orderableDocumentListDeskItem");
30
- //# sourceMappingURL=index.js.map
1
+ var $3KLdq$lexorank = require("lexorank");
2
+ var $3KLdq$sanityicons = require("@sanity/icons");
3
+ var $3KLdq$reactjsxruntime = require("react/jsx-runtime");
4
+ var $3KLdq$react = require("react");
5
+ var $3KLdq$sanityui = require("@sanity/ui");
6
+ var $3KLdq$sanity = require("sanity");
7
+ var $3KLdq$reactbeautifuldnd = require("react-beautiful-dnd");
8
+ var $3KLdq$sanitydesk = require("sanity/desk");
9
+ var $3KLdq$sanity_unstable = require("sanity/_unstable");
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, "orderRankField", () => $cc532e4527e08c0f$export$64a609a9111ff100);
19
+ $parcel$export(module.exports, "orderRankOrdering", () => $0a2b7163675b4332$export$db2ff2f898748a67);
20
+ $parcel$export(module.exports, "orderableDocumentListDeskItem", () => $9f7e9a421b4d07af$export$3b014deba4b8ca00);
21
+ const $7e21cb9e508f672b$export$64f27603cb09ba16 = `orderRank`;
22
+
23
+
24
+
25
+ function $b1e493eff806e5a4$export$2e2bcd8739ae039(lastRankValue = ``) {
26
+ const lastRank = lastRankValue ? (0, $3KLdq$lexorank.LexoRank).parse(lastRankValue) : (0, $3KLdq$lexorank.LexoRank).min();
27
+ const nextRank = lastRank.genNext().genNext();
28
+ return nextRank.value;
29
+ }
30
+
31
+
32
+ const $21298532e6cb38a9$var$subscriptions = {};
33
+ function $21298532e6cb38a9$export$59b6ebc56d192aaa(context) {
34
+ ($21298532e6cb38a9$var$subscriptions[$21298532e6cb38a9$var$clientKey(context)] ?? []).forEach((subscriber)=>subscriber(context.client));
35
+ }
36
+ function $21298532e6cb38a9$export$a2a87dc3ab91967(context, callback) {
37
+ const key = $21298532e6cb38a9$var$clientKey(context);
38
+ const existing = $21298532e6cb38a9$var$subscriptions[key] ?? [];
39
+ $21298532e6cb38a9$var$subscriptions[key] = [
40
+ ...existing,
41
+ callback
42
+ ];
43
+ }
44
+ function $21298532e6cb38a9$var$clientKey(context) {
45
+ return `${context.projectId}:${context.dataset}`;
46
+ }
47
+
48
+
49
+ const $cc532e4527e08c0f$export$64a609a9111ff100 = (config)=>{
50
+ if (!config?.type || !config.context) throw new Error(`
51
+ type and context must be provided. context is available when configuring schema.
52
+ Example: orderRankField({type: 'category', context})
53
+ `);
54
+ const { type: type } = config;
55
+ let client;
56
+ (0, $21298532e6cb38a9$export$a2a87dc3ab91967)(config.context, (updatedClient)=>{
57
+ client = updatedClient;
58
+ });
59
+ return {
60
+ title: "Order Rank",
61
+ readOnly: true,
62
+ hidden: true,
63
+ ...config,
64
+ name: (0, $7e21cb9e508f672b$export$64f27603cb09ba16),
65
+ type: "string",
66
+ initialValue: async ()=>{
67
+ const lastDocOrderRank = await client?.fetch(`*[_type == $type]|order(@[$order] desc)[0][$order]`, {
68
+ type: type,
69
+ order: (0, $7e21cb9e508f672b$export$64f27603cb09ba16)
70
+ });
71
+ return (0, $b1e493eff806e5a4$export$2e2bcd8739ae039)(lastDocOrderRank);
72
+ }
73
+ };
74
+ };
75
+
76
+
77
+
78
+ const $0a2b7163675b4332$export$db2ff2f898748a67 = {
79
+ title: "Ordered",
80
+ name: "ordered",
81
+ by: [
82
+ {
83
+ field: (0, $7e21cb9e508f672b$export$64f27603cb09ba16),
84
+ direction: "asc"
85
+ }
86
+ ]
87
+ };
88
+
89
+
90
+
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+
104
+
105
+
106
+
107
+
108
+
109
+
110
+
111
+
112
+ const $ad5dfe08a2c834b7$export$2a2017d0ec5437fa = (0, ($parcel$interopDefault($3KLdq$react))).createContext({});
113
+
114
+
115
+ function $8d444d838b27ec52$export$2e2bcd8739ae039({ doc: doc , increment: increment , entities: entities , handleSelect: handleSelect , index: index , isFirst: isFirst , isLast: isLast }) {
116
+ const { showIncrements: showIncrements } = (0, $3KLdq$react.useContext)((0, $ad5dfe08a2c834b7$export$2a2017d0ec5437fa));
117
+ const schema = (0, $3KLdq$sanity.useSchema)();
118
+ return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsxs)((0, $3KLdq$sanityui.Flex), {
119
+ align: "center",
120
+ children: [
121
+ /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityui.Box), {
122
+ paddingX: 3,
123
+ style: {
124
+ flexShrink: 0
125
+ },
126
+ children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityui.Text), {
127
+ size: 4,
128
+ children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityicons.DragHandleIcon), {})
129
+ })
130
+ }),
131
+ showIncrements && /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsxs)((0, $3KLdq$sanityui.Flex), {
132
+ style: {
133
+ flexShrink: 0
134
+ },
135
+ align: "center",
136
+ gap: 1,
137
+ paddingRight: 1,
138
+ children: [
139
+ /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityui.Button), {
140
+ padding: 2,
141
+ mode: "ghost",
142
+ onClick: ()=>increment(index, index + -1, doc._id, entities),
143
+ disabled: isFirst,
144
+ icon: (0, $3KLdq$sanityicons.ChevronUpIcon)
145
+ }),
146
+ /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityui.Button), {
147
+ padding: 2,
148
+ mode: "ghost",
149
+ disabled: isLast,
150
+ onClick: ()=>increment(index, index + 1, doc._id, entities),
151
+ icon: (0, $3KLdq$sanityicons.ChevronDownIcon)
152
+ })
153
+ ]
154
+ }),
155
+ /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityui.Button), {
156
+ style: {
157
+ width: `100%`
158
+ },
159
+ padding: 2,
160
+ mode: "bleed",
161
+ onClick: (e)=>handleSelect(doc._id, index, e.nativeEvent),
162
+ children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityui.Flex), {
163
+ flex: 1,
164
+ align: "center",
165
+ children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityui.Box), {
166
+ flex: 1,
167
+ children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanity_unstable.SanityPreview), {
168
+ layout: "default",
169
+ value: doc,
170
+ schemaType: schema.get(doc._type)
171
+ })
172
+ })
173
+ })
174
+ })
175
+ ]
176
+ });
177
+ }
178
+
179
+
180
+
181
+
182
+ function $460233bd0d4c2ff3$var$lexicographicalSort(a, b) {
183
+ if (a[0, $7e21cb9e508f672b$export$64f27603cb09ba16] < b[0, $7e21cb9e508f672b$export$64f27603cb09ba16]) return -1;
184
+ if (a[0, $7e21cb9e508f672b$export$64f27603cb09ba16] > b[0, $7e21cb9e508f672b$export$64f27603cb09ba16]) return 1;
185
+ return 0;
186
+ }
187
+ const $460233bd0d4c2ff3$export$1b86f2c90605ffb9 = ({ entities: entities , selectedIds: selectedIds , source: source , destination: destination , debug: debug = false })=>{
188
+ const startIndex = source.index;
189
+ const endIndex = destination.index;
190
+ const isMovingUp = startIndex > endIndex;
191
+ const selectedItems = entities.filter((item)=>selectedIds.includes(item._id));
192
+ const message = [
193
+ `Moved`,
194
+ selectedItems.length === 1 ? `1 Document` : `${selectedItems.length} Documents`,
195
+ isMovingUp ? `up` : `down`,
196
+ `from position`,
197
+ `${startIndex + 1} to ${endIndex + 1}`,
198
+ ].join(" ");
199
+ const { all: all , selected: selected } = entities.reduce((acc, cur, curIndex)=>{
200
+ // Selected items get spread in below, so skip them here
201
+ if (selectedIds.includes(cur._id)) return {
202
+ all: acc.all,
203
+ selected: acc.selected
204
+ };
205
+ // Drop seleced items in
206
+ if (curIndex === endIndex) {
207
+ const prevIndex = curIndex - 1;
208
+ const prevRank = entities[prevIndex]?.[0, $7e21cb9e508f672b$export$64f27603cb09ba16] ? (0, $3KLdq$lexorank.LexoRank).parse(entities[prevIndex]?.[0, $7e21cb9e508f672b$export$64f27603cb09ba16]) : (0, $3KLdq$lexorank.LexoRank).min();
209
+ const curRank = (0, $3KLdq$lexorank.LexoRank).parse(entities[curIndex][0, $7e21cb9e508f672b$export$64f27603cb09ba16]);
210
+ const nextIndex = curIndex + 1;
211
+ const nextRank = entities[nextIndex]?.[0, $7e21cb9e508f672b$export$64f27603cb09ba16] ? (0, $3KLdq$lexorank.LexoRank).parse(entities[nextIndex]?.[0, $7e21cb9e508f672b$export$64f27603cb09ba16]) : (0, $3KLdq$lexorank.LexoRank).max();
212
+ let betweenRank = isMovingUp ? prevRank.between(curRank) : curRank.between(nextRank);
213
+ // For each selected item, assign a new orderRank between now and next
214
+ for(let selectedIndex = 0; selectedIndex < selectedItems.length; selectedIndex += 1){
215
+ selectedItems[selectedIndex][0, $7e21cb9e508f672b$export$64f27603cb09ba16] = betweenRank.value;
216
+ betweenRank = isMovingUp ? betweenRank.between(curRank) : betweenRank.between(nextRank);
217
+ }
218
+ return {
219
+ // The `all` array gets sorted by order field later anyway
220
+ // so that this probably isn't necessary ¯\_(ツ)_/¯
221
+ all: isMovingUp ? [
222
+ ...acc.all,
223
+ ...selectedItems,
224
+ cur
225
+ ] : [
226
+ ...acc.all,
227
+ cur,
228
+ ...selectedItems
229
+ ],
230
+ selected: selectedItems
231
+ };
232
+ }
233
+ return {
234
+ all: [
235
+ ...acc.all,
236
+ cur
237
+ ],
238
+ selected: acc.selected
239
+ };
240
+ }, {
241
+ all: [],
242
+ selected: []
243
+ });
244
+ const patches = selected.map((doc)=>{
245
+ return [
246
+ doc._id,
247
+ {
248
+ set: {
249
+ [(0, $7e21cb9e508f672b$export$64f27603cb09ba16)]: doc[0, $7e21cb9e508f672b$export$64f27603cb09ba16]
250
+ }
251
+ },
252
+ ];
253
+ });
254
+ // Safety-check to make sure everything is in order
255
+ const allSorted = all.sort($460233bd0d4c2ff3$var$lexicographicalSort);
256
+ return {
257
+ newOrder: allSorted,
258
+ patches: patches,
259
+ message: message
260
+ };
261
+ };
262
+
263
+
264
+
265
+
266
+
267
+ function $66c7844c36e4ff21$export$8d49af9be9632eba() {
268
+ const baseClient = (0, $3KLdq$sanity.useClient)();
269
+ return (0, $3KLdq$react.useMemo)(()=>baseClient.withConfig({
270
+ apiVersion: "2021-09-01"
271
+ }), [
272
+ baseClient
273
+ ]);
274
+ }
275
+
276
+
277
+ const $9cae087253e865f7$var$getItemStyle = (draggableStyle, itemIsUpdating)=>({
278
+ userSelect: "none",
279
+ transition: `opacity 500ms ease-in-out`,
280
+ opacity: itemIsUpdating ? 0.2 : 1,
281
+ pointerEvents: itemIsUpdating ? `none` : undefined,
282
+ ...draggableStyle
283
+ });
284
+ const $9cae087253e865f7$var$cardTone = (settings)=>{
285
+ const { isDuplicate: isDuplicate , isGhosting: isGhosting , isDragging: isDragging , isSelected: isSelected } = settings;
286
+ if (isGhosting) return `transparent`;
287
+ if (isDragging || isSelected) return `primary`;
288
+ if (isDuplicate) return `caution`;
289
+ return undefined;
290
+ };
291
+ function $9cae087253e865f7$export$2e2bcd8739ae039({ data: data , type: type , listIsUpdating: listIsUpdating , setListIsUpdating: setListIsUpdating }) {
292
+ const toast = (0, $3KLdq$sanityui.useToast)();
293
+ const router = (0, $3KLdq$sanitydesk.usePaneRouter)();
294
+ const { navigateIntent: navigateIntent } = router;
295
+ // Maintains local state order before transaction completes
296
+ const [orderedData, setOrderedData] = (0, $3KLdq$react.useState)(data);
297
+ // Update local state when documents change from an outside source
298
+ (0, $3KLdq$react.useEffect)(()=>{
299
+ if (!listIsUpdating) setOrderedData(data);
300
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */ }, [
301
+ data
302
+ ]);
303
+ const [draggingId, setDraggingId] = (0, $3KLdq$react.useState)(``);
304
+ const [selectedIds, setSelectedIds] = (0, $3KLdq$react.useState)([]);
305
+ const clearSelected = (0, $3KLdq$react.useCallback)(()=>setSelectedIds([]), [
306
+ setSelectedIds
307
+ ]);
308
+ const handleSelect = (0, $3KLdq$react.useCallback)((clickedId, index, nativeEvent)=>{
309
+ const isSelected = selectedIds.includes(clickedId);
310
+ const selectMultiple = nativeEvent.shiftKey;
311
+ const isUsingWindows = navigator.appVersion.indexOf("Win") !== -1;
312
+ const selectAdditional = isUsingWindows ? nativeEvent.ctrlKey : nativeEvent.metaKey;
313
+ let updatedIds = [];
314
+ // No modifier keys pressed during click:
315
+ // - update selected to just this one
316
+ // - open document
317
+ if (!selectMultiple && !selectAdditional) {
318
+ navigateIntent("edit", {
319
+ id: clickedId,
320
+ type: type
321
+ });
322
+ return setSelectedIds([
323
+ clickedId
324
+ ]);
325
+ }
326
+ // Shift key was held, add id's between last selected and this one
327
+ // ...before adding this one
328
+ if (selectMultiple && !isSelected) {
329
+ const lastSelectedId = selectedIds[selectedIds.length - 1];
330
+ const lastSelectedIndex = orderedData.findIndex((item)=>item._id === lastSelectedId);
331
+ const firstSelected = index < lastSelectedIndex ? index : lastSelectedIndex;
332
+ const lastSelected = index > lastSelectedIndex ? index : lastSelectedIndex;
333
+ const betweenIds = orderedData.filter((item, itemIndex)=>itemIndex > firstSelected && itemIndex < lastSelected).map((item)=>item._id);
334
+ updatedIds = [
335
+ ...selectedIds,
336
+ ...betweenIds,
337
+ clickedId
338
+ ];
339
+ } else if (isSelected) // Toggle off a single id
340
+ updatedIds = selectedIds.filter((id)=>id !== clickedId);
341
+ else // Toggle on a single id
342
+ updatedIds = [
343
+ ...selectedIds,
344
+ clickedId
345
+ ];
346
+ return setSelectedIds(updatedIds);
347
+ }, [
348
+ setSelectedIds,
349
+ navigateIntent,
350
+ orderedData,
351
+ selectedIds,
352
+ type
353
+ ]);
354
+ const client = (0, $66c7844c36e4ff21$export$8d49af9be9632eba)();
355
+ const transactPatches = (0, $3KLdq$react.useCallback)(async (patches, message)=>{
356
+ const transaction = client.transaction();
357
+ patches.forEach(([docId, ops])=>transaction.patch(docId, ops));
358
+ await transaction.commit().then((updated)=>{
359
+ clearSelected();
360
+ setDraggingId(``);
361
+ setListIsUpdating(false);
362
+ toast.push({
363
+ title: `${updated.results.length === 1 ? `1 Document` : `${updated.results.length} Documents`} Reordered`,
364
+ status: `success`,
365
+ description: message
366
+ });
367
+ }).catch(()=>{
368
+ setDraggingId(``);
369
+ setListIsUpdating(false);
370
+ toast.push({
371
+ title: `Reordering failed`,
372
+ status: `error`
373
+ });
374
+ });
375
+ }, [
376
+ client,
377
+ setDraggingId,
378
+ clearSelected,
379
+ setListIsUpdating,
380
+ toast
381
+ ]);
382
+ const handleDragEnd = (0, $3KLdq$react.useCallback)((result, entities)=>{
383
+ setDraggingId(``);
384
+ const { source: source , destination: destination , draggableId: draggableId } = result ?? {};
385
+ // Don't do anything if nothing changed
386
+ if (source?.index === destination?.index) return;
387
+ // Don't do anything if we don't have the entitites
388
+ if (!entities?.length || !draggableId) return;
389
+ // A document can be dragged without being one-of-many-selected
390
+ const effectedIds = selectedIds?.length ? selectedIds : [
391
+ draggableId
392
+ ];
393
+ // Don't do anything if we don't have ids to effect
394
+ if (!effectedIds?.length) return;
395
+ // Update state to update styles + prevent data refetching
396
+ setListIsUpdating(true);
397
+ setSelectedIds(effectedIds);
398
+ const { newOrder: newOrder , patches: patches , message: message } = (0, $460233bd0d4c2ff3$export$1b86f2c90605ffb9)({
399
+ entities: entities,
400
+ selectedIds: effectedIds,
401
+ source: source,
402
+ destination: destination
403
+ });
404
+ // Update local state
405
+ if (newOrder?.length) setOrderedData(newOrder);
406
+ // Transact new order patches
407
+ if (patches?.length) transactPatches(patches, message);
408
+ }, [
409
+ selectedIds,
410
+ setDraggingId,
411
+ setSelectedIds,
412
+ transactPatches,
413
+ setListIsUpdating
414
+ ]);
415
+ const handleDragStart = (0, $3KLdq$react.useCallback)((start)=>{
416
+ const id = start.draggableId;
417
+ const selected = selectedIds.includes(id);
418
+ // if dragging an item that is not selected - unselect all items
419
+ if (!selected) clearSelected();
420
+ setDraggingId(id);
421
+ }, [
422
+ selectedIds,
423
+ clearSelected,
424
+ setDraggingId
425
+ ]);
426
+ // Move one document up or down one place, by fake invoking the drag function
427
+ const incrementIndex = (0, $3KLdq$react.useCallback)((shiftFrom, shiftTo, id, entities)=>{
428
+ const result = {
429
+ draggableId: id,
430
+ source: {
431
+ index: shiftFrom
432
+ },
433
+ destination: {
434
+ index: shiftTo
435
+ }
436
+ };
437
+ return handleDragEnd(result, entities);
438
+ }, [
439
+ handleDragEnd
440
+ ]);
441
+ const onWindowKeyDown = (0, $3KLdq$react.useCallback)((event)=>{
442
+ if (event.key === "Escape") clearSelected();
443
+ }, [
444
+ clearSelected
445
+ ]);
446
+ (0, $3KLdq$react.useEffect)(()=>{
447
+ window.addEventListener("keydown", onWindowKeyDown);
448
+ return ()=>{
449
+ window.removeEventListener("keydown", onWindowKeyDown);
450
+ };
451
+ }, [
452
+ onWindowKeyDown
453
+ ]);
454
+ // Find all items with duplicate order field
455
+ const duplicateOrders = (0, $3KLdq$react.useMemo)(()=>{
456
+ if (!orderedData.length) return [];
457
+ const orderField = orderedData.map((item)=>item[0, $7e21cb9e508f672b$export$64f27603cb09ba16]);
458
+ return orderField.filter((item, index)=>orderField.indexOf(item) !== index);
459
+ }, [
460
+ orderedData
461
+ ]);
462
+ const onDragEnd = (0, $3KLdq$react.useCallback)((result)=>handleDragEnd(result, orderedData), [
463
+ orderedData,
464
+ handleDragEnd
465
+ ]);
466
+ return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$reactbeautifuldnd.DragDropContext), {
467
+ onDragStart: handleDragStart,
468
+ onDragEnd: onDragEnd,
469
+ children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$reactbeautifuldnd.Droppable), {
470
+ droppableId: "documentSortZone",
471
+ children: (provided)=>/*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsxs)("div", {
472
+ ...provided.droppableProps,
473
+ ref: provided.innerRef,
474
+ children: [
475
+ orderedData.map((item, index)=>/*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$reactbeautifuldnd.Draggable), {
476
+ draggableId: item._id,
477
+ index: index,
478
+ children: (innerProvided, innerSnapshot)=>{
479
+ const isSelected = selectedIds.includes(item._id);
480
+ const isDragging = innerSnapshot.isDragging;
481
+ const isGhosting = Boolean(!isDragging && draggingId && isSelected);
482
+ const isUpdating = listIsUpdating && isSelected;
483
+ const isDisabled = Boolean(!item[0, $7e21cb9e508f672b$export$64f27603cb09ba16]);
484
+ const isDuplicate = duplicateOrders.includes(item[0, $7e21cb9e508f672b$export$64f27603cb09ba16]);
485
+ const tone = $9cae087253e865f7$var$cardTone({
486
+ isDuplicate: isDuplicate,
487
+ isGhosting: isGhosting,
488
+ isDragging: isDragging,
489
+ isSelected: isSelected
490
+ });
491
+ return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)("div", {
492
+ ref: innerProvided.innerRef,
493
+ ...innerProvided.draggableProps,
494
+ ...innerProvided.dragHandleProps,
495
+ style: isDisabled ? {
496
+ opacity: 0.2,
497
+ pointerEvents: `none`
498
+ } : $9cae087253e865f7$var$getItemStyle(innerProvided.draggableProps.style, isUpdating),
499
+ children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityui.Box), {
500
+ paddingBottom: 1,
501
+ children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityui.Card), {
502
+ tone: tone,
503
+ shadow: isDragging ? 2 : undefined,
504
+ radius: 2,
505
+ children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $8d444d838b27ec52$export$2e2bcd8739ae039), {
506
+ doc: item,
507
+ entities: orderedData,
508
+ handleSelect: handleSelect,
509
+ increment: incrementIndex,
510
+ index: index,
511
+ isFirst: index === 0,
512
+ isLast: index === orderedData.length - 1
513
+ })
514
+ })
515
+ })
516
+ });
517
+ }
518
+ }, `${item._id}-${item[0, $7e21cb9e508f672b$export$64f27603cb09ba16]}`)),
519
+ provided.placeholder
520
+ ]
521
+ })
522
+ })
523
+ });
524
+ }
525
+
526
+
527
+
528
+
529
+
530
+
531
+ function $8f6d54ef8e8d6bcf$export$2e2bcd8739ae039({ children: children }) {
532
+ return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityui.Box), {
533
+ padding: 3,
534
+ children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityui.Card), {
535
+ padding: 4,
536
+ radius: 2,
537
+ shadow: 1,
538
+ tone: "caution",
539
+ children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityui.Text), {
540
+ children: children
541
+ })
542
+ })
543
+ });
544
+ }
545
+
546
+
547
+
548
+ const $d59638856f04a407$var$DEFAULT_PARAMS = {};
549
+ function $d59638856f04a407$export$2e2bcd8739ae039({ type: type , filter: filter , params: params = $d59638856f04a407$var$DEFAULT_PARAMS }) {
550
+ const [isLoading, setIsLoading] = (0, $3KLdq$react.useState)(true);
551
+ const [listIsUpdating, setListIsUpdating] = (0, $3KLdq$react.useState)(false);
552
+ const [data, setData] = (0, $3KLdq$react.useState)([]);
553
+ const client = (0, $66c7844c36e4ff21$export$8d49af9be9632eba)();
554
+ (0, $3KLdq$react.useEffect)(()=>{
555
+ const query = `*[_type == $type ${filter ? `&& ${filter}` : ""}]|order(@[$order] asc){
556
+ _id, _type, ${(0, $7e21cb9e508f672b$export$64f27603cb09ba16)}
557
+ }`;
558
+ const queryParams = Object.assign(params, {
559
+ type: type,
560
+ order: (0, $7e21cb9e508f672b$export$64f27603cb09ba16)
561
+ });
562
+ let subscription;
563
+ // eslint-disable-next-line require-await
564
+ const fetchData = async ()=>{
565
+ client.fetch(query, queryParams).then((documents)=>{
566
+ // Remove published document from list if draft also exists
567
+ const filteredDocuments = documents.reduce((acc, cur)=>{
568
+ if (!cur._id.startsWith(`drafts.`)) {
569
+ // eslint-disable-next-line max-nested-callbacks
570
+ const alsoHasDraft = documents.some((doc)=>doc._id === `drafts.${cur._id}`);
571
+ return alsoHasDraft ? acc : [
572
+ ...acc,
573
+ cur
574
+ ];
575
+ }
576
+ return [
577
+ ...acc,
578
+ cur
579
+ ];
580
+ }, []);
581
+ setData(filteredDocuments);
582
+ if (isLoading) setIsLoading(false);
583
+ });
584
+ };
585
+ const prepareData = async ()=>{
586
+ setIsLoading(true);
587
+ await fetchData();
588
+ if (!subscription) subscription = client.listen(query, queryParams).subscribe(()=>fetchData());
589
+ };
590
+ // Get data but only if a document isn't being patched or we don't yet have data
591
+ if (!listIsUpdating && !data.length) prepareData();
592
+ return ()=>subscription?.unsubscribe();
593
+ /* eslint-disable-next-line react-hooks/exhaustive-deps */ }, [
594
+ type
595
+ ]);
596
+ const unorderedDataCount = (0, $3KLdq$react.useMemo)(()=>data.length ? data.filter((doc)=>!doc[0, $7e21cb9e508f672b$export$64f27603cb09ba16]).length : 0, [
597
+ data
598
+ ]);
599
+ if (isLoading) return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityui.Flex), {
600
+ style: {
601
+ width: `100%`,
602
+ height: `100%`
603
+ },
604
+ align: "center",
605
+ justify: "center",
606
+ children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityui.Spinner), {})
607
+ });
608
+ return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsxs)((0, $3KLdq$sanityui.Stack), {
609
+ space: 1,
610
+ style: {
611
+ overflow: `scroll`,
612
+ height: `100%`
613
+ },
614
+ children: [
615
+ unorderedDataCount > 0 && /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsxs)((0, $8f6d54ef8e8d6bcf$export$2e2bcd8739ae039), {
616
+ children: [
617
+ unorderedDataCount,
618
+ "/",
619
+ data.length,
620
+ " Documents have no Order. Select",
621
+ " ",
622
+ /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)("strong", {
623
+ children: "Reset Order"
624
+ }),
625
+ " from the Menu above to fix."
626
+ ]
627
+ }),
628
+ /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $3KLdq$sanityui.Box), {
629
+ padding: 1,
630
+ children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $9cae087253e865f7$export$2e2bcd8739ae039), {
631
+ data: data,
632
+ type: type,
633
+ listIsUpdating: listIsUpdating,
634
+ setListIsUpdating: setListIsUpdating
635
+ })
636
+ })
637
+ ]
638
+ });
639
+ }
640
+
641
+
642
+
643
+
644
+
645
+ function $a8b1e0d5707b32a2$export$2e2bcd8739ae039({ type: type , showIncrements: showIncrements , resetOrderTransaction: resetOrderTransaction , filter: filter , params: params }) {
646
+ const toast = (0, $3KLdq$sanityui.useToast)();
647
+ const schema = (0, $3KLdq$sanity.useSchema)();
648
+ (0, $3KLdq$react.useEffect)(()=>{
649
+ if (resetOrderTransaction?.title && resetOrderTransaction?.status) toast.push(resetOrderTransaction);
650
+ }, [
651
+ resetOrderTransaction,
652
+ toast
653
+ ]);
654
+ const schemaIsInvalid = (0, $3KLdq$react.useMemo)(()=>{
655
+ // Option not passed
656
+ if (!type) return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsxs)((0, $3KLdq$reactjsxruntime.Fragment), {
657
+ children: [
658
+ "No ",
659
+ /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)("code", {
660
+ children: "type"
661
+ }),
662
+ " was configured"
663
+ ]
664
+ });
665
+ const typeSchema = schema.get(type);
666
+ // Schema not found
667
+ if (!typeSchema) return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsxs)((0, $3KLdq$reactjsxruntime.Fragment), {
668
+ children: [
669
+ "Schema ",
670
+ /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)("code", {
671
+ children: type
672
+ }),
673
+ " not found"
674
+ ]
675
+ });
676
+ // Schema lacks an order field
677
+ if (!("fields" in typeSchema) || !typeSchema.fields.some((field)=>field?.name === (0, $7e21cb9e508f672b$export$64f27603cb09ba16))) return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsxs)((0, $3KLdq$reactjsxruntime.Fragment), {
678
+ children: [
679
+ "Schema ",
680
+ /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)("code", {
681
+ children: type
682
+ }),
683
+ " must have an ",
684
+ /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)("code", {
685
+ children: (0, $7e21cb9e508f672b$export$64f27603cb09ba16)
686
+ }),
687
+ " field of type",
688
+ " ",
689
+ /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)("code", {
690
+ children: "string"
691
+ })
692
+ ]
693
+ });
694
+ // Schema's order field is not a string
695
+ if ("fields" in typeSchema && typeSchema.fields.some((field)=>field?.name === (0, $7e21cb9e508f672b$export$64f27603cb09ba16) && field?.type?.name !== "string")) return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsxs)((0, $3KLdq$reactjsxruntime.Fragment), {
696
+ children: [
697
+ /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)("code", {
698
+ children: (0, $7e21cb9e508f672b$export$64f27603cb09ba16)
699
+ }),
700
+ " field on Schema ",
701
+ /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)("code", {
702
+ children: type
703
+ }),
704
+ " must be",
705
+ " ",
706
+ /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)("code", {
707
+ children: "string"
708
+ }),
709
+ " type"
710
+ ]
711
+ });
712
+ return "";
713
+ }, [
714
+ type,
715
+ schema
716
+ ]);
717
+ if (schemaIsInvalid) return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $8f6d54ef8e8d6bcf$export$2e2bcd8739ae039), {
718
+ children: schemaIsInvalid
719
+ });
720
+ return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $ad5dfe08a2c834b7$export$2a2017d0ec5437fa).Provider, {
721
+ value: {
722
+ showIncrements: showIncrements
723
+ },
724
+ children: /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $d59638856f04a407$export$2e2bcd8739ae039), {
725
+ type: type,
726
+ filter: filter,
727
+ params: params
728
+ })
729
+ });
730
+ }
731
+
732
+
733
+
734
+
735
+ async function $0448f7faaab547e3$export$ee841d674ca80db0(type = ``, client) {
736
+ const query = `*[_type == $type]|order(@[$order] asc)._id`;
737
+ const queryParams = {
738
+ type: type,
739
+ order: (0, $7e21cb9e508f672b$export$64f27603cb09ba16)
740
+ };
741
+ const documents = await client.fetch(query, queryParams);
742
+ if (!documents.length) return null;
743
+ const transaction = client.transaction();
744
+ let aLexoRank = (0, $3KLdq$lexorank.LexoRank).min();
745
+ for(let index = 0; index < documents.length; index += 1){
746
+ // Generate next rank before even the first document so there's room to move!
747
+ aLexoRank = aLexoRank.genNext().genNext();
748
+ transaction.patch(documents[index], {
749
+ set: {
750
+ [(0, $7e21cb9e508f672b$export$64f27603cb09ba16)]: aLexoRank.value
751
+ }
752
+ });
753
+ }
754
+ return transaction.commit().then((update)=>update).catch((err)=>err);
755
+ }
756
+
757
+
758
+ class $7faf82429f78b250$export$2e2bcd8739ae039 extends (0, $3KLdq$react.Component) {
759
+ constructor(props){
760
+ super(props);
761
+ this.state = {
762
+ showIncrements: false,
763
+ resetOrderTransaction: {}
764
+ };
765
+ }
766
+ actionHandlers = {
767
+ showIncrements: ()=>{
768
+ this.setState((state)=>({
769
+ showIncrements: !state.showIncrements
770
+ }));
771
+ },
772
+ resetOrder: async ()=>{
773
+ this.setState(()=>({
774
+ resetOrderTransaction: {
775
+ status: `info`,
776
+ title: `Reordering started...`,
777
+ closable: true
778
+ }
779
+ }));
780
+ const update = await (0, $0448f7faaab547e3$export$ee841d674ca80db0)(this.props.options.type, this.props.options.client);
781
+ const reorderWasSuccessful = update?.results?.length;
782
+ this.setState(()=>({
783
+ resetOrderTransaction: {
784
+ status: reorderWasSuccessful ? `success` : `info`,
785
+ title: reorderWasSuccessful ? `Reordered ${update.results.length === 1 ? `Document` : `Documents`}` : `Reordering failed`,
786
+ closable: true
787
+ }
788
+ }));
789
+ }
790
+ };
791
+ render() {
792
+ const type = this?.props?.options?.type;
793
+ if (!type) return null;
794
+ return /*#__PURE__*/ (0, $3KLdq$reactjsxruntime.jsx)((0, $a8b1e0d5707b32a2$export$2e2bcd8739ae039), {
795
+ filter: this?.props?.options?.filter,
796
+ params: this?.props?.options?.params,
797
+ type: type,
798
+ showIncrements: this.state.showIncrements,
799
+ resetOrderTransaction: this.state.resetOrderTransaction
800
+ });
801
+ }
802
+ }
803
+
804
+
805
+
806
+ function $9f7e9a421b4d07af$export$3b014deba4b8ca00(config) {
807
+ if (!config?.type || !config.context || !config.S) throw new Error(`
808
+ type, context and S (StructureBuilder) must be provided.
809
+ context and S are available when configuring structure.
810
+ Example: orderableDocumentListDeskItem({type: 'category'})
811
+ `);
812
+ const { type: type , filter: filter , params: params , title: title , icon: icon , id: id , context: context , S: S } = config;
813
+ const { schema: schema , client: client } = context;
814
+ // workaround so schemas can get access to client in callbacks
815
+ (0, $21298532e6cb38a9$export$59b6ebc56d192aaa)(context);
816
+ const listTitle = title ?? `Orderable ${type}`;
817
+ const listId = id ?? `orderable-${type}`;
818
+ const listIcon = icon ?? (0, $3KLdq$sanityicons.SortIcon);
819
+ const typeTitle = schema.get(type)?.title ?? type;
820
+ return S.listItem().title(listTitle).id(listId).icon(listIcon).child(Object.assign(S.documentTypeList(type).serialize(), {
821
+ // Prevents the component from re-rendering when switching documents
822
+ __preserveInstance: true,
823
+ // Prevents the component from NOT re-rendering when switching listItems
824
+ key: listId,
825
+ type: "component",
826
+ component: (0, $7faf82429f78b250$export$2e2bcd8739ae039),
827
+ options: {
828
+ type: type,
829
+ filter: filter,
830
+ params: params,
831
+ client: client
832
+ },
833
+ menuItems: [
834
+ S.menuItem().title(`Create new ${typeTitle}`).intent({
835
+ type: "create",
836
+ params: {
837
+ type: type
838
+ }
839
+ }).serialize(),
840
+ S.menuItem().title(`Reset Order`).icon((0, $3KLdq$sanityicons.GenerateIcon)).action(`resetOrder`).serialize(),
841
+ S.menuItem().title(`Show Increments`).icon((0, $3KLdq$sanityicons.SortIcon)).action(`showIncrements`).serialize(),
842
+ ]
843
+ })).serialize();
844
+ }
845
+
846
+
847
+
848
+
849
+ //# sourceMappingURL=index.js.map