next-cloudinary 7.0.0-beta.8 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +18 -6
  3. package/dist/{CldImage-88363cf7.esm.js → CldImage-07dde903.esm.js} +2 -2
  4. package/dist/{CldImage-04771bcb.cjs.js → CldImage-31b93c94.cjs.js} +6 -6
  5. package/dist/{CldUploadButton-db9b095b.cjs.js → CldUploadButton-7867eb66.cjs.js} +1 -3
  6. package/dist/{CldUploadButton-196b419b.esm.js → CldUploadButton-8cb106b1.esm.js} +1 -3
  7. package/dist/{CldUploadWidget-e61be307.esm.js → CldUploadWidget-088119fa.esm.js} +22 -21
  8. package/dist/{CldUploadWidget-552ed202.cjs.js → CldUploadWidget-a1e60409.cjs.js} +27 -25
  9. package/dist/{CldVideoPlayer-b8f0145b.cjs.js → CldVideoPlayer-42f73054.cjs.js} +75 -28
  10. package/dist/{CldVideoPlayer-1fa32403.esm.js → CldVideoPlayer-7e753e1c.esm.js} +73 -26
  11. package/dist/cld-video-player.css +5 -2
  12. package/dist/{cloudinary-b3d74a97.cjs.js → cloudinary-ed5f879f.cjs.js} +34 -20
  13. package/dist/{cloudinary-bd3de558.esm.js → cloudinary-ef6def0a.esm.js} +34 -20
  14. package/dist/{cloudinary-loader-4ccbec73.esm.js → cloudinary-loader-3f16f899.esm.js} +1 -3
  15. package/dist/{cloudinary-loader-7bbd42f3.cjs.js → cloudinary-loader-837b1bbc.cjs.js} +1 -3
  16. package/dist/declarations/src/components/CldOgImage/CldOgImage.d.ts +1 -1
  17. package/dist/declarations/src/components/CldOgImage/CldOgImage.d.ts.map +1 -1
  18. package/dist/declarations/src/components/CldUploadButton/CldUploadButton.d.ts +3 -2
  19. package/dist/declarations/src/components/CldUploadButton/CldUploadButton.d.ts.map +1 -1
  20. package/dist/declarations/src/components/CldUploadWidget/CldUploadWidget.d.ts +2 -1
  21. package/dist/declarations/src/components/CldUploadWidget/CldUploadWidget.d.ts.map +1 -1
  22. package/dist/declarations/src/components/CldUploadWidget/CldUploadWidget.types.d.ts +2 -6
  23. package/dist/declarations/src/components/CldUploadWidget/CldUploadWidget.types.d.ts.map +1 -1
  24. package/dist/declarations/src/components/CldVideoPlayer/CldVideoPlayer.d.ts +1 -1
  25. package/dist/declarations/src/components/CldVideoPlayer/CldVideoPlayer.d.ts.map +1 -1
  26. package/dist/declarations/src/components/CldVideoPlayer/CldVideoPlayer.types.d.ts +1 -0
  27. package/dist/declarations/src/components/CldVideoPlayer/CldVideoPlayer.types.d.ts.map +1 -1
  28. package/dist/declarations/src/loaders/cloudinary-loader.d.ts +1 -0
  29. package/dist/declarations/src/loaders/cloudinary-loader.d.ts.map +1 -1
  30. package/dist/next-cloudinary.cjs.js +6 -6
  31. package/dist/next-cloudinary.esm.js +7 -7
  32. package/package.json +29 -26
  33. package/dist/fonts/cloudinary_icon_for_black_bg.svg +0 -1
  34. package/dist/fonts/cloudinary_icon_for_white_bg.svg +0 -1
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Colby Fayock
3
+ Copyright (c) 2023 Cloudinary
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -11,10 +11,6 @@
11
11
 
12
12
  # Next Cloudinary
13
13
 
14
- <!-- doc-gen PKGJSON optionOne="hey" -->
15
- undefined
16
- <!-- end-doc-gen -->
17
-
18
14
  High-performance image delivery and uploading at scale in Next.js powered by Cloudinary.
19
15
 
20
16
  <a href="#-features">Features</a> • <a href="#-getting-started">Getting Started</a> • <a href="#%EF%B8%8F-community--support">Community & Support</a> • <a href="#-contributing">Contributing</a>
@@ -79,7 +75,7 @@ import { CldImage } from 'next-cloudinary';
79
75
  ## ❤️ Community & Support
80
76
 
81
77
  * [GitHub: Create an Issue](https://github.com/cloudinary-community/next-cloudinary/issues)
82
- * [Twitter: @colbyfayock](https://twitter.com/colbyfayock)
78
+ * [Twitter: @cloudinary](https://twitter.com/cloudinary)
83
79
 
84
80
  ## 🛠 Contributing
85
81
 
@@ -203,10 +199,26 @@ pnpm test
203
199
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/mr-loop-1"><img src="https://avatars.githubusercontent.com/u/62374784?v=4?s=100" width="100px;" alt="Abdul Samad"/><br /><sub><b>Abdul Samad</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=mr-loop-1" title="Documentation">📖</a></td>
204
200
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/DevRish"><img src="https://avatars.githubusercontent.com/u/78094670?v=4?s=100" width="100px;" alt="Rishav Chattopadhyay"/><br /><sub><b>Rishav Chattopadhyay</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=DevRish" title="Documentation">📖</a></td>
205
201
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/Prathamesh010"><img src="https://avatars.githubusercontent.com/u/41731424?v=4?s=100" width="100px;" alt="Prathamesh Gawas"/><br /><sub><b>Prathamesh Gawas</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=Prathamesh010" title="Documentation">📖</a></td>
206
- <td align="center" valign="top" width="14.28%"><a href="https://victory-nwani.dev"><img src="https://avatars.githubusercontent.com/u/29664439?v=4?s=100" width="100px;" alt="Nwani Victory"/><br /><sub><b>Nwani Victory</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=vickywane" title="Documentation">📖</a></td>
202
+ <td align="center" valign="top" width="14.28%"><a href="https://victory-nwani.dev"><img src="https://avatars.githubusercontent.com/u/29664439?v=4?s=100" width="100px;" alt="Nwani Victory"/><br /><sub><b>Nwani Victory</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=vickywane" title="Documentation">📖</a> <a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=vickywane" title="Code">💻</a></td>
207
203
  <td align="center" valign="top" width="14.28%"><a href="http://neilblaze.live"><img src="https://avatars.githubusercontent.com/u/48355572?v=4?s=100" width="100px;" alt="Pratyay Banerjee"/><br /><sub><b>Pratyay Banerjee</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=Neilblaze" title="Documentation">📖</a></td>
208
204
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/saai-syvendra"><img src="https://avatars.githubusercontent.com/u/157691467?v=4?s=100" width="100px;" alt="Saai Syvendra"/><br /><sub><b>Saai Syvendra</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=saai-syvendra" title="Documentation">📖</a></td>
209
205
  </tr>
206
+ <tr>
207
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Zaki-Mohd"><img src="https://avatars.githubusercontent.com/u/181067270?v=4?s=100" width="100px;" alt="Mohammad Zaki"/><br /><sub><b>Mohammad Zaki</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=Zaki-Mohd" title="Documentation">📖</a></td>
208
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/thinkverse"><img src="https://avatars.githubusercontent.com/u/2221746?v=4?s=100" width="100px;" alt="Kim Hallberg"/><br /><sub><b>Kim Hallberg</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=thinkverse" title="Documentation">📖</a></td>
209
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Waqibsk"><img src="https://avatars.githubusercontent.com/u/162541991?v=4?s=100" width="100px;" alt="Md Waqib Sk"/><br /><sub><b>Md Waqib Sk</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=Waqibsk" title="Documentation">📖</a></td>
210
+ <td align="center" valign="top" width="14.28%"><a href="https://arjuncodess.is-a.dev/"><img src="https://avatars.githubusercontent.com/u/137415649?v=4?s=100" width="100px;" alt="Arjun Vijay Prakash"/><br /><sub><b>Arjun Vijay Prakash</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=ArjunCodess" title="Code">💻</a></td>
211
+ <td align="center" valign="top" width="14.28%"><a href="https://musaddiq625.carrd.co"><img src="https://avatars.githubusercontent.com/u/37911054?v=4?s=100" width="100px;" alt="Musaddiq Ahmed Khan"/><br /><sub><b>Musaddiq Ahmed Khan</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=Musaddiq625" title="Documentation">📖</a></td>
212
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/SarthakJain29"><img src="https://avatars.githubusercontent.com/u/93116216?v=4?s=100" width="100px;" alt="Sarthak Jain"/><br /><sub><b>Sarthak Jain</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=SarthakJain29" title="Code">💻</a></td>
213
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/HRIDYANSHU054"><img src="https://avatars.githubusercontent.com/u/124202756?v=4?s=100" width="100px;" alt="Hridyanshu"/><br /><sub><b>Hridyanshu</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=HRIDYANSHU054" title="Documentation">📖</a></td>
214
+ </tr>
215
+ <tr>
216
+ <td align="center" valign="top" width="14.28%"><a href="https://anurag2787.vercel.app/"><img src="https://avatars.githubusercontent.com/u/143180737?v=4?s=100" width="100px;" alt="Anurag Yadav"/><br /><sub><b>Anurag Yadav</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=anurag2787" title="Code">💻</a></td>
217
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/error9098x"><img src="https://avatars.githubusercontent.com/u/43810146?v=4?s=100" width="100px;" alt="ProCodec"/><br /><sub><b>ProCodec</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=error9098x" title="Code">💻</a> <a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=error9098x" title="Documentation">📖</a></td>
218
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/chawdamrunal"><img src="https://avatars.githubusercontent.com/u/32319538?v=4?s=100" width="100px;" alt="chawda mrunal"/><br /><sub><b>chawda mrunal</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=chawdamrunal" title="Code">💻</a></td>
219
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/dharamghevariya"><img src="https://avatars.githubusercontent.com/u/144807441?v=4?s=100" width="100px;" alt="Dharam Ghevariya"/><br /><sub><b>Dharam Ghevariya</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=dharamghevariya" title="Code">💻</a></td>
220
+ <td align="center" valign="top" width="14.28%"><a href="https://github.com/Meghana-2124"><img src="https://avatars.githubusercontent.com/u/204466699?v=4?s=100" width="100px;" alt="Meghana"/><br /><sub><b>Meghana</b></sub></a><br /><a href="https://github.com/cloudinary-community/next-cloudinary/commits?author=Meghana-2124" title="Documentation">📖</a></td>
221
+ </tr>
210
222
  </tbody>
211
223
  </table>
212
224
 
@@ -3,9 +3,9 @@ import { forwardRef, useState, useCallback } from 'react';
3
3
  import Image from 'next/image';
4
4
  import { pollForProcessingImage } from '@cloudinary-util/util';
5
5
  import { cloudinaryPluginKeys } from '@cloudinary-util/url-loader';
6
- import { g as getCldImageUrl, c as cloudinaryLoader } from './cloudinary-loader-4ccbec73.esm.js';
6
+ import { g as getCldImageUrl, c as cloudinaryLoader } from './cloudinary-loader-3f16f899.esm.js';
7
7
  import { jsx } from 'react/jsx-runtime';
8
- import './cloudinary-bd3de558.esm.js';
8
+ import './cloudinary-ef6def0a.esm.js';
9
9
  import 'next/package.json';
10
10
 
11
11
  const CldImage = /*#__PURE__*/forwardRef(function CldImage(props, ref) {
@@ -3,20 +3,20 @@
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
- var react = require('react');
6
+ var React = require('react');
7
7
  var Image = require('next/image');
8
8
  var util = require('@cloudinary-util/util');
9
9
  var urlLoader = require('@cloudinary-util/url-loader');
10
- var cloudinaryLoader = require('./cloudinary-loader-7bbd42f3.cjs.js');
10
+ var cloudinaryLoader = require('./cloudinary-loader-837b1bbc.cjs.js');
11
11
  var jsxRuntime = require('react/jsx-runtime');
12
- require('./cloudinary-b3d74a97.cjs.js');
12
+ require('./cloudinary-ed5f879f.cjs.js');
13
13
  require('next/package.json');
14
14
 
15
15
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
16
16
 
17
17
  var Image__default = /*#__PURE__*/_interopDefault(Image);
18
18
 
19
- const CldImage = /*#__PURE__*/react.forwardRef(function CldImage(props, ref) {
19
+ const CldImage = /*#__PURE__*/React.forwardRef(function CldImage(props, ref) {
20
20
  let hasThrownError = false;
21
21
 
22
22
  // Add props here that are intended to only be used for
@@ -35,7 +35,7 @@ const CldImage = /*#__PURE__*/react.forwardRef(function CldImage(props, ref) {
35
35
  };
36
36
  Object.keys(props).filter(key => typeof key === 'string' && !CLD_OPTIONS.includes(key)).forEach(key => imageProps[key] = props[key]);
37
37
  const defaultImgKey = Object.keys(imageProps).map(key => `${key}:${imageProps[key]}`).join(';');
38
- const [imgKey, setImgKey] = react.useState(defaultImgKey);
38
+ const [imgKey, setImgKey] = React.useState(defaultImgKey);
39
39
 
40
40
  // The unoptimized flag is intended to remove all optimizations including quality, format, and sizing
41
41
  // via responsive sizing. When passing this in, it also prevents the `loader` from running, thus
@@ -95,7 +95,7 @@ const CldImage = /*#__PURE__*/react.forwardRef(function CldImage(props, ref) {
95
95
  setImgKey(`${defaultImgKey};${Date.now()}`);
96
96
  }
97
97
  }
98
- const handleOnError = react.useCallback(onError, [util.pollForProcessingImage, defaultImgKey]);
98
+ const handleOnError = React.useCallback(onError, [util.pollForProcessingImage, defaultImgKey]);
99
99
 
100
100
  // Copypasta from https://github.com/prismicio/prismic-next/pull/79/files
101
101
  // Thanks Angelo!
@@ -4,7 +4,7 @@
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
6
  require('react');
7
- var CldUploadWidget = require('./CldUploadWidget-552ed202.cjs.js');
7
+ var CldUploadWidget = require('./CldUploadWidget-a1e60409.cjs.js');
8
8
  var jsxRuntime = require('react/jsx-runtime');
9
9
 
10
10
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
@@ -17,7 +17,6 @@ const CldUploadButton = ({
17
17
  onClick,
18
18
  onError,
19
19
  onOpen,
20
- onUpload,
21
20
  onAbort,
22
21
  onBatchCancelled,
23
22
  onClose,
@@ -53,7 +52,6 @@ const CldUploadButton = ({
53
52
  children: /*#__PURE__*/jsxRuntime.jsx(CldUploadWidget__default["default"], {
54
53
  onError: onError,
55
54
  onOpen: onOpen,
56
- onUpload: onUpload,
57
55
  onAbort: onAbort,
58
56
  onBatchCancelled: onBatchCancelled,
59
57
  onClose: onClose,
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import 'react';
3
- import CldUploadWidget from './CldUploadWidget-e61be307.esm.js';
3
+ import CldUploadWidget from './CldUploadWidget-088119fa.esm.js';
4
4
  import { jsx, Fragment } from 'react/jsx-runtime';
5
5
 
6
6
  const CldUploadButton = ({
@@ -9,7 +9,6 @@ const CldUploadButton = ({
9
9
  onClick,
10
10
  onError,
11
11
  onOpen,
12
- onUpload,
13
12
  onAbort,
14
13
  onBatchCancelled,
15
14
  onClose,
@@ -45,7 +44,6 @@ const CldUploadButton = ({
45
44
  children: /*#__PURE__*/jsx(CldUploadWidget, {
46
45
  onError: onError,
47
46
  onOpen: onOpen,
48
- onUpload: onUpload,
49
47
  onAbort: onAbort,
50
48
  onBatchCancelled: onBatchCancelled,
51
49
  onClose: onClose,
@@ -1,8 +1,8 @@
1
1
  'use client';
2
- import { useRef, useState, useEffect } from 'react';
2
+ import React, { useRef, useState, useEffect } from 'react';
3
3
  import Script from 'next/script';
4
4
  import { generateSignatureCallback, getUploadWidgetOptions, generateUploadWidgetResultCallback, UPLOAD_WIDGET_EVENTS } from '@cloudinary-util/url-loader';
5
- import { g as getCloudinaryConfig } from './cloudinary-bd3de558.esm.js';
5
+ import { g as getCloudinaryConfig } from './cloudinary-ef6def0a.esm.js';
6
6
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
7
7
  import 'next/package.json';
8
8
 
@@ -18,19 +18,30 @@ function triggerOnIdle(callback) {
18
18
  return setTimeout(() => callback(), 1);
19
19
  }
20
20
 
21
+ const useUploadWidgetId = () => {
22
+ const reactId = React.useId?.() ?? null;
23
+
24
+ // Preserve the original random ID behavior for React < 18
25
+ const fallbackId = React.useRef(Math.floor(Math.random() * 100)).current;
26
+
27
+ // Remove colons from React useId() output (e.g., ":r1:" -> "r1") to avoid issues with CSS selectors and HTML IDs
28
+ const sanitizedId = reactId ? reactId.replace(/:/g, '') : fallbackId;
29
+ return `cloudinary-uploadwidget-${sanitizedId}`;
30
+ };
21
31
  const CldUploadWidget = ({
22
32
  children,
23
33
  config,
24
34
  onError,
25
35
  onOpen,
26
- onUpload,
27
36
  options,
28
37
  signatureEndpoint,
29
38
  uploadPreset,
30
39
  ...props
31
40
  }) => {
32
- const cloudinary = useRef();
33
- const widget = useRef();
41
+ const uploadWidgetId = useUploadWidgetId();
42
+ const cloudinary = useRef(undefined);
43
+ const widget = useRef(undefined);
44
+ const isMounted = useRef(false);
34
45
  const [error, setError] = useState(undefined);
35
46
  const [results, setResults] = useState(undefined);
36
47
  const [isScriptLoading, setIsScriptLoading] = useState(true);
@@ -79,25 +90,13 @@ const CldUploadWidget = ({
79
90
  }
80
91
  });
81
92
 
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_ENV === 'development') {
89
- console.warn('The onUpload callback is deprecated. Please use onSuccess instead.');
90
- }
91
- onUpload(results, widget.current);
92
- }
93
- }, [results]);
94
-
95
93
  /**
96
94
  * handleOnLoad
97
95
  * @description Stores the Cloudinary window instance to a ref when the widget script loads
98
96
  */
99
97
 
100
98
  function handleOnLoad() {
99
+ if (!isMounted.current) return;
101
100
  setIsScriptLoading(false);
102
101
  if (!cloudinary.current) {
103
102
  cloudinary.current = window.cloudinary;
@@ -107,13 +106,15 @@ const CldUploadWidget = ({
107
106
  // to trigger widget creation. Optional.
108
107
 
109
108
  triggerOnIdle(() => {
110
- if (!widget.current) {
109
+ if (isMounted.current && !widget.current) {
111
110
  widget.current = createWidget();
112
111
  }
113
112
  });
114
113
  }
115
114
  useEffect(() => {
115
+ isMounted.current = true;
116
116
  return () => {
117
+ isMounted.current = false;
117
118
  widget.current?.destroy();
118
119
  widget.current = undefined;
119
120
  };
@@ -129,7 +130,7 @@ const CldUploadWidget = ({
129
130
  if (!widget.current) {
130
131
  widget.current = createWidget();
131
132
  }
132
- if (typeof widget?.current[method] === "function") {
133
+ if (typeof widget.current?.[method] === "function") {
133
134
  return widget.current[method](...options);
134
135
  }
135
136
  }
@@ -196,7 +197,7 @@ const CldUploadWidget = ({
196
197
  isLoading: isScriptLoading,
197
198
  ...instanceMethods
198
199
  }), /*#__PURE__*/jsx(Script, {
199
- id: `cloudinary-uploadwidget-${Math.floor(Math.random() * 100)}`,
200
+ id: uploadWidgetId,
200
201
  src: "https://upload-widget.cloudinary.com/global/all.js",
201
202
  onLoad: handleOnLoad,
202
203
  onError: e => console.error(`Failed to load Cloudinary Upload Widget: ${e.message}`)
@@ -3,15 +3,16 @@
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
- var react = require('react');
6
+ var React = require('react');
7
7
  var Script = require('next/script');
8
8
  var urlLoader = require('@cloudinary-util/url-loader');
9
- var cloudinary = require('./cloudinary-b3d74a97.cjs.js');
9
+ var cloudinary = require('./cloudinary-ed5f879f.cjs.js');
10
10
  var jsxRuntime = require('react/jsx-runtime');
11
11
  require('next/package.json');
12
12
 
13
13
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
14
14
 
15
+ var React__default = /*#__PURE__*/_interopDefault(React);
15
16
  var Script__default = /*#__PURE__*/_interopDefault(Script);
16
17
 
17
18
  /**
@@ -26,22 +27,33 @@ function triggerOnIdle(callback) {
26
27
  return setTimeout(() => callback(), 1);
27
28
  }
28
29
 
30
+ const useUploadWidgetId = () => {
31
+ const reactId = React__default["default"].useId?.() ?? null;
32
+
33
+ // Preserve the original random ID behavior for React < 18
34
+ const fallbackId = React__default["default"].useRef(Math.floor(Math.random() * 100)).current;
35
+
36
+ // Remove colons from React useId() output (e.g., ":r1:" -> "r1") to avoid issues with CSS selectors and HTML IDs
37
+ const sanitizedId = reactId ? reactId.replace(/:/g, '') : fallbackId;
38
+ return `cloudinary-uploadwidget-${sanitizedId}`;
39
+ };
29
40
  const CldUploadWidget = ({
30
41
  children,
31
42
  config,
32
43
  onError,
33
44
  onOpen,
34
- onUpload,
35
45
  options,
36
46
  signatureEndpoint,
37
47
  uploadPreset,
38
48
  ...props
39
49
  }) => {
40
- const cloudinary$1 = react.useRef();
41
- const widget = react.useRef();
42
- const [error, setError] = react.useState(undefined);
43
- const [results, setResults] = react.useState(undefined);
44
- const [isScriptLoading, setIsScriptLoading] = react.useState(true);
50
+ const uploadWidgetId = useUploadWidgetId();
51
+ const cloudinary$1 = React.useRef(undefined);
52
+ const widget = React.useRef(undefined);
53
+ const isMounted = React.useRef(false);
54
+ const [error, setError] = React.useState(undefined);
55
+ const [results, setResults] = React.useState(undefined);
56
+ const [isScriptLoading, setIsScriptLoading] = React.useState(true);
45
57
 
46
58
  // When creating a signed upload, you need to provide both your Cloudinary API Key
47
59
  // as well as a signature generator function that will sign any paramters
@@ -87,25 +99,13 @@ const CldUploadWidget = ({
87
99
  }
88
100
  });
89
101
 
90
- // Handle result states and callbacks
91
-
92
- react.useEffect(() => {
93
- if (typeof results === 'undefined') return;
94
- const isSuccess = results.event === 'success';
95
- if (isSuccess && typeof onUpload === 'function') {
96
- if (process.env.NODE_ENV === 'development') {
97
- console.warn('The onUpload callback is deprecated. Please use onSuccess instead.');
98
- }
99
- onUpload(results, widget.current);
100
- }
101
- }, [results]);
102
-
103
102
  /**
104
103
  * handleOnLoad
105
104
  * @description Stores the Cloudinary window instance to a ref when the widget script loads
106
105
  */
107
106
 
108
107
  function handleOnLoad() {
108
+ if (!isMounted.current) return;
109
109
  setIsScriptLoading(false);
110
110
  if (!cloudinary$1.current) {
111
111
  cloudinary$1.current = window.cloudinary;
@@ -115,13 +115,15 @@ const CldUploadWidget = ({
115
115
  // to trigger widget creation. Optional.
116
116
 
117
117
  triggerOnIdle(() => {
118
- if (!widget.current) {
118
+ if (isMounted.current && !widget.current) {
119
119
  widget.current = createWidget();
120
120
  }
121
121
  });
122
122
  }
123
- react.useEffect(() => {
123
+ React.useEffect(() => {
124
+ isMounted.current = true;
124
125
  return () => {
126
+ isMounted.current = false;
125
127
  widget.current?.destroy();
126
128
  widget.current = undefined;
127
129
  };
@@ -137,7 +139,7 @@ const CldUploadWidget = ({
137
139
  if (!widget.current) {
138
140
  widget.current = createWidget();
139
141
  }
140
- if (typeof widget?.current[method] === "function") {
142
+ if (typeof widget.current?.[method] === "function") {
141
143
  return widget.current[method](...options);
142
144
  }
143
145
  }
@@ -204,7 +206,7 @@ const CldUploadWidget = ({
204
206
  isLoading: isScriptLoading,
205
207
  ...instanceMethods
206
208
  }), /*#__PURE__*/jsxRuntime.jsx(Script__default["default"], {
207
- id: `cloudinary-uploadwidget-${Math.floor(Math.random() * 100)}`,
209
+ id: uploadWidgetId,
208
210
  src: "https://upload-widget.cloudinary.com/global/all.js",
209
211
  onLoad: handleOnLoad,
210
212
  onError: e => console.error(`Failed to load Cloudinary Upload Widget: ${e.message}`)
@@ -3,11 +3,11 @@
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
- var react = require('react');
6
+ var React = require('react');
7
7
  var Script = require('next/script');
8
8
  var Head = require('next/head');
9
9
  var urlLoader = require('@cloudinary-util/url-loader');
10
- var cloudinary = require('./cloudinary-b3d74a97.cjs.js');
10
+ var cloudinary = require('./cloudinary-ed5f879f.cjs.js');
11
11
  var jsxRuntime = require('react/jsx-runtime');
12
12
  require('next/package.json');
13
13
 
@@ -17,11 +17,12 @@ var Script__default = /*#__PURE__*/_interopDefault(Script);
17
17
  var Head__default = /*#__PURE__*/_interopDefault(Head);
18
18
 
19
19
  let playerInstances = [];
20
- const PLAYER_VERSION = '1.11.1';
20
+ const PLAYER_VERSION = '4.1.2';
21
21
  const CldVideoPlayer = props => {
22
22
  const {
23
23
  className,
24
24
  config,
25
+ disableRemotePlayback,
25
26
  height,
26
27
  id,
27
28
  onDataLoad,
@@ -32,7 +33,9 @@ const CldVideoPlayer = props => {
32
33
  onEnded,
33
34
  width
34
35
  } = props;
35
- const uniqueId = react.useId();
36
+ const uniqueId = React.useId();
37
+ const [isScriptLoaded, setIsScriptLoaded] = React.useState(false);
38
+ const [playerInitialized, setPlayerInitialized] = React.useState(false);
36
39
  const cloudinaryConfig = cloudinary.getCloudinaryConfig(config);
37
40
  const playerOptions = urlLoader.getVideoPlayerOptions(props, cloudinaryConfig);
38
41
  const {
@@ -45,26 +48,18 @@ const CldVideoPlayer = props => {
45
48
  // Setup the refs and allow for the caller to pass through their
46
49
  // own ref instance
47
50
 
48
- const cloudinaryRef = react.useRef();
49
- const defaultVideoRef = react.useRef();
51
+ const cloudinaryRef = React.useRef(undefined);
52
+ const defaultVideoRef = React.useRef(null);
50
53
  const videoRef = props.videoRef || defaultVideoRef;
51
- const defaultPlayerRef = react.useRef();
54
+ const defaultPlayerRef = React.useRef(null);
52
55
  const playerRef = props.playerRef || defaultPlayerRef;
56
+ // The <video> element the player was created on (video.js keeps using it inside the player)
57
+ const playerVideoElementRef = React.useRef(null);
53
58
  const playerId = id || `player-${uniqueId.replace(/:/g, '')}`;
54
59
  let playerClassName = 'cld-video-player cld-fluid';
55
60
  if (className) {
56
61
  playerClassName = `${playerClassName} ${className}`;
57
62
  }
58
-
59
- // Check if the same id is being used for multiple video instances.
60
- const checkForMultipleInstance = playerInstances.filter(id => id === playerId).length > 1;
61
- if (checkForMultipleInstance) {
62
- console.warn(`Multiple instances of the same video detected on the
63
- page which may cause some features to not work.
64
- Try adding a unique id to each player.`);
65
- } else {
66
- playerInstances.push(playerId);
67
- }
68
63
  const events = {
69
64
  error: onError,
70
65
  loadeddata: onDataLoad,
@@ -87,28 +82,77 @@ const CldVideoPlayer = props => {
87
82
  }
88
83
 
89
84
  /**
90
- * handleOnLoad
91
- * @description Stores the Cloudinary window instance to a ref when the widget script loads
85
+ * disposePlayer
86
+ * @description Properly dispose of the player instance and clean up
92
87
  */
93
88
 
94
- function handleOnLoad() {
95
- if ('cloudinary' in window) {
89
+ const disposePlayer = () => {
90
+ // React Strict Mode runs effect cleanups without removing the DOM, then reuses the same
91
+ // <video> element. Keep the player in that case; dispose() would remove the element.
92
+ if (playerVideoElementRef.current?.isConnected) return;
93
+
94
+ // dispose() on the player instance also removes it from the video.js registry,
95
+ // so a remount with the same id creates a new player instead of reusing a stale one
96
+ if (typeof playerRef.current?.dispose === 'function') {
97
+ playerRef.current.dispose();
98
+ }
99
+ // remove from global instances array
100
+ playerInstances = playerInstances.filter(instanceId => instanceId !== playerId);
101
+ playerRef.current = null;
102
+ setPlayerInitialized(false);
103
+ };
104
+
105
+ /**
106
+ * initializePlayer
107
+ * @description Initialize the Cloudinary video player
108
+ */
109
+
110
+ const initializePlayer = () => {
111
+ // Check the ref, not the playerInitialized state: onLoad and onReady can both call this
112
+ // during the same render, and the state value seen there may be stale
113
+ if (typeof window !== 'undefined' && 'cloudinary' in window && videoRef.current && !playerRef.current) {
96
114
  cloudinaryRef.current = window.cloudinary;
115
+ playerVideoElementRef.current = videoRef.current;
97
116
  playerRef.current = cloudinaryRef.current.videoPlayer(videoRef.current, playerOptions);
117
+ setPlayerInitialized(true);
98
118
  Object.keys(events).forEach(key => {
99
119
  if (typeof events[key] === 'function') {
100
120
  playerRef.current?.on(key, handleEvent);
101
121
  }
102
122
  });
103
123
  }
124
+ };
125
+
126
+ /**
127
+ * handleOnLoad
128
+ * @description Stores the Cloudinary window instance to a ref when the widget script loads
129
+ */
130
+
131
+ function handleOnLoad() {
132
+ setIsScriptLoaded(true);
133
+ if ('cloudinary' in window) {
134
+ initializePlayer();
135
+ }
104
136
  }
105
- react.useEffect(() => {
137
+
138
+ // effect to handle component mounting and cleanup
139
+ React.useEffect(() => {
140
+ // initialize player if script is already loaded
141
+ if (isScriptLoaded && typeof window !== 'undefined' && 'cloudinary' in window) {
142
+ initializePlayer();
143
+ }
106
144
  return () => {
107
- playerRef.current?.videojs.cloudinary.dispose();
108
- playerInstances = playerInstances.filter(id => id !== playerId);
145
+ disposePlayer();
109
146
  };
110
147
  }, []);
111
148
 
149
+ // effect to handle script loading after mount
150
+ React.useEffect(() => {
151
+ if (isScriptLoaded && !playerInitialized && typeof window !== 'undefined' && 'cloudinary' in window) {
152
+ initializePlayer();
153
+ }
154
+ }, [isScriptLoaded, playerInitialized]);
155
+
112
156
  /**
113
157
  *getPlayerRefs
114
158
  */
@@ -127,19 +171,22 @@ const CldVideoPlayer = props => {
127
171
  })
128
172
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
129
173
  style: {
130
- width: '100%',
131
- aspectRatio: `${width} / ${height}`
174
+ width: '100%'
132
175
  },
133
176
  children: [/*#__PURE__*/jsxRuntime.jsx("video", {
134
177
  ref: videoRef,
135
178
  id: playerId,
136
179
  className: playerClassName,
137
180
  width: width,
138
- height: height
181
+ height: height,
182
+ disableRemotePlayback: disableRemotePlayback
139
183
  }), /*#__PURE__*/jsxRuntime.jsx(Script__default["default"], {
140
184
  id: `cloudinary-videoplayer-${playerId}`,
141
185
  src: `https://unpkg.com/cloudinary-video-player@${PLAYER_VERSION}/dist/cld-video-player.min.js`,
142
- onLoad: handleOnLoad,
186
+ onLoad: handleOnLoad
187
+ // onReady also runs on later mounts with the same script id, where onLoad doesn't fire again
188
+ ,
189
+ onReady: handleOnLoad,
143
190
  onError: e => console.error(`Failed to load Cloudinary Video Player: ${e.message}`)
144
191
  })]
145
192
  })]