@maas/payload-plugin-media-cloud 0.0.32 → 0.0.34
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/dist/collectionHooks/afterChange.mjs +1 -1
- package/dist/collectionHooks/afterChange.mjs.map +1 -1
- package/dist/components/folderFileCard/folderFileCard.mjs +61 -16
- package/dist/components/folderFileCard/folderFileCard.mjs.map +1 -1
- package/dist/components/gridContext/gridContext.mjs +30 -30
- package/dist/components/gridContext/gridContext.mjs.map +1 -1
- package/dist/components/gridView/gridView.mjs +250 -91
- package/dist/components/gridView/gridView.mjs.map +1 -1
- package/dist/components/itemCardGrid/itemCardGrid.mjs +30 -10
- package/dist/components/itemCardGrid/itemCardGrid.mjs.map +1 -1
- package/dist/components/muxPreview/muxPreview.mjs +46 -10
- package/dist/components/muxPreview/muxPreview.mjs.map +1 -1
- package/dist/components/uploadHandler/uploadHandler.mjs.map +1 -1
- package/dist/components/uploadManager/uploadManager.mjs +320 -230
- package/dist/components/uploadManager/uploadManager.mjs.map +1 -1
- package/dist/utils/mux.d.mts +3 -3
- package/dist/utils/tus.d.mts +3 -3
- package/package.json +3 -1
|
@@ -22,7 +22,7 @@ const afterChangeHook = async ({ collection, doc, previousDoc, req }) => {
|
|
|
22
22
|
const thumbnail = buildThumbnailURL({
|
|
23
23
|
storage: doc.storage,
|
|
24
24
|
playbackId: doc.storage === "mux" ? doc.id : void 0,
|
|
25
|
-
s3Key: doc.storage === "s3" ? doc.path : void 0,
|
|
25
|
+
s3Key: doc.storage === "s3" ? doc.path ?? doc.filename : void 0,
|
|
26
26
|
s3Store
|
|
27
27
|
});
|
|
28
28
|
req.payload.update({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"afterChange.mjs","names":["afterChangeHook: CollectionAfterChangeHook"],"sources":["../../src/collectionHooks/afterChange.ts"],"sourcesContent":["import { buildThumbnailURL } from '../utils/buildThumbnailURL'\nimport { s3Store } from '../plugin'\nimport { MediaCloudErrors } from '../types/errors'\nimport { useErrorHandler } from '../hooks/useErrorHandler'\n\nimport type { CollectionAfterChangeHook } from 'payload'\n\nexport const afterChangeHook: CollectionAfterChangeHook = async ({\n collection,\n doc,\n previousDoc,\n req,\n}) => {\n const { throwError } = useErrorHandler()\n\n // Move asset in S3 if path has changed\n if (doc.path !== previousDoc?.path) {\n if (doc.storage === 's3' && s3Store) {\n try {\n const oldKey = previousDoc?.path ?? previousDoc?.filename\n const newKey = doc.path\n\n await s3Store.copy(oldKey, newKey)\n } catch (error) {\n throwError({ ...MediaCloudErrors.S3_MOVE_ERROR, cause: error })\n }\n }\n }\n\n // Handle thumbnail\n if (!doc.thumbnail || previousDoc?.path !== doc.path) {\n const thumbnail = buildThumbnailURL({\n storage: doc.storage,\n playbackId: doc.storage === 'mux' ? doc.id : undefined,\n s3Key: doc.storage === 's3' ? doc.path : undefined,\n s3Store,\n })\n\n req.payload.update({\n collection: collection.slug,\n id: doc.id,\n data: { thumbnail },\n })\n }\n\n return doc\n}\n"],"mappings":";;;;;;AAOA,MAAaA,kBAA6C,OAAO,EAC/D,YACA,KACA,aACA,UACI;CACJ,MAAM,EAAE,eAAe,iBAAiB;AAGxC,KAAI,IAAI,SAAS,aAAa,MAC5B;MAAI,IAAI,YAAY,QAAQ,QAC1B,KAAI;GACF,MAAM,SAAS,aAAa,QAAQ,aAAa;GACjD,MAAM,SAAS,IAAI;AAEnB,SAAM,QAAQ,KAAK,QAAQ,OAAO;WAC3B,OAAO;AACd,cAAW;IAAE,GAAG,iBAAiB;IAAe,OAAO;IAAO,CAAC;;;AAMrE,KAAI,CAAC,IAAI,aAAa,aAAa,SAAS,IAAI,MAAM;EACpD,MAAM,YAAY,kBAAkB;GAClC,SAAS,IAAI;GACb,YAAY,IAAI,YAAY,QAAQ,IAAI,KAAK;GAC7C,OAAO,IAAI,YAAY,
|
|
1
|
+
{"version":3,"file":"afterChange.mjs","names":["afterChangeHook: CollectionAfterChangeHook"],"sources":["../../src/collectionHooks/afterChange.ts"],"sourcesContent":["import { buildThumbnailURL } from '../utils/buildThumbnailURL'\nimport { s3Store } from '../plugin'\nimport { MediaCloudErrors } from '../types/errors'\nimport { useErrorHandler } from '../hooks/useErrorHandler'\n\nimport type { CollectionAfterChangeHook } from 'payload'\n\nexport const afterChangeHook: CollectionAfterChangeHook = async ({\n collection,\n doc,\n previousDoc,\n req,\n}) => {\n const { throwError } = useErrorHandler()\n\n // Move asset in S3 if path has changed\n if (doc.path !== previousDoc?.path) {\n if (doc.storage === 's3' && s3Store) {\n try {\n const oldKey = previousDoc?.path ?? previousDoc?.filename\n const newKey = doc.path\n\n await s3Store.copy(oldKey, newKey)\n } catch (error) {\n throwError({ ...MediaCloudErrors.S3_MOVE_ERROR, cause: error })\n }\n }\n }\n\n // Handle thumbnail\n if (!doc.thumbnail || previousDoc?.path !== doc.path) {\n const thumbnail = buildThumbnailURL({\n storage: doc.storage,\n playbackId: doc.storage === 'mux' ? doc.id : undefined,\n s3Key: doc.storage === 's3' ? (doc.path ?? doc.filename) : undefined,\n s3Store,\n })\n\n req.payload.update({\n collection: collection.slug,\n id: doc.id,\n data: { thumbnail },\n })\n }\n\n return doc\n}\n"],"mappings":";;;;;;AAOA,MAAaA,kBAA6C,OAAO,EAC/D,YACA,KACA,aACA,UACI;CACJ,MAAM,EAAE,eAAe,iBAAiB;AAGxC,KAAI,IAAI,SAAS,aAAa,MAC5B;MAAI,IAAI,YAAY,QAAQ,QAC1B,KAAI;GACF,MAAM,SAAS,aAAa,QAAQ,aAAa;GACjD,MAAM,SAAS,IAAI;AAEnB,SAAM,QAAQ,KAAK,QAAQ,OAAO;WAC3B,OAAO;AACd,cAAW;IAAE,GAAG,iBAAiB;IAAe,OAAO;IAAO,CAAC;;;AAMrE,KAAI,CAAC,IAAI,aAAa,aAAa,SAAS,IAAI,MAAM;EACpD,MAAM,YAAY,kBAAkB;GAClC,SAAS,IAAI;GACb,YAAY,IAAI,YAAY,QAAQ,IAAI,KAAK;GAC7C,OAAO,IAAI,YAAY,OAAQ,IAAI,QAAQ,IAAI,WAAY;GAC3D;GACD,CAAC;AAEF,MAAI,QAAQ,OAAO;GACjB,YAAY,WAAW;GACvB,IAAI,IAAI;GACR,MAAM,EAAE,WAAW;GACpB,CAAC;;AAGJ,QAAO"}
|
|
@@ -1,28 +1,73 @@
|
|
|
1
1
|
import { useGrid } from "../gridContext/gridContext.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { c } from "react/compiler-runtime";
|
|
3
3
|
import { useSelection } from "@payloadcms/ui";
|
|
4
4
|
import { FolderFileCard } from "@payloadcms/ui/elements/FolderView/FolderFileCard";
|
|
5
5
|
|
|
6
6
|
//#region src/components/folderFileCard/folderFileCard.tsx
|
|
7
7
|
function ContextFolderFileCard(props) {
|
|
8
|
+
const $ = c(23);
|
|
8
9
|
const { className, index, item } = props;
|
|
9
10
|
const { focusedItemIndex, onItemClick, onItemKeyPress } = useGrid();
|
|
10
11
|
const { selectedIDs } = useSelection();
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
12
|
+
let t0;
|
|
13
|
+
if ($[0] !== item.id || $[1] !== selectedIDs) {
|
|
14
|
+
t0 = selectedIDs.includes(item.id);
|
|
15
|
+
$[0] = item.id;
|
|
16
|
+
$[1] = selectedIDs;
|
|
17
|
+
$[2] = t0;
|
|
18
|
+
} else t0 = $[2];
|
|
19
|
+
const isSelected = t0;
|
|
20
|
+
const isFocused = focusedItemIndex === index;
|
|
21
|
+
const t1 = item.id;
|
|
22
|
+
let t2;
|
|
23
|
+
if ($[3] !== item.id) {
|
|
24
|
+
t2 = item.id.toString();
|
|
25
|
+
$[3] = item.id;
|
|
26
|
+
$[4] = t2;
|
|
27
|
+
} else t2 = $[4];
|
|
28
|
+
let t3;
|
|
29
|
+
if ($[5] !== index || $[6] !== item || $[7] !== onItemClick) {
|
|
30
|
+
t3 = (event) => {
|
|
31
|
+
onItemClick({
|
|
32
|
+
event,
|
|
33
|
+
index,
|
|
34
|
+
item
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
$[5] = index;
|
|
38
|
+
$[6] = item;
|
|
39
|
+
$[7] = onItemClick;
|
|
40
|
+
$[8] = t3;
|
|
41
|
+
} else t3 = $[8];
|
|
42
|
+
let t4;
|
|
43
|
+
if ($[9] !== index || $[10] !== item || $[11] !== onItemKeyPress) {
|
|
44
|
+
t4 = (event_0) => {
|
|
45
|
+
onItemKeyPress({
|
|
46
|
+
event: event_0,
|
|
47
|
+
index,
|
|
48
|
+
item
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
$[9] = index;
|
|
52
|
+
$[10] = item;
|
|
53
|
+
$[11] = onItemKeyPress;
|
|
54
|
+
$[12] = t4;
|
|
55
|
+
} else t4 = $[12];
|
|
56
|
+
let t5;
|
|
57
|
+
if ($[13] !== className || $[14] !== isFocused || $[15] !== isSelected || $[16] !== item.id || $[17] !== item.thumbnailURL || $[18] !== item.title || $[19] !== t2 || $[20] !== t3 || $[21] !== t4) {
|
|
58
|
+
t5 = <FolderFileCard className={className} id={t1} isFocused={isFocused} isSelected={isSelected} itemKey={t2} previewUrl={item.thumbnailURL} title={item.title} type="file" onClick={t3} onKeyDown={t4} />;
|
|
59
|
+
$[13] = className;
|
|
60
|
+
$[14] = isFocused;
|
|
61
|
+
$[15] = isSelected;
|
|
62
|
+
$[16] = item.id;
|
|
63
|
+
$[17] = item.thumbnailURL;
|
|
64
|
+
$[18] = item.title;
|
|
65
|
+
$[19] = t2;
|
|
66
|
+
$[20] = t3;
|
|
67
|
+
$[21] = t4;
|
|
68
|
+
$[22] = t5;
|
|
69
|
+
} else t5 = $[22];
|
|
70
|
+
return t5;
|
|
26
71
|
}
|
|
27
72
|
|
|
28
73
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"folderFileCard.mjs","names":[],"sources":["../../../src/components/folderFileCard/folderFileCard.tsx"],"sourcesContent":["import { useMemo } from 'react'\nimport { FolderFileCard } from '@payloadcms/ui/elements/FolderView/FolderFileCard'\nimport { useSelection } from '@payloadcms/ui'\nimport { useGrid } from '../gridContext/gridContext'\n\nimport type { MappedDocument } from '../gridView/gridView'\n\ntype ContextCardProps = {\n readonly className?: string\n readonly index: number\n readonly item: MappedDocument\n}\n\nexport function ContextFolderFileCard(props: ContextCardProps) {\n const { className, index, item } = props\n\n const { focusedItemIndex, onItemClick, onItemKeyPress } = useGrid()\n const { selectedIDs } = useSelection()\n\n const isSelected = useMemo(\n () => selectedIDs.includes(item.id),\n [selectedIDs, item.id]\n )\n\n const isFocused = useMemo(\n () => focusedItemIndex === index,\n [focusedItemIndex, index]\n )\n\n return (\n <FolderFileCard\n className={className}\n id={item.id}\n isFocused={isFocused}\n isSelected={isSelected}\n itemKey={item.id.toString()}\n previewUrl={item.thumbnailURL}\n title={item.title}\n type={'file'}\n onClick={(event) => {\n void onItemClick({ event, index, item })\n }}\n onKeyDown={(event) => {\n void onItemKeyPress({ event, index, item })\n }}\n />\n )\n}\n"],"mappings":";;;;;;AAaA,
|
|
1
|
+
{"version":3,"file":"folderFileCard.mjs","names":["useMemo","FolderFileCard","useSelection","useGrid","MappedDocument","ContextCardProps","className","index","item","ContextFolderFileCard","props","$","_c","focusedItemIndex","onItemClick","onItemKeyPress","selectedIDs","t0","id","includes","isSelected","isFocused","t1","t2","toString","t3","event","t4","event_0","t5","thumbnailURL","title"],"sources":["../../../src/components/folderFileCard/folderFileCard.tsx"],"sourcesContent":["import { useMemo } from 'react'\nimport { FolderFileCard } from '@payloadcms/ui/elements/FolderView/FolderFileCard'\nimport { useSelection } from '@payloadcms/ui'\nimport { useGrid } from '../gridContext/gridContext'\n\nimport type { MappedDocument } from '../gridView/gridView'\n\ntype ContextCardProps = {\n readonly className?: string\n readonly index: number\n readonly item: MappedDocument\n}\n\nexport function ContextFolderFileCard(props: ContextCardProps) {\n const { className, index, item } = props\n\n const { focusedItemIndex, onItemClick, onItemKeyPress } = useGrid()\n const { selectedIDs } = useSelection()\n\n const isSelected = useMemo(\n () => selectedIDs.includes(item.id),\n [selectedIDs, item.id]\n )\n\n const isFocused = useMemo(\n () => focusedItemIndex === index,\n [focusedItemIndex, index]\n )\n\n return (\n <FolderFileCard\n className={className}\n id={item.id}\n isFocused={isFocused}\n isSelected={isSelected}\n itemKey={item.id.toString()}\n previewUrl={item.thumbnailURL}\n title={item.title}\n type={'file'}\n onClick={(event) => {\n void onItemClick({ event, index, item })\n }}\n onKeyDown={(event) => {\n void onItemKeyPress({ event, index, item })\n }}\n />\n )\n}\n"],"mappings":";;;;;;AAaA,SAAOS,sBAAAC,OAAA;CAAA,MAAAC,IAAAC,EAAA,GAAA;CACL,MAAA,EAAAN,WAAAC,OAAAC,SAAmCE;CAEnC,MAAA,EAAAG,kBAAAC,aAAAC,mBAA0DZ,SAAS;CACnE,MAAA,EAAAa,gBAAwBd,cAAc;CAAA,IAAAe;AAAA,KAAAN,EAAA,OAAAH,KAAAU,MAAAP,EAAA,OAAAK,aAAA;AAG9BC,OAAAD,YAAWG,SAAUX,KAAIU,GAAI;AAAAP,IAAA,KAAAH,KAAAU;AAAAP,IAAA,KAAAK;AAAAL,IAAA,KAAAM;OAAAA,MAAAN,EAAA;CADrC,MAAAS,aACQH;CAIR,MAAAI,YACQR,qBAAqBN;CAOrB,MAAAe,KAAAd,KAAIU;CAAG,IAAAK;AAAA,KAAAZ,EAAA,OAAAH,KAAAU,IAAA;AAGFK,OAAAf,KAAIU,GAAGM,UAAW;AAAAb,IAAA,KAAAH,KAAAU;AAAAP,IAAA,KAAAY;OAAAA,MAAAZ,EAAA;CAAA,IAAAc;AAAA,KAAAd,EAAA,OAAAJ,SAAAI,EAAA,OAAAH,QAAAG,EAAA,OAAAG,aAAA;AAIlBW,QAAAC,UAAA;AACFZ,eAAY;IAAAY;IAAAnB;IAAAC;IAAsB,CAAC;;AACzCG,IAAA,KAAAJ;AAAAI,IAAA,KAAAH;AAAAG,IAAA,KAAAG;AAAAH,IAAA,KAAAc;OAAAA,MAAAd,EAAA;CAAA,IAAAgB;AAAA,KAAAhB,EAAA,OAAAJ,SAAAI,EAAA,QAAAH,QAAAG,EAAA,QAAAI,gBAAA;AACUY,QAAAC,YAAA;AACJb,kBAAe;IAAAW,OAAEA;IAAKnB;IAAAC;IAAe,CAAC;;AAC5CG,IAAA,KAAAJ;AAAAI,IAAA,MAAAH;AAAAG,IAAA,MAAAI;AAAAJ,IAAA,MAAAgB;OAAAA,MAAAhB,EAAA;CAAA,IAAAkB;AAAA,KAAAlB,EAAA,QAAAL,aAAAK,EAAA,QAAAU,aAAAV,EAAA,QAAAS,cAAAT,EAAA,QAAAH,KAAAU,MAAAP,EAAA,QAAAH,KAAAsB,gBAAAnB,EAAA,QAAAH,KAAAuB,SAAApB,EAAA,QAAAY,MAAAZ,EAAA,QAAAc,MAAAd,EAAA,QAAAgB,IAAA;AAdHE,OAAA,CAAC,eACYvB,WAAAA,WACP,IAAAgB,IACOD,WAAAA,WACCD,YAAAA,YACH,SAAAG,IACG,YAAAf,KAAIsB,cACT,OAAAtB,KAAIuB,OACL,YACG,SAAAN,IAGE,WAAAE;AAGXhB,IAAA,MAAAL;AAAAK,IAAA,MAAAU;AAAAV,IAAA,MAAAS;AAAAT,IAAA,MAAAH,KAAAU;AAAAP,IAAA,MAAAH,KAAAsB;AAAAnB,IAAA,MAAAH,KAAAuB;AAAApB,IAAA,MAAAY;AAAAZ,IAAA,MAAAc;AAAAd,IAAA,MAAAgB;AAAAhB,IAAA,MAAAkB;OAAAA,MAAAlB,EAAA;AAAA,QAfFkB"}
|
|
@@ -74,16 +74,16 @@ function GridProvider(props) {
|
|
|
74
74
|
}
|
|
75
75
|
}, [docs, selectedIDs]);
|
|
76
76
|
const updateSelections = React.useCallback(({ indexes }) => {
|
|
77
|
-
const { newSelectedIDs } = docs.reduce((
|
|
78
|
-
if (indexes.includes(index))
|
|
79
|
-
return
|
|
77
|
+
const { newSelectedIDs } = docs.reduce((acc_0, item_0, index) => {
|
|
78
|
+
if (indexes.includes(index)) acc_0.newSelectedIDs.add(item_0.id);
|
|
79
|
+
return acc_0;
|
|
80
80
|
}, { newSelectedIDs: /* @__PURE__ */ new Set() });
|
|
81
|
-
selectedIDs.forEach((
|
|
82
|
-
setSelection(
|
|
81
|
+
selectedIDs.forEach((id_0) => {
|
|
82
|
+
setSelection(id_0);
|
|
83
83
|
});
|
|
84
|
-
newSelectedIDs.forEach((
|
|
85
|
-
const
|
|
86
|
-
if (
|
|
84
|
+
newSelectedIDs.forEach((id_1) => {
|
|
85
|
+
const item_1 = getItem(id_1);
|
|
86
|
+
if (item_1) setSelection(item_1.id);
|
|
87
87
|
});
|
|
88
88
|
}, [
|
|
89
89
|
docs,
|
|
@@ -95,7 +95,7 @@ function GridProvider(props) {
|
|
|
95
95
|
const isShiftPressed = shiftKey;
|
|
96
96
|
const isCtrlPressed = ctrlKey || metaKey;
|
|
97
97
|
const isCurrentlySelected = selectedIDs.includes(currentItem.id);
|
|
98
|
-
const currentItemIndex = docs.findIndex((
|
|
98
|
+
const currentItemIndex = docs.findIndex((item_2) => item_2.id === currentItem.id);
|
|
99
99
|
switch (code) {
|
|
100
100
|
case "ArrowDown":
|
|
101
101
|
case "ArrowLeft":
|
|
@@ -130,17 +130,17 @@ function GridProvider(props) {
|
|
|
130
130
|
if (allowMultiSelection && isCtrlPressed) {
|
|
131
131
|
event.preventDefault();
|
|
132
132
|
setFocusedItemIndex(totalCount - 1);
|
|
133
|
-
updateSelections({ indexes: Array.from({ length: totalCount }, (
|
|
133
|
+
updateSelections({ indexes: Array.from({ length: totalCount }, (__0, i_0) => i_0) });
|
|
134
134
|
}
|
|
135
135
|
break;
|
|
136
136
|
case "Space":
|
|
137
137
|
if (allowMultiSelection && isShiftPressed) {
|
|
138
138
|
event.preventDefault();
|
|
139
|
-
updateSelections({ indexes: docs.reduce((
|
|
140
|
-
if (
|
|
141
|
-
else
|
|
142
|
-
else if (selectedIDs.includes(
|
|
143
|
-
return
|
|
139
|
+
updateSelections({ indexes: docs.reduce((acc_1, item_3, idx_0) => {
|
|
140
|
+
if (item_3.id === currentItem.id) if (isCurrentlySelected) return acc_1;
|
|
141
|
+
else acc_1.push(idx_0);
|
|
142
|
+
else if (selectedIDs.includes(item_3.id)) acc_1.push(idx_0);
|
|
143
|
+
return acc_1;
|
|
144
144
|
}, []) });
|
|
145
145
|
} else {
|
|
146
146
|
event.preventDefault();
|
|
@@ -165,30 +165,30 @@ function GridProvider(props) {
|
|
|
165
165
|
totalCount
|
|
166
166
|
]);
|
|
167
167
|
const [lastClickedItem, setLastClickedItem] = React.useState();
|
|
168
|
-
const onItemClick = React.useCallback(({ event, item: clickedItem }) => {
|
|
168
|
+
const onItemClick = React.useCallback(({ event: event_0, item: clickedItem }) => {
|
|
169
169
|
let doubleClicked = false;
|
|
170
|
-
const
|
|
171
|
-
const
|
|
172
|
-
const
|
|
173
|
-
const
|
|
170
|
+
const isCtrlPressed_0 = event_0.ctrlKey || event_0.metaKey;
|
|
171
|
+
const isShiftPressed_0 = event_0.shiftKey;
|
|
172
|
+
const isCurrentlySelected_0 = selectedIDs.includes(clickedItem.id);
|
|
173
|
+
const currentItemIndex_0 = docs.findIndex((item_4) => item_4.id === clickedItem.id);
|
|
174
174
|
switch (true) {
|
|
175
|
-
case allowMultiSelection &&
|
|
176
|
-
|
|
177
|
-
updateSelections({ indexes: docs.reduce((
|
|
178
|
-
if (
|
|
179
|
-
if (!
|
|
180
|
-
} else if (selectedIDs.includes(
|
|
181
|
-
return
|
|
175
|
+
case allowMultiSelection && isCtrlPressed_0:
|
|
176
|
+
event_0.preventDefault();
|
|
177
|
+
updateSelections({ indexes: docs.reduce((acc_2, item_5, idx_1) => {
|
|
178
|
+
if (item_5.id === clickedItem.id) {
|
|
179
|
+
if (!isCurrentlySelected_0) acc_2.push(idx_1);
|
|
180
|
+
} else if (selectedIDs.includes(item_5.id)) acc_2.push(idx_1);
|
|
181
|
+
return acc_2;
|
|
182
182
|
}, []) });
|
|
183
183
|
break;
|
|
184
|
-
case allowMultiSelection &&
|
|
185
|
-
if (
|
|
184
|
+
case allowMultiSelection && isShiftPressed_0:
|
|
185
|
+
if (currentItemIndex_0 !== -1) updateSelections({ indexes: handleShiftSelection(currentItemIndex_0) });
|
|
186
186
|
break;
|
|
187
187
|
default: {
|
|
188
188
|
const now = Date.now();
|
|
189
189
|
doubleClicked = now - (lastClickTime.current ?? 0) < 400 && lastClickedItem?.id === clickedItem.id;
|
|
190
190
|
lastClickTime.current = now;
|
|
191
|
-
if (!doubleClicked) updateSelections({ indexes:
|
|
191
|
+
if (!doubleClicked) updateSelections({ indexes: isCurrentlySelected_0 && selectedIDs.length === 1 ? [] : [currentItemIndex_0] });
|
|
192
192
|
break;
|
|
193
193
|
}
|
|
194
194
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gridContext.mjs","names":["onItemKeyPress: GridContextValue['onItemKeyPress']","onItemClick: GridContextValue['onItemClick']","doubleClicked: boolean"],"sources":["../../../src/components/gridContext/gridContext.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { formatAdminURL } from 'payload/shared'\n\nimport { useDrawerDepth } from '@payloadcms/ui/elements/Drawer'\nimport { useConfig, useRouteTransition, useSelection } from '@payloadcms/ui'\n\nimport type { FolderSortKeys } from 'payload'\nimport type { MappedDocument } from '../gridView/gridView'\ninterface OnItemClickArgs {\n event: React.MouseEvent\n index: number\n item: MappedDocument\n}\n\ninterface OnItemKeyPressArgs {\n event: React.KeyboardEvent\n index: number\n item: MappedDocument\n}\n\nexport type GridContextValue = {\n docs?: MappedDocument[]\n clearSelections: () => void\n onItemClick: (args: OnItemClickArgs) => void\n onItemKeyPress: (args: OnItemKeyPressArgs) => void\n setFocusedItemIndex: React.Dispatch<React.SetStateAction<number>>\n focusedItemIndex: number\n}\n\nconst Context = React.createContext<GridContextValue>({\n docs: [],\n clearSelections: () => {},\n onItemClick: () => undefined,\n onItemKeyPress: () => undefined,\n setFocusedItemIndex: () => -1,\n focusedItemIndex: -1,\n})\n\nexport type GridProviderProps = {\n readonly allowMultiSelection?: boolean\n /**\n * Children to render inside the provider\n */\n readonly children: React.ReactNode\n /**\n * All documents in the current folder\n */\n readonly docs: MappedDocument[]\n /**\n * The intial search query\n */\n readonly search?: string\n /**\n * The sort order of the documents\n *\n * @example\n * `name` for descending\n * `-name` for ascending\n */\n readonly sort?: FolderSortKeys\n}\nexport function GridProvider(props: GridProviderProps) {\n const { allowMultiSelection = true, children, docs } = props\n\n const { config } = useConfig()\n const drawerDepth = useDrawerDepth()\n const router = useRouter()\n const { startRouteTransition } = useRouteTransition()\n\n const { setSelection, selectedIDs } = useSelection()\n const currentlySelectedIndexes = React.useRef(new Set<number>())\n\n const [focusedItemIndex, setFocusedItemIndex] = React.useState(-1)\n const lastClickTime = React.useRef<null | number>(null)\n const totalCount = docs.length\n\n const clearSelections = React.useCallback(() => {\n setFocusedItemIndex(-1)\n\n currentlySelectedIndexes.current = new Set()\n }, [])\n\n const getItem = React.useCallback(\n (id: string | number) => {\n return docs.find((doc) => doc.id === id)\n },\n [docs]\n )\n\n const navigateAfterSelection = React.useCallback(\n ({\n collectionSlug,\n docID,\n }: {\n collectionSlug: string\n docID?: number | string\n }) => {\n if (drawerDepth === 1) {\n // not in a drawer (default is 1)\n if (collectionSlug) {\n // clicked on document, take the user to the documet view\n startRouteTransition(() => {\n router.push(\n formatAdminURL({\n adminRoute: config.routes.admin,\n path: `/collections/${collectionSlug}/${docID}`,\n })\n )\n clearSelections()\n })\n }\n } else {\n clearSelections()\n }\n },\n [\n clearSelections,\n config.routes.admin,\n drawerDepth,\n getItem,\n router,\n startRouteTransition,\n ]\n )\n\n const handleShiftSelection = React.useCallback(\n (targetIndex: number) => {\n // Find existing selection boundaries\n const existingIndexes = docs.reduce((acc, item, idx) => {\n if (selectedIDs.includes(item.id)) {\n acc.push(idx)\n }\n return acc\n }, [] as number[])\n\n if (existingIndexes.length === 0) {\n // No existing selection, just select target\n return [targetIndex]\n }\n\n const firstSelectedIndex = Math.min(...existingIndexes)\n const lastSelectedIndex = Math.max(...existingIndexes)\n const isWithinBounds =\n targetIndex >= firstSelectedIndex && targetIndex <= lastSelectedIndex\n\n // Choose anchor based on whether we're contracting or extending\n let anchorIndex = targetIndex\n if (isWithinBounds) {\n // Contracting: if target is at a boundary, use target as anchor\n // Otherwise, use furthest boundary to maintain opposite edge\n if (\n targetIndex === firstSelectedIndex ||\n targetIndex === lastSelectedIndex\n ) {\n anchorIndex = targetIndex\n } else {\n const distanceToFirst = Math.abs(targetIndex - firstSelectedIndex)\n const distanceToLast = Math.abs(targetIndex - lastSelectedIndex)\n anchorIndex =\n distanceToFirst >= distanceToLast\n ? firstSelectedIndex\n : lastSelectedIndex\n }\n } else {\n // Extending: use closest boundary\n const distanceToFirst = Math.abs(targetIndex - firstSelectedIndex)\n const distanceToLast = Math.abs(targetIndex - lastSelectedIndex)\n anchorIndex =\n distanceToFirst <= distanceToLast\n ? firstSelectedIndex\n : lastSelectedIndex\n }\n\n // Create range from anchor to target\n const startIndex = Math.min(anchorIndex, targetIndex)\n const endIndex = Math.max(anchorIndex, targetIndex)\n const newRangeIndexes = Array.from(\n { length: endIndex - startIndex + 1 },\n (_, i) => startIndex + i\n )\n\n if (isWithinBounds) {\n // Contracting: replace with new range\n return newRangeIndexes\n } else {\n // Extending: union with existing\n const mappedSet = new Set([...existingIndexes, ...newRangeIndexes])\n return Array.from(mappedSet)\n }\n },\n [docs, selectedIDs]\n )\n\n const updateSelections = React.useCallback(\n ({ indexes }: { indexes: number[] }) => {\n const { newSelectedIDs } = docs.reduce(\n (acc, item, index) => {\n if (indexes.includes(index)) {\n acc.newSelectedIDs.add(item.id)\n }\n return acc\n },\n {\n newSelectedIDs: new Set<string | number>(),\n }\n )\n\n // Clear previous selection in global selection context\n selectedIDs.forEach((id) => {\n setSelection(id)\n })\n\n // Update selection in global selection context\n newSelectedIDs.forEach((id) => {\n const item = getItem(id)\n if (item) {\n setSelection(item.id)\n }\n })\n },\n [docs, getItem, setSelection]\n )\n\n const onItemKeyPress: GridContextValue['onItemKeyPress'] = React.useCallback(\n ({ event, item: currentItem }) => {\n const { code, ctrlKey, metaKey, shiftKey } = event\n\n const isShiftPressed = shiftKey\n const isCtrlPressed = ctrlKey || metaKey\n const isCurrentlySelected = selectedIDs.includes(currentItem.id)\n const currentItemIndex = docs.findIndex(\n (item) => item.id === currentItem.id\n )\n\n switch (code) {\n case 'ArrowDown':\n case 'ArrowLeft':\n case 'ArrowRight':\n case 'ArrowUp': {\n event.preventDefault()\n\n if (currentItemIndex === -1) {\n break\n }\n\n const isBackward = code === 'ArrowLeft' || code === 'ArrowUp'\n const newItemIndex = isBackward\n ? currentItemIndex - 1\n : currentItemIndex + 1\n\n if (newItemIndex < 0 || newItemIndex > totalCount - 1) {\n // out of bounds, keep current selection\n return\n }\n\n setFocusedItemIndex(newItemIndex)\n\n if (isCtrlPressed) {\n break\n }\n\n if (isShiftPressed && allowMultiSelection) {\n const selectedIndexes = handleShiftSelection(newItemIndex)\n updateSelections({ indexes: selectedIndexes })\n return\n }\n\n // Single selection without shift\n if (!isShiftPressed) {\n // const newItem = allItems[newItemIndex]\n updateSelections({ indexes: [newItemIndex] })\n }\n\n break\n }\n case 'Enter': {\n if (selectedIDs.length === 1) {\n // setFocusedItemIndex(undefined)\n navigateAfterSelection({\n collectionSlug: currentItem.relationTo,\n docID: currentItem.id,\n })\n return\n }\n break\n }\n case 'Escape': {\n clearSelections()\n break\n }\n case 'KeyA': {\n if (allowMultiSelection && isCtrlPressed) {\n event.preventDefault()\n setFocusedItemIndex(totalCount - 1)\n updateSelections({\n indexes: Array.from({ length: totalCount }, (_, i) => i),\n })\n }\n break\n }\n case 'Space': {\n if (allowMultiSelection && isShiftPressed) {\n event.preventDefault()\n updateSelections({\n indexes: docs.reduce((acc, item, idx) => {\n if (item.id === currentItem.id) {\n if (isCurrentlySelected) {\n return acc\n } else {\n acc.push(idx)\n }\n } else if (selectedIDs.includes(item.id)) {\n acc.push(idx)\n }\n return acc\n }, [] as number[]),\n })\n } else {\n event.preventDefault()\n updateSelections({\n indexes: isCurrentlySelected ? [] : [currentItemIndex],\n })\n }\n break\n }\n case 'Tab': {\n if (allowMultiSelection && isShiftPressed) {\n const prevIndex = currentItemIndex - 1\n if (prevIndex < 0 && selectedIDs.length > 0) {\n setFocusedItemIndex(prevIndex)\n }\n } else {\n const nextIndex = currentItemIndex + 1\n if (nextIndex === totalCount && selectedIDs.length > 0) {\n setFocusedItemIndex(totalCount - 1)\n }\n }\n break\n }\n }\n },\n [\n selectedIDs,\n docs,\n allowMultiSelection,\n handleShiftSelection,\n updateSelections,\n navigateAfterSelection,\n clearSelections,\n totalCount,\n ]\n )\n\n // Track last clicked item for double-click detection\n const [lastClickedItem, setLastClickedItem] = React.useState<\n MappedDocument | undefined\n >()\n\n const onItemClick: GridContextValue['onItemClick'] = React.useCallback(\n ({ event, item: clickedItem }) => {\n let doubleClicked: boolean = false\n const isCtrlPressed = event.ctrlKey || event.metaKey\n const isShiftPressed = event.shiftKey\n const isCurrentlySelected = selectedIDs.includes(clickedItem.id)\n const currentItemIndex = docs.findIndex(\n (item) => item.id === clickedItem.id\n )\n\n switch (true) {\n case allowMultiSelection && isCtrlPressed: {\n event.preventDefault()\n const indexes = docs.reduce((acc, item, idx) => {\n if (item.id === clickedItem.id) {\n if (!isCurrentlySelected) {\n acc.push(idx)\n }\n } else if (selectedIDs.includes(item.id)) {\n acc.push(idx)\n }\n return acc\n }, [] as number[])\n\n updateSelections({ indexes })\n break\n }\n case allowMultiSelection && isShiftPressed: {\n if (currentItemIndex !== -1) {\n const selectedIndexes = handleShiftSelection(currentItemIndex)\n updateSelections({ indexes: selectedIndexes })\n }\n break\n }\n default: {\n const now = Date.now()\n doubleClicked =\n now - (lastClickTime.current ?? 0) < 400 &&\n lastClickedItem?.id === clickedItem.id\n lastClickTime.current = now\n\n if (!doubleClicked) {\n updateSelections({\n indexes:\n isCurrentlySelected && selectedIDs.length === 1\n ? []\n : [currentItemIndex],\n })\n }\n break\n }\n }\n\n // Update last clicked item to determine double clicks\n setLastClickedItem(clickedItem)\n\n if (doubleClicked) {\n navigateAfterSelection({\n collectionSlug: clickedItem.relationTo,\n docID: clickedItem.id,\n })\n }\n },\n [\n docs,\n allowMultiSelection,\n getItem,\n updateSelections,\n navigateAfterSelection,\n handleShiftSelection,\n ]\n )\n\n return (\n <Context\n value={{\n clearSelections,\n docs,\n focusedItemIndex,\n onItemClick,\n onItemKeyPress,\n setFocusedItemIndex,\n }}\n >\n {children}\n </Context>\n )\n}\n\nexport function useGrid(): GridContextValue {\n const context = React.use(Context)\n\n if (context === undefined) {\n throw new Error('useGrid must be used within a GridProvider')\n }\n\n return context\n}\n"],"mappings":";;;;;;;;;AAgCA,MAAM,UAAU,MAAM,cAAgC;CACpD,MAAM,EAAE;CACR,uBAAuB;CACvB,mBAAmB;CACnB,sBAAsB;CACtB,2BAA2B;CAC3B,kBAAkB;CACnB,CAAC;AAyBF,SAAgB,aAAa,OAA0B;CACrD,MAAM,EAAE,sBAAsB,MAAM,UAAU,SAAS;CAEvD,MAAM,EAAE,WAAW,WAAW;CAC9B,MAAM,cAAc,gBAAgB;CACpC,MAAM,SAAS,WAAW;CAC1B,MAAM,EAAE,yBAAyB,oBAAoB;CAErD,MAAM,EAAE,cAAc,gBAAgB,cAAc;CACpD,MAAM,2BAA2B,MAAM,uBAAO,IAAI,KAAa,CAAC;CAEhE,MAAM,CAAC,kBAAkB,uBAAuB,MAAM,SAAS,GAAG;CAClE,MAAM,gBAAgB,MAAM,OAAsB,KAAK;CACvD,MAAM,aAAa,KAAK;CAExB,MAAM,kBAAkB,MAAM,kBAAkB;AAC9C,sBAAoB,GAAG;AAEvB,2BAAyB,0BAAU,IAAI,KAAK;IAC3C,EAAE,CAAC;CAEN,MAAM,UAAU,MAAM,aACnB,OAAwB;AACvB,SAAO,KAAK,MAAM,QAAQ,IAAI,OAAO,GAAG;IAE1C,CAAC,KAAK,CACP;CAED,MAAM,yBAAyB,MAAM,aAClC,EACC,gBACA,YAII;AACJ,MAAI,gBAAgB,GAElB;OAAI,eAEF,4BAA2B;AACzB,WAAO,KACL,eAAe;KACb,YAAY,OAAO,OAAO;KAC1B,MAAM,gBAAgB,eAAe,GAAG;KACzC,CAAC,CACH;AACD,qBAAiB;KACjB;QAGJ,kBAAiB;IAGrB;EACE;EACA,OAAO,OAAO;EACd;EACA;EACA;EACA;EACD,CACF;CAED,MAAM,uBAAuB,MAAM,aAChC,gBAAwB;EAEvB,MAAM,kBAAkB,KAAK,QAAQ,KAAK,MAAM,QAAQ;AACtD,OAAI,YAAY,SAAS,KAAK,GAAG,CAC/B,KAAI,KAAK,IAAI;AAEf,UAAO;KACN,EAAE,CAAa;AAElB,MAAI,gBAAgB,WAAW,EAE7B,QAAO,CAAC,YAAY;EAGtB,MAAM,qBAAqB,KAAK,IAAI,GAAG,gBAAgB;EACvD,MAAM,oBAAoB,KAAK,IAAI,GAAG,gBAAgB;EACtD,MAAM,iBACJ,eAAe,sBAAsB,eAAe;EAGtD,IAAI,cAAc;AAClB,MAAI,eAGF,KACE,gBAAgB,sBAChB,gBAAgB,kBAEhB,eAAc;MAId,eAFwB,KAAK,IAAI,cAAc,mBAAmB,IAC3C,KAAK,IAAI,cAAc,kBAAkB,GAG1D,qBACA;MAMR,eAFwB,KAAK,IAAI,cAAc,mBAAmB,IAC3C,KAAK,IAAI,cAAc,kBAAkB,GAG1D,qBACA;EAIR,MAAM,aAAa,KAAK,IAAI,aAAa,YAAY;EACrD,MAAM,WAAW,KAAK,IAAI,aAAa,YAAY;EACnD,MAAM,kBAAkB,MAAM,KAC5B,EAAE,QAAQ,WAAW,aAAa,GAAG,GACpC,GAAG,MAAM,aAAa,EACxB;AAED,MAAI,eAEF,QAAO;OACF;GAEL,MAAM,YAAY,IAAI,IAAI,CAAC,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AACnE,UAAO,MAAM,KAAK,UAAU;;IAGhC,CAAC,MAAM,YAAY,CACpB;CAED,MAAM,mBAAmB,MAAM,aAC5B,EAAE,cAAqC;EACtC,MAAM,EAAE,mBAAmB,KAAK,QAC7B,KAAK,MAAM,UAAU;AACpB,OAAI,QAAQ,SAAS,MAAM,CACzB,KAAI,eAAe,IAAI,KAAK,GAAG;AAEjC,UAAO;KAET,EACE,gCAAgB,IAAI,KAAsB,EAC3C,CACF;AAGD,cAAY,SAAS,OAAO;AAC1B,gBAAa,GAAG;IAChB;AAGF,iBAAe,SAAS,OAAO;GAC7B,MAAM,OAAO,QAAQ,GAAG;AACxB,OAAI,KACF,cAAa,KAAK,GAAG;IAEvB;IAEJ;EAAC;EAAM;EAAS;EAAa,CAC9B;CAED,MAAMA,iBAAqD,MAAM,aAC9D,EAAE,OAAO,MAAM,kBAAkB;EAChC,MAAM,EAAE,MAAM,SAAS,SAAS,aAAa;EAE7C,MAAM,iBAAiB;EACvB,MAAM,gBAAgB,WAAW;EACjC,MAAM,sBAAsB,YAAY,SAAS,YAAY,GAAG;EAChE,MAAM,mBAAmB,KAAK,WAC3B,SAAS,KAAK,OAAO,YAAY,GACnC;AAED,UAAQ,MAAR;GACE,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK,WAAW;AACd,UAAM,gBAAgB;AAEtB,QAAI,qBAAqB,GACvB;IAIF,MAAM,eADa,SAAS,eAAe,SAAS,YAEhD,mBAAmB,IACnB,mBAAmB;AAEvB,QAAI,eAAe,KAAK,eAAe,aAAa,EAElD;AAGF,wBAAoB,aAAa;AAEjC,QAAI,cACF;AAGF,QAAI,kBAAkB,qBAAqB;AAEzC,sBAAiB,EAAE,SADK,qBAAqB,aAAa,EACb,CAAC;AAC9C;;AAIF,QAAI,CAAC,eAEH,kBAAiB,EAAE,SAAS,CAAC,aAAa,EAAE,CAAC;AAG/C;;GAEF,KAAK;AACH,QAAI,YAAY,WAAW,GAAG;AAE5B,4BAAuB;MACrB,gBAAgB,YAAY;MAC5B,OAAO,YAAY;MACpB,CAAC;AACF;;AAEF;GAEF,KAAK;AACH,qBAAiB;AACjB;GAEF,KAAK;AACH,QAAI,uBAAuB,eAAe;AACxC,WAAM,gBAAgB;AACtB,yBAAoB,aAAa,EAAE;AACnC,sBAAiB,EACf,SAAS,MAAM,KAAK,EAAE,QAAQ,YAAY,GAAG,GAAG,MAAM,EAAE,EACzD,CAAC;;AAEJ;GAEF,KAAK;AACH,QAAI,uBAAuB,gBAAgB;AACzC,WAAM,gBAAgB;AACtB,sBAAiB,EACf,SAAS,KAAK,QAAQ,KAAK,MAAM,QAAQ;AACvC,UAAI,KAAK,OAAO,YAAY,GAC1B,KAAI,oBACF,QAAO;UAEP,KAAI,KAAK,IAAI;eAEN,YAAY,SAAS,KAAK,GAAG,CACtC,KAAI,KAAK,IAAI;AAEf,aAAO;QACN,EAAE,CAAa,EACnB,CAAC;WACG;AACL,WAAM,gBAAgB;AACtB,sBAAiB,EACf,SAAS,sBAAsB,EAAE,GAAG,CAAC,iBAAiB,EACvD,CAAC;;AAEJ;GAEF,KAAK;AACH,QAAI,uBAAuB,gBAAgB;KACzC,MAAM,YAAY,mBAAmB;AACrC,SAAI,YAAY,KAAK,YAAY,SAAS,EACxC,qBAAoB,UAAU;eAGd,mBAAmB,MACnB,cAAc,YAAY,SAAS,EACnD,qBAAoB,aAAa,EAAE;AAGvC;;IAIN;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF;CAGD,MAAM,CAAC,iBAAiB,sBAAsB,MAAM,UAEjD;CAEH,MAAMC,cAA+C,MAAM,aACxD,EAAE,OAAO,MAAM,kBAAkB;EAChC,IAAIC,gBAAyB;EAC7B,MAAM,gBAAgB,MAAM,WAAW,MAAM;EAC7C,MAAM,iBAAiB,MAAM;EAC7B,MAAM,sBAAsB,YAAY,SAAS,YAAY,GAAG;EAChE,MAAM,mBAAmB,KAAK,WAC3B,SAAS,KAAK,OAAO,YAAY,GACnC;AAED,UAAQ,MAAR;GACE,KAAK,uBAAuB;AAC1B,UAAM,gBAAgB;AAYtB,qBAAiB,EAAE,SAXH,KAAK,QAAQ,KAAK,MAAM,QAAQ;AAC9C,SAAI,KAAK,OAAO,YAAY,IAC1B;UAAI,CAAC,oBACH,KAAI,KAAK,IAAI;gBAEN,YAAY,SAAS,KAAK,GAAG,CACtC,KAAI,KAAK,IAAI;AAEf,YAAO;OACN,EAAE,CAAa,EAEU,CAAC;AAC7B;GAEF,KAAK,uBAAuB;AAC1B,QAAI,qBAAqB,GAEvB,kBAAiB,EAAE,SADK,qBAAqB,iBAAiB,EACjB,CAAC;AAEhD;GAEF,SAAS;IACP,MAAM,MAAM,KAAK,KAAK;AACtB,oBACE,OAAO,cAAc,WAAW,KAAK,OACrC,iBAAiB,OAAO,YAAY;AACtC,kBAAc,UAAU;AAExB,QAAI,CAAC,cACH,kBAAiB,EACf,SACE,uBAAuB,YAAY,WAAW,IAC1C,EAAE,GACF,CAAC,iBAAiB,EACzB,CAAC;AAEJ;;;AAKJ,qBAAmB,YAAY;AAE/B,MAAI,cACF,wBAAuB;GACrB,gBAAgB,YAAY;GAC5B,OAAO,YAAY;GACpB,CAAC;IAGN;EACE;EACA;EACA;EACA;EACA;EACA;EACD,CACF;AAED,QACE,CAAC,QACC,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACD,EACF;OACE,SAAS;IACZ,EAAE;;AAIN,SAAgB,UAA4B;CAC1C,MAAM,UAAU,MAAM,IAAI,QAAQ;AAElC,KAAI,YAAY,OACd,OAAM,IAAI,MAAM,6CAA6C;AAG/D,QAAO"}
|
|
1
|
+
{"version":3,"file":"gridContext.mjs","names":["React","useRouter","formatAdminURL","useDrawerDepth","useConfig","useRouteTransition","useSelection","FolderSortKeys","MappedDocument","OnItemClickArgs","event","MouseEvent","index","item","OnItemKeyPressArgs","KeyboardEvent","GridContextValue","docs","clearSelections","onItemClick","args","onItemKeyPress","setFocusedItemIndex","Dispatch","SetStateAction","focusedItemIndex","Context","createContext","undefined","GridProviderProps","allowMultiSelection","children","ReactNode","search","sort","GridProvider","props","config","drawerDepth","router","startRouteTransition","setSelection","selectedIDs","currentlySelectedIndexes","useRef","Set","useState","lastClickTime","totalCount","length","useCallback","current","getItem","id","find","doc","navigateAfterSelection","collectionSlug","docID","push","adminRoute","routes","admin","path","handleShiftSelection","targetIndex","existingIndexes","reduce","acc","idx","includes","firstSelectedIndex","Math","min","lastSelectedIndex","max","isWithinBounds","anchorIndex","distanceToFirst","abs","distanceToLast","startIndex","endIndex","newRangeIndexes","Array","from","_","i","mappedSet","updateSelections","indexes","newSelectedIDs","add","forEach","currentItem","code","ctrlKey","metaKey","shiftKey","isShiftPressed","isCtrlPressed","isCurrentlySelected","currentItemIndex","findIndex","preventDefault","isBackward","newItemIndex","selectedIndexes","relationTo","prevIndex","nextIndex","lastClickedItem","setLastClickedItem","clickedItem","doubleClicked","now","Date","useGrid","context","use","Error"],"sources":["../../../src/components/gridContext/gridContext.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { formatAdminURL } from 'payload/shared'\n\nimport { useDrawerDepth } from '@payloadcms/ui/elements/Drawer'\nimport { useConfig, useRouteTransition, useSelection } from '@payloadcms/ui'\n\nimport type { FolderSortKeys } from 'payload'\nimport type { MappedDocument } from '../gridView/gridView'\ninterface OnItemClickArgs {\n event: React.MouseEvent\n index: number\n item: MappedDocument\n}\n\ninterface OnItemKeyPressArgs {\n event: React.KeyboardEvent\n index: number\n item: MappedDocument\n}\n\nexport type GridContextValue = {\n docs?: MappedDocument[]\n clearSelections: () => void\n onItemClick: (args: OnItemClickArgs) => void\n onItemKeyPress: (args: OnItemKeyPressArgs) => void\n setFocusedItemIndex: React.Dispatch<React.SetStateAction<number>>\n focusedItemIndex: number\n}\n\nconst Context = React.createContext<GridContextValue>({\n docs: [],\n clearSelections: () => {},\n onItemClick: () => undefined,\n onItemKeyPress: () => undefined,\n setFocusedItemIndex: () => -1,\n focusedItemIndex: -1,\n})\n\nexport type GridProviderProps = {\n readonly allowMultiSelection?: boolean\n /**\n * Children to render inside the provider\n */\n readonly children: React.ReactNode\n /**\n * All documents in the current folder\n */\n readonly docs: MappedDocument[]\n /**\n * The intial search query\n */\n readonly search?: string\n /**\n * The sort order of the documents\n *\n * @example\n * `name` for descending\n * `-name` for ascending\n */\n readonly sort?: FolderSortKeys\n}\nexport function GridProvider(props: GridProviderProps) {\n const { allowMultiSelection = true, children, docs } = props\n\n const { config } = useConfig()\n const drawerDepth = useDrawerDepth()\n const router = useRouter()\n const { startRouteTransition } = useRouteTransition()\n\n const { setSelection, selectedIDs } = useSelection()\n const currentlySelectedIndexes = React.useRef(new Set<number>())\n\n const [focusedItemIndex, setFocusedItemIndex] = React.useState(-1)\n const lastClickTime = React.useRef<null | number>(null)\n const totalCount = docs.length\n\n const clearSelections = React.useCallback(() => {\n setFocusedItemIndex(-1)\n\n currentlySelectedIndexes.current = new Set()\n }, [])\n\n const getItem = React.useCallback(\n (id: string | number) => {\n return docs.find((doc) => doc.id === id)\n },\n [docs]\n )\n\n const navigateAfterSelection = React.useCallback(\n ({\n collectionSlug,\n docID,\n }: {\n collectionSlug: string\n docID?: number | string\n }) => {\n if (drawerDepth === 1) {\n // not in a drawer (default is 1)\n if (collectionSlug) {\n // clicked on document, take the user to the documet view\n startRouteTransition(() => {\n router.push(\n formatAdminURL({\n adminRoute: config.routes.admin,\n path: `/collections/${collectionSlug}/${docID}`,\n })\n )\n clearSelections()\n })\n }\n } else {\n clearSelections()\n }\n },\n [\n clearSelections,\n config.routes.admin,\n drawerDepth,\n getItem,\n router,\n startRouteTransition,\n ]\n )\n\n const handleShiftSelection = React.useCallback(\n (targetIndex: number) => {\n // Find existing selection boundaries\n const existingIndexes = docs.reduce((acc, item, idx) => {\n if (selectedIDs.includes(item.id)) {\n acc.push(idx)\n }\n return acc\n }, [] as number[])\n\n if (existingIndexes.length === 0) {\n // No existing selection, just select target\n return [targetIndex]\n }\n\n const firstSelectedIndex = Math.min(...existingIndexes)\n const lastSelectedIndex = Math.max(...existingIndexes)\n const isWithinBounds =\n targetIndex >= firstSelectedIndex && targetIndex <= lastSelectedIndex\n\n // Choose anchor based on whether we're contracting or extending\n let anchorIndex = targetIndex\n if (isWithinBounds) {\n // Contracting: if target is at a boundary, use target as anchor\n // Otherwise, use furthest boundary to maintain opposite edge\n if (\n targetIndex === firstSelectedIndex ||\n targetIndex === lastSelectedIndex\n ) {\n anchorIndex = targetIndex\n } else {\n const distanceToFirst = Math.abs(targetIndex - firstSelectedIndex)\n const distanceToLast = Math.abs(targetIndex - lastSelectedIndex)\n anchorIndex =\n distanceToFirst >= distanceToLast\n ? firstSelectedIndex\n : lastSelectedIndex\n }\n } else {\n // Extending: use closest boundary\n const distanceToFirst = Math.abs(targetIndex - firstSelectedIndex)\n const distanceToLast = Math.abs(targetIndex - lastSelectedIndex)\n anchorIndex =\n distanceToFirst <= distanceToLast\n ? firstSelectedIndex\n : lastSelectedIndex\n }\n\n // Create range from anchor to target\n const startIndex = Math.min(anchorIndex, targetIndex)\n const endIndex = Math.max(anchorIndex, targetIndex)\n const newRangeIndexes = Array.from(\n { length: endIndex - startIndex + 1 },\n (_, i) => startIndex + i\n )\n\n if (isWithinBounds) {\n // Contracting: replace with new range\n return newRangeIndexes\n } else {\n // Extending: union with existing\n const mappedSet = new Set([...existingIndexes, ...newRangeIndexes])\n return Array.from(mappedSet)\n }\n },\n [docs, selectedIDs]\n )\n\n const updateSelections = React.useCallback(\n ({ indexes }: { indexes: number[] }) => {\n const { newSelectedIDs } = docs.reduce(\n (acc, item, index) => {\n if (indexes.includes(index)) {\n acc.newSelectedIDs.add(item.id)\n }\n return acc\n },\n {\n newSelectedIDs: new Set<string | number>(),\n }\n )\n\n // Clear previous selection in global selection context\n selectedIDs.forEach((id) => {\n setSelection(id)\n })\n\n // Update selection in global selection context\n newSelectedIDs.forEach((id) => {\n const item = getItem(id)\n if (item) {\n setSelection(item.id)\n }\n })\n },\n [docs, getItem, setSelection]\n )\n\n const onItemKeyPress: GridContextValue['onItemKeyPress'] = React.useCallback(\n ({ event, item: currentItem }) => {\n const { code, ctrlKey, metaKey, shiftKey } = event\n\n const isShiftPressed = shiftKey\n const isCtrlPressed = ctrlKey || metaKey\n const isCurrentlySelected = selectedIDs.includes(currentItem.id)\n const currentItemIndex = docs.findIndex(\n (item) => item.id === currentItem.id\n )\n\n switch (code) {\n case 'ArrowDown':\n case 'ArrowLeft':\n case 'ArrowRight':\n case 'ArrowUp': {\n event.preventDefault()\n\n if (currentItemIndex === -1) {\n break\n }\n\n const isBackward = code === 'ArrowLeft' || code === 'ArrowUp'\n const newItemIndex = isBackward\n ? currentItemIndex - 1\n : currentItemIndex + 1\n\n if (newItemIndex < 0 || newItemIndex > totalCount - 1) {\n // out of bounds, keep current selection\n return\n }\n\n setFocusedItemIndex(newItemIndex)\n\n if (isCtrlPressed) {\n break\n }\n\n if (isShiftPressed && allowMultiSelection) {\n const selectedIndexes = handleShiftSelection(newItemIndex)\n updateSelections({ indexes: selectedIndexes })\n return\n }\n\n // Single selection without shift\n if (!isShiftPressed) {\n // const newItem = allItems[newItemIndex]\n updateSelections({ indexes: [newItemIndex] })\n }\n\n break\n }\n case 'Enter': {\n if (selectedIDs.length === 1) {\n // setFocusedItemIndex(undefined)\n navigateAfterSelection({\n collectionSlug: currentItem.relationTo,\n docID: currentItem.id,\n })\n return\n }\n break\n }\n case 'Escape': {\n clearSelections()\n break\n }\n case 'KeyA': {\n if (allowMultiSelection && isCtrlPressed) {\n event.preventDefault()\n setFocusedItemIndex(totalCount - 1)\n updateSelections({\n indexes: Array.from({ length: totalCount }, (_, i) => i),\n })\n }\n break\n }\n case 'Space': {\n if (allowMultiSelection && isShiftPressed) {\n event.preventDefault()\n updateSelections({\n indexes: docs.reduce((acc, item, idx) => {\n if (item.id === currentItem.id) {\n if (isCurrentlySelected) {\n return acc\n } else {\n acc.push(idx)\n }\n } else if (selectedIDs.includes(item.id)) {\n acc.push(idx)\n }\n return acc\n }, [] as number[]),\n })\n } else {\n event.preventDefault()\n updateSelections({\n indexes: isCurrentlySelected ? [] : [currentItemIndex],\n })\n }\n break\n }\n case 'Tab': {\n if (allowMultiSelection && isShiftPressed) {\n const prevIndex = currentItemIndex - 1\n if (prevIndex < 0 && selectedIDs.length > 0) {\n setFocusedItemIndex(prevIndex)\n }\n } else {\n const nextIndex = currentItemIndex + 1\n if (nextIndex === totalCount && selectedIDs.length > 0) {\n setFocusedItemIndex(totalCount - 1)\n }\n }\n break\n }\n }\n },\n [\n selectedIDs,\n docs,\n allowMultiSelection,\n handleShiftSelection,\n updateSelections,\n navigateAfterSelection,\n clearSelections,\n totalCount,\n ]\n )\n\n // Track last clicked item for double-click detection\n const [lastClickedItem, setLastClickedItem] = React.useState<\n MappedDocument | undefined\n >()\n\n const onItemClick: GridContextValue['onItemClick'] = React.useCallback(\n ({ event, item: clickedItem }) => {\n let doubleClicked: boolean = false\n const isCtrlPressed = event.ctrlKey || event.metaKey\n const isShiftPressed = event.shiftKey\n const isCurrentlySelected = selectedIDs.includes(clickedItem.id)\n const currentItemIndex = docs.findIndex(\n (item) => item.id === clickedItem.id\n )\n\n switch (true) {\n case allowMultiSelection && isCtrlPressed: {\n event.preventDefault()\n const indexes = docs.reduce((acc, item, idx) => {\n if (item.id === clickedItem.id) {\n if (!isCurrentlySelected) {\n acc.push(idx)\n }\n } else if (selectedIDs.includes(item.id)) {\n acc.push(idx)\n }\n return acc\n }, [] as number[])\n\n updateSelections({ indexes })\n break\n }\n case allowMultiSelection && isShiftPressed: {\n if (currentItemIndex !== -1) {\n const selectedIndexes = handleShiftSelection(currentItemIndex)\n updateSelections({ indexes: selectedIndexes })\n }\n break\n }\n default: {\n const now = Date.now()\n doubleClicked =\n now - (lastClickTime.current ?? 0) < 400 &&\n lastClickedItem?.id === clickedItem.id\n lastClickTime.current = now\n\n if (!doubleClicked) {\n updateSelections({\n indexes:\n isCurrentlySelected && selectedIDs.length === 1\n ? []\n : [currentItemIndex],\n })\n }\n break\n }\n }\n\n // Update last clicked item to determine double clicks\n setLastClickedItem(clickedItem)\n\n if (doubleClicked) {\n navigateAfterSelection({\n collectionSlug: clickedItem.relationTo,\n docID: clickedItem.id,\n })\n }\n },\n [\n docs,\n allowMultiSelection,\n getItem,\n updateSelections,\n navigateAfterSelection,\n handleShiftSelection,\n ]\n )\n\n return (\n <Context\n value={{\n clearSelections,\n docs,\n focusedItemIndex,\n onItemClick,\n onItemKeyPress,\n setFocusedItemIndex,\n }}\n >\n {children}\n </Context>\n )\n}\n\nexport function useGrid(): GridContextValue {\n const context = React.use(Context)\n\n if (context === undefined) {\n throw new Error('useGrid must be used within a GridProvider')\n }\n\n return context\n}\n"],"mappings":"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"}
|