next-cloudinary 6.12.0 → 7.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CldImage-4b579fe8.esm.js +138 -0
- package/dist/CldImage-68dff3e6.cjs.js +146 -0
- package/dist/CldUploadButton-196b419b.esm.js +101 -0
- package/dist/CldUploadButton-db9b095b.cjs.js +109 -0
- package/dist/CldUploadWidget-a9c04a78.esm.js +207 -0
- package/dist/CldUploadWidget-e39838cc.cjs.js +215 -0
- package/dist/CldVideoPlayer-49ac4380.cjs.js +149 -0
- package/dist/CldVideoPlayer-7b1734a7.esm.js +140 -0
- package/dist/cloudinary-1cbbab64.cjs.js +138 -0
- package/dist/cloudinary-9437f0ad.esm.js +131 -0
- package/dist/cloudinary-loader-1863f0f4.esm.js +59 -0
- package/dist/cloudinary-loader-80d421f0.cjs.js +62 -0
- package/dist/next-cloudinary.cjs.d.mts +2 -0
- package/dist/next-cloudinary.cjs.d.ts +2 -0
- package/dist/next-cloudinary.cjs.js +165 -0
- package/dist/next-cloudinary.cjs.mjs +11 -0
- package/dist/next-cloudinary.esm.js +134 -0
- package/package.json +49 -14
- package/scripts/copy-assets.ts +78 -0
- package/tsconfig.json +5 -3
- package/dist/index.d.mts +0 -152
- package/dist/index.d.ts +0 -152
- package/dist/index.js +0 -4
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -4
- package/dist/index.mjs.map +0 -1
- package/plugins/copy-assets.ts +0 -80
- package/tsup.config.ts +0 -18
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { forwardRef, useState, useCallback } from 'react';
|
|
3
|
+
import Image from 'next/image';
|
|
4
|
+
import { pollForProcessingImage } from '@cloudinary-util/util';
|
|
5
|
+
import { transformationPlugins } from '@cloudinary-util/url-loader';
|
|
6
|
+
import { g as getCldImageUrl, c as cloudinaryLoader } from './cloudinary-loader-1863f0f4.esm.js';
|
|
7
|
+
import { jsx } from 'react/jsx-runtime';
|
|
8
|
+
import './cloudinary-9437f0ad.esm.js';
|
|
9
|
+
import 'next/package.json';
|
|
10
|
+
|
|
11
|
+
const CldImage = /*#__PURE__*/forwardRef(function CldImage(props, ref) {
|
|
12
|
+
let hasThrownError = false;
|
|
13
|
+
|
|
14
|
+
// Add props here that are intended to only be used for
|
|
15
|
+
// Cloudinary URL construction to avoid them being forwarded
|
|
16
|
+
// to the DOM
|
|
17
|
+
|
|
18
|
+
const CLD_OPTIONS = ['assetType', 'config', 'deliveryType', 'strictTransformations'];
|
|
19
|
+
|
|
20
|
+
// Loop through all of the props available on the transformation plugins and verify
|
|
21
|
+
// that we're not accientally applying the same prop twice
|
|
22
|
+
|
|
23
|
+
// We're also using those props to push into CLD_OPTIONS which helps us filter what
|
|
24
|
+
// props are applied to the underlaying Image component vs what's being sent
|
|
25
|
+
// to Cloudinary URL construction
|
|
26
|
+
|
|
27
|
+
transformationPlugins.forEach(({
|
|
28
|
+
props
|
|
29
|
+
}) => {
|
|
30
|
+
const pluginProps = Object.keys(props);
|
|
31
|
+
pluginProps.forEach(prop => {
|
|
32
|
+
if (CLD_OPTIONS.includes(prop)) {
|
|
33
|
+
throw new Error(`Option ${prop} already exists!`);
|
|
34
|
+
}
|
|
35
|
+
CLD_OPTIONS.push(prop);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Construct the base Image component props by filtering out Cloudinary-specific props
|
|
40
|
+
|
|
41
|
+
const imageProps = {
|
|
42
|
+
alt: props.alt,
|
|
43
|
+
src: props.src
|
|
44
|
+
};
|
|
45
|
+
Object.keys(props).filter(key => typeof key === 'string' && !CLD_OPTIONS.includes(key)).forEach(key => imageProps[key] = props[key]);
|
|
46
|
+
const defaultImgKey = Object.keys(imageProps).map(key => `${key}:${imageProps[key]}`).join(';');
|
|
47
|
+
const [imgKey, setImgKey] = useState(defaultImgKey);
|
|
48
|
+
|
|
49
|
+
// Construct Cloudinary-specific props by looking for values for any of the supported prop keys
|
|
50
|
+
|
|
51
|
+
const cldOptions = {};
|
|
52
|
+
CLD_OPTIONS.forEach(key => {
|
|
53
|
+
const prop = props[key];
|
|
54
|
+
if (prop) {
|
|
55
|
+
// @ts-expect-error
|
|
56
|
+
cldOptions[key] = prop;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// The unoptimized flag is intended to remove all optimizations including quality, format, and sizing
|
|
61
|
+
// via responsive sizing. When passing this in, it also prevents the `loader` from running, thus
|
|
62
|
+
// breaking this component. This rewrites the `src` to construct a fully formed Cloudinary URL
|
|
63
|
+
// that also disables format and quality transformations, to deliver it as unoptimized
|
|
64
|
+
// See about unoptimized not working with loader: https://github.com/vercel/next.js/issues/50764
|
|
65
|
+
|
|
66
|
+
const IMAGE_OPTIONS = process.env.__NEXT_IMAGE_OPTS || {};
|
|
67
|
+
if (props.unoptimized === true || IMAGE_OPTIONS?.unoptimized === true) {
|
|
68
|
+
imageProps.src = getCldImageUrl({
|
|
69
|
+
...cldOptions,
|
|
70
|
+
width: imageProps.width,
|
|
71
|
+
height: imageProps.height,
|
|
72
|
+
src: imageProps.src,
|
|
73
|
+
format: 'default',
|
|
74
|
+
quality: 'default'
|
|
75
|
+
}, props.config);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* handleOnError
|
|
80
|
+
*/
|
|
81
|
+
|
|
82
|
+
async function onError(options) {
|
|
83
|
+
let pollForImage = true;
|
|
84
|
+
|
|
85
|
+
// The onError function should never fire more than once. The use case for tracking it
|
|
86
|
+
// at all outside of the standard Next Image flow is for scenarios like when Cloudinary
|
|
87
|
+
// is processing an image where we want to try to update the UI upon completion.
|
|
88
|
+
// If this fires a second time, it is likely because of another issue, which will end
|
|
89
|
+
// up triggering an infinite loop if the resulting image keeps erroring and
|
|
90
|
+
// this function sets a key using the current time to force refresh the UI
|
|
91
|
+
|
|
92
|
+
if (hasThrownError) return;
|
|
93
|
+
hasThrownError = true;
|
|
94
|
+
if (typeof props.onError === 'function') {
|
|
95
|
+
const onErrorResult = props.onError(options);
|
|
96
|
+
if (typeof onErrorResult === 'boolean' && onErrorResult === false) {
|
|
97
|
+
pollForImage = false;
|
|
98
|
+
}
|
|
99
|
+
} else if (typeof props.onError === 'boolean' && props.onError === false) {
|
|
100
|
+
pollForImage = false;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Give an escape hatch in case the user wants to handle the error themselves
|
|
104
|
+
// or if they want to disable polling for the image
|
|
105
|
+
|
|
106
|
+
if (pollForImage === false) return;
|
|
107
|
+
const image = options.target;
|
|
108
|
+
const result = await pollForProcessingImage({
|
|
109
|
+
src: image.src
|
|
110
|
+
});
|
|
111
|
+
if (result) {
|
|
112
|
+
setImgKey(`${defaultImgKey};${Date.now()}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const handleOnError = useCallback(onError, [pollForProcessingImage, defaultImgKey]);
|
|
116
|
+
|
|
117
|
+
// Copypasta from https://github.com/prismicio/prismic-next/pull/79/files
|
|
118
|
+
// Thanks Angelo!
|
|
119
|
+
// TODO: Remove once https://github.com/vercel/next.js/issues/52216 is resolved.
|
|
120
|
+
|
|
121
|
+
let ResolvedImage = Image;
|
|
122
|
+
if ("default" in ResolvedImage) {
|
|
123
|
+
ResolvedImage = ResolvedImage.default;
|
|
124
|
+
}
|
|
125
|
+
return /*#__PURE__*/jsx(ResolvedImage, {
|
|
126
|
+
...imageProps,
|
|
127
|
+
loader: loaderOptions => cloudinaryLoader({
|
|
128
|
+
loaderOptions,
|
|
129
|
+
imageProps,
|
|
130
|
+
cldOptions,
|
|
131
|
+
cldConfig: props.config
|
|
132
|
+
}),
|
|
133
|
+
onError: handleOnError,
|
|
134
|
+
ref: ref
|
|
135
|
+
}, imgKey);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
export { CldImage as default };
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var react = require('react');
|
|
7
|
+
var Image = require('next/image');
|
|
8
|
+
var util = require('@cloudinary-util/util');
|
|
9
|
+
var urlLoader = require('@cloudinary-util/url-loader');
|
|
10
|
+
var cloudinaryLoader = require('./cloudinary-loader-80d421f0.cjs.js');
|
|
11
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
12
|
+
require('./cloudinary-1cbbab64.cjs.js');
|
|
13
|
+
require('next/package.json');
|
|
14
|
+
|
|
15
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
16
|
+
|
|
17
|
+
var Image__default = /*#__PURE__*/_interopDefault(Image);
|
|
18
|
+
|
|
19
|
+
const CldImage = /*#__PURE__*/react.forwardRef(function CldImage(props, ref) {
|
|
20
|
+
let hasThrownError = false;
|
|
21
|
+
|
|
22
|
+
// Add props here that are intended to only be used for
|
|
23
|
+
// Cloudinary URL construction to avoid them being forwarded
|
|
24
|
+
// to the DOM
|
|
25
|
+
|
|
26
|
+
const CLD_OPTIONS = ['assetType', 'config', 'deliveryType', 'strictTransformations'];
|
|
27
|
+
|
|
28
|
+
// Loop through all of the props available on the transformation plugins and verify
|
|
29
|
+
// that we're not accientally applying the same prop twice
|
|
30
|
+
|
|
31
|
+
// We're also using those props to push into CLD_OPTIONS which helps us filter what
|
|
32
|
+
// props are applied to the underlaying Image component vs what's being sent
|
|
33
|
+
// to Cloudinary URL construction
|
|
34
|
+
|
|
35
|
+
urlLoader.transformationPlugins.forEach(({
|
|
36
|
+
props
|
|
37
|
+
}) => {
|
|
38
|
+
const pluginProps = Object.keys(props);
|
|
39
|
+
pluginProps.forEach(prop => {
|
|
40
|
+
if (CLD_OPTIONS.includes(prop)) {
|
|
41
|
+
throw new Error(`Option ${prop} already exists!`);
|
|
42
|
+
}
|
|
43
|
+
CLD_OPTIONS.push(prop);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Construct the base Image component props by filtering out Cloudinary-specific props
|
|
48
|
+
|
|
49
|
+
const imageProps = {
|
|
50
|
+
alt: props.alt,
|
|
51
|
+
src: props.src
|
|
52
|
+
};
|
|
53
|
+
Object.keys(props).filter(key => typeof key === 'string' && !CLD_OPTIONS.includes(key)).forEach(key => imageProps[key] = props[key]);
|
|
54
|
+
const defaultImgKey = Object.keys(imageProps).map(key => `${key}:${imageProps[key]}`).join(';');
|
|
55
|
+
const [imgKey, setImgKey] = react.useState(defaultImgKey);
|
|
56
|
+
|
|
57
|
+
// Construct Cloudinary-specific props by looking for values for any of the supported prop keys
|
|
58
|
+
|
|
59
|
+
const cldOptions = {};
|
|
60
|
+
CLD_OPTIONS.forEach(key => {
|
|
61
|
+
const prop = props[key];
|
|
62
|
+
if (prop) {
|
|
63
|
+
// @ts-expect-error
|
|
64
|
+
cldOptions[key] = prop;
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// The unoptimized flag is intended to remove all optimizations including quality, format, and sizing
|
|
69
|
+
// via responsive sizing. When passing this in, it also prevents the `loader` from running, thus
|
|
70
|
+
// breaking this component. This rewrites the `src` to construct a fully formed Cloudinary URL
|
|
71
|
+
// that also disables format and quality transformations, to deliver it as unoptimized
|
|
72
|
+
// See about unoptimized not working with loader: https://github.com/vercel/next.js/issues/50764
|
|
73
|
+
|
|
74
|
+
const IMAGE_OPTIONS = process.env.__NEXT_IMAGE_OPTS || {};
|
|
75
|
+
if (props.unoptimized === true || IMAGE_OPTIONS?.unoptimized === true) {
|
|
76
|
+
imageProps.src = cloudinaryLoader.getCldImageUrl({
|
|
77
|
+
...cldOptions,
|
|
78
|
+
width: imageProps.width,
|
|
79
|
+
height: imageProps.height,
|
|
80
|
+
src: imageProps.src,
|
|
81
|
+
format: 'default',
|
|
82
|
+
quality: 'default'
|
|
83
|
+
}, props.config);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* handleOnError
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
async function onError(options) {
|
|
91
|
+
let pollForImage = true;
|
|
92
|
+
|
|
93
|
+
// The onError function should never fire more than once. The use case for tracking it
|
|
94
|
+
// at all outside of the standard Next Image flow is for scenarios like when Cloudinary
|
|
95
|
+
// is processing an image where we want to try to update the UI upon completion.
|
|
96
|
+
// If this fires a second time, it is likely because of another issue, which will end
|
|
97
|
+
// up triggering an infinite loop if the resulting image keeps erroring and
|
|
98
|
+
// this function sets a key using the current time to force refresh the UI
|
|
99
|
+
|
|
100
|
+
if (hasThrownError) return;
|
|
101
|
+
hasThrownError = true;
|
|
102
|
+
if (typeof props.onError === 'function') {
|
|
103
|
+
const onErrorResult = props.onError(options);
|
|
104
|
+
if (typeof onErrorResult === 'boolean' && onErrorResult === false) {
|
|
105
|
+
pollForImage = false;
|
|
106
|
+
}
|
|
107
|
+
} else if (typeof props.onError === 'boolean' && props.onError === false) {
|
|
108
|
+
pollForImage = false;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Give an escape hatch in case the user wants to handle the error themselves
|
|
112
|
+
// or if they want to disable polling for the image
|
|
113
|
+
|
|
114
|
+
if (pollForImage === false) return;
|
|
115
|
+
const image = options.target;
|
|
116
|
+
const result = await util.pollForProcessingImage({
|
|
117
|
+
src: image.src
|
|
118
|
+
});
|
|
119
|
+
if (result) {
|
|
120
|
+
setImgKey(`${defaultImgKey};${Date.now()}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const handleOnError = react.useCallback(onError, [util.pollForProcessingImage, defaultImgKey]);
|
|
124
|
+
|
|
125
|
+
// Copypasta from https://github.com/prismicio/prismic-next/pull/79/files
|
|
126
|
+
// Thanks Angelo!
|
|
127
|
+
// TODO: Remove once https://github.com/vercel/next.js/issues/52216 is resolved.
|
|
128
|
+
|
|
129
|
+
let ResolvedImage = Image__default["default"];
|
|
130
|
+
if ("default" in ResolvedImage) {
|
|
131
|
+
ResolvedImage = ResolvedImage.default;
|
|
132
|
+
}
|
|
133
|
+
return /*#__PURE__*/jsxRuntime.jsx(ResolvedImage, {
|
|
134
|
+
...imageProps,
|
|
135
|
+
loader: loaderOptions => cloudinaryLoader.cloudinaryLoader({
|
|
136
|
+
loaderOptions,
|
|
137
|
+
imageProps,
|
|
138
|
+
cldOptions,
|
|
139
|
+
cldConfig: props.config
|
|
140
|
+
}),
|
|
141
|
+
onError: handleOnError,
|
|
142
|
+
ref: ref
|
|
143
|
+
}, imgKey);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
exports["default"] = CldImage;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import 'react';
|
|
3
|
+
import CldUploadWidget from './CldUploadWidget-a9c04a78.esm.js';
|
|
4
|
+
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
const CldUploadButton = ({
|
|
7
|
+
className,
|
|
8
|
+
children,
|
|
9
|
+
onClick,
|
|
10
|
+
onError,
|
|
11
|
+
onOpen,
|
|
12
|
+
onUpload,
|
|
13
|
+
onAbort,
|
|
14
|
+
onBatchCancelled,
|
|
15
|
+
onClose,
|
|
16
|
+
onDisplayChanged,
|
|
17
|
+
onPublicId,
|
|
18
|
+
onQueuesEnd,
|
|
19
|
+
onQueuesStart,
|
|
20
|
+
onRetry,
|
|
21
|
+
onShowCompleted,
|
|
22
|
+
onSourceChanged,
|
|
23
|
+
onSuccess,
|
|
24
|
+
onTags,
|
|
25
|
+
onUploadAdded,
|
|
26
|
+
options,
|
|
27
|
+
signatureEndpoint,
|
|
28
|
+
uploadPreset,
|
|
29
|
+
onAbortAction,
|
|
30
|
+
onBatchCancelledAction,
|
|
31
|
+
onCloseAction,
|
|
32
|
+
onDisplayChangedAction,
|
|
33
|
+
onPublicIdAction,
|
|
34
|
+
onQueuesEndAction,
|
|
35
|
+
onQueuesStartAction,
|
|
36
|
+
onRetryAction,
|
|
37
|
+
onShowCompletedAction,
|
|
38
|
+
onSourceChangedAction,
|
|
39
|
+
onSuccessAction,
|
|
40
|
+
onTagsAction,
|
|
41
|
+
onUploadAddedAction,
|
|
42
|
+
...props
|
|
43
|
+
}) => {
|
|
44
|
+
return /*#__PURE__*/jsx(Fragment, {
|
|
45
|
+
children: /*#__PURE__*/jsx(CldUploadWidget, {
|
|
46
|
+
onError: onError,
|
|
47
|
+
onOpen: onOpen,
|
|
48
|
+
onUpload: onUpload,
|
|
49
|
+
onAbort: onAbort,
|
|
50
|
+
onBatchCancelled: onBatchCancelled,
|
|
51
|
+
onClose: onClose,
|
|
52
|
+
onDisplayChanged: onDisplayChanged,
|
|
53
|
+
onPublicId: onPublicId,
|
|
54
|
+
onQueuesEnd: onQueuesEnd,
|
|
55
|
+
onQueuesStart: onQueuesStart,
|
|
56
|
+
onRetry: onRetry,
|
|
57
|
+
onShowCompleted: onShowCompleted,
|
|
58
|
+
onSourceChanged: onSourceChanged,
|
|
59
|
+
onSuccess: onSuccess,
|
|
60
|
+
onTags: onTags,
|
|
61
|
+
onUploadAdded: onUploadAdded,
|
|
62
|
+
options: options,
|
|
63
|
+
signatureEndpoint: signatureEndpoint,
|
|
64
|
+
uploadPreset: uploadPreset,
|
|
65
|
+
onAbortAction: onAbortAction,
|
|
66
|
+
onBatchCancelledAction: onBatchCancelledAction,
|
|
67
|
+
onCloseAction: onCloseAction,
|
|
68
|
+
onDisplayChangedAction: onDisplayChangedAction,
|
|
69
|
+
onPublicIdAction: onPublicIdAction,
|
|
70
|
+
onQueuesEndAction: onQueuesEndAction,
|
|
71
|
+
onQueuesStartAction: onQueuesStartAction,
|
|
72
|
+
onRetryAction: onRetryAction,
|
|
73
|
+
onShowCompletedAction: onShowCompletedAction,
|
|
74
|
+
onSourceChangedAction: onSourceChangedAction,
|
|
75
|
+
onSuccessAction: onSuccessAction,
|
|
76
|
+
onTagsAction: onTagsAction,
|
|
77
|
+
onUploadAddedAction: onUploadAddedAction,
|
|
78
|
+
children: ({
|
|
79
|
+
open,
|
|
80
|
+
isLoading
|
|
81
|
+
}) => {
|
|
82
|
+
function handleOnClick(e) {
|
|
83
|
+
e.preventDefault();
|
|
84
|
+
open();
|
|
85
|
+
if (typeof onClick === 'function') {
|
|
86
|
+
onClick(e);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return /*#__PURE__*/jsx("button", {
|
|
90
|
+
...props,
|
|
91
|
+
className: className || '',
|
|
92
|
+
onClick: handleOnClick,
|
|
93
|
+
disabled: isLoading,
|
|
94
|
+
children: children || 'Upload'
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export { CldUploadButton as default };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
require('react');
|
|
7
|
+
var CldUploadWidget = require('./CldUploadWidget-e39838cc.cjs.js');
|
|
8
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
9
|
+
|
|
10
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
11
|
+
|
|
12
|
+
var CldUploadWidget__default = /*#__PURE__*/_interopDefault(CldUploadWidget);
|
|
13
|
+
|
|
14
|
+
const CldUploadButton = ({
|
|
15
|
+
className,
|
|
16
|
+
children,
|
|
17
|
+
onClick,
|
|
18
|
+
onError,
|
|
19
|
+
onOpen,
|
|
20
|
+
onUpload,
|
|
21
|
+
onAbort,
|
|
22
|
+
onBatchCancelled,
|
|
23
|
+
onClose,
|
|
24
|
+
onDisplayChanged,
|
|
25
|
+
onPublicId,
|
|
26
|
+
onQueuesEnd,
|
|
27
|
+
onQueuesStart,
|
|
28
|
+
onRetry,
|
|
29
|
+
onShowCompleted,
|
|
30
|
+
onSourceChanged,
|
|
31
|
+
onSuccess,
|
|
32
|
+
onTags,
|
|
33
|
+
onUploadAdded,
|
|
34
|
+
options,
|
|
35
|
+
signatureEndpoint,
|
|
36
|
+
uploadPreset,
|
|
37
|
+
onAbortAction,
|
|
38
|
+
onBatchCancelledAction,
|
|
39
|
+
onCloseAction,
|
|
40
|
+
onDisplayChangedAction,
|
|
41
|
+
onPublicIdAction,
|
|
42
|
+
onQueuesEndAction,
|
|
43
|
+
onQueuesStartAction,
|
|
44
|
+
onRetryAction,
|
|
45
|
+
onShowCompletedAction,
|
|
46
|
+
onSourceChangedAction,
|
|
47
|
+
onSuccessAction,
|
|
48
|
+
onTagsAction,
|
|
49
|
+
onUploadAddedAction,
|
|
50
|
+
...props
|
|
51
|
+
}) => {
|
|
52
|
+
return /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
|
|
53
|
+
children: /*#__PURE__*/jsxRuntime.jsx(CldUploadWidget__default["default"], {
|
|
54
|
+
onError: onError,
|
|
55
|
+
onOpen: onOpen,
|
|
56
|
+
onUpload: onUpload,
|
|
57
|
+
onAbort: onAbort,
|
|
58
|
+
onBatchCancelled: onBatchCancelled,
|
|
59
|
+
onClose: onClose,
|
|
60
|
+
onDisplayChanged: onDisplayChanged,
|
|
61
|
+
onPublicId: onPublicId,
|
|
62
|
+
onQueuesEnd: onQueuesEnd,
|
|
63
|
+
onQueuesStart: onQueuesStart,
|
|
64
|
+
onRetry: onRetry,
|
|
65
|
+
onShowCompleted: onShowCompleted,
|
|
66
|
+
onSourceChanged: onSourceChanged,
|
|
67
|
+
onSuccess: onSuccess,
|
|
68
|
+
onTags: onTags,
|
|
69
|
+
onUploadAdded: onUploadAdded,
|
|
70
|
+
options: options,
|
|
71
|
+
signatureEndpoint: signatureEndpoint,
|
|
72
|
+
uploadPreset: uploadPreset,
|
|
73
|
+
onAbortAction: onAbortAction,
|
|
74
|
+
onBatchCancelledAction: onBatchCancelledAction,
|
|
75
|
+
onCloseAction: onCloseAction,
|
|
76
|
+
onDisplayChangedAction: onDisplayChangedAction,
|
|
77
|
+
onPublicIdAction: onPublicIdAction,
|
|
78
|
+
onQueuesEndAction: onQueuesEndAction,
|
|
79
|
+
onQueuesStartAction: onQueuesStartAction,
|
|
80
|
+
onRetryAction: onRetryAction,
|
|
81
|
+
onShowCompletedAction: onShowCompletedAction,
|
|
82
|
+
onSourceChangedAction: onSourceChangedAction,
|
|
83
|
+
onSuccessAction: onSuccessAction,
|
|
84
|
+
onTagsAction: onTagsAction,
|
|
85
|
+
onUploadAddedAction: onUploadAddedAction,
|
|
86
|
+
children: ({
|
|
87
|
+
open,
|
|
88
|
+
isLoading
|
|
89
|
+
}) => {
|
|
90
|
+
function handleOnClick(e) {
|
|
91
|
+
e.preventDefault();
|
|
92
|
+
open();
|
|
93
|
+
if (typeof onClick === 'function') {
|
|
94
|
+
onClick(e);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return /*#__PURE__*/jsxRuntime.jsx("button", {
|
|
98
|
+
...props,
|
|
99
|
+
className: className || '',
|
|
100
|
+
onClick: handleOnClick,
|
|
101
|
+
disabled: isLoading,
|
|
102
|
+
children: children || 'Upload'
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
exports["default"] = CldUploadButton;
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useRef, useState, useEffect } from 'react';
|
|
3
|
+
import Script from 'next/script';
|
|
4
|
+
import { generateSignatureCallback, getUploadWidgetOptions, generateUploadWidgetResultCallback, UPLOAD_WIDGET_EVENTS } from '@cloudinary-util/url-loader';
|
|
5
|
+
import { g as getCloudinaryConfig } from './cloudinary-9437f0ad.esm.js';
|
|
6
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
7
|
+
import 'next/package.json';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* triggerOnIdle
|
|
11
|
+
* @see MDN Polyfill https://github.com/behnammodi/polyfill/blob/master/window.polyfill.js#L7-L24
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
function triggerOnIdle(callback) {
|
|
15
|
+
if (typeof window !== undefined && 'requestIdleCallback' in window) {
|
|
16
|
+
return requestIdleCallback(callback);
|
|
17
|
+
}
|
|
18
|
+
return setTimeout(() => callback(), 1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const CldUploadWidget = ({
|
|
22
|
+
children,
|
|
23
|
+
config,
|
|
24
|
+
onError,
|
|
25
|
+
onOpen,
|
|
26
|
+
onUpload,
|
|
27
|
+
options,
|
|
28
|
+
signatureEndpoint,
|
|
29
|
+
uploadPreset,
|
|
30
|
+
...props
|
|
31
|
+
}) => {
|
|
32
|
+
const cloudinary = useRef();
|
|
33
|
+
const widget = useRef();
|
|
34
|
+
const [error, setError] = useState(undefined);
|
|
35
|
+
const [results, setResults] = useState(undefined);
|
|
36
|
+
const [isScriptLoading, setIsScriptLoading] = useState(true);
|
|
37
|
+
|
|
38
|
+
// When creating a signed upload, you need to provide both your Cloudinary API Key
|
|
39
|
+
// as well as a signature generator function that will sign any paramters
|
|
40
|
+
// either on page load or during the upload process. Read more about signed uploads at:
|
|
41
|
+
// https://cloudinary.com/documentation/upload_widget#signed_uploads
|
|
42
|
+
|
|
43
|
+
const cloudinaryConfig = getCloudinaryConfig(config);
|
|
44
|
+
const uploadSignature = signatureEndpoint && generateSignatureCallback({
|
|
45
|
+
signatureEndpoint: String(signatureEndpoint),
|
|
46
|
+
fetch
|
|
47
|
+
});
|
|
48
|
+
const uploadOptions = getUploadWidgetOptions({
|
|
49
|
+
uploadPreset: uploadPreset || process.env.NEXT_PUBLIC_CLOUDINARY_UPLOAD_PRESET,
|
|
50
|
+
uploadSignature,
|
|
51
|
+
...options
|
|
52
|
+
}, cloudinaryConfig);
|
|
53
|
+
const resultsCallback = generateUploadWidgetResultCallback({
|
|
54
|
+
onError: uploadError => {
|
|
55
|
+
setError(uploadError);
|
|
56
|
+
if (typeof onError === 'function') {
|
|
57
|
+
onError(uploadError, {
|
|
58
|
+
widget: widget.current,
|
|
59
|
+
...instanceMethods
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
onResult: uploadResult => {
|
|
64
|
+
if (typeof uploadResult?.event !== 'string') return;
|
|
65
|
+
setResults(uploadResult);
|
|
66
|
+
const widgetEvent = UPLOAD_WIDGET_EVENTS[uploadResult.event];
|
|
67
|
+
if (typeof widgetEvent === 'string' && typeof props[widgetEvent] === 'function') {
|
|
68
|
+
const callback = props[widgetEvent];
|
|
69
|
+
callback(uploadResult, {
|
|
70
|
+
widget: widget.current,
|
|
71
|
+
...instanceMethods
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
const widgetEventAction = `${widgetEvent}Action`;
|
|
75
|
+
if (widgetEventAction && typeof props[widgetEventAction] === 'function') {
|
|
76
|
+
const action = props[widgetEventAction];
|
|
77
|
+
action(uploadResult);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Handle result states and callbacks
|
|
83
|
+
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
if (typeof results === 'undefined') return;
|
|
86
|
+
const isSuccess = results.event === 'success';
|
|
87
|
+
if (isSuccess && typeof onUpload === 'function') {
|
|
88
|
+
if (process.env.NODE_ENVIRONMENT === 'development') {
|
|
89
|
+
console.warn('The onUpload callback is deprecated. Please use onSuccess instead.');
|
|
90
|
+
}
|
|
91
|
+
onUpload(results, widget.current);
|
|
92
|
+
}
|
|
93
|
+
}, [results]);
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* handleOnLoad
|
|
97
|
+
* @description Stores the Cloudinary window instance to a ref when the widget script loads
|
|
98
|
+
*/
|
|
99
|
+
|
|
100
|
+
function handleOnLoad() {
|
|
101
|
+
setIsScriptLoading(false);
|
|
102
|
+
if (!cloudinary.current) {
|
|
103
|
+
cloudinary.current = window.cloudinary;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// To help improve load time of the widget on first instance, use requestIdleCallback
|
|
107
|
+
// to trigger widget creation. Optional.
|
|
108
|
+
|
|
109
|
+
triggerOnIdle(() => {
|
|
110
|
+
if (!widget.current) {
|
|
111
|
+
widget.current = createWidget();
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
return () => {
|
|
117
|
+
widget.current?.destroy();
|
|
118
|
+
widget.current = undefined;
|
|
119
|
+
};
|
|
120
|
+
}, []);
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Instance Methods
|
|
124
|
+
* Gives the ability to interface directly with the Upload Widget instance methods like open and close
|
|
125
|
+
* https://cloudinary.com/documentation/upload_widget_reference#instance_methods
|
|
126
|
+
*/
|
|
127
|
+
|
|
128
|
+
function invokeInstanceMethod(method, options = []) {
|
|
129
|
+
if (!widget.current) {
|
|
130
|
+
widget.current = createWidget();
|
|
131
|
+
}
|
|
132
|
+
if (typeof widget?.current[method] === "function") {
|
|
133
|
+
return widget.current[method](...options);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function close(options) {
|
|
137
|
+
invokeInstanceMethod('close', [options]);
|
|
138
|
+
}
|
|
139
|
+
function destroy(options) {
|
|
140
|
+
return invokeInstanceMethod('destroy', [options]);
|
|
141
|
+
}
|
|
142
|
+
function hide() {
|
|
143
|
+
invokeInstanceMethod('hide');
|
|
144
|
+
}
|
|
145
|
+
function isDestroyed() {
|
|
146
|
+
return invokeInstanceMethod('isDestroyed');
|
|
147
|
+
}
|
|
148
|
+
function isMinimized() {
|
|
149
|
+
return invokeInstanceMethod('isMinimized');
|
|
150
|
+
}
|
|
151
|
+
function isShowing() {
|
|
152
|
+
return invokeInstanceMethod('isShowing');
|
|
153
|
+
}
|
|
154
|
+
function minimize() {
|
|
155
|
+
invokeInstanceMethod('minimize');
|
|
156
|
+
}
|
|
157
|
+
function open(widgetSource, options) {
|
|
158
|
+
invokeInstanceMethod('open', [widgetSource, options]);
|
|
159
|
+
if (typeof onOpen === 'function') {
|
|
160
|
+
onOpen(widget.current);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function show() {
|
|
164
|
+
invokeInstanceMethod('show');
|
|
165
|
+
}
|
|
166
|
+
function update() {
|
|
167
|
+
invokeInstanceMethod('update');
|
|
168
|
+
}
|
|
169
|
+
const instanceMethods = {
|
|
170
|
+
close,
|
|
171
|
+
destroy,
|
|
172
|
+
hide,
|
|
173
|
+
isDestroyed,
|
|
174
|
+
isMinimized,
|
|
175
|
+
isShowing,
|
|
176
|
+
minimize,
|
|
177
|
+
open,
|
|
178
|
+
show,
|
|
179
|
+
update
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* createWidget
|
|
184
|
+
* @description Creates a new instance of the Cloudinary widget and stores in a ref
|
|
185
|
+
*/
|
|
186
|
+
|
|
187
|
+
function createWidget() {
|
|
188
|
+
return cloudinary.current?.createUploadWidget(uploadOptions, resultsCallback);
|
|
189
|
+
}
|
|
190
|
+
return /*#__PURE__*/jsxs(Fragment, {
|
|
191
|
+
children: [typeof children === 'function' && children({
|
|
192
|
+
cloudinary: cloudinary.current,
|
|
193
|
+
widget: widget.current,
|
|
194
|
+
results,
|
|
195
|
+
error,
|
|
196
|
+
isLoading: isScriptLoading,
|
|
197
|
+
...instanceMethods
|
|
198
|
+
}), /*#__PURE__*/jsx(Script, {
|
|
199
|
+
id: `cloudinary-uploadwidget-${Math.floor(Math.random() * 100)}`,
|
|
200
|
+
src: "https://upload-widget.cloudinary.com/global/all.js",
|
|
201
|
+
onLoad: handleOnLoad,
|
|
202
|
+
onError: e => console.error(`Failed to load Cloudinary Upload Widget: ${e.message}`)
|
|
203
|
+
})]
|
|
204
|
+
});
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
export { CldUploadWidget as default };
|