diff --git a/README.md b/README.md
index 9c067e7..123a6ef 100644
--- a/README.md
+++ b/README.md
@@ -43,13 +43,14 @@ const SimpleCloud = () => (
| Option | Type | Required | Note |
|-----------|----------|--------|---|
-|`tags` |`Array` |`true`|Array of objects representing tags (see [Tag object](#tag-object))|
-|`maxSize` |`Number` |`true` |Maximal font size (px) used in cloud|
-|`minSize` |`Number` |`true` |Minimal font size (px) used in cloud|
-|`shuffle` |`Boolean` |`false`|If true, tags are shuffled. When `tags` are modified, cloud is re-shuffled. Default: `true`|
-|`colorOptions` |`Object` |`false`|Random color options (see [randomColor#options](https://github.com/davidmerfield/randomColor#options))|
-|`disableRandomColor`|`Boolean` |`false`|If `true`, random color is not used|
-|`renderer` |`Function`|`false`|Function used to render each tag|
+|`tags` |`Array` |`true`|Array of objects representing tags (see [Tag object](#tag-object))|
+|`maxSize` |`Number` |`true` |Maximal font size (px) used in cloud|
+|`minSize` |`Number` |`true` |Minimal font size (px) used in cloud|
+|`shuffle` |`Boolean` |`false`|If true, tags are shuffled. When `tags` are modified, cloud is re-shuffled. Default: `true`|
+|`randomNumberGenerator`|`Function`|`false`|Specifies a custom random number generator that is being used by shuffle algorithm. Default: `Math.random`
+|`colorOptions` |`Object` |`false`|Random color options (see [randomColor#options](https://github.com/davidmerfield/randomColor#options))|
+|`disableRandomColor` |`Boolean` |`false`|If `true`, random color is not used|
+|`renderer` |`Function`|`false`|Function used to render each tag|
*Note:* Furthermore you can pass any other option and it will be passed forward to the wrapping `
` component (e.g. `style`, `className`).
diff --git a/__tests__/TagCloud-test.js b/__tests__/TagCloud-test.js
index 9b716b1..966d08d 100644
--- a/__tests__/TagCloud-test.js
+++ b/__tests__/TagCloud-test.js
@@ -2,7 +2,10 @@ jest.unmock('../src/TagCloud');
jest.unmock('../src/defaultRenderer');
jest.unmock('../src/helpers');
-jest.mock('array-shuffle', () => arr => arr.slice().reverse());
+jest.mock('shuffle-array', () => (arr, opts = {}) => {
+ opts.rng && opts.rng();
+ return arr.slice().reverse();
+});
import React from 'react';
import ReactDOM from 'react-dom';
@@ -120,4 +123,12 @@ describe('TagCloud', () => {
cloud._data.forEach((t, i) => expect(t.tag).toEqual(data[i]));
});
+ it('should use custom rng', () => {
+ const rng = jest.fn();
+ TestUtils.renderIntoDocument(
+
+ );
+
+ expect(rng).toHaveBeenCalled();
+ });
});
diff --git a/examples/src/App.js b/examples/src/App.js
index d464157..6682e94 100644
--- a/examples/src/App.js
+++ b/examples/src/App.js
@@ -8,7 +8,8 @@ const examples = [
{file: 'simple-cloud.js', title: 'Simple cloud', key: 1},
{file: 'custom-color-options.js', title: 'Custom color options', key: 2},
{file: 'custom-styles.js', title: 'Custom styles', key: 3},
- {file: 'custom-renderer.js', title: 'Custom renderer', key: 4}
+ {file: 'custom-renderer.js', title: 'Custom renderer', key: 4},
+ {file: 'shuffle-with-seed.js', title: 'Shuffle with seed', key: 5}
];
class App extends React.Component {
diff --git a/examples/src/shuffle-with-seed.js b/examples/src/shuffle-with-seed.js
new file mode 100644
index 0000000..63545f2
--- /dev/null
+++ b/examples/src/shuffle-with-seed.js
@@ -0,0 +1,29 @@
+import React from "react";
+import { TagCloud } from "react-tagcloud";
+
+const data = [
+ { value: "jQuery", count: 25 }, { value: "MongoDB", count: 18 },
+ { value: "JavaScript", count: 38 }, { value: "React", count: 30 },
+ { value: "Nodejs", count: 28 }, { value: "Express.js", count: 25 },
+ { value: "HTML5", count: 33 }, { value: "CSS3", count: 20 },
+ { value: "Webpack", count: 22 }, { value: "Babel.js", count: 7 },
+ { value: "ECMAScript", count: 25 }, { value: "Jest", count: 15 },
+ { value: "Mocha", count: 17 }, { value: "React Native", count: 27 },
+ { value: "Angular.js", count: 30 }, { value: "TypeScript", count: 15 },
+ { value: "Flow", count: 30 }, { value: "NPM", count: 11 },
+];
+
+// bring your own implementation of rng
+let seed = 1337;
+function random() {
+ const x = Math.sin(seed++) * 10000;
+ return x - Math.floor(x);
+}
+
+export default () => (
+
+);
+
diff --git a/lib/TagCloud.js b/lib/TagCloud.js
index 7f47300..adab68e 100644
--- a/lib/TagCloud.js
+++ b/lib/TagCloud.js
@@ -17,9 +17,9 @@ var _propTypes2 = _interopRequireDefault(_propTypes);
var _defaultRenderer = require('./defaultRenderer');
-var _arrayShuffle = require('array-shuffle');
+var _shuffleArray = require('shuffle-array');
-var _arrayShuffle2 = _interopRequireDefault(_arrayShuffle);
+var _shuffleArray2 = _interopRequireDefault(_shuffleArray);
var _randomcolor = require('randomcolor');
@@ -38,7 +38,7 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var eventHandlers = ['onClick', 'onDoubleClick', 'onMouseMove'];
-var cloudProps = ['tags', 'shuffle', 'renderer', 'maxSize', 'minSize', 'colorOptions', 'disableRandomColor'];
+var cloudProps = ['tags', 'shuffle', 'renderer', 'maxSize', 'minSize', 'colorOptions', 'disableRandomColor', 'randomNumberGenerator'];
var generateColor = function generateColor(tag, _ref) {
var disableRandomColor = _ref.disableRandomColor,
@@ -116,7 +116,8 @@ var TagCloud = exports.TagCloud = function (_React$Component) {
var tags = props.tags,
shuffle = props.shuffle,
minSize = props.minSize,
- maxSize = props.maxSize;
+ maxSize = props.maxSize,
+ randomNumberGenerator = props.randomNumberGenerator;
var counts = tags.map(function (tag) {
return tag.count;
@@ -130,7 +131,7 @@ var TagCloud = exports.TagCloud = function (_React$Component) {
fontSize: (0, _helpers.fontSizeConverter)(tag.count, min, max, minSize, maxSize)
};
});
- this._data = shuffle ? (0, _arrayShuffle2.default)(data) : data;
+ this._data = shuffle ? (0, _shuffleArray2.default)(data, { copy: true, rng: randomNumberGenerator }) : data;
}
}]);
@@ -145,7 +146,8 @@ TagCloud.propTypes = {
colorOptions: _propTypes2.default.object,
disableRandomColor: _propTypes2.default.bool,
renderer: _propTypes2.default.func,
- className: _propTypes2.default.string
+ className: _propTypes2.default.string,
+ randomNumberGenerator: _propTypes2.default.func
};
TagCloud.defaultProps = {
diff --git a/lib/tag-cloud.js b/lib/tag-cloud.js
index f5a98b8..b7df357 100644
--- a/lib/tag-cloud.js
+++ b/lib/tag-cloud.js
@@ -24,7 +24,7 @@ var _defaultRenderer = require("./default-renderer");
var _defaultRenderer2 = _interopRequireDefault(_defaultRenderer);
-var _arrayShuffle = require("array-shuffle");
+var _arrayShuffle = require("shuffle-array");
var _arrayShuffle2 = _interopRequireDefault(_arrayShuffle);
@@ -105,4 +105,4 @@ TagCloud.defaultProps = {
shuffle: true,
className: "tag-cloud"
};
-module.exports = exports["default"];
\ No newline at end of file
+module.exports = exports["default"];
diff --git a/package.json b/package.json
index cefd9ab..55734c1 100644
--- a/package.json
+++ b/package.json
@@ -29,10 +29,10 @@
"collectCoverage": true
},
"dependencies": {
- "array-shuffle": "^1.0.0",
"object-assign": "^4.1.0",
"prop-types": "^15.6.2",
- "randomcolor": "^0.4.2"
+ "randomcolor": "^0.4.2",
+ "shuffle-array": "^1.0.1"
},
"peerDependencies": {
"react": "^16.0.0"
diff --git a/src/TagCloud.js b/src/TagCloud.js
index 934025a..756497c 100644
--- a/src/TagCloud.js
+++ b/src/TagCloud.js
@@ -1,12 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types';
import { defaultRenderer } from './defaultRenderer';
-import arrayShuffle from 'array-shuffle';
+import arrayShuffle from 'shuffle-array';
import randomColor from 'randomcolor';
import { omitProps, includeProps, fontSizeConverter, arraysEqual, propertiesEqual } from './helpers';
const eventHandlers = ['onClick', 'onDoubleClick', 'onMouseMove'];
-const cloudProps = ['tags', 'shuffle', 'renderer', 'maxSize', 'minSize', 'colorOptions', 'disableRandomColor'];
+const cloudProps = ['tags', 'shuffle', 'renderer', 'maxSize', 'minSize', 'colorOptions', 'disableRandomColor', 'randomNumberGenerator'];
const generateColor = (tag, {disableRandomColor, colorOptions}) => {
if (tag.color) {
@@ -59,7 +59,7 @@ export class TagCloud extends React.Component {
}
_populate(props) {
- const { tags, shuffle, minSize, maxSize } = props;
+ const { tags, shuffle, minSize, maxSize, randomNumberGenerator } = props;
const counts = tags.map(tag => tag.count),
min = Math.min(...counts),
max = Math.max(...counts);
@@ -68,7 +68,7 @@ export class TagCloud extends React.Component {
color: generateColor(tag, props),
fontSize: fontSizeConverter(tag.count, min, max, minSize, maxSize)
}));
- this._data = shuffle ? arrayShuffle(data) : data;
+ this._data = shuffle ? arrayShuffle(data, { copy: true, rng: randomNumberGenerator }) : data;
}
}
@@ -81,7 +81,8 @@ TagCloud.propTypes = {
colorOptions: PropTypes.object,
disableRandomColor: PropTypes.bool,
renderer: PropTypes.func,
- className: PropTypes.string
+ className: PropTypes.string,
+ randomNumberGenerator: PropTypes.func,
};
TagCloud.defaultProps = {