@payloadcms/ui 3.68.0-internal-debug.2eb12b9 → 3.68.0-internal-debug.185cc5f
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/elements/AnimateHeight/usePatchAnimateHeight.js +2 -2
- package/dist/elements/AnimateHeight/usePatchAnimateHeight.js.map +1 -1
- package/dist/elements/Autosave/index.js +1 -0
- package/dist/elements/Autosave/index.js.map +1 -1
- package/dist/elements/BulkUpload/EditMany/index.js +2 -2
- package/dist/elements/BulkUpload/EditMany/index.js.map +1 -1
- package/dist/elements/BulkUpload/FormsManager/index.js +8 -8
- package/dist/elements/BulkUpload/FormsManager/index.js.map +1 -1
- package/dist/elements/BulkUpload/index.js +12 -1
- package/dist/elements/BulkUpload/index.js.map +1 -1
- package/dist/elements/Button/index.js +2 -2
- package/dist/elements/Button/index.js.map +1 -1
- package/dist/elements/Button/types.js +13 -1
- package/dist/elements/Button/types.js.map +1 -1
- package/dist/elements/Card/index.js +5 -1
- package/dist/elements/Card/index.js.map +1 -1
- package/dist/elements/CodeEditor/CodeEditor.js +2 -2
- package/dist/elements/CodeEditor/CodeEditor.js.map +1 -1
- package/dist/elements/CodeEditor/types.js +3 -1
- package/dist/elements/CodeEditor/types.js.map +1 -1
- package/dist/elements/Collapsible/index.js +8 -1
- package/dist/elements/Collapsible/index.js.map +1 -1
- package/dist/elements/Combobox/index.js +6 -0
- package/dist/elements/Combobox/index.js.map +1 -1
- package/dist/elements/DatePicker/DatePicker.js +1 -0
- package/dist/elements/DatePicker/DatePicker.js.map +1 -1
- package/dist/elements/DatePicker/getFormattedLocale.js +1 -0
- package/dist/elements/DatePicker/getFormattedLocale.js.map +1 -1
- package/dist/elements/DeleteMany/index.js +25 -1
- package/dist/elements/DeleteMany/index.js.map +1 -1
- package/dist/elements/DocumentControls/index.js +1 -1
- package/dist/elements/DocumentControls/index.js.map +1 -1
- package/dist/elements/DocumentDrawer/Provider.js +5 -1
- package/dist/elements/DocumentDrawer/Provider.js.map +1 -1
- package/dist/elements/DocumentDrawer/types.js +11 -1
- package/dist/elements/DocumentDrawer/types.js.map +1 -1
- package/dist/elements/DraggableSortable/useDraggableSortable/index.js +1 -0
- package/dist/elements/DraggableSortable/useDraggableSortable/index.js.map +1 -1
- package/dist/elements/Drawer/index.js +3 -1
- package/dist/elements/Drawer/index.js.map +1 -1
- package/dist/elements/EditMany/DrawerContent.js +15 -1
- package/dist/elements/EditMany/DrawerContent.js.map +1 -1
- package/dist/elements/EditMany/index.js +3 -1
- package/dist/elements/EditMany/index.js.map +1 -1
- package/dist/elements/FolderView/Drawers/MoveToFolder/index.js +8 -1
- package/dist/elements/FolderView/Drawers/MoveToFolder/index.js.map +1 -1
- package/dist/elements/FolderView/FolderFileCard/index.js +1 -0
- package/dist/elements/FolderView/FolderFileCard/index.js.map +1 -1
- package/dist/elements/FolderView/MoveDocToFolder/index.js +2 -3
- package/dist/elements/FolderView/MoveDocToFolder/index.js.map +1 -1
- package/dist/elements/HTMLDiff/diff/index.js +24 -3
- package/dist/elements/HTMLDiff/diff/index.js.map +1 -1
- package/dist/elements/HydrateAuthProvider/index.js +6 -1
- package/dist/elements/HydrateAuthProvider/index.js.map +1 -1
- package/dist/elements/LeaveWithoutSaving/usePreventLeave.js +3 -1
- package/dist/elements/LeaveWithoutSaving/usePreventLeave.js.map +1 -1
- package/dist/elements/Link/index.js +5 -1
- package/dist/elements/Link/index.js.map +1 -1
- package/dist/elements/ListControls/types.js +7 -1
- package/dist/elements/ListControls/types.js.map +1 -1
- package/dist/elements/ListDrawer/DrawerContent.js +2 -2
- package/dist/elements/ListDrawer/DrawerContent.js.map +1 -1
- package/dist/elements/ListDrawer/Provider.js +8 -1
- package/dist/elements/ListDrawer/Provider.js.map +1 -1
- package/dist/elements/ListDrawer/index.js +2 -1
- package/dist/elements/ListDrawer/index.js.map +1 -1
- package/dist/elements/ListDrawer/types.js +5 -1
- package/dist/elements/ListDrawer/types.js.map +1 -1
- package/dist/elements/ListHeader/TitleActions/ListBulkUploadButton.js +5 -1
- package/dist/elements/ListHeader/TitleActions/ListBulkUploadButton.js.map +1 -1
- package/dist/elements/ListSelection/index.js +11 -1
- package/dist/elements/ListSelection/index.js.map +1 -1
- package/dist/elements/LivePreview/Toolbar/Controls/index.js +1 -1
- package/dist/elements/LivePreview/Toolbar/Controls/index.js.map +1 -1
- package/dist/elements/Logout/index.js +5 -1
- package/dist/elements/Logout/index.js.map +1 -1
- package/dist/elements/Pill/index.js +5 -2
- package/dist/elements/Pill/index.js.map +1 -1
- package/dist/elements/PublishMany/index.js +3 -1
- package/dist/elements/PublishMany/index.js.map +1 -1
- package/dist/elements/QueryPresets/QueryPresetBar/index.js +1 -2
- package/dist/elements/QueryPresets/QueryPresetBar/index.js.map +1 -1
- package/dist/elements/ReactSelect/index.js +2 -2
- package/dist/elements/ReactSelect/index.js.map +1 -1
- package/dist/elements/ReactSelect/types.js +8 -1
- package/dist/elements/ReactSelect/types.js.map +1 -1
- package/dist/elements/RelationshipTable/index.js +2 -2
- package/dist/elements/RelationshipTable/index.js.map +1 -1
- package/dist/elements/RestoreMany/index.js +1 -0
- package/dist/elements/RestoreMany/index.js.map +1 -1
- package/dist/elements/SaveButton/index.js +1 -2
- package/dist/elements/SaveButton/index.js.map +1 -1
- package/dist/elements/SaveDraftButton/index.js +1 -2
- package/dist/elements/SaveDraftButton/index.js.map +1 -1
- package/dist/elements/SearchFilter/types.js +19 -1
- package/dist/elements/SearchFilter/types.js.map +1 -1
- package/dist/elements/Status/index.js +2 -2
- package/dist/elements/Status/index.js.map +1 -1
- package/dist/elements/StepNav/index.js +5 -1
- package/dist/elements/StepNav/index.js.map +1 -1
- package/dist/elements/Table/DefaultCell/fields/Select/index.js +4 -4
- package/dist/elements/Table/DefaultCell/fields/Select/index.js.map +1 -1
- package/dist/elements/Table/DefaultCell/index.js +2 -1
- package/dist/elements/Table/DefaultCell/index.js.map +1 -1
- package/dist/elements/Table/RelationshipProvider/index.js +3 -0
- package/dist/elements/Table/RelationshipProvider/index.js.map +1 -1
- package/dist/elements/Thumbnail/createThumbnail.js +12 -12
- package/dist/elements/Thumbnail/createThumbnail.js.map +1 -1
- package/dist/elements/Tooltip/index.js +3 -1
- package/dist/elements/Tooltip/index.js.map +1 -1
- package/dist/elements/UnpublishMany/index.js +3 -1
- package/dist/elements/UnpublishMany/index.js.map +1 -1
- package/dist/elements/Upload/index.js +8 -8
- package/dist/elements/Upload/index.js.map +1 -1
- package/dist/elements/WhereBuilder/Condition/Number/index.js +1 -0
- package/dist/elements/WhereBuilder/Condition/Number/index.js.map +1 -1
- package/dist/elements/WhereBuilder/Condition/Relationship/index.js +5 -6
- package/dist/elements/WhereBuilder/Condition/Relationship/index.js.map +1 -1
- package/dist/elements/WhereBuilder/Condition/Text/index.js +1 -0
- package/dist/elements/WhereBuilder/Condition/Text/index.js.map +1 -1
- package/dist/elements/WhereBuilder/index.js +2 -2
- package/dist/elements/WhereBuilder/index.js.map +1 -1
- package/dist/exports/client/index.js +26 -2
- package/dist/exports/client/index.js.map +1 -1
- package/dist/exports/shared/index.js +2 -1
- package/dist/exports/shared/index.js.map +1 -1
- package/dist/fields/Blocks/BlockSelector/index.js +3 -1
- package/dist/fields/Blocks/BlockSelector/index.js.map +1 -1
- package/dist/fields/Email/index.js +1 -1
- package/dist/fields/Email/index.js.map +1 -1
- package/dist/fields/Group/index.js +1 -1
- package/dist/fields/Group/index.js.map +1 -1
- package/dist/fields/Number/index.js +5 -3
- package/dist/fields/Number/index.js.map +1 -1
- package/dist/fields/Password/types.js +11 -1
- package/dist/fields/Password/types.js.map +1 -1
- package/dist/fields/Point/index.js +2 -2
- package/dist/fields/Point/index.js.map +1 -1
- package/dist/fields/Relationship/select-components/MultiValueLabel/index.js +4 -1
- package/dist/fields/Relationship/select-components/MultiValueLabel/index.js.map +1 -1
- package/dist/fields/Relationship/select-components/SingleValue/index.js +4 -1
- package/dist/fields/Relationship/select-components/SingleValue/index.js.map +1 -1
- package/dist/fields/Text/index.js +3 -2
- package/dist/fields/Text/index.js.map +1 -1
- package/dist/fields/Upload/Input.js +3 -1
- package/dist/fields/Upload/Input.js.map +1 -1
- package/dist/fields/Upload/types.js +1 -0
- package/dist/fields/Upload/types.js.map +1 -1
- package/dist/fields/shared/index.js +2 -3
- package/dist/fields/shared/index.js.map +1 -1
- package/dist/forms/Form/fieldReducer.js +2 -1
- package/dist/forms/Form/fieldReducer.js.map +1 -1
- package/dist/forms/Form/index.js +12 -9
- package/dist/forms/Form/index.js.map +1 -1
- package/dist/forms/Form/mergeServerFormState.js +11 -3
- package/dist/forms/Form/mergeServerFormState.js.map +1 -1
- package/dist/forms/Form/reduceToSerializableFields.js +2 -2
- package/dist/forms/Form/reduceToSerializableFields.js.map +1 -1
- package/dist/forms/Form/types.js +52 -1
- package/dist/forms/Form/types.js.map +1 -1
- package/dist/forms/NullifyField/index.js +2 -1
- package/dist/forms/NullifyField/index.js.map +1 -1
- package/dist/forms/WatchChildErrors/index.js +6 -1
- package/dist/forms/WatchChildErrors/index.js.map +1 -1
- package/dist/forms/fieldSchemasToFormState/addFieldStatePromise.js +20 -0
- package/dist/forms/fieldSchemasToFormState/addFieldStatePromise.js.map +1 -1
- package/dist/forms/fieldSchemasToFormState/index.js +33 -1
- package/dist/forms/fieldSchemasToFormState/index.js.map +1 -1
- package/dist/forms/fieldSchemasToFormState/isRowCollapsed.js +2 -2
- package/dist/forms/fieldSchemasToFormState/isRowCollapsed.js.map +1 -1
- package/dist/forms/fieldSchemasToFormState/iterateFields.js +16 -0
- package/dist/forms/fieldSchemasToFormState/iterateFields.js.map +1 -1
- package/dist/forms/fieldSchemasToFormState/renderField.js +2 -2
- package/dist/forms/fieldSchemasToFormState/renderField.js.map +1 -1
- package/dist/forms/fieldSchemasToFormState/serverFunctions/renderFieldServerFn.js +22 -1
- package/dist/forms/fieldSchemasToFormState/serverFunctions/renderFieldServerFn.js.map +1 -1
- package/dist/forms/fieldSchemasToFormState/types.js +5 -1
- package/dist/forms/fieldSchemasToFormState/types.js.map +1 -1
- package/dist/forms/useField/index.js +1 -0
- package/dist/forms/useField/index.js.map +1 -1
- package/dist/forms/useField/types.js +19 -1
- package/dist/forms/useField/types.js.map +1 -1
- package/dist/hooks/useControllableState.js +9 -1
- package/dist/hooks/useControllableState.js.map +1 -1
- package/dist/hooks/useDelayedRender.js +3 -1
- package/dist/hooks/useDelayedRender.js.map +1 -1
- package/dist/hooks/useHotkey.js +2 -2
- package/dist/hooks/useHotkey.js.map +1 -1
- package/dist/hooks/usePayloadAPI.js +3 -4
- package/dist/hooks/usePayloadAPI.js.map +1 -1
- package/dist/hooks/usePopupWindow.js +2 -2
- package/dist/hooks/usePopupWindow.js.map +1 -1
- package/dist/hooks/useQueue.js +15 -7
- package/dist/hooks/useQueue.js.map +1 -1
- package/dist/hooks/useResize.js +4 -3
- package/dist/hooks/useResize.js.map +1 -1
- package/dist/providers/Auth/index.js +35 -3
- package/dist/providers/Auth/index.js.map +1 -1
- package/dist/providers/Config/index.js +10 -1
- package/dist/providers/Config/index.js.map +1 -1
- package/dist/providers/DocumentInfo/index.js +6 -7
- package/dist/providers/DocumentInfo/index.js.map +1 -1
- package/dist/providers/DocumentInfo/types.js +25 -1
- package/dist/providers/DocumentInfo/types.js.map +1 -1
- package/dist/providers/Folders/index.js +44 -2
- package/dist/providers/Folders/index.js.map +1 -1
- package/dist/providers/ListQuery/types.js +5 -1
- package/dist/providers/ListQuery/types.js.map +1 -1
- package/dist/providers/LivePreview/context.js +11 -1
- package/dist/providers/LivePreview/context.js.map +1 -1
- package/dist/providers/LivePreview/index.js +7 -4
- package/dist/providers/LivePreview/index.js.map +1 -1
- package/dist/providers/Preferences/index.js +7 -2
- package/dist/providers/Preferences/index.js.map +1 -1
- package/dist/providers/RouteTransition/index.js +9 -9
- package/dist/providers/RouteTransition/index.js.map +1 -1
- package/dist/providers/Selection/index.js +7 -2
- package/dist/providers/Selection/index.js.map +1 -1
- package/dist/providers/ServerFunctions/index.js +25 -22
- package/dist/providers/ServerFunctions/index.js.map +1 -1
- package/dist/providers/TableColumns/buildColumnState/index.js +10 -9
- package/dist/providers/TableColumns/buildColumnState/index.js.map +1 -1
- package/dist/providers/TableColumns/buildColumnState/renderCell.js +4 -3
- package/dist/providers/TableColumns/buildColumnState/renderCell.js.map +1 -1
- package/dist/providers/TableColumns/types.js +17 -1
- package/dist/providers/TableColumns/types.js.map +1 -1
- package/dist/utilities/abortAndIgnore.js +4 -6
- package/dist/utilities/abortAndIgnore.js.map +1 -1
- package/dist/utilities/buildFieldSchemaMap/traverseFields.js +2 -2
- package/dist/utilities/buildFieldSchemaMap/traverseFields.js.map +1 -1
- package/dist/utilities/copyDataFromLocale.js +6 -2
- package/dist/utilities/copyDataFromLocale.js.map +1 -1
- package/dist/utilities/getDisplayedFieldValue.js +8 -8
- package/dist/utilities/getDisplayedFieldValue.js.map +1 -1
- package/dist/utilities/getFolderResultsComponentAndData.js +2 -1
- package/dist/utilities/getFolderResultsComponentAndData.js.map +1 -1
- package/dist/utilities/handleFormStateLocking.js +2 -2
- package/dist/utilities/handleFormStateLocking.js.map +1 -1
- package/dist/utilities/hasSavePermission.js +5 -1
- package/dist/utilities/hasSavePermission.js.map +1 -1
- package/dist/utilities/isURLAllowed.js +6 -6
- package/dist/utilities/isURLAllowed.js.map +1 -1
- package/dist/utilities/renderTable.js +2 -1
- package/dist/utilities/renderTable.js.map +1 -1
- package/dist/utilities/schedulePublishHandler.js +3 -1
- package/dist/utilities/schedulePublishHandler.js.map +1 -1
- package/dist/utilities/upsertPreferences.js +1 -0
- package/dist/utilities/upsertPreferences.js.map +1 -1
- package/dist/views/Edit/index.js +7 -7
- package/dist/views/Edit/index.js.map +1 -1
- package/dist/views/List/ListHeader/index.js +6 -1
- package/dist/views/List/ListHeader/index.js.map +1 -1
- package/package.json +6 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/providers/Folders/index.tsx"],"sourcesContent":["'use client'\n\nimport type { ClientCollectionConfig, CollectionSlug, FolderSortKeys } from 'payload'\nimport type { FolderBreadcrumb, FolderDocumentItemKey, FolderOrDocument } from 'payload/shared'\n\nimport { useRouter, useSearchParams } from 'next/navigation.js'\nimport { extractID, formatAdminURL, formatFolderOrDocumentItem } from 'payload/shared'\nimport * as qs from 'qs-esm'\nimport React from 'react'\nimport { toast } from 'sonner'\n\nimport { useDrawerDepth } from '../../elements/Drawer/index.js'\nimport { parseSearchParams } from '../../utilities/parseSearchParams.js'\nimport { useConfig } from '../Config/index.js'\nimport { useLocale } from '../Locale/index.js'\nimport { useRouteTransition } from '../RouteTransition/index.js'\nimport { useTranslation } from '../Translation/index.js'\nimport { groupItemIDsByRelation } from './groupItemIDsByRelation.js'\n\ntype FolderQueryParams = {\n page?: string\n relationTo?: CollectionSlug[]\n search?: string\n sort?: string\n}\n\nexport type FileCardData = {\n filename: string\n id: number | string\n mimeType: string\n name: string\n url: string\n}\n\nexport type FolderContextValue = {\n /**\n * The collection slugs that a view can be filtered by\n * Used in the browse-by-folder view\n */\n activeCollectionFolderSlugs: CollectionSlug[]\n /**\n * Folder enabled collection slugs that can be populated within the provider\n */\n readonly allCollectionFolderSlugs?: CollectionSlug[]\n allowCreateCollectionSlugs: CollectionSlug[]\n breadcrumbs?: FolderBreadcrumb[]\n checkIfItemIsDisabled: (item: FolderOrDocument) => boolean\n clearSelections: () => void\n currentFolder?: FolderOrDocument | null\n documents?: FolderOrDocument[]\n dragOverlayItem?: FolderOrDocument | undefined\n focusedRowIndex: number\n folderCollectionConfig: ClientCollectionConfig\n folderCollectionSlug: string\n folderFieldName: string\n folderID?: number | string\n FolderResultsComponent: React.ReactNode\n folderType: CollectionSlug[] | undefined\n getFolderRoute: (toFolderID?: number | string) => string\n getSelectedItems?: () => FolderOrDocument[]\n isDragging: boolean\n itemKeysToMove?: Set<FolderDocumentItemKey>\n moveToFolder: (args: {\n itemsToMove: FolderOrDocument[]\n toFolderID?: number | string\n }) => Promise<void>\n onItemClick: (args: { event: React.MouseEvent; index: number; item: FolderOrDocument }) => void\n onItemKeyPress: (args: {\n event: React.KeyboardEvent\n index: number\n item: FolderOrDocument\n }) => void\n refineFolderData: (args: { query?: FolderQueryParams; updateURL: boolean }) => void\n search: string\n selectedFolderCollections?: CollectionSlug[]\n readonly selectedItemKeys: Set<FolderDocumentItemKey>\n setBreadcrumbs: React.Dispatch<React.SetStateAction<FolderBreadcrumb[]>>\n setFocusedRowIndex: React.Dispatch<React.SetStateAction<number>>\n setIsDragging: React.Dispatch<React.SetStateAction<boolean>>\n sort: FolderSortKeys\n subfolders?: FolderOrDocument[]\n}\n\nconst Context = React.createContext<FolderContextValue>({\n activeCollectionFolderSlugs: [],\n allCollectionFolderSlugs: [],\n allowCreateCollectionSlugs: [],\n breadcrumbs: [],\n checkIfItemIsDisabled: () => false,\n clearSelections: () => {},\n currentFolder: null,\n documents: [],\n dragOverlayItem: undefined,\n focusedRowIndex: -1,\n folderCollectionConfig: null,\n folderCollectionSlug: '',\n folderFieldName: 'folder',\n folderID: undefined,\n FolderResultsComponent: null,\n folderType: undefined,\n getFolderRoute: () => '',\n getSelectedItems: () => [],\n isDragging: false,\n itemKeysToMove: undefined,\n moveToFolder: () => Promise.resolve(undefined),\n onItemClick: () => undefined,\n onItemKeyPress: () => undefined,\n refineFolderData: () => undefined,\n search: '',\n selectedFolderCollections: undefined,\n selectedItemKeys: new Set<FolderDocumentItemKey>(),\n setBreadcrumbs: () => {},\n setFocusedRowIndex: () => -1,\n setIsDragging: () => false,\n sort: 'name',\n subfolders: [],\n})\n\nexport type FolderProviderProps = {\n /**\n * The collection slugs that are being viewed\n */\n readonly activeCollectionFolderSlugs?: CollectionSlug[]\n /**\n * Folder enabled collection slugs that can be populated within the provider\n */\n readonly allCollectionFolderSlugs: CollectionSlug[]\n /**\n * Array of slugs that can be created in the folder view\n */\n readonly allowCreateCollectionSlugs: CollectionSlug[]\n readonly allowMultiSelection?: boolean\n /**\n * The base folder route path\n *\n * @example\n * `/collections/:collectionSlug/:folderCollectionSlug`\n * or\n * `/browse-by-folder`\n */\n readonly baseFolderPath?: `/${string}`\n /**\n * Breadcrumbs for the current folder\n */\n readonly breadcrumbs?: FolderBreadcrumb[]\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 documents: FolderOrDocument[]\n /**\n * The name of the field that contains the folder relation\n */\n readonly folderFieldName: string\n /**\n * The ID of the current folder\n */\n readonly folderID?: number | string\n /**\n * The component to render the folder results\n */\n readonly FolderResultsComponent: React.ReactNode\n /**\n * Optional function to call when an item is clicked\n */\n readonly onItemClick?: (itme: FolderOrDocument) => void\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 /**\n * All subfolders in the current folder\n */\n readonly subfolders: FolderOrDocument[]\n}\nexport function FolderProvider({\n activeCollectionFolderSlugs: activeCollectionSlugs,\n allCollectionFolderSlugs = [],\n allowCreateCollectionSlugs,\n allowMultiSelection = true,\n baseFolderPath,\n breadcrumbs: _breadcrumbsFromProps = [],\n children,\n documents,\n folderFieldName,\n folderID,\n FolderResultsComponent: InitialFolderResultsComponent,\n onItemClick: onItemClickFromProps,\n search,\n sort = 'name',\n subfolders,\n}: FolderProviderProps) {\n const parentFolderContext = useFolder()\n const { config } = useConfig()\n const { routes, serverURL } = config\n const drawerDepth = useDrawerDepth()\n const { t } = useTranslation()\n const router = useRouter()\n const { startRouteTransition } = useRouteTransition()\n const locale = useLocale()\n const localeCode = locale ? locale.code : undefined\n\n const currentlySelectedIndexes = React.useRef(new Set<number>())\n\n const [selectedFolderCollections, setSelectedFolderCollections] = React.useState<\n CollectionSlug[]\n >([])\n const [FolderResultsComponent, setFolderResultsComponent] = React.useState(\n InitialFolderResultsComponent || (() => null),\n )\n const [folderCollectionConfig] = React.useState(() =>\n config.collections.find(\n (collection) => config.folders && collection.slug === config.folders.slug,\n ),\n )\n const folderCollectionSlug = folderCollectionConfig.slug\n\n const rawSearchParams = useSearchParams()\n const searchParams = React.useMemo(() => parseSearchParams(rawSearchParams), [rawSearchParams])\n const [currentQuery, setCurrentQuery] = React.useState<FolderQueryParams>(searchParams)\n\n const [isDragging, setIsDragging] = React.useState(false)\n const [selectedItemKeys, setSelectedItemKeys] = React.useState<Set<FolderDocumentItemKey>>(\n () => new Set(),\n )\n const [focusedRowIndex, setFocusedRowIndex] = React.useState(-1)\n // This is used to determine what data to display on the drag overlay\n const [dragOverlayItem, setDragOverlayItem] = React.useState<FolderOrDocument | undefined>()\n const [breadcrumbs, setBreadcrumbs] =\n React.useState<FolderContextValue['breadcrumbs']>(_breadcrumbsFromProps)\n const lastClickTime = React.useRef<null | number>(null)\n const totalCount = subfolders.length + documents.length\n\n const clearSelections = React.useCallback(() => {\n setFocusedRowIndex(-1)\n setSelectedItemKeys(new Set())\n setDragOverlayItem(undefined)\n currentlySelectedIndexes.current = new Set()\n }, [])\n\n const mergeQuery = React.useCallback(\n (newQuery: Partial<FolderQueryParams> = {}): Partial<FolderQueryParams> => {\n let page = 'page' in newQuery ? newQuery.page : currentQuery?.page\n\n if ('search' in newQuery) {\n page = '1'\n }\n\n const mergedQuery = {\n ...currentQuery,\n ...newQuery,\n locale: localeCode,\n page,\n relationTo: 'relationTo' in newQuery ? newQuery.relationTo : currentQuery?.relationTo,\n search: 'search' in newQuery ? newQuery.search : currentQuery?.search,\n sort: 'sort' in newQuery ? newQuery.sort : (currentQuery?.sort ?? undefined),\n }\n\n return mergedQuery\n },\n [currentQuery, localeCode],\n )\n\n const refineFolderData: FolderContextValue['refineFolderData'] = React.useCallback(\n ({ query, updateURL }) => {\n if (updateURL) {\n const queryParams = mergeQuery(query)\n\n startRouteTransition(() =>\n router.replace(\n `${qs.stringify({ ...queryParams, relationTo: JSON.stringify(queryParams.relationTo) }, { addQueryPrefix: true })}`,\n ),\n )\n\n setCurrentQuery(queryParams)\n }\n },\n [mergeQuery, router, startRouteTransition],\n )\n\n const getFolderRoute: FolderContextValue['getFolderRoute'] = React.useCallback(\n (toFolderID) => {\n const queryParams = qs.stringify(mergeQuery({ page: '1', search: '' }), {\n addQueryPrefix: true,\n })\n return formatAdminURL({\n adminRoute: config.routes.admin,\n path: `${baseFolderPath}${toFolderID ? `/${toFolderID}` : ''}${queryParams}`,\n serverURL: config.serverURL,\n })\n },\n [baseFolderPath, config.routes.admin, config.serverURL, mergeQuery],\n )\n\n const getItem = React.useCallback(\n (itemKey: FolderDocumentItemKey) => {\n return [...subfolders, ...documents].find((doc) => doc.itemKey === itemKey)\n },\n [documents, subfolders],\n )\n\n const getSelectedItems = React.useCallback(() => {\n return Array.from(selectedItemKeys).reduce((acc, itemKey) => {\n const item = getItem(itemKey)\n if (item) {\n acc.push(item)\n }\n return acc\n }, [])\n }, [selectedItemKeys, getItem])\n\n const navigateAfterSelection = React.useCallback(\n ({ collectionSlug, docID }: { collectionSlug: string; docID?: number | string }) => {\n if (drawerDepth === 1) {\n // not in a drawer (default is 1)\n if (collectionSlug === folderCollectionSlug) {\n // clicked on folder, take the user to the folder view\n startRouteTransition(() => {\n router.push(getFolderRoute(docID))\n clearSelections()\n })\n } else 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 if (typeof onItemClickFromProps === 'function') {\n onItemClickFromProps(getItem(`${collectionSlug}-${docID}`))\n }\n },\n [\n clearSelections,\n config.routes.admin,\n drawerDepth,\n folderCollectionSlug,\n getFolderRoute,\n getItem,\n onItemClickFromProps,\n router,\n startRouteTransition,\n ],\n )\n\n const handleShiftSelection = React.useCallback(\n (targetIndex: number) => {\n const allItems = [...subfolders, ...documents]\n\n // Find existing selection boundaries\n const existingIndexes = allItems.reduce((acc, item, idx) => {\n if (selectedItemKeys.has(item.itemKey)) {\n acc.push(idx)\n }\n return acc\n }, [])\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 = 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 (targetIndex === firstSelectedIndex || targetIndex === lastSelectedIndex) {\n anchorIndex = targetIndex\n } else {\n const distanceToFirst = Math.abs(targetIndex - firstSelectedIndex)\n const distanceToLast = Math.abs(targetIndex - lastSelectedIndex)\n anchorIndex = distanceToFirst >= distanceToLast ? firstSelectedIndex : 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 = distanceToFirst <= distanceToLast ? firstSelectedIndex : 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 return [...new Set([...existingIndexes, ...newRangeIndexes])]\n }\n },\n [subfolders, documents, selectedItemKeys],\n )\n\n const updateSelections = React.useCallback(\n ({ indexes }: { indexes: number[] }) => {\n const allItems = [...subfolders, ...documents]\n const { newSelectedFolderCollections, newSelectedItemKeys } = allItems.reduce(\n (acc, item, index) => {\n if (indexes.includes(index)) {\n acc.newSelectedItemKeys.add(item.itemKey)\n if (item.relationTo === folderCollectionSlug) {\n item.value.folderType?.forEach((collectionSlug) => {\n if (!acc.newSelectedFolderCollections.includes(collectionSlug)) {\n acc.newSelectedFolderCollections.push(collectionSlug)\n }\n })\n } else {\n if (!acc.newSelectedFolderCollections.includes(item.relationTo)) {\n acc.newSelectedFolderCollections.push(item.relationTo)\n }\n }\n }\n return acc\n },\n {\n newSelectedFolderCollections: [] satisfies CollectionSlug[],\n newSelectedItemKeys: new Set<FolderDocumentItemKey>(),\n },\n )\n\n setSelectedFolderCollections(newSelectedFolderCollections)\n setSelectedItemKeys(newSelectedItemKeys)\n },\n [documents, folderCollectionSlug, subfolders],\n )\n\n const onItemKeyPress: FolderContextValue['onItemKeyPress'] = React.useCallback(\n ({ event, item: currentItem }) => {\n const { code, ctrlKey, metaKey, shiftKey } = event\n const isShiftPressed = shiftKey\n const isCtrlPressed = ctrlKey || metaKey\n const isCurrentlySelected = selectedItemKeys.has(currentItem.itemKey)\n const allItems = [...subfolders, ...documents]\n const currentItemIndex = allItems.findIndex((item) => item.itemKey === currentItem.itemKey)\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 ? currentItemIndex - 1 : currentItemIndex + 1\n\n if (newItemIndex < 0 || newItemIndex > totalCount - 1) {\n // out of bounds, keep current selection\n return\n }\n\n setFocusedRowIndex(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 setSelectedItemKeys(new Set([newItem.itemKey]))\n }\n\n break\n }\n case 'Enter': {\n if (selectedItemKeys.size === 1) {\n setFocusedRowIndex(undefined)\n navigateAfterSelection({\n collectionSlug: currentItem.relationTo,\n docID: extractID(currentItem.value),\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 setFocusedRowIndex(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 const allItems = [...subfolders, ...documents]\n updateSelections({\n indexes: allItems.reduce((acc, item, idx) => {\n if (item.itemKey === currentItem.itemKey) {\n if (isCurrentlySelected) {\n return acc\n } else {\n acc.push(idx)\n }\n } else if (selectedItemKeys.has(item.itemKey)) {\n acc.push(idx)\n }\n return acc\n }, []),\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 && selectedItemKeys?.size > 0) {\n setFocusedRowIndex(prevIndex)\n }\n } else {\n const nextIndex = currentItemIndex + 1\n if (nextIndex === totalCount && selectedItemKeys.size > 0) {\n setFocusedRowIndex(totalCount - 1)\n }\n }\n break\n }\n }\n },\n [\n selectedItemKeys,\n subfolders,\n documents,\n allowMultiSelection,\n handleShiftSelection,\n updateSelections,\n navigateAfterSelection,\n clearSelections,\n totalCount,\n ],\n )\n\n const onItemClick: FolderContextValue['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 = selectedItemKeys.has(clickedItem.itemKey)\n const allItems = [...subfolders, ...documents]\n const currentItemIndex = allItems.findIndex((item) => item.itemKey === clickedItem.itemKey)\n\n if (allowMultiSelection && isCtrlPressed) {\n event.preventDefault()\n let overlayItemKey: FolderDocumentItemKey | undefined\n const indexes = allItems.reduce((acc, item, idx) => {\n if (item.itemKey === clickedItem.itemKey) {\n if (isCurrentlySelected && event.type !== 'pointermove') {\n return acc\n } else {\n acc.push(idx)\n overlayItemKey = item.itemKey\n }\n } else if (selectedItemKeys.has(item.itemKey)) {\n acc.push(idx)\n }\n return acc\n }, [])\n\n updateSelections({ indexes })\n\n if (overlayItemKey) {\n setDragOverlayItem(getItem(overlayItemKey))\n }\n } else if (allowMultiSelection && isShiftPressed) {\n if (currentItemIndex !== -1) {\n const selectedIndexes = handleShiftSelection(currentItemIndex)\n updateSelections({ indexes: selectedIndexes })\n }\n } else if (allowMultiSelection && event.type === 'pointermove') {\n // on drag start of an unselected item\n if (!isCurrentlySelected) {\n updateSelections({\n indexes: allItems.reduce((acc, item, idx) => {\n if (item.itemKey === clickedItem.itemKey) {\n acc.push(idx)\n }\n return acc\n }, []),\n })\n }\n setDragOverlayItem(getItem(clickedItem.itemKey))\n } else {\n // Normal click - select single item\n const now = Date.now()\n doubleClicked =\n now - lastClickTime.current < 400 && dragOverlayItem?.itemKey === clickedItem.itemKey\n lastClickTime.current = now\n if (!doubleClicked) {\n updateSelections({\n indexes: isCurrentlySelected && selectedItemKeys.size === 1 ? [] : [currentItemIndex],\n })\n }\n setDragOverlayItem(getItem(clickedItem.itemKey))\n }\n\n if (doubleClicked) {\n navigateAfterSelection({\n collectionSlug: clickedItem.relationTo,\n docID: extractID(clickedItem.value),\n })\n }\n },\n [\n selectedItemKeys,\n subfolders,\n documents,\n allowMultiSelection,\n dragOverlayItem,\n getItem,\n updateSelections,\n navigateAfterSelection,\n handleShiftSelection,\n ],\n )\n\n /**\n * Makes requests to the server to update the folder field on passed in documents\n *\n * Might rewrite this in the future to return the promises so errors can be handled contextually\n */\n const moveToFolder: FolderContextValue['moveToFolder'] = React.useCallback(\n async (args) => {\n const { itemsToMove: items, toFolderID } = args\n if (!items.length) {\n return\n }\n\n const movingCurrentFolder =\n items.length === 1 &&\n items[0].relationTo === folderCollectionSlug &&\n items[0].value.id === folderID\n\n if (movingCurrentFolder) {\n const queryParams = qs.stringify(\n {\n depth: 0,\n locale: localeCode,\n },\n {\n addQueryPrefix: true,\n },\n )\n const req = await fetch(\n `${serverURL}${routes.api}/${folderCollectionSlug}/${folderID}${queryParams}`,\n {\n body: JSON.stringify({ [folderFieldName]: toFolderID || null }),\n credentials: 'include',\n headers: {\n 'content-type': 'application/json',\n },\n method: 'PATCH',\n },\n )\n if (req.status !== 200) {\n toast.error(t('general:error'))\n }\n } else {\n for (const [collectionSlug, ids] of Object.entries(groupItemIDsByRelation(items))) {\n const queryParams = qs.stringify(\n {\n depth: 0,\n limit: 0,\n locale: localeCode,\n where: {\n id: {\n in: ids,\n },\n },\n },\n {\n addQueryPrefix: true,\n },\n )\n try {\n await fetch(`${serverURL}${routes.api}/${collectionSlug}${queryParams}`, {\n body: JSON.stringify({ [folderFieldName]: toFolderID || null }),\n credentials: 'include',\n headers: {\n 'content-type': 'application/json',\n },\n method: 'PATCH',\n })\n } catch (error) {\n toast.error(t('general:error'))\n // eslint-disable-next-line no-console\n console.error(error)\n continue\n }\n }\n }\n\n clearSelections()\n },\n [\n folderID,\n clearSelections,\n folderCollectionSlug,\n folderFieldName,\n routes.api,\n serverURL,\n t,\n localeCode,\n ],\n )\n\n const checkIfItemIsDisabled: FolderContextValue['checkIfItemIsDisabled'] = React.useCallback(\n (item) => {\n function folderAcceptsItem({\n item,\n selectedFolderCollections,\n }: {\n item: FolderOrDocument\n selectedFolderCollections: string[]\n }): boolean {\n if (\n !item.value.folderType ||\n (Array.isArray(item.value.folderType) && item.value.folderType.length === 0)\n ) {\n // Enable folder that accept all collections\n return false\n }\n\n if (selectedFolderCollections.length === 0) {\n // If no collections are selected, enable folders that accept all collections\n return Boolean(item.value.folderType || item.value.folderType.length > 0)\n }\n\n // Disable folders that do not accept all of the selected collections\n return selectedFolderCollections.some((slug) => {\n return !item.value.folderType.includes(slug)\n })\n }\n\n if (isDragging) {\n const isSelected = selectedItemKeys.has(item.itemKey)\n if (isSelected) {\n return true\n } else if (item.relationTo === folderCollectionSlug) {\n return folderAcceptsItem({ item, selectedFolderCollections })\n } else {\n // Non folder items are disabled on drag\n return true\n }\n } else if (parentFolderContext?.selectedItemKeys?.size) {\n // Disable selected items from being navigated to in move to drawer\n if (parentFolderContext.selectedItemKeys.has(item.itemKey)) {\n return true\n }\n // Moving items to folder\n if (item.relationTo === folderCollectionSlug) {\n return folderAcceptsItem({\n item,\n selectedFolderCollections: parentFolderContext.selectedFolderCollections,\n })\n }\n // If the item is not a folder, it is disabled on move\n return true\n }\n },\n [\n selectedFolderCollections,\n isDragging,\n selectedItemKeys,\n folderCollectionSlug,\n parentFolderContext?.selectedFolderCollections,\n parentFolderContext?.selectedItemKeys,\n ],\n )\n\n // If a new component is provided, update the state so children can re-render with the new component\n React.useEffect(() => {\n if (InitialFolderResultsComponent) {\n setFolderResultsComponent(InitialFolderResultsComponent)\n }\n }, [InitialFolderResultsComponent])\n\n return (\n <Context\n value={{\n activeCollectionFolderSlugs: activeCollectionSlugs || allCollectionFolderSlugs,\n allCollectionFolderSlugs,\n allowCreateCollectionSlugs,\n breadcrumbs,\n checkIfItemIsDisabled,\n clearSelections,\n currentFolder:\n breadcrumbs?.[breadcrumbs.length - 1]?.id !== undefined\n ? formatFolderOrDocumentItem({\n folderFieldName,\n isUpload: false,\n relationTo: folderCollectionSlug,\n useAsTitle: folderCollectionConfig.admin.useAsTitle,\n value: breadcrumbs[breadcrumbs.length - 1],\n })\n : null,\n documents,\n dragOverlayItem,\n focusedRowIndex,\n folderCollectionConfig,\n folderCollectionSlug,\n folderFieldName,\n folderID,\n FolderResultsComponent,\n folderType: breadcrumbs?.[breadcrumbs.length - 1]?.folderType,\n getFolderRoute,\n getSelectedItems,\n isDragging,\n itemKeysToMove: parentFolderContext.selectedItemKeys,\n moveToFolder,\n onItemClick,\n onItemKeyPress,\n refineFolderData,\n search,\n selectedFolderCollections,\n selectedItemKeys,\n setBreadcrumbs,\n setFocusedRowIndex,\n setIsDragging,\n sort,\n subfolders,\n }}\n >\n {children}\n </Context>\n )\n}\n\nexport function useFolder(): FolderContextValue {\n const context = React.use(Context)\n\n if (context === undefined) {\n throw new Error('useFolder must be used within a FolderProvider')\n }\n\n return context\n}\n"],"names":["useRouter","useSearchParams","extractID","formatAdminURL","formatFolderOrDocumentItem","qs","React","toast","useDrawerDepth","parseSearchParams","useConfig","useLocale","useRouteTransition","useTranslation","groupItemIDsByRelation","Context","createContext","activeCollectionFolderSlugs","allCollectionFolderSlugs","allowCreateCollectionSlugs","breadcrumbs","checkIfItemIsDisabled","clearSelections","currentFolder","documents","dragOverlayItem","undefined","focusedRowIndex","folderCollectionConfig","folderCollectionSlug","folderFieldName","folderID","FolderResultsComponent","folderType","getFolderRoute","getSelectedItems","isDragging","itemKeysToMove","moveToFolder","Promise","resolve","onItemClick","onItemKeyPress","refineFolderData","search","selectedFolderCollections","selectedItemKeys","Set","setBreadcrumbs","setFocusedRowIndex","setIsDragging","sort","subfolders","FolderProvider","activeCollectionSlugs","allowMultiSelection","baseFolderPath","_breadcrumbsFromProps","children","InitialFolderResultsComponent","onItemClickFromProps","parentFolderContext","useFolder","config","routes","serverURL","drawerDepth","t","router","startRouteTransition","locale","localeCode","code","currentlySelectedIndexes","useRef","setSelectedFolderCollections","useState","setFolderResultsComponent","collections","find","collection","folders","slug","rawSearchParams","searchParams","useMemo","currentQuery","setCurrentQuery","setSelectedItemKeys","setDragOverlayItem","lastClickTime","totalCount","length","useCallback","current","mergeQuery","newQuery","page","mergedQuery","relationTo","query","updateURL","queryParams","replace","stringify","JSON","addQueryPrefix","toFolderID","adminRoute","admin","path","getItem","itemKey","doc","Array","from","reduce","acc","item","push","navigateAfterSelection","collectionSlug","docID","handleShiftSelection","targetIndex","allItems","existingIndexes","idx","has","firstSelectedIndex","Math","min","lastSelectedIndex","max","isWithinBounds","anchorIndex","distanceToFirst","abs","distanceToLast","startIndex","endIndex","newRangeIndexes","_","i","updateSelections","indexes","newSelectedFolderCollections","newSelectedItemKeys","index","includes","add","value","forEach","event","currentItem","ctrlKey","metaKey","shiftKey","isShiftPressed","isCtrlPressed","isCurrentlySelected","currentItemIndex","findIndex","preventDefault","isBackward","newItemIndex","selectedIndexes","newItem","size","prevIndex","nextIndex","clickedItem","doubleClicked","overlayItemKey","type","now","Date","args","itemsToMove","items","movingCurrentFolder","id","depth","req","fetch","api","body","credentials","headers","method","status","error","ids","Object","entries","limit","where","in","console","folderAcceptsItem","isArray","Boolean","some","isSelected","useEffect","isUpload","useAsTitle","context","use","Error"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/providers/Folders/index.tsx"],"sourcesContent":["'use client'\n\nimport type { ClientCollectionConfig, CollectionSlug, FolderSortKeys } from 'payload'\nimport type { FolderBreadcrumb, FolderDocumentItemKey, FolderOrDocument } from 'payload/shared'\n\nimport { useRouter, useSearchParams } from 'next/navigation.js'\nimport { extractID, formatAdminURL, formatFolderOrDocumentItem } from 'payload/shared'\nimport * as qs from 'qs-esm'\nimport React from 'react'\nimport { toast } from 'sonner'\n\nimport { useDrawerDepth } from '../../elements/Drawer/index.js'\nimport { parseSearchParams } from '../../utilities/parseSearchParams.js'\nimport { useConfig } from '../Config/index.js'\nimport { useLocale } from '../Locale/index.js'\nimport { useRouteTransition } from '../RouteTransition/index.js'\nimport { useTranslation } from '../Translation/index.js'\nimport { groupItemIDsByRelation } from './groupItemIDsByRelation.js'\n\ntype FolderQueryParams = {\n page?: string\n relationTo?: CollectionSlug[]\n search?: string\n sort?: string\n}\n\nexport type FileCardData = {\n filename: string\n id: number | string\n mimeType: string\n name: string\n url: string\n}\n\nexport type FolderContextValue = {\n /**\n * The collection slugs that a view can be filtered by\n * Used in the browse-by-folder view\n */\n activeCollectionFolderSlugs: CollectionSlug[]\n /**\n * Folder enabled collection slugs that can be populated within the provider\n */\n readonly allCollectionFolderSlugs?: CollectionSlug[]\n allowCreateCollectionSlugs: CollectionSlug[]\n breadcrumbs?: FolderBreadcrumb[]\n checkIfItemIsDisabled: (item: FolderOrDocument) => boolean\n clearSelections: () => void\n currentFolder?: FolderOrDocument | null\n documents?: FolderOrDocument[]\n dragOverlayItem?: FolderOrDocument | undefined\n focusedRowIndex: number\n folderCollectionConfig: ClientCollectionConfig\n folderCollectionSlug: string\n folderFieldName: string\n folderID?: number | string\n FolderResultsComponent: React.ReactNode\n folderType: CollectionSlug[] | undefined\n getFolderRoute: (toFolderID?: number | string) => string\n getSelectedItems?: () => FolderOrDocument[]\n isDragging: boolean\n itemKeysToMove?: Set<FolderDocumentItemKey>\n moveToFolder: (args: {\n itemsToMove: FolderOrDocument[]\n toFolderID?: number | string\n }) => Promise<void>\n onItemClick: (args: { event: React.MouseEvent; index: number; item: FolderOrDocument }) => void\n onItemKeyPress: (args: {\n event: React.KeyboardEvent\n index: number\n item: FolderOrDocument\n }) => void\n refineFolderData: (args: { query?: FolderQueryParams; updateURL: boolean }) => void\n search: string\n selectedFolderCollections?: CollectionSlug[]\n readonly selectedItemKeys: Set<FolderDocumentItemKey>\n setBreadcrumbs: React.Dispatch<React.SetStateAction<FolderBreadcrumb[]>>\n setFocusedRowIndex: React.Dispatch<React.SetStateAction<number>>\n setIsDragging: React.Dispatch<React.SetStateAction<boolean>>\n sort: FolderSortKeys\n subfolders?: FolderOrDocument[]\n}\n\nconst Context = React.createContext<FolderContextValue>({\n activeCollectionFolderSlugs: [],\n allCollectionFolderSlugs: [],\n allowCreateCollectionSlugs: [],\n breadcrumbs: [],\n checkIfItemIsDisabled: () => false,\n clearSelections: () => {},\n currentFolder: null,\n documents: [],\n dragOverlayItem: undefined,\n focusedRowIndex: -1,\n folderCollectionConfig: null,\n folderCollectionSlug: '',\n folderFieldName: 'folder',\n folderID: undefined,\n FolderResultsComponent: null,\n folderType: undefined,\n getFolderRoute: () => '',\n getSelectedItems: () => [],\n isDragging: false,\n itemKeysToMove: undefined,\n moveToFolder: () => Promise.resolve(undefined),\n onItemClick: () => undefined,\n onItemKeyPress: () => undefined,\n refineFolderData: () => undefined,\n search: '',\n selectedFolderCollections: undefined,\n selectedItemKeys: new Set<FolderDocumentItemKey>(),\n setBreadcrumbs: () => {},\n setFocusedRowIndex: () => -1,\n setIsDragging: () => false,\n sort: 'name',\n subfolders: [],\n})\n\nexport type FolderProviderProps = {\n /**\n * The collection slugs that are being viewed\n */\n readonly activeCollectionFolderSlugs?: CollectionSlug[]\n /**\n * Folder enabled collection slugs that can be populated within the provider\n */\n readonly allCollectionFolderSlugs: CollectionSlug[]\n /**\n * Array of slugs that can be created in the folder view\n */\n readonly allowCreateCollectionSlugs: CollectionSlug[]\n readonly allowMultiSelection?: boolean\n /**\n * The base folder route path\n *\n * @example\n * `/collections/:collectionSlug/:folderCollectionSlug`\n * or\n * `/browse-by-folder`\n */\n readonly baseFolderPath?: `/${string}`\n /**\n * Breadcrumbs for the current folder\n */\n readonly breadcrumbs?: FolderBreadcrumb[]\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 documents: FolderOrDocument[]\n /**\n * The name of the field that contains the folder relation\n */\n readonly folderFieldName: string\n /**\n * The ID of the current folder\n */\n readonly folderID?: number | string\n /**\n * The component to render the folder results\n */\n readonly FolderResultsComponent: React.ReactNode\n /**\n * Optional function to call when an item is clicked\n */\n readonly onItemClick?: (itme: FolderOrDocument) => void\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 /**\n * All subfolders in the current folder\n */\n readonly subfolders: FolderOrDocument[]\n}\nexport function FolderProvider({\n activeCollectionFolderSlugs: activeCollectionSlugs,\n allCollectionFolderSlugs = [],\n allowCreateCollectionSlugs,\n allowMultiSelection = true,\n baseFolderPath,\n breadcrumbs: _breadcrumbsFromProps = [],\n children,\n documents,\n folderFieldName,\n folderID,\n FolderResultsComponent: InitialFolderResultsComponent,\n onItemClick: onItemClickFromProps,\n search,\n sort = 'name',\n subfolders,\n}: FolderProviderProps) {\n const parentFolderContext = useFolder()\n const { config } = useConfig()\n const { routes, serverURL } = config\n const drawerDepth = useDrawerDepth()\n const { t } = useTranslation()\n const router = useRouter()\n const { startRouteTransition } = useRouteTransition()\n const locale = useLocale()\n const localeCode = locale ? locale.code : undefined\n\n const currentlySelectedIndexes = React.useRef(new Set<number>())\n\n const [selectedFolderCollections, setSelectedFolderCollections] = React.useState<\n CollectionSlug[]\n >([])\n const [FolderResultsComponent, setFolderResultsComponent] = React.useState(\n InitialFolderResultsComponent || (() => null),\n )\n const [folderCollectionConfig] = React.useState(() =>\n config.collections.find(\n (collection) => config.folders && collection.slug === config.folders.slug,\n ),\n )\n const folderCollectionSlug = folderCollectionConfig.slug\n\n const rawSearchParams = useSearchParams()\n const searchParams = React.useMemo(() => parseSearchParams(rawSearchParams), [rawSearchParams])\n const [currentQuery, setCurrentQuery] = React.useState<FolderQueryParams>(searchParams)\n\n const [isDragging, setIsDragging] = React.useState(false)\n const [selectedItemKeys, setSelectedItemKeys] = React.useState<Set<FolderDocumentItemKey>>(\n () => new Set(),\n )\n const [focusedRowIndex, setFocusedRowIndex] = React.useState(-1)\n // This is used to determine what data to display on the drag overlay\n const [dragOverlayItem, setDragOverlayItem] = React.useState<FolderOrDocument | undefined>()\n const [breadcrumbs, setBreadcrumbs] =\n React.useState<FolderContextValue['breadcrumbs']>(_breadcrumbsFromProps)\n const lastClickTime = React.useRef<null | number>(null)\n const totalCount = subfolders.length + documents.length\n\n const clearSelections = React.useCallback(() => {\n setFocusedRowIndex(-1)\n setSelectedItemKeys(new Set())\n setDragOverlayItem(undefined)\n currentlySelectedIndexes.current = new Set()\n }, [])\n\n const mergeQuery = React.useCallback(\n (newQuery: Partial<FolderQueryParams> = {}): Partial<FolderQueryParams> => {\n let page = 'page' in newQuery ? newQuery.page : currentQuery?.page\n\n if ('search' in newQuery) {\n page = '1'\n }\n\n const mergedQuery = {\n ...currentQuery,\n ...newQuery,\n locale: localeCode,\n page,\n relationTo: 'relationTo' in newQuery ? newQuery.relationTo : currentQuery?.relationTo,\n search: 'search' in newQuery ? newQuery.search : currentQuery?.search,\n sort: 'sort' in newQuery ? newQuery.sort : (currentQuery?.sort ?? undefined),\n }\n\n return mergedQuery\n },\n [currentQuery, localeCode],\n )\n\n const refineFolderData: FolderContextValue['refineFolderData'] = React.useCallback(\n ({ query, updateURL }) => {\n if (updateURL) {\n const queryParams = mergeQuery(query)\n\n startRouteTransition(() =>\n router.replace(\n `${qs.stringify({ ...queryParams, relationTo: JSON.stringify(queryParams.relationTo) }, { addQueryPrefix: true })}`,\n ),\n )\n\n setCurrentQuery(queryParams)\n }\n },\n [mergeQuery, router, startRouteTransition],\n )\n\n const getFolderRoute: FolderContextValue['getFolderRoute'] = React.useCallback(\n (toFolderID) => {\n const queryParams = qs.stringify(mergeQuery({ page: '1', search: '' }), {\n addQueryPrefix: true,\n })\n return formatAdminURL({\n adminRoute: config.routes.admin,\n path: `${baseFolderPath}${toFolderID ? `/${toFolderID}` : ''}${queryParams}`,\n serverURL: config.serverURL,\n })\n },\n [baseFolderPath, config.routes.admin, config.serverURL, mergeQuery],\n )\n\n const getItem = React.useCallback(\n (itemKey: FolderDocumentItemKey) => {\n return [...subfolders, ...documents].find((doc) => doc.itemKey === itemKey)\n },\n [documents, subfolders],\n )\n\n const getSelectedItems = React.useCallback(() => {\n return Array.from(selectedItemKeys).reduce((acc, itemKey) => {\n const item = getItem(itemKey)\n if (item) {\n acc.push(item)\n }\n return acc\n }, [])\n }, [selectedItemKeys, getItem])\n\n const navigateAfterSelection = React.useCallback(\n ({ collectionSlug, docID }: { collectionSlug: string; docID?: number | string }) => {\n if (drawerDepth === 1) {\n // not in a drawer (default is 1)\n if (collectionSlug === folderCollectionSlug) {\n // clicked on folder, take the user to the folder view\n startRouteTransition(() => {\n router.push(getFolderRoute(docID))\n clearSelections()\n })\n } else 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 if (typeof onItemClickFromProps === 'function') {\n onItemClickFromProps(getItem(`${collectionSlug}-${docID}`))\n }\n },\n [\n clearSelections,\n config.routes.admin,\n drawerDepth,\n folderCollectionSlug,\n getFolderRoute,\n getItem,\n onItemClickFromProps,\n router,\n startRouteTransition,\n ],\n )\n\n const handleShiftSelection = React.useCallback(\n (targetIndex: number) => {\n const allItems = [...subfolders, ...documents]\n\n // Find existing selection boundaries\n const existingIndexes = allItems.reduce((acc, item, idx) => {\n if (selectedItemKeys.has(item.itemKey)) {\n acc.push(idx)\n }\n return acc\n }, [])\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 = 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 (targetIndex === firstSelectedIndex || targetIndex === lastSelectedIndex) {\n anchorIndex = targetIndex\n } else {\n const distanceToFirst = Math.abs(targetIndex - firstSelectedIndex)\n const distanceToLast = Math.abs(targetIndex - lastSelectedIndex)\n anchorIndex = distanceToFirst >= distanceToLast ? firstSelectedIndex : 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 = distanceToFirst <= distanceToLast ? firstSelectedIndex : 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 return [...new Set([...existingIndexes, ...newRangeIndexes])]\n }\n },\n [subfolders, documents, selectedItemKeys],\n )\n\n const updateSelections = React.useCallback(\n ({ indexes }: { indexes: number[] }) => {\n const allItems = [...subfolders, ...documents]\n const { newSelectedFolderCollections, newSelectedItemKeys } = allItems.reduce(\n (acc, item, index) => {\n if (indexes.includes(index)) {\n acc.newSelectedItemKeys.add(item.itemKey)\n if (item.relationTo === folderCollectionSlug) {\n item.value.folderType?.forEach((collectionSlug) => {\n if (!acc.newSelectedFolderCollections.includes(collectionSlug)) {\n acc.newSelectedFolderCollections.push(collectionSlug)\n }\n })\n } else {\n if (!acc.newSelectedFolderCollections.includes(item.relationTo)) {\n acc.newSelectedFolderCollections.push(item.relationTo)\n }\n }\n }\n return acc\n },\n {\n newSelectedFolderCollections: [] satisfies CollectionSlug[],\n newSelectedItemKeys: new Set<FolderDocumentItemKey>(),\n },\n )\n\n setSelectedFolderCollections(newSelectedFolderCollections)\n setSelectedItemKeys(newSelectedItemKeys)\n },\n [documents, folderCollectionSlug, subfolders],\n )\n\n const onItemKeyPress: FolderContextValue['onItemKeyPress'] = React.useCallback(\n ({ event, item: currentItem }) => {\n const { code, ctrlKey, metaKey, shiftKey } = event\n const isShiftPressed = shiftKey\n const isCtrlPressed = ctrlKey || metaKey\n const isCurrentlySelected = selectedItemKeys.has(currentItem.itemKey)\n const allItems = [...subfolders, ...documents]\n const currentItemIndex = allItems.findIndex((item) => item.itemKey === currentItem.itemKey)\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 ? currentItemIndex - 1 : currentItemIndex + 1\n\n if (newItemIndex < 0 || newItemIndex > totalCount - 1) {\n // out of bounds, keep current selection\n return\n }\n\n setFocusedRowIndex(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 setSelectedItemKeys(new Set([newItem.itemKey]))\n }\n\n break\n }\n case 'Enter': {\n if (selectedItemKeys.size === 1) {\n setFocusedRowIndex(undefined)\n navigateAfterSelection({\n collectionSlug: currentItem.relationTo,\n docID: extractID(currentItem.value),\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 setFocusedRowIndex(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 const allItems = [...subfolders, ...documents]\n updateSelections({\n indexes: allItems.reduce((acc, item, idx) => {\n if (item.itemKey === currentItem.itemKey) {\n if (isCurrentlySelected) {\n return acc\n } else {\n acc.push(idx)\n }\n } else if (selectedItemKeys.has(item.itemKey)) {\n acc.push(idx)\n }\n return acc\n }, []),\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 && selectedItemKeys?.size > 0) {\n setFocusedRowIndex(prevIndex)\n }\n } else {\n const nextIndex = currentItemIndex + 1\n if (nextIndex === totalCount && selectedItemKeys.size > 0) {\n setFocusedRowIndex(totalCount - 1)\n }\n }\n break\n }\n }\n },\n [\n selectedItemKeys,\n subfolders,\n documents,\n allowMultiSelection,\n handleShiftSelection,\n updateSelections,\n navigateAfterSelection,\n clearSelections,\n totalCount,\n ],\n )\n\n const onItemClick: FolderContextValue['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 = selectedItemKeys.has(clickedItem.itemKey)\n const allItems = [...subfolders, ...documents]\n const currentItemIndex = allItems.findIndex((item) => item.itemKey === clickedItem.itemKey)\n\n if (allowMultiSelection && isCtrlPressed) {\n event.preventDefault()\n let overlayItemKey: FolderDocumentItemKey | undefined\n const indexes = allItems.reduce((acc, item, idx) => {\n if (item.itemKey === clickedItem.itemKey) {\n if (isCurrentlySelected && event.type !== 'pointermove') {\n return acc\n } else {\n acc.push(idx)\n overlayItemKey = item.itemKey\n }\n } else if (selectedItemKeys.has(item.itemKey)) {\n acc.push(idx)\n }\n return acc\n }, [])\n\n updateSelections({ indexes })\n\n if (overlayItemKey) {\n setDragOverlayItem(getItem(overlayItemKey))\n }\n } else if (allowMultiSelection && isShiftPressed) {\n if (currentItemIndex !== -1) {\n const selectedIndexes = handleShiftSelection(currentItemIndex)\n updateSelections({ indexes: selectedIndexes })\n }\n } else if (allowMultiSelection && event.type === 'pointermove') {\n // on drag start of an unselected item\n if (!isCurrentlySelected) {\n updateSelections({\n indexes: allItems.reduce((acc, item, idx) => {\n if (item.itemKey === clickedItem.itemKey) {\n acc.push(idx)\n }\n return acc\n }, []),\n })\n }\n setDragOverlayItem(getItem(clickedItem.itemKey))\n } else {\n // Normal click - select single item\n const now = Date.now()\n doubleClicked =\n now - lastClickTime.current < 400 && dragOverlayItem?.itemKey === clickedItem.itemKey\n lastClickTime.current = now\n if (!doubleClicked) {\n updateSelections({\n indexes: isCurrentlySelected && selectedItemKeys.size === 1 ? [] : [currentItemIndex],\n })\n }\n setDragOverlayItem(getItem(clickedItem.itemKey))\n }\n\n if (doubleClicked) {\n navigateAfterSelection({\n collectionSlug: clickedItem.relationTo,\n docID: extractID(clickedItem.value),\n })\n }\n },\n [\n selectedItemKeys,\n subfolders,\n documents,\n allowMultiSelection,\n dragOverlayItem,\n getItem,\n updateSelections,\n navigateAfterSelection,\n handleShiftSelection,\n ],\n )\n\n /**\n * Makes requests to the server to update the folder field on passed in documents\n *\n * Might rewrite this in the future to return the promises so errors can be handled contextually\n */\n const moveToFolder: FolderContextValue['moveToFolder'] = React.useCallback(\n async (args) => {\n const { itemsToMove: items, toFolderID } = args\n if (!items.length) {\n return\n }\n\n const movingCurrentFolder =\n items.length === 1 &&\n items[0].relationTo === folderCollectionSlug &&\n items[0].value.id === folderID\n\n if (movingCurrentFolder) {\n const queryParams = qs.stringify(\n {\n depth: 0,\n locale: localeCode,\n },\n {\n addQueryPrefix: true,\n },\n )\n const req = await fetch(\n `${serverURL}${routes.api}/${folderCollectionSlug}/${folderID}${queryParams}`,\n {\n body: JSON.stringify({ [folderFieldName]: toFolderID || null }),\n credentials: 'include',\n headers: {\n 'content-type': 'application/json',\n },\n method: 'PATCH',\n },\n )\n if (req.status !== 200) {\n toast.error(t('general:error'))\n }\n } else {\n for (const [collectionSlug, ids] of Object.entries(groupItemIDsByRelation(items))) {\n const queryParams = qs.stringify(\n {\n depth: 0,\n limit: 0,\n locale: localeCode,\n where: {\n id: {\n in: ids,\n },\n },\n },\n {\n addQueryPrefix: true,\n },\n )\n try {\n await fetch(`${serverURL}${routes.api}/${collectionSlug}${queryParams}`, {\n body: JSON.stringify({ [folderFieldName]: toFolderID || null }),\n credentials: 'include',\n headers: {\n 'content-type': 'application/json',\n },\n method: 'PATCH',\n })\n } catch (error) {\n toast.error(t('general:error'))\n // eslint-disable-next-line no-console\n console.error(error)\n continue\n }\n }\n }\n\n clearSelections()\n },\n [\n folderID,\n clearSelections,\n folderCollectionSlug,\n folderFieldName,\n routes.api,\n serverURL,\n t,\n localeCode,\n ],\n )\n\n const checkIfItemIsDisabled: FolderContextValue['checkIfItemIsDisabled'] = React.useCallback(\n (item) => {\n function folderAcceptsItem({\n item,\n selectedFolderCollections,\n }: {\n item: FolderOrDocument\n selectedFolderCollections: string[]\n }): boolean {\n if (\n !item.value.folderType ||\n (Array.isArray(item.value.folderType) && item.value.folderType.length === 0)\n ) {\n // Enable folder that accept all collections\n return false\n }\n\n if (selectedFolderCollections.length === 0) {\n // If no collections are selected, enable folders that accept all collections\n return Boolean(item.value.folderType || item.value.folderType.length > 0)\n }\n\n // Disable folders that do not accept all of the selected collections\n return selectedFolderCollections.some((slug) => {\n return !item.value.folderType.includes(slug)\n })\n }\n\n if (isDragging) {\n const isSelected = selectedItemKeys.has(item.itemKey)\n if (isSelected) {\n return true\n } else if (item.relationTo === folderCollectionSlug) {\n return folderAcceptsItem({ item, selectedFolderCollections })\n } else {\n // Non folder items are disabled on drag\n return true\n }\n } else if (parentFolderContext?.selectedItemKeys?.size) {\n // Disable selected items from being navigated to in move to drawer\n if (parentFolderContext.selectedItemKeys.has(item.itemKey)) {\n return true\n }\n // Moving items to folder\n if (item.relationTo === folderCollectionSlug) {\n return folderAcceptsItem({\n item,\n selectedFolderCollections: parentFolderContext.selectedFolderCollections,\n })\n }\n // If the item is not a folder, it is disabled on move\n return true\n }\n },\n [\n selectedFolderCollections,\n isDragging,\n selectedItemKeys,\n folderCollectionSlug,\n parentFolderContext?.selectedFolderCollections,\n parentFolderContext?.selectedItemKeys,\n ],\n )\n\n // If a new component is provided, update the state so children can re-render with the new component\n React.useEffect(() => {\n if (InitialFolderResultsComponent) {\n setFolderResultsComponent(InitialFolderResultsComponent)\n }\n }, [InitialFolderResultsComponent])\n\n return (\n <Context\n value={{\n activeCollectionFolderSlugs: activeCollectionSlugs || allCollectionFolderSlugs,\n allCollectionFolderSlugs,\n allowCreateCollectionSlugs,\n breadcrumbs,\n checkIfItemIsDisabled,\n clearSelections,\n currentFolder:\n breadcrumbs?.[breadcrumbs.length - 1]?.id !== undefined\n ? formatFolderOrDocumentItem({\n folderFieldName,\n isUpload: false,\n relationTo: folderCollectionSlug,\n useAsTitle: folderCollectionConfig.admin.useAsTitle,\n value: breadcrumbs[breadcrumbs.length - 1],\n })\n : null,\n documents,\n dragOverlayItem,\n focusedRowIndex,\n folderCollectionConfig,\n folderCollectionSlug,\n folderFieldName,\n folderID,\n FolderResultsComponent,\n folderType: breadcrumbs?.[breadcrumbs.length - 1]?.folderType,\n getFolderRoute,\n getSelectedItems,\n isDragging,\n itemKeysToMove: parentFolderContext.selectedItemKeys,\n moveToFolder,\n onItemClick,\n onItemKeyPress,\n refineFolderData,\n search,\n selectedFolderCollections,\n selectedItemKeys,\n setBreadcrumbs,\n setFocusedRowIndex,\n setIsDragging,\n sort,\n subfolders,\n }}\n >\n {children}\n </Context>\n )\n}\n\nexport function useFolder(): FolderContextValue {\n const context = React.use(Context)\n\n if (context === undefined) {\n throw new Error('useFolder must be used within a FolderProvider')\n }\n\n return context\n}\n"],"names":["useRouter","useSearchParams","extractID","formatAdminURL","formatFolderOrDocumentItem","qs","React","toast","useDrawerDepth","parseSearchParams","useConfig","useLocale","useRouteTransition","useTranslation","groupItemIDsByRelation","Context","createContext","activeCollectionFolderSlugs","allCollectionFolderSlugs","allowCreateCollectionSlugs","breadcrumbs","checkIfItemIsDisabled","clearSelections","currentFolder","documents","dragOverlayItem","undefined","focusedRowIndex","folderCollectionConfig","folderCollectionSlug","folderFieldName","folderID","FolderResultsComponent","folderType","getFolderRoute","getSelectedItems","isDragging","itemKeysToMove","moveToFolder","Promise","resolve","onItemClick","onItemKeyPress","refineFolderData","search","selectedFolderCollections","selectedItemKeys","Set","setBreadcrumbs","setFocusedRowIndex","setIsDragging","sort","subfolders","FolderProvider","activeCollectionSlugs","allowMultiSelection","baseFolderPath","_breadcrumbsFromProps","children","InitialFolderResultsComponent","onItemClickFromProps","parentFolderContext","useFolder","config","routes","serverURL","drawerDepth","t","router","startRouteTransition","locale","localeCode","code","currentlySelectedIndexes","useRef","setSelectedFolderCollections","useState","setFolderResultsComponent","collections","find","collection","folders","slug","rawSearchParams","searchParams","useMemo","currentQuery","setCurrentQuery","setSelectedItemKeys","setDragOverlayItem","lastClickTime","totalCount","length","useCallback","current","mergeQuery","newQuery","page","mergedQuery","relationTo","query","updateURL","queryParams","replace","stringify","JSON","addQueryPrefix","toFolderID","adminRoute","admin","path","getItem","itemKey","doc","Array","from","reduce","acc","item","push","navigateAfterSelection","collectionSlug","docID","handleShiftSelection","targetIndex","allItems","existingIndexes","idx","has","firstSelectedIndex","Math","min","lastSelectedIndex","max","isWithinBounds","anchorIndex","distanceToFirst","abs","distanceToLast","startIndex","endIndex","newRangeIndexes","_","i","updateSelections","indexes","newSelectedFolderCollections","newSelectedItemKeys","index","includes","add","value","forEach","event","currentItem","ctrlKey","metaKey","shiftKey","isShiftPressed","isCtrlPressed","isCurrentlySelected","currentItemIndex","findIndex","preventDefault","isBackward","newItemIndex","selectedIndexes","newItem","size","prevIndex","nextIndex","clickedItem","doubleClicked","overlayItemKey","type","now","Date","args","itemsToMove","items","movingCurrentFolder","id","depth","req","fetch","api","body","credentials","headers","method","status","error","ids","Object","entries","limit","where","in","console","folderAcceptsItem","isArray","Boolean","some","isSelected","useEffect","isUpload","useAsTitle","context","use","Error"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/providers/ListQuery/types.ts"],"sourcesContent":["import type {\n ClientCollectionConfig,\n ListQuery,\n PaginatedDistinctDocs,\n PaginatedDocs,\n Sort,\n Where,\n} from 'payload'\n\ntype ContextHandlers = {\n handlePageChange?: (page: number) => Promise<void>\n handlePerPageChange?: (limit: number) => Promise<void>\n handleSearchChange?: (search: string) => Promise<void>\n handleSortChange?: (sort: string) => Promise<void>\n handleWhereChange?: (where: Where) => Promise<void>\n}\n\nexport type OnListQueryChange = (query: ListQuery) => void\n\nexport type ListQueryProps = {\n readonly children: React.ReactNode\n readonly collectionSlug?: ClientCollectionConfig['slug']\n readonly data: PaginatedDocs | undefined\n readonly modifySearchParams?: boolean\n readonly onQueryChange?: OnListQueryChange\n readonly orderableFieldName?: string\n /**\n * @deprecated\n */\n readonly preferenceKey?: string\n readonly query?: ListQuery\n}\n\nexport type IListQueryContext = {\n collectionSlug: ClientCollectionConfig['slug']\n data: ListQueryProps['data']\n defaultLimit?: number\n defaultSort?: Sort\n /**\n * @experimental This prop is subject to change. Use at your own risk.\n */\n isGroupingBy: boolean\n modified: boolean\n orderableFieldName?: string\n query: ListQuery\n refineListData: (args: ListQuery, setModified?: boolean) => Promise<void>\n setModified: (modified: boolean) => void\n} & ContextHandlers\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/providers/ListQuery/types.ts"],"sourcesContent":["import type {\n ClientCollectionConfig,\n ListQuery,\n PaginatedDistinctDocs,\n PaginatedDocs,\n Sort,\n Where,\n} from 'payload'\n\ntype ContextHandlers = {\n handlePageChange?: (page: number) => Promise<void>\n handlePerPageChange?: (limit: number) => Promise<void>\n handleSearchChange?: (search: string) => Promise<void>\n handleSortChange?: (sort: string) => Promise<void>\n handleWhereChange?: (where: Where) => Promise<void>\n}\n\nexport type OnListQueryChange = (query: ListQuery) => void\n\nexport type ListQueryProps = {\n readonly children: React.ReactNode\n readonly collectionSlug?: ClientCollectionConfig['slug']\n readonly data: PaginatedDocs | undefined\n readonly modifySearchParams?: boolean\n readonly onQueryChange?: OnListQueryChange\n readonly orderableFieldName?: string\n /**\n * @deprecated\n */\n readonly preferenceKey?: string\n readonly query?: ListQuery\n}\n\nexport type IListQueryContext = {\n collectionSlug: ClientCollectionConfig['slug']\n data: ListQueryProps['data']\n defaultLimit?: number\n defaultSort?: Sort\n /**\n * @experimental This prop is subject to change. Use at your own risk.\n */\n isGroupingBy: boolean\n modified: boolean\n orderableFieldName?: string\n query: ListQuery\n refineListData: (args: ListQuery, setModified?: boolean) => Promise<void>\n setModified: (modified: boolean) => void\n} & ContextHandlers\n"],"names":[],"mappings":"AA0BE;;GAEC,GAKH,WAcmB,CATjB;;GAEC"}
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { createContext, use } from 'react';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* The URL that has finished loading in the iframe or popup.
|
|
5
|
+
* For example, if you set the `url`, it will begin to load into the iframe,
|
|
6
|
+
* but `loadedURL` will not be set until the iframe's `onLoad` event fires.
|
|
7
|
+
*/ /**
|
|
8
|
+
* Sets the URL of the preview (either iframe or popup).
|
|
9
|
+
* Will trigger a reload of the window.
|
|
10
|
+
*/ /**
|
|
11
|
+
* The live preview url property can be either a string or a function that returns a string.
|
|
12
|
+
* It is important to know which one it is, so that we can opt in/out of certain behaviors, e.g. calling the server to get the URL.
|
|
13
|
+
*/ export const LivePreviewContext = createContext({
|
|
4
14
|
appIsReady: false,
|
|
5
15
|
breakpoint: undefined,
|
|
6
16
|
breakpoints: undefined,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/providers/LivePreview/context.ts"],"sourcesContent":["'use client'\nimport type { LivePreviewConfig, LivePreviewURLType } from 'payload'\nimport type { Dispatch } from 'react'\nimport type React from 'react'\n\nimport { createContext, use } from 'react'\n\nimport type { usePopupWindow } from '../../hooks/usePopupWindow.js'\nimport type { SizeReducerAction } from './sizeReducer.js'\n\nexport interface LivePreviewContextType {\n appIsReady: boolean\n breakpoint: LivePreviewConfig['breakpoints'][number]['name']\n breakpoints: LivePreviewConfig['breakpoints']\n iframeRef: React.RefObject<HTMLIFrameElement | null>\n isLivePreviewEnabled: boolean\n isLivePreviewing: boolean\n isPopupOpen: boolean\n isPreviewEnabled: boolean\n listeningForMessages?: boolean\n /**\n * The URL that has finished loading in the iframe or popup.\n * For example, if you set the `url`, it will begin to load into the iframe,\n * but `loadedURL` will not be set until the iframe's `onLoad` event fires.\n */\n loadedURL?: string\n measuredDeviceSize: {\n height: number\n width: number\n }\n openPopupWindow: ReturnType<typeof usePopupWindow>['openPopupWindow']\n popupRef?: React.RefObject<null | Window>\n previewURL?: string\n previewWindowType: 'iframe' | 'popup'\n setAppIsReady: (appIsReady: boolean) => void\n setBreakpoint: (breakpoint: LivePreviewConfig['breakpoints'][number]['name']) => void\n setHeight: (height: number) => void\n setIsLivePreviewing: (isLivePreviewing: boolean) => void\n setLoadedURL: (loadedURL: string) => void\n setMeasuredDeviceSize: (size: { height: number; width: number }) => void\n setPreviewURL: (url: string) => void\n setPreviewWindowType: (previewWindowType: 'iframe' | 'popup') => void\n setSize: Dispatch<SizeReducerAction>\n setToolbarPosition: (position: { x: number; y: number }) => void\n\n /**\n * Sets the URL of the preview (either iframe or popup).\n * Will trigger a reload of the window.\n */\n setURL: (url: string) => void\n setWidth: (width: number) => void\n setZoom: (zoom: number) => void\n size: {\n height: number\n width: number\n }\n toolbarPosition: {\n x: number\n y: number\n }\n /**\n * The live preview url property can be either a string or a function that returns a string.\n * It is important to know which one it is, so that we can opt in/out of certain behaviors, e.g. calling the server to get the URL.\n */\n typeofLivePreviewURL?: 'function' | 'string'\n url: LivePreviewURLType\n zoom: number\n}\n\nexport const LivePreviewContext = createContext<LivePreviewContextType>({\n appIsReady: false,\n breakpoint: undefined,\n breakpoints: undefined,\n iframeRef: undefined,\n isLivePreviewEnabled: undefined,\n isLivePreviewing: false,\n isPopupOpen: false,\n isPreviewEnabled: undefined,\n measuredDeviceSize: {\n height: 0,\n width: 0,\n },\n openPopupWindow: () => {},\n popupRef: undefined,\n previewURL: undefined,\n previewWindowType: 'iframe',\n setAppIsReady: () => {},\n setBreakpoint: () => {},\n setHeight: () => {},\n setIsLivePreviewing: () => {},\n setLoadedURL: () => {},\n setMeasuredDeviceSize: () => {},\n setPreviewURL: () => {},\n setPreviewWindowType: () => {},\n setSize: () => {},\n setToolbarPosition: () => {},\n setURL: () => {},\n setWidth: () => {},\n setZoom: () => {},\n size: {\n height: 0,\n width: 0,\n },\n toolbarPosition: {\n x: 0,\n y: 0,\n },\n typeofLivePreviewURL: undefined,\n url: undefined,\n zoom: 1,\n})\n\nexport const useLivePreviewContext = () => use(LivePreviewContext)\n\n/**\n * Hook to access live preview context values. Separated to prevent breaking changes. In the future this hook can be removed in favour of just using the LivePreview one.\n */\nexport const usePreviewURL = () => {\n const { isPreviewEnabled, previewURL, setPreviewURL } = use(LivePreviewContext)\n\n return { isPreviewEnabled, previewURL, setPreviewURL }\n}\n"],"names":["createContext","use","LivePreviewContext","appIsReady","breakpoint","undefined","breakpoints","iframeRef","isLivePreviewEnabled","isLivePreviewing","isPopupOpen","isPreviewEnabled","measuredDeviceSize","height","width","openPopupWindow","popupRef","previewURL","previewWindowType","setAppIsReady","setBreakpoint","setHeight","setIsLivePreviewing","setLoadedURL","setMeasuredDeviceSize","setPreviewURL","setPreviewWindowType","setSize","setToolbarPosition","setURL","setWidth","setZoom","size","toolbarPosition","x","y","typeofLivePreviewURL","url","zoom","useLivePreviewContext","usePreviewURL"],"mappings":"AAAA;AAKA,SAASA,aAAa,EAAEC,GAAG,QAAQ,QAAO;
|
|
1
|
+
{"version":3,"sources":["../../../src/providers/LivePreview/context.ts"],"sourcesContent":["'use client'\nimport type { LivePreviewConfig, LivePreviewURLType } from 'payload'\nimport type { Dispatch } from 'react'\nimport type React from 'react'\n\nimport { createContext, use } from 'react'\n\nimport type { usePopupWindow } from '../../hooks/usePopupWindow.js'\nimport type { SizeReducerAction } from './sizeReducer.js'\n\nexport interface LivePreviewContextType {\n appIsReady: boolean\n breakpoint: LivePreviewConfig['breakpoints'][number]['name']\n breakpoints: LivePreviewConfig['breakpoints']\n iframeRef: React.RefObject<HTMLIFrameElement | null>\n isLivePreviewEnabled: boolean\n isLivePreviewing: boolean\n isPopupOpen: boolean\n isPreviewEnabled: boolean\n listeningForMessages?: boolean\n /**\n * The URL that has finished loading in the iframe or popup.\n * For example, if you set the `url`, it will begin to load into the iframe,\n * but `loadedURL` will not be set until the iframe's `onLoad` event fires.\n */\n loadedURL?: string\n measuredDeviceSize: {\n height: number\n width: number\n }\n openPopupWindow: ReturnType<typeof usePopupWindow>['openPopupWindow']\n popupRef?: React.RefObject<null | Window>\n previewURL?: string\n previewWindowType: 'iframe' | 'popup'\n setAppIsReady: (appIsReady: boolean) => void\n setBreakpoint: (breakpoint: LivePreviewConfig['breakpoints'][number]['name']) => void\n setHeight: (height: number) => void\n setIsLivePreviewing: (isLivePreviewing: boolean) => void\n setLoadedURL: (loadedURL: string) => void\n setMeasuredDeviceSize: (size: { height: number; width: number }) => void\n setPreviewURL: (url: string) => void\n setPreviewWindowType: (previewWindowType: 'iframe' | 'popup') => void\n setSize: Dispatch<SizeReducerAction>\n setToolbarPosition: (position: { x: number; y: number }) => void\n\n /**\n * Sets the URL of the preview (either iframe or popup).\n * Will trigger a reload of the window.\n */\n setURL: (url: string) => void\n setWidth: (width: number) => void\n setZoom: (zoom: number) => void\n size: {\n height: number\n width: number\n }\n toolbarPosition: {\n x: number\n y: number\n }\n /**\n * The live preview url property can be either a string or a function that returns a string.\n * It is important to know which one it is, so that we can opt in/out of certain behaviors, e.g. calling the server to get the URL.\n */\n typeofLivePreviewURL?: 'function' | 'string'\n url: LivePreviewURLType\n zoom: number\n}\n\nexport const LivePreviewContext = createContext<LivePreviewContextType>({\n appIsReady: false,\n breakpoint: undefined,\n breakpoints: undefined,\n iframeRef: undefined,\n isLivePreviewEnabled: undefined,\n isLivePreviewing: false,\n isPopupOpen: false,\n isPreviewEnabled: undefined,\n measuredDeviceSize: {\n height: 0,\n width: 0,\n },\n openPopupWindow: () => {},\n popupRef: undefined,\n previewURL: undefined,\n previewWindowType: 'iframe',\n setAppIsReady: () => {},\n setBreakpoint: () => {},\n setHeight: () => {},\n setIsLivePreviewing: () => {},\n setLoadedURL: () => {},\n setMeasuredDeviceSize: () => {},\n setPreviewURL: () => {},\n setPreviewWindowType: () => {},\n setSize: () => {},\n setToolbarPosition: () => {},\n setURL: () => {},\n setWidth: () => {},\n setZoom: () => {},\n size: {\n height: 0,\n width: 0,\n },\n toolbarPosition: {\n x: 0,\n y: 0,\n },\n typeofLivePreviewURL: undefined,\n url: undefined,\n zoom: 1,\n})\n\nexport const useLivePreviewContext = () => use(LivePreviewContext)\n\n/**\n * Hook to access live preview context values. Separated to prevent breaking changes. In the future this hook can be removed in favour of just using the LivePreview one.\n */\nexport const usePreviewURL = () => {\n const { isPreviewEnabled, previewURL, setPreviewURL } = use(LivePreviewContext)\n\n return { isPreviewEnabled, previewURL, setPreviewURL }\n}\n"],"names":["createContext","use","LivePreviewContext","appIsReady","breakpoint","undefined","breakpoints","iframeRef","isLivePreviewEnabled","isLivePreviewing","isPopupOpen","isPreviewEnabled","measuredDeviceSize","height","width","openPopupWindow","popupRef","previewURL","previewWindowType","setAppIsReady","setBreakpoint","setHeight","setIsLivePreviewing","setLoadedURL","setMeasuredDeviceSize","setPreviewURL","setPreviewWindowType","setSize","setToolbarPosition","setURL","setWidth","setZoom","size","toolbarPosition","x","y","typeofLivePreviewURL","url","zoom","useLivePreviewContext","usePreviewURL"],"mappings":"AAAA;AAKA,SAASA,aAAa,EAAEC,GAAG,QAAQ,QAAO;AAexC;;;;GAIC,GAqBD;;;GAGC,GAYD;;;GAGC,GAMH,OAAO,MAAMC,qBAAqBF,cAAsC;IACtEG,YAAY;IACZC,YAAYC;IACZC,aAAaD;IACbE,WAAWF;IACXG,sBAAsBH;IACtBI,kBAAkB;IAClBC,aAAa;IACbC,kBAAkBN;IAClBO,oBAAoB;QAClBC,QAAQ;QACRC,OAAO;IACT;IACAC,iBAAiB,KAAO;IACxBC,UAAUX;IACVY,YAAYZ;IACZa,mBAAmB;IACnBC,eAAe,KAAO;IACtBC,eAAe,KAAO;IACtBC,WAAW,KAAO;IAClBC,qBAAqB,KAAO;IAC5BC,cAAc,KAAO;IACrBC,uBAAuB,KAAO;IAC9BC,eAAe,KAAO;IACtBC,sBAAsB,KAAO;IAC7BC,SAAS,KAAO;IAChBC,oBAAoB,KAAO;IAC3BC,QAAQ,KAAO;IACfC,UAAU,KAAO;IACjBC,SAAS,KAAO;IAChBC,MAAM;QACJnB,QAAQ;QACRC,OAAO;IACT;IACAmB,iBAAiB;QACfC,GAAG;QACHC,GAAG;IACL;IACAC,sBAAsB/B;IACtBgC,KAAKhC;IACLiC,MAAM;AACR,GAAE;AAEF,OAAO,MAAMC,wBAAwB,IAAMtC,IAAIC,oBAAmB;AAElE;;CAEC,GACD,OAAO,MAAMsC,gBAAgB;IAC3B,MAAM,EAAE7B,gBAAgB,EAAEM,UAAU,EAAEQ,aAAa,EAAE,GAAGxB,IAAIC;IAE5D,OAAO;QAAES;QAAkBM;QAAYQ;IAAc;AACvD,EAAC"}
|
|
@@ -9,7 +9,11 @@ import { formatAbsoluteURL } from '../../utilities/formatAbsoluteURL.js';
|
|
|
9
9
|
import { customCollisionDetection } from './collisionDetection.js';
|
|
10
10
|
import { LivePreviewContext } from './context.js';
|
|
11
11
|
import { sizeReducer } from './sizeReducer.js';
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* This specifically relates to `admin.preview` function in the config instead of live preview.
|
|
14
|
+
*/ /**
|
|
15
|
+
* This specifically relates to `admin.preview` function in the config instead of live preview.
|
|
16
|
+
*/ export const LivePreviewProvider = ({ breakpoints: incomingBreakpoints, children, isLivePreviewEnabled, isLivePreviewing: incomingIsLivePreviewing, isPreviewEnabled, previewURL: previewURLFromProps, typeofLivePreviewURL, url: urlFromProps })=>{
|
|
13
17
|
const [previewWindowType, setPreviewWindowType] = useState('iframe');
|
|
14
18
|
const [isLivePreviewing, setIsLivePreviewing] = useState(incomingIsLivePreviewing);
|
|
15
19
|
const breakpoints = useMemo(()=>[
|
|
@@ -90,10 +94,9 @@ export const LivePreviewProvider = ({ breakpoints: incomingBreakpoints, children
|
|
|
90
94
|
y: position.y + ev.delta.y
|
|
91
95
|
};
|
|
92
96
|
setPosition(newPos);
|
|
93
|
-
} else {
|
|
94
|
-
// reset
|
|
95
|
-
}
|
|
97
|
+
} else {}
|
|
96
98
|
};
|
|
99
|
+
// reset
|
|
97
100
|
const setWidth = useCallback((width)=>{
|
|
98
101
|
setSize({
|
|
99
102
|
type: 'width',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/providers/LivePreview/index.tsx"],"sourcesContent":["'use client'\nimport type { CollectionPreferences, LivePreviewConfig, LivePreviewURLType } from 'payload'\n\nimport { DndContext } from '@dnd-kit/core'\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport type { LivePreviewContextType } from './context.js'\n\nimport { usePopupWindow } from '../../hooks/usePopupWindow.js'\nimport { useDocumentInfo } from '../../providers/DocumentInfo/index.js'\nimport { usePreferences } from '../../providers/Preferences/index.js'\nimport { formatAbsoluteURL } from '../../utilities/formatAbsoluteURL.js'\nimport { customCollisionDetection } from './collisionDetection.js'\nimport { LivePreviewContext } from './context.js'\nimport { sizeReducer } from './sizeReducer.js'\n\nexport type LivePreviewProviderProps = {\n appIsReady?: boolean\n breakpoints?: LivePreviewConfig['breakpoints']\n children: React.ReactNode\n deviceSize?: {\n height: number\n width: number\n }\n isLivePreviewEnabled?: boolean\n isLivePreviewing: boolean\n /**\n * This specifically relates to `admin.preview` function in the config instead of live preview.\n */\n isPreviewEnabled?: boolean\n /**\n * This specifically relates to `admin.preview` function in the config instead of live preview.\n */\n previewURL?: string\n} & Pick<LivePreviewContextType, 'typeofLivePreviewURL' | 'url'>\n\nexport const LivePreviewProvider: React.FC<LivePreviewProviderProps> = ({\n breakpoints: incomingBreakpoints,\n children,\n isLivePreviewEnabled,\n isLivePreviewing: incomingIsLivePreviewing,\n isPreviewEnabled,\n previewURL: previewURLFromProps,\n typeofLivePreviewURL,\n url: urlFromProps,\n}) => {\n const [previewWindowType, setPreviewWindowType] = useState<'iframe' | 'popup'>('iframe')\n const [isLivePreviewing, setIsLivePreviewing] = useState(incomingIsLivePreviewing)\n\n const breakpoints: LivePreviewConfig['breakpoints'] = useMemo(\n () => [\n ...(incomingBreakpoints || []),\n {\n name: 'responsive',\n height: '100%',\n label: 'Responsive',\n width: '100%',\n },\n ],\n [incomingBreakpoints],\n )\n\n const [url, setURL] = useState<string>('')\n const [previewURL, setPreviewURL] = useState<string>(previewURLFromProps)\n\n const { isPopupOpen, openPopupWindow, popupRef } = usePopupWindow({\n eventType: 'payload-live-preview',\n url,\n })\n\n const [appIsReady, setAppIsReady] = useState(false)\n const [listeningForMessages, setListeningForMessages] = useState(false)\n\n const { collectionSlug, globalSlug } = useDocumentInfo()\n\n const isFirstRender = useRef(true)\n\n const { setPreference } = usePreferences()\n\n const iframeRef = React.useRef<HTMLIFrameElement>(null)\n\n const [loadedURL, setLoadedURL] = useState<string>()\n\n const [zoom, setZoom] = useState(1)\n\n const [position, setPosition] = useState({ x: 0, y: 0 })\n\n const [size, setSize] = React.useReducer(sizeReducer, { height: 0, width: 0 })\n\n const [measuredDeviceSize, setMeasuredDeviceSize] = useState({\n height: 0,\n width: 0,\n })\n\n const [breakpoint, setBreakpoint] =\n React.useState<LivePreviewConfig['breakpoints'][0]['name']>('responsive')\n\n /**\n * A \"middleware\" callback fn that does some additional work before `setURL`.\n * This is what we provide through context, bc it:\n * - ensures the URL is absolute\n * - resets `appIsReady` to `false` while the new URL is loading\n */\n const setLivePreviewURL = useCallback<LivePreviewContextType['setURL']>(\n (_incomingURL) => {\n let incomingURL: LivePreviewURLType\n\n if (typeof _incomingURL === 'string') {\n incomingURL = formatAbsoluteURL(_incomingURL)\n }\n\n if (!incomingURL) {\n setIsLivePreviewing(false)\n }\n\n if (incomingURL !== url) {\n setAppIsReady(false)\n setURL(incomingURL)\n }\n },\n [url],\n )\n\n /**\n * `url` needs to be relative to the window, which cannot be done on initial render.\n */\n useEffect(() => {\n if (typeof urlFromProps === 'string') {\n setURL(formatAbsoluteURL(urlFromProps))\n }\n }, [urlFromProps])\n\n // The toolbar needs to freely drag and drop around the page\n const handleDragEnd = (ev) => {\n // only update position if the toolbar is completely within the preview area\n // otherwise reset it back to the previous position\n // TODO: reset to the nearest edge of the preview area\n if (ev.over && ev.over.id === 'live-preview-area') {\n const newPos = {\n x: position.x + ev.delta.x,\n y: position.y + ev.delta.y,\n }\n\n setPosition(newPos)\n } else {\n // reset\n }\n }\n\n const setWidth = useCallback(\n (width) => {\n setSize({ type: 'width', value: width })\n },\n [setSize],\n )\n\n const setHeight = useCallback(\n (height) => {\n setSize({ type: 'height', value: height })\n },\n [setSize],\n )\n\n // explicitly set new width and height when as new breakpoints are selected\n // exclude `custom` breakpoint as it is handled by the `setWidth` and `setHeight` directly\n useEffect(() => {\n const foundBreakpoint = breakpoints?.find((bp) => bp.name === breakpoint)\n\n if (\n foundBreakpoint &&\n breakpoint !== 'responsive' &&\n breakpoint !== 'custom' &&\n typeof foundBreakpoint?.width === 'number' &&\n typeof foundBreakpoint?.height === 'number'\n ) {\n setSize({\n type: 'reset',\n value: {\n height: foundBreakpoint.height,\n width: foundBreakpoint.width,\n },\n })\n }\n }, [breakpoint, breakpoints])\n\n /**\n * Receive the `ready` message from the popup window\n * This indicates that the app is ready to receive `window.postMessage` events\n * This is also the only cross-origin way of detecting when a popup window has loaded\n * Unlike iframe elements which have an `onLoad` handler, there is no way to access `window.open` on popups\n */\n useEffect(() => {\n const handleMessage = (event: MessageEvent) => {\n if (\n url?.startsWith(event.origin) &&\n event.data &&\n typeof event.data === 'object' &&\n event.data.type === 'payload-live-preview'\n ) {\n if (event.data.ready) {\n setAppIsReady(true)\n }\n }\n }\n\n window.addEventListener('message', handleMessage)\n\n setListeningForMessages(true)\n\n return () => {\n window.removeEventListener('message', handleMessage)\n }\n }, [url, listeningForMessages])\n\n const handleWindowChange = useCallback(\n (type: 'iframe' | 'popup') => {\n setAppIsReady(false)\n setPreviewWindowType(type)\n if (type === 'popup') {\n openPopupWindow()\n }\n },\n [openPopupWindow],\n )\n\n // when the user closes the popup window, switch back to the iframe\n // the `usePopupWindow` reports the `isPopupOpen` state for us to use here\n useEffect(() => {\n const newPreviewWindowType = isPopupOpen ? 'popup' : 'iframe'\n\n if (newPreviewWindowType !== previewWindowType) {\n handleWindowChange('iframe')\n }\n }, [previewWindowType, isPopupOpen, handleWindowChange])\n\n useEffect(() => {\n if (isFirstRender.current) {\n isFirstRender.current = false\n return\n }\n\n void setPreference<CollectionPreferences>(\n collectionSlug ? `collection-${collectionSlug}` : `global-${globalSlug}`,\n {\n editViewType: isLivePreviewing ? 'live-preview' : 'default',\n },\n true,\n )\n }, [isLivePreviewing, setPreference, collectionSlug, globalSlug])\n\n return (\n <LivePreviewContext\n value={{\n appIsReady,\n breakpoint,\n breakpoints,\n iframeRef,\n isLivePreviewEnabled,\n isLivePreviewing,\n isPopupOpen,\n isPreviewEnabled,\n listeningForMessages,\n loadedURL,\n measuredDeviceSize,\n openPopupWindow,\n popupRef,\n previewURL,\n previewWindowType,\n setAppIsReady,\n setBreakpoint,\n setHeight,\n setIsLivePreviewing,\n setLoadedURL,\n setMeasuredDeviceSize,\n setPreviewURL,\n setPreviewWindowType: handleWindowChange,\n setSize,\n setToolbarPosition: setPosition,\n setURL: setLivePreviewURL,\n setWidth,\n setZoom,\n size,\n toolbarPosition: position,\n typeofLivePreviewURL,\n url,\n zoom,\n }}\n >\n <DndContext collisionDetection={customCollisionDetection} onDragEnd={handleDragEnd}>\n {children}\n </DndContext>\n </LivePreviewContext>\n )\n}\n"],"names":["DndContext","React","useCallback","useEffect","useMemo","useRef","useState","usePopupWindow","useDocumentInfo","usePreferences","formatAbsoluteURL","customCollisionDetection","LivePreviewContext","sizeReducer","LivePreviewProvider","breakpoints","incomingBreakpoints","children","isLivePreviewEnabled","isLivePreviewing","incomingIsLivePreviewing","isPreviewEnabled","previewURL","previewURLFromProps","typeofLivePreviewURL","url","urlFromProps","previewWindowType","setPreviewWindowType","setIsLivePreviewing","name","height","label","width","setURL","setPreviewURL","isPopupOpen","openPopupWindow","popupRef","eventType","appIsReady","setAppIsReady","listeningForMessages","setListeningForMessages","collectionSlug","globalSlug","isFirstRender","setPreference","iframeRef","loadedURL","setLoadedURL","zoom","setZoom","position","setPosition","x","y","size","setSize","useReducer","measuredDeviceSize","setMeasuredDeviceSize","breakpoint","setBreakpoint","setLivePreviewURL","_incomingURL","incomingURL","handleDragEnd","ev","over","id","newPos","delta","setWidth","type","value","setHeight","foundBreakpoint","find","bp","handleMessage","event","startsWith","origin","data","ready","window","addEventListener","removeEventListener","handleWindowChange","newPreviewWindowType","current","editViewType","setToolbarPosition","toolbarPosition","collisionDetection","onDragEnd"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/providers/LivePreview/index.tsx"],"sourcesContent":["'use client'\nimport type { CollectionPreferences, LivePreviewConfig, LivePreviewURLType } from 'payload'\n\nimport { DndContext } from '@dnd-kit/core'\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport type { LivePreviewContextType } from './context.js'\n\nimport { usePopupWindow } from '../../hooks/usePopupWindow.js'\nimport { useDocumentInfo } from '../../providers/DocumentInfo/index.js'\nimport { usePreferences } from '../../providers/Preferences/index.js'\nimport { formatAbsoluteURL } from '../../utilities/formatAbsoluteURL.js'\nimport { customCollisionDetection } from './collisionDetection.js'\nimport { LivePreviewContext } from './context.js'\nimport { sizeReducer } from './sizeReducer.js'\n\nexport type LivePreviewProviderProps = {\n appIsReady?: boolean\n breakpoints?: LivePreviewConfig['breakpoints']\n children: React.ReactNode\n deviceSize?: {\n height: number\n width: number\n }\n isLivePreviewEnabled?: boolean\n isLivePreviewing: boolean\n /**\n * This specifically relates to `admin.preview` function in the config instead of live preview.\n */\n isPreviewEnabled?: boolean\n /**\n * This specifically relates to `admin.preview` function in the config instead of live preview.\n */\n previewURL?: string\n} & Pick<LivePreviewContextType, 'typeofLivePreviewURL' | 'url'>\n\nexport const LivePreviewProvider: React.FC<LivePreviewProviderProps> = ({\n breakpoints: incomingBreakpoints,\n children,\n isLivePreviewEnabled,\n isLivePreviewing: incomingIsLivePreviewing,\n isPreviewEnabled,\n previewURL: previewURLFromProps,\n typeofLivePreviewURL,\n url: urlFromProps,\n}) => {\n const [previewWindowType, setPreviewWindowType] = useState<'iframe' | 'popup'>('iframe')\n const [isLivePreviewing, setIsLivePreviewing] = useState(incomingIsLivePreviewing)\n\n const breakpoints: LivePreviewConfig['breakpoints'] = useMemo(\n () => [\n ...(incomingBreakpoints || []),\n {\n name: 'responsive',\n height: '100%',\n label: 'Responsive',\n width: '100%',\n },\n ],\n [incomingBreakpoints],\n )\n\n const [url, setURL] = useState<string>('')\n const [previewURL, setPreviewURL] = useState<string>(previewURLFromProps)\n\n const { isPopupOpen, openPopupWindow, popupRef } = usePopupWindow({\n eventType: 'payload-live-preview',\n url,\n })\n\n const [appIsReady, setAppIsReady] = useState(false)\n const [listeningForMessages, setListeningForMessages] = useState(false)\n\n const { collectionSlug, globalSlug } = useDocumentInfo()\n\n const isFirstRender = useRef(true)\n\n const { setPreference } = usePreferences()\n\n const iframeRef = React.useRef<HTMLIFrameElement>(null)\n\n const [loadedURL, setLoadedURL] = useState<string>()\n\n const [zoom, setZoom] = useState(1)\n\n const [position, setPosition] = useState({ x: 0, y: 0 })\n\n const [size, setSize] = React.useReducer(sizeReducer, { height: 0, width: 0 })\n\n const [measuredDeviceSize, setMeasuredDeviceSize] = useState({\n height: 0,\n width: 0,\n })\n\n const [breakpoint, setBreakpoint] =\n React.useState<LivePreviewConfig['breakpoints'][0]['name']>('responsive')\n\n /**\n * A \"middleware\" callback fn that does some additional work before `setURL`.\n * This is what we provide through context, bc it:\n * - ensures the URL is absolute\n * - resets `appIsReady` to `false` while the new URL is loading\n */\n const setLivePreviewURL = useCallback<LivePreviewContextType['setURL']>(\n (_incomingURL) => {\n let incomingURL: LivePreviewURLType\n\n if (typeof _incomingURL === 'string') {\n incomingURL = formatAbsoluteURL(_incomingURL)\n }\n\n if (!incomingURL) {\n setIsLivePreviewing(false)\n }\n\n if (incomingURL !== url) {\n setAppIsReady(false)\n setURL(incomingURL)\n }\n },\n [url],\n )\n\n /**\n * `url` needs to be relative to the window, which cannot be done on initial render.\n */\n useEffect(() => {\n if (typeof urlFromProps === 'string') {\n setURL(formatAbsoluteURL(urlFromProps))\n }\n }, [urlFromProps])\n\n // The toolbar needs to freely drag and drop around the page\n const handleDragEnd = (ev) => {\n // only update position if the toolbar is completely within the preview area\n // otherwise reset it back to the previous position\n // TODO: reset to the nearest edge of the preview area\n if (ev.over && ev.over.id === 'live-preview-area') {\n const newPos = {\n x: position.x + ev.delta.x,\n y: position.y + ev.delta.y,\n }\n\n setPosition(newPos)\n } else {\n // reset\n }\n }\n\n const setWidth = useCallback(\n (width) => {\n setSize({ type: 'width', value: width })\n },\n [setSize],\n )\n\n const setHeight = useCallback(\n (height) => {\n setSize({ type: 'height', value: height })\n },\n [setSize],\n )\n\n // explicitly set new width and height when as new breakpoints are selected\n // exclude `custom` breakpoint as it is handled by the `setWidth` and `setHeight` directly\n useEffect(() => {\n const foundBreakpoint = breakpoints?.find((bp) => bp.name === breakpoint)\n\n if (\n foundBreakpoint &&\n breakpoint !== 'responsive' &&\n breakpoint !== 'custom' &&\n typeof foundBreakpoint?.width === 'number' &&\n typeof foundBreakpoint?.height === 'number'\n ) {\n setSize({\n type: 'reset',\n value: {\n height: foundBreakpoint.height,\n width: foundBreakpoint.width,\n },\n })\n }\n }, [breakpoint, breakpoints])\n\n /**\n * Receive the `ready` message from the popup window\n * This indicates that the app is ready to receive `window.postMessage` events\n * This is also the only cross-origin way of detecting when a popup window has loaded\n * Unlike iframe elements which have an `onLoad` handler, there is no way to access `window.open` on popups\n */\n useEffect(() => {\n const handleMessage = (event: MessageEvent) => {\n if (\n url?.startsWith(event.origin) &&\n event.data &&\n typeof event.data === 'object' &&\n event.data.type === 'payload-live-preview'\n ) {\n if (event.data.ready) {\n setAppIsReady(true)\n }\n }\n }\n\n window.addEventListener('message', handleMessage)\n\n setListeningForMessages(true)\n\n return () => {\n window.removeEventListener('message', handleMessage)\n }\n }, [url, listeningForMessages])\n\n const handleWindowChange = useCallback(\n (type: 'iframe' | 'popup') => {\n setAppIsReady(false)\n setPreviewWindowType(type)\n if (type === 'popup') {\n openPopupWindow()\n }\n },\n [openPopupWindow],\n )\n\n // when the user closes the popup window, switch back to the iframe\n // the `usePopupWindow` reports the `isPopupOpen` state for us to use here\n useEffect(() => {\n const newPreviewWindowType = isPopupOpen ? 'popup' : 'iframe'\n\n if (newPreviewWindowType !== previewWindowType) {\n handleWindowChange('iframe')\n }\n }, [previewWindowType, isPopupOpen, handleWindowChange])\n\n useEffect(() => {\n if (isFirstRender.current) {\n isFirstRender.current = false\n return\n }\n\n void setPreference<CollectionPreferences>(\n collectionSlug ? `collection-${collectionSlug}` : `global-${globalSlug}`,\n {\n editViewType: isLivePreviewing ? 'live-preview' : 'default',\n },\n true,\n )\n }, [isLivePreviewing, setPreference, collectionSlug, globalSlug])\n\n return (\n <LivePreviewContext\n value={{\n appIsReady,\n breakpoint,\n breakpoints,\n iframeRef,\n isLivePreviewEnabled,\n isLivePreviewing,\n isPopupOpen,\n isPreviewEnabled,\n listeningForMessages,\n loadedURL,\n measuredDeviceSize,\n openPopupWindow,\n popupRef,\n previewURL,\n previewWindowType,\n setAppIsReady,\n setBreakpoint,\n setHeight,\n setIsLivePreviewing,\n setLoadedURL,\n setMeasuredDeviceSize,\n setPreviewURL,\n setPreviewWindowType: handleWindowChange,\n setSize,\n setToolbarPosition: setPosition,\n setURL: setLivePreviewURL,\n setWidth,\n setZoom,\n size,\n toolbarPosition: position,\n typeofLivePreviewURL,\n url,\n zoom,\n }}\n >\n <DndContext collisionDetection={customCollisionDetection} onDragEnd={handleDragEnd}>\n {children}\n </DndContext>\n </LivePreviewContext>\n )\n}\n"],"names":["DndContext","React","useCallback","useEffect","useMemo","useRef","useState","usePopupWindow","useDocumentInfo","usePreferences","formatAbsoluteURL","customCollisionDetection","LivePreviewContext","sizeReducer","LivePreviewProvider","breakpoints","incomingBreakpoints","children","isLivePreviewEnabled","isLivePreviewing","incomingIsLivePreviewing","isPreviewEnabled","previewURL","previewURLFromProps","typeofLivePreviewURL","url","urlFromProps","previewWindowType","setPreviewWindowType","setIsLivePreviewing","name","height","label","width","setURL","setPreviewURL","isPopupOpen","openPopupWindow","popupRef","eventType","appIsReady","setAppIsReady","listeningForMessages","setListeningForMessages","collectionSlug","globalSlug","isFirstRender","setPreference","iframeRef","loadedURL","setLoadedURL","zoom","setZoom","position","setPosition","x","y","size","setSize","useReducer","measuredDeviceSize","setMeasuredDeviceSize","breakpoint","setBreakpoint","setLivePreviewURL","_incomingURL","incomingURL","handleDragEnd","ev","over","id","newPos","delta","setWidth","type","value","setHeight","foundBreakpoint","find","bp","handleMessage","event","startsWith","origin","data","ready","window","addEventListener","removeEventListener","handleWindowChange","newPreviewWindowType","current","editViewType","setToolbarPosition","toolbarPosition","collisionDetection","onDragEnd"],"mappings":"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"}
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { dequal } from 'dequal/lite';
|
|
3
|
+
import { dequal } from 'dequal/lite';
|
|
4
|
+
// lite: no need for Map and Set support
|
|
4
5
|
import React, { createContext, use, useCallback, useEffect, useRef } from 'react';
|
|
5
6
|
import { useTranslation } from '../../providers/Translation/index.js';
|
|
6
7
|
import { requests } from '../../utilities/api.js';
|
|
7
8
|
import { deepMergeSimple } from '../../utilities/deepMerge.js';
|
|
8
9
|
import { useAuth } from '../Auth/index.js';
|
|
9
10
|
import { useConfig } from '../Config/index.js';
|
|
10
|
-
|
|
11
|
+
/**
|
|
12
|
+
* @param key - a string identifier for the property being set
|
|
13
|
+
* @param value - preference data to store
|
|
14
|
+
* @param merge - when true will combine the existing preference object batch the change into one request for objects, default = false
|
|
15
|
+
*/ const Context = /*#__PURE__*/ createContext({});
|
|
11
16
|
const requestOptions = (value, language)=>({
|
|
12
17
|
body: JSON.stringify({
|
|
13
18
|
value
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/providers/Preferences/index.tsx"],"sourcesContent":["'use client'\nimport { dequal } from 'dequal/lite' // lite: no need for Map and Set support\nimport React, { createContext, use, useCallback, useEffect, useRef } from 'react'\n\nimport type { Preferences } from '../../forms/Form/types.js'\n\nimport { useTranslation } from '../../providers/Translation/index.js'\nimport { requests } from '../../utilities/api.js'\nimport { deepMergeSimple } from '../../utilities/deepMerge.js'\nimport { useAuth } from '../Auth/index.js'\nimport { useConfig } from '../Config/index.js'\n\ntype PreferencesContext = {\n getPreference: <T = Preferences>(key: string) => Promise<T>\n /**\n * @param key - a string identifier for the property being set\n * @param value - preference data to store\n * @param merge - when true will combine the existing preference object batch the change into one request for objects, default = false\n */\n setPreference: <T = Preferences>(key: string, value: T, merge?: boolean) => Promise<void>\n}\n\nconst Context = createContext({} as PreferencesContext)\n\nconst requestOptions = (value, language) => ({\n body: JSON.stringify({ value }),\n headers: {\n 'Accept-Language': language,\n 'Content-Type': 'application/json',\n },\n})\n\nexport const PreferencesProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) => {\n const contextRef = useRef({} as PreferencesContext)\n const preferencesRef = useRef({})\n const pendingUpdate = useRef({})\n const { config } = useConfig()\n const { user } = useAuth()\n const { i18n } = useTranslation()\n\n const {\n routes: { api },\n serverURL,\n } = config\n\n useEffect(() => {\n if (!user) {\n // clear preferences between users\n preferencesRef.current = {}\n }\n }, [user])\n\n const getPreference = useCallback(\n async <T = unknown,>(key: string): Promise<T> => {\n const prefs = preferencesRef.current\n\n if (typeof prefs[key] !== 'undefined') {\n return prefs[key]\n }\n\n const promise = new Promise((resolve: (value: T) => void) => {\n void (async () => {\n const request = await requests.get(`${serverURL}${api}/payload-preferences/${key}`, {\n credentials: 'include',\n headers: {\n 'Accept-Language': i18n.language,\n },\n })\n\n let value = null\n\n if (request.status === 200) {\n const preference = await request.json()\n value = preference.value\n }\n\n preferencesRef.current[key] = value\n\n resolve(value)\n })()\n })\n\n prefs[key] = promise\n\n return promise\n },\n [i18n.language, api, preferencesRef, serverURL],\n )\n\n const setPreference = useCallback(\n async (key: string, value: unknown, merge = false): Promise<void> => {\n if (merge === false) {\n preferencesRef.current[key] = value\n\n await requests.post(\n `${serverURL}${api}/payload-preferences/${key}`,\n requestOptions(value, i18n.language),\n )\n\n return\n }\n\n let newValue = value\n const currentPreference = await getPreference(key)\n\n // handle value objects where multiple values can be set under one key\n if (\n typeof value === 'object' &&\n typeof currentPreference === 'object' &&\n typeof newValue === 'object'\n ) {\n // merge the value with any existing preference for the key\n if (currentPreference) {\n newValue = deepMergeSimple(currentPreference, newValue)\n }\n\n if (dequal(newValue, currentPreference)) {\n return\n }\n\n // add the requested changes to a pendingUpdate batch for the key\n pendingUpdate.current[key] = {\n ...pendingUpdate.current[key],\n ...(newValue as Record<string, unknown>),\n }\n } else {\n if (newValue === currentPreference) {\n return\n }\n\n pendingUpdate.current[key] = newValue\n }\n\n const updatePreference = async () => {\n // compare the value stored in context before sending to eliminate duplicate requests\n if (dequal(pendingUpdate.current[key], preferencesRef.current[key])) {\n return\n }\n\n // preference set in context here to prevent other updatePreference at the same time\n preferencesRef.current[key] = pendingUpdate.current[key]\n\n await requests.post(\n `${serverURL}${api}/payload-preferences/${key}`,\n requestOptions(preferencesRef.current[key], i18n.language),\n )\n\n // reset any changes for this key after sending the request\n delete pendingUpdate.current[key]\n }\n\n // use timeout to allow multiple changes of different values using the same key in one request\n setTimeout(() => {\n void updatePreference()\n })\n },\n [api, getPreference, i18n.language, pendingUpdate, serverURL],\n )\n\n contextRef.current.getPreference = getPreference\n contextRef.current.setPreference = setPreference\n return <Context value={contextRef.current}>{children}</Context>\n}\n\nexport const usePreferences = (): PreferencesContext => use(Context)\n"],"names":["dequal","React","createContext","use","useCallback","useEffect","useRef","useTranslation","requests","deepMergeSimple","useAuth","useConfig","Context","requestOptions","value","language","body","JSON","stringify","headers","PreferencesProvider","children","contextRef","preferencesRef","pendingUpdate","config","user","i18n","routes","api","serverURL","current","getPreference","key","prefs","promise","Promise","resolve","request","get","credentials","status","preference","json","setPreference","merge","post","newValue","currentPreference","updatePreference","setTimeout","usePreferences"],"mappings":"AAAA;;AACA,SAASA,MAAM,QAAQ,cAAa,
|
|
1
|
+
{"version":3,"sources":["../../../src/providers/Preferences/index.tsx"],"sourcesContent":["'use client'\nimport { dequal } from 'dequal/lite' // lite: no need for Map and Set support\nimport React, { createContext, use, useCallback, useEffect, useRef } from 'react'\n\nimport type { Preferences } from '../../forms/Form/types.js'\n\nimport { useTranslation } from '../../providers/Translation/index.js'\nimport { requests } from '../../utilities/api.js'\nimport { deepMergeSimple } from '../../utilities/deepMerge.js'\nimport { useAuth } from '../Auth/index.js'\nimport { useConfig } from '../Config/index.js'\n\ntype PreferencesContext = {\n getPreference: <T = Preferences>(key: string) => Promise<T>\n /**\n * @param key - a string identifier for the property being set\n * @param value - preference data to store\n * @param merge - when true will combine the existing preference object batch the change into one request for objects, default = false\n */\n setPreference: <T = Preferences>(key: string, value: T, merge?: boolean) => Promise<void>\n}\n\nconst Context = createContext({} as PreferencesContext)\n\nconst requestOptions = (value, language) => ({\n body: JSON.stringify({ value }),\n headers: {\n 'Accept-Language': language,\n 'Content-Type': 'application/json',\n },\n})\n\nexport const PreferencesProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) => {\n const contextRef = useRef({} as PreferencesContext)\n const preferencesRef = useRef({})\n const pendingUpdate = useRef({})\n const { config } = useConfig()\n const { user } = useAuth()\n const { i18n } = useTranslation()\n\n const {\n routes: { api },\n serverURL,\n } = config\n\n useEffect(() => {\n if (!user) {\n // clear preferences between users\n preferencesRef.current = {}\n }\n }, [user])\n\n const getPreference = useCallback(\n async <T = unknown,>(key: string): Promise<T> => {\n const prefs = preferencesRef.current\n\n if (typeof prefs[key] !== 'undefined') {\n return prefs[key]\n }\n\n const promise = new Promise((resolve: (value: T) => void) => {\n void (async () => {\n const request = await requests.get(`${serverURL}${api}/payload-preferences/${key}`, {\n credentials: 'include',\n headers: {\n 'Accept-Language': i18n.language,\n },\n })\n\n let value = null\n\n if (request.status === 200) {\n const preference = await request.json()\n value = preference.value\n }\n\n preferencesRef.current[key] = value\n\n resolve(value)\n })()\n })\n\n prefs[key] = promise\n\n return promise\n },\n [i18n.language, api, preferencesRef, serverURL],\n )\n\n const setPreference = useCallback(\n async (key: string, value: unknown, merge = false): Promise<void> => {\n if (merge === false) {\n preferencesRef.current[key] = value\n\n await requests.post(\n `${serverURL}${api}/payload-preferences/${key}`,\n requestOptions(value, i18n.language),\n )\n\n return\n }\n\n let newValue = value\n const currentPreference = await getPreference(key)\n\n // handle value objects where multiple values can be set under one key\n if (\n typeof value === 'object' &&\n typeof currentPreference === 'object' &&\n typeof newValue === 'object'\n ) {\n // merge the value with any existing preference for the key\n if (currentPreference) {\n newValue = deepMergeSimple(currentPreference, newValue)\n }\n\n if (dequal(newValue, currentPreference)) {\n return\n }\n\n // add the requested changes to a pendingUpdate batch for the key\n pendingUpdate.current[key] = {\n ...pendingUpdate.current[key],\n ...(newValue as Record<string, unknown>),\n }\n } else {\n if (newValue === currentPreference) {\n return\n }\n\n pendingUpdate.current[key] = newValue\n }\n\n const updatePreference = async () => {\n // compare the value stored in context before sending to eliminate duplicate requests\n if (dequal(pendingUpdate.current[key], preferencesRef.current[key])) {\n return\n }\n\n // preference set in context here to prevent other updatePreference at the same time\n preferencesRef.current[key] = pendingUpdate.current[key]\n\n await requests.post(\n `${serverURL}${api}/payload-preferences/${key}`,\n requestOptions(preferencesRef.current[key], i18n.language),\n )\n\n // reset any changes for this key after sending the request\n delete pendingUpdate.current[key]\n }\n\n // use timeout to allow multiple changes of different values using the same key in one request\n setTimeout(() => {\n void updatePreference()\n })\n },\n [api, getPreference, i18n.language, pendingUpdate, serverURL],\n )\n\n contextRef.current.getPreference = getPreference\n contextRef.current.setPreference = setPreference\n return <Context value={contextRef.current}>{children}</Context>\n}\n\nexport const usePreferences = (): PreferencesContext => use(Context)\n"],"names":["dequal","React","createContext","use","useCallback","useEffect","useRef","useTranslation","requests","deepMergeSimple","useAuth","useConfig","Context","requestOptions","value","language","body","JSON","stringify","headers","PreferencesProvider","children","contextRef","preferencesRef","pendingUpdate","config","user","i18n","routes","api","serverURL","current","getPreference","key","prefs","promise","Promise","resolve","request","get","credentials","status","preference","json","setPreference","merge","post","newValue","currentPreference","updatePreference","setTimeout","usePreferences"],"mappings":"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"}
|
|
@@ -27,18 +27,18 @@ import React, { startTransition, useCallback, useEffect, useOptimistic, useRef }
|
|
|
27
27
|
// cap the progress to ensure it never fully reaches completion
|
|
28
28
|
// accelerate quickly then decelerate slowly
|
|
29
29
|
const maxProgress = 0.93;
|
|
30
|
-
const jumpFactor = 0.2
|
|
31
|
-
|
|
32
|
-
const growthFactor = 0.75
|
|
33
|
-
|
|
34
|
-
const slowdownFactor = 0.75
|
|
35
|
-
|
|
30
|
+
const jumpFactor = 0.2;
|
|
31
|
+
// lower to reduce jumps in progress
|
|
32
|
+
const growthFactor = 0.75;
|
|
33
|
+
// adjust to control acceleration
|
|
34
|
+
const slowdownFactor = 0.75;
|
|
35
|
+
// adjust to control deceleration
|
|
36
36
|
const newProgress = transitionProgressRef.current + (maxProgress - transitionProgressRef.current) * Math.random() * jumpFactor * Math.pow(Math.log(1 + (1 - transitionProgressRef.current) * growthFactor), slowdownFactor);
|
|
37
37
|
setTransitionProgress(newProgress);
|
|
38
38
|
transitionProgressRef.current = newProgress;
|
|
39
|
-
}, 250)
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
}, 250);
|
|
40
|
+
}, // every n ms, update progress
|
|
41
|
+
[]);
|
|
42
42
|
useEffect(()=>{
|
|
43
43
|
setTransitionProgress(0);
|
|
44
44
|
transitionProgressRef.current = 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/providers/RouteTransition/index.tsx"],"sourcesContent":["'use client'\nimport React, { startTransition, useCallback, useEffect, useOptimistic, useRef } from 'react'\n\n/**\n * Route transitions are useful in showing immediate visual feedback to the user when navigating between pages. This is especially useful on slow networks when navigating to data heavy or process intensive pages.\n * To use route transitions, place the `RouteTransitionProvider` at the root of your application, outside of the `ProgressBar` component.\n * To trigger a route transition, use the `Link` component from `@payloadcms/ui`,\n * or wrap a callback function with the `startRouteTransition` method.\n * To gain access to the `RouteTransitionContext`, call the `useRouteTransition` hook in your component.\n * @returns A context provider with methods and state for transitioning between routes, including `isTransitioning`, `startRouteTransition`, and `transitionProgress`.\n * @example\n * import { RouteTransitionProvider, ProgressBar, Link } from '@payloadcms/ui'\n * const App = () => (\n * <RouteTransitionProvider>\n * <ProgressBar />\n * <Link href=\"/somewhere\">Go Somewhere</Link>\n * </RouteTransitionProvider>\n * )\n */\nexport const RouteTransitionProvider: React.FC<RouteTransitionProps> = ({ children }) => {\n const [isTransitioning, setIsTransitioning] = useOptimistic(false)\n const [transitionProgress, setTransitionProgress] = React.useState<number>(0)\n\n const transitionProgressRef = useRef(transitionProgress)\n\n const timerID = useRef(null)\n\n const initiateProgress = useCallback(() => {\n timerID.current = setInterval(() => {\n // randomly update progress using an exponential curve\n // cap the progress to ensure it never fully reaches completion\n // accelerate quickly then decelerate slowly\n const maxProgress = 0.93\n const jumpFactor = 0.2 // lower to reduce jumps in progress\n const growthFactor = 0.75 // adjust to control acceleration\n const slowdownFactor = 0.75 // adjust to control deceleration\n\n const newProgress =\n transitionProgressRef.current +\n (maxProgress - transitionProgressRef.current) *\n Math.random() *\n jumpFactor *\n Math.pow(Math.log(1 + (1 - transitionProgressRef.current) * growthFactor), slowdownFactor)\n\n setTransitionProgress(newProgress)\n transitionProgressRef.current = newProgress\n }, 250) // every n ms, update progress\n }, [])\n\n useEffect(() => {\n setTransitionProgress(0)\n transitionProgressRef.current = 0\n\n if (isTransitioning) {\n initiateProgress()\n } else {\n if (timerID.current) {\n clearInterval(timerID.current)\n }\n }\n }, [isTransitioning, initiateProgress])\n\n const startRouteTransition: StartRouteTransition = useCallback(\n (callback?: () => void) => {\n startTransition(() => {\n setIsTransitioning(true)\n\n if (typeof callback === 'function') {\n callback()\n }\n })\n },\n [setIsTransitioning],\n )\n\n return (\n <RouteTransitionContext value={{ isTransitioning, startRouteTransition, transitionProgress }}>\n {children}\n </RouteTransitionContext>\n )\n}\n\ntype RouteTransitionProps = {\n children: React.ReactNode\n}\n\ntype StartRouteTransition = (callback?: () => void) => void\n\ntype RouteTransitionContextValue = {\n isTransitioning: boolean\n startRouteTransition: StartRouteTransition\n transitionProgress: number\n}\n\nconst RouteTransitionContext = React.createContext<RouteTransitionContextValue>({\n isTransitioning: false,\n startRouteTransition: () => undefined,\n transitionProgress: 0,\n})\n\n/**\n * Use this hook to access the `RouteTransitionContext` provided by the `RouteTransitionProvider`.\n * To start a transition, fire the `startRouteTransition` method with a provided callback to run while the transition takes place.\n * @returns The `RouteTransitionContext` needed for transitioning between routes, including `isTransitioning`, `startRouteTransition`, and `transitionProgress`.\n * @example\n * 'use client'\n * import React, { useCallback } from 'react'\n * import { useTransition } from '@payloadcms/ui'\n * import { useRouter } from 'next/navigation'\n *\n * const MyComponent: React.FC = () => {\n * const router = useRouter()\n * const { startRouteTransition } = useRouteTransition()\n *\n * const redirectSomewhere = useCallback(() => {\n * startRouteTransition(() => router.push('/somewhere'))\n * }, [startRouteTransition, router])\n *\n * // ...\n * }\n */\nexport const useRouteTransition = () => React.use(RouteTransitionContext)\n"],"names":["React","startTransition","useCallback","useEffect","useOptimistic","useRef","RouteTransitionProvider","children","isTransitioning","setIsTransitioning","transitionProgress","setTransitionProgress","useState","transitionProgressRef","timerID","initiateProgress","current","setInterval","maxProgress","jumpFactor","growthFactor","slowdownFactor","newProgress","Math","random","pow","log","clearInterval","startRouteTransition","callback","RouteTransitionContext","value","createContext","undefined","useRouteTransition","use"],"mappings":"AAAA;;AACA,OAAOA,SAASC,eAAe,EAAEC,WAAW,EAAEC,SAAS,EAAEC,aAAa,EAAEC,MAAM,QAAQ,QAAO;AAE7F;;;;;;;;;;;;;;;CAeC,GACD,OAAO,MAAMC,0BAA0D,CAAC,EAAEC,QAAQ,EAAE;IAClF,MAAM,CAACC,iBAAiBC,mBAAmB,GAAGL,cAAc;IAC5D,MAAM,CAACM,oBAAoBC,sBAAsB,GAAGX,MAAMY,QAAQ,CAAS;IAE3E,MAAMC,wBAAwBR,OAAOK;IAErC,MAAMI,UAAUT,OAAO;IAEvB,MAAMU,mBAAmBb,YAAY;QACnCY,QAAQE,OAAO,GAAGC,YAAY;YAC5B,sDAAsD;YACtD,+DAA+D;YAC/D,4CAA4C;YAC5C,MAAMC,cAAc;YACpB,MAAMC,aAAa,
|
|
1
|
+
{"version":3,"sources":["../../../src/providers/RouteTransition/index.tsx"],"sourcesContent":["'use client'\nimport React, { startTransition, useCallback, useEffect, useOptimistic, useRef } from 'react'\n\n/**\n * Route transitions are useful in showing immediate visual feedback to the user when navigating between pages. This is especially useful on slow networks when navigating to data heavy or process intensive pages.\n * To use route transitions, place the `RouteTransitionProvider` at the root of your application, outside of the `ProgressBar` component.\n * To trigger a route transition, use the `Link` component from `@payloadcms/ui`,\n * or wrap a callback function with the `startRouteTransition` method.\n * To gain access to the `RouteTransitionContext`, call the `useRouteTransition` hook in your component.\n * @returns A context provider with methods and state for transitioning between routes, including `isTransitioning`, `startRouteTransition`, and `transitionProgress`.\n * @example\n * import { RouteTransitionProvider, ProgressBar, Link } from '@payloadcms/ui'\n * const App = () => (\n * <RouteTransitionProvider>\n * <ProgressBar />\n * <Link href=\"/somewhere\">Go Somewhere</Link>\n * </RouteTransitionProvider>\n * )\n */\nexport const RouteTransitionProvider: React.FC<RouteTransitionProps> = ({ children }) => {\n const [isTransitioning, setIsTransitioning] = useOptimistic(false)\n const [transitionProgress, setTransitionProgress] = React.useState<number>(0)\n\n const transitionProgressRef = useRef(transitionProgress)\n\n const timerID = useRef(null)\n\n const initiateProgress = useCallback(() => {\n timerID.current = setInterval(() => {\n // randomly update progress using an exponential curve\n // cap the progress to ensure it never fully reaches completion\n // accelerate quickly then decelerate slowly\n const maxProgress = 0.93\n const jumpFactor = 0.2 // lower to reduce jumps in progress\n const growthFactor = 0.75 // adjust to control acceleration\n const slowdownFactor = 0.75 // adjust to control deceleration\n\n const newProgress =\n transitionProgressRef.current +\n (maxProgress - transitionProgressRef.current) *\n Math.random() *\n jumpFactor *\n Math.pow(Math.log(1 + (1 - transitionProgressRef.current) * growthFactor), slowdownFactor)\n\n setTransitionProgress(newProgress)\n transitionProgressRef.current = newProgress\n }, 250) // every n ms, update progress\n }, [])\n\n useEffect(() => {\n setTransitionProgress(0)\n transitionProgressRef.current = 0\n\n if (isTransitioning) {\n initiateProgress()\n } else {\n if (timerID.current) {\n clearInterval(timerID.current)\n }\n }\n }, [isTransitioning, initiateProgress])\n\n const startRouteTransition: StartRouteTransition = useCallback(\n (callback?: () => void) => {\n startTransition(() => {\n setIsTransitioning(true)\n\n if (typeof callback === 'function') {\n callback()\n }\n })\n },\n [setIsTransitioning],\n )\n\n return (\n <RouteTransitionContext value={{ isTransitioning, startRouteTransition, transitionProgress }}>\n {children}\n </RouteTransitionContext>\n )\n}\n\ntype RouteTransitionProps = {\n children: React.ReactNode\n}\n\ntype StartRouteTransition = (callback?: () => void) => void\n\ntype RouteTransitionContextValue = {\n isTransitioning: boolean\n startRouteTransition: StartRouteTransition\n transitionProgress: number\n}\n\nconst RouteTransitionContext = React.createContext<RouteTransitionContextValue>({\n isTransitioning: false,\n startRouteTransition: () => undefined,\n transitionProgress: 0,\n})\n\n/**\n * Use this hook to access the `RouteTransitionContext` provided by the `RouteTransitionProvider`.\n * To start a transition, fire the `startRouteTransition` method with a provided callback to run while the transition takes place.\n * @returns The `RouteTransitionContext` needed for transitioning between routes, including `isTransitioning`, `startRouteTransition`, and `transitionProgress`.\n * @example\n * 'use client'\n * import React, { useCallback } from 'react'\n * import { useTransition } from '@payloadcms/ui'\n * import { useRouter } from 'next/navigation'\n *\n * const MyComponent: React.FC = () => {\n * const router = useRouter()\n * const { startRouteTransition } = useRouteTransition()\n *\n * const redirectSomewhere = useCallback(() => {\n * startRouteTransition(() => router.push('/somewhere'))\n * }, [startRouteTransition, router])\n *\n * // ...\n * }\n */\nexport const useRouteTransition = () => React.use(RouteTransitionContext)\n"],"names":["React","startTransition","useCallback","useEffect","useOptimistic","useRef","RouteTransitionProvider","children","isTransitioning","setIsTransitioning","transitionProgress","setTransitionProgress","useState","transitionProgressRef","timerID","initiateProgress","current","setInterval","maxProgress","jumpFactor","growthFactor","slowdownFactor","newProgress","Math","random","pow","log","clearInterval","startRouteTransition","callback","RouteTransitionContext","value","createContext","undefined","useRouteTransition","use"],"mappings":"AAAA;;AACA,OAAOA,SAASC,eAAe,EAAEC,WAAW,EAAEC,SAAS,EAAEC,aAAa,EAAEC,MAAM,QAAQ,QAAO;AAE7F;;;;;;;;;;;;;;;CAeC,GACD,OAAO,MAAMC,0BAA0D,CAAC,EAAEC,QAAQ,EAAE;IAClF,MAAM,CAACC,iBAAiBC,mBAAmB,GAAGL,cAAc;IAC5D,MAAM,CAACM,oBAAoBC,sBAAsB,GAAGX,MAAMY,QAAQ,CAAS;IAE3E,MAAMC,wBAAwBR,OAAOK;IAErC,MAAMI,UAAUT,OAAO;IAEvB,MAAMU,mBAAmBb,YAAY;QACnCY,QAAQE,OAAO,GAAGC,YAAY;YAC5B,sDAAsD;YACtD,+DAA+D;YAC/D,4CAA4C;YAC5C,MAAMC,cAAc;YACpB,MAAMC,aAAa;YAAI,oCAAoC;YAC3D,MAAMC,eAAe;YAAK,iCAAiC;YAC3D,MAAMC,iBAAiB;YAAK,iCAAiC;YAE7D,MAAMC,cACJT,sBAAsBG,OAAO,GAC7B,AAACE,CAAAA,cAAcL,sBAAsBG,OAAO,AAAD,IACzCO,KAAKC,MAAM,KACXL,aACAI,KAAKE,GAAG,CAACF,KAAKG,GAAG,CAAC,IAAI,AAAC,CAAA,IAAIb,sBAAsBG,OAAO,AAAD,IAAKI,eAAeC;YAE/EV,sBAAsBW;YACtBT,sBAAsBG,OAAO,GAAGM;QAClC,GAAG;IACL,GADU,8BAA8B;IACrC,EAAE;IAELnB,UAAU;QACRQ,sBAAsB;QACtBE,sBAAsBG,OAAO,GAAG;QAEhC,IAAIR,iBAAiB;YACnBO;QACF,OAAO;YACL,IAAID,QAAQE,OAAO,EAAE;gBACnBW,cAAcb,QAAQE,OAAO;YAC/B;QACF;IACF,GAAG;QAACR;QAAiBO;KAAiB;IAEtC,MAAMa,uBAA6C1B,YACjD,CAAC2B;QACC5B,gBAAgB;YACdQ,mBAAmB;YAEnB,IAAI,OAAOoB,aAAa,YAAY;gBAClCA;YACF;QACF;IACF,GACA;QAACpB;KAAmB;IAGtB,qBACE,KAACqB;QAAuBC,OAAO;YAAEvB;YAAiBoB;YAAsBlB;QAAmB;kBACxFH;;AAGP,EAAC;AAcD,MAAMuB,uCAAyB9B,MAAMgC,aAAa,CAA8B;IAC9ExB,iBAAiB;IACjBoB,sBAAsB,IAAMK;IAC5BvB,oBAAoB;AACtB;AAEA;;;;;;;;;;;;;;;;;;;;CAoBC,GACD,OAAO,MAAMwB,qBAAqB,IAAMlC,MAAMmC,GAAG,CAACL,wBAAuB"}
|
|
@@ -14,7 +14,10 @@ export var SelectAllStatus = /*#__PURE__*/ function(SelectAllStatus) {
|
|
|
14
14
|
SelectAllStatus["Some"] = "some";
|
|
15
15
|
return SelectAllStatus;
|
|
16
16
|
}({});
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Selects all rows on the current page within the current query.
|
|
19
|
+
* If `allAvailable` is true, does not select specific IDs so that the query itself affects all rows across all pages.
|
|
20
|
+
*/ const Context = /*#__PURE__*/ createContext({
|
|
18
21
|
count: undefined,
|
|
19
22
|
getQueryParams: (additionalParams)=>'',
|
|
20
23
|
getSelectedIds: ()=>[],
|
|
@@ -25,6 +28,7 @@ const Context = /*#__PURE__*/ createContext({
|
|
|
25
28
|
toggleAll: (toggleAll)=>{},
|
|
26
29
|
totalDocs: undefined
|
|
27
30
|
});
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
32
|
const reduceActiveSelections = (selected)=>{
|
|
29
33
|
const ids = [];
|
|
30
34
|
for (const [key, value] of selected){
|
|
@@ -77,8 +81,9 @@ export const SelectionProvider = ({ children, docs = [], totalDocs })=>{
|
|
|
77
81
|
const setSelection = useCallback((id)=>{
|
|
78
82
|
const doc = docs.find((doc)=>doc.id === id);
|
|
79
83
|
if (doc?._isLocked && user?.id !== doc?._userEditing.id) {
|
|
80
|
-
return;
|
|
84
|
+
return;
|
|
81
85
|
}
|
|
86
|
+
// Prevent selection if the document is locked
|
|
82
87
|
const existingValue = selected.get(id);
|
|
83
88
|
const isSelected = typeof existingValue === 'boolean' ? !existingValue : true;
|
|
84
89
|
const newMap = new Map(selected.set(id, isSelected));
|