diff --git a/.eslintrc.js b/.eslintrc.js index c0a0b60..26e4772 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -6,5 +6,7 @@ module.exports = { jest: true, browser: true, }, - rules: {}, + rules: { + 'react/sort-prop-types': 'off', + }, }; diff --git a/README.md b/README.md index 86ce0d6..abff5ff 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,11 @@ const data = [ { text: "duck", value: 10 }, ]; -const fontSizeMapper = (word) => Math.log2(word.value) * 5; +const fontSize = (word) => Math.log2(word.value) * 5; const rotate = (word) => word.value % 360; render( - , + , document.getElementById("root") ); ``` @@ -41,18 +41,22 @@ for more detailed props, please refer to below: ## Props -| name | description | type | required | default | -| --------------- | ------------------------------------------------------------------------------------------------------------ | ----------------------------------------------- | -------- | --------------------- | -| data | The input data for rendering | Array<{ text: string, value: number }> | ✓ | -| width | Width of component (px) | number | | 700 | -| height | Height of component (px) | number | | 600 | -| fontSizeMapper | Map each element of `data` to font size (px) | Function: `(word: string, idx: number): number` | | `word => word.value;` | -| rotate | Map each element of `data` to font rotation degree. Or simply provide a number for global rotation. (degree) | Function \| number | | 0 | -| padding | Map each element of `data` to font padding. Or simply provide a number for global padding. (px) | Function \| number | | 5 | -| font | The font of text shown | Function \| string | | serif | -| onWordClick | Function called when click event triggered on a word | Function: `word => {}` | | null | -| onWordMouseOver | Function called when mouseover event triggered on a word | Function: `word => {}` | | null | -| onWordMouseOut | Function called when mouseout event triggered on a word | Function: `word => {}` | | null | +| name | description | type | required | default | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------ | -------------- | ---------------------------------------- | ---------- | +| data | The words array | `{ text: string, value: number }>[]` | ✓ | +| width | Width of the layout (px) | `number` | | `700` | +| height | Height of the layout (px) | `number` | | `600` | +| font | The font accessor function, which indicates the font face for each word. A constant may be specified instead of a function. | `string | (d) => string` | | `serif` | +| fontStyle | The fontStyle accessor function, which indicates the font style for each word. A constant may be specified instead of a function. | `string | (d) => string` | | `'normal'` | +| fontWeight | The fontWeight accessor function, which indicates the font weight for each word. A constant may be specified instead of a function. | `string | (d) => string` | | `'normal'` | +| fontSize | The fontSize accessor function, which indicates the numerical font size for each word. | `(d) => number` | | `(d) => Math.sqrt(d.value)` | +| rotate | The rotate accessor function, which indicates the rotation angle (in degrees) for each word. | `(d) => number` | | `() => (~~(Math.random() * 6) - 3) * 30` | +| spiral | The current type of spiral used for positioning words. This can either be one of the two built-in spirals, "archimedean" and "rectangular", or an arbitrary spiral generator can be used | `([width, height]) => t => [x, y]` | | `'archimedean'` | +| padding | The padding accessor function, which indicates the numerical padding for each word. | `number | (d) => number` | | `1` | +| random | The internal random number generator, used for selecting the initial position of each word, and the clockwise/counterclockwise direction of the spiral for each word. This should return a number in the range `[0, 1)`. | `(d) => number` | | `Math.random` | +| onWordClick | The function will be called when `click` event is triggered on a word | `word => {}` | | null | +| onWorwordMouseOver | The function will be called when `mouseover` event is triggered on a word | `word => {}` | | null | +| onWordMouseOut | The function will be called when `mouseout` event is triggered on a word | `word => {}` | | null | ## Build diff --git a/src/WordCloud.js b/src/WordCloud.js index b9b5866..91bbf3b 100644 --- a/src/WordCloud.js +++ b/src/WordCloud.js @@ -6,8 +6,6 @@ import { schemeCategory10 } from 'd3-scale-chromatic'; import { select } from 'd3-selection'; import { useRef } from 'react'; -import { defaultFontSizeMapper } from './defaultMappers'; - const fill = scaleOrdinal(schemeCategory10); function WordCloud(props) { @@ -23,10 +21,14 @@ function WordCloud(props) { data, width, height, - padding, font, - fontSizeMapper, + fontStyle, + fontWeight, + fontSize, rotate, + spiral, + padding, + random, onWordClick, onWordMouseOver, onWordMouseOut, @@ -37,12 +39,16 @@ function WordCloud(props) { // render based on new data const layout = cloud() + .words(data) .size([width, height]) .font(font) - .words(data) - .padding(padding) + .fontStyle(fontStyle) + .fontWeight(fontWeight) + .fontSize(fontSize) .rotate(rotate) - .fontSize(fontSizeMapper) + .spiral(spiral) + .padding(padding) + .random(random) .on('end', (words) => { const texts = select(el) .append('svg') @@ -87,12 +93,16 @@ WordCloud.propTypes = { value: PropTypes.number.isRequired, }) ).isRequired, - font: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), - fontSizeMapper: PropTypes.func, + width: PropTypes.number, height: PropTypes.number, + font: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), + fontStyle: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), + fontWeight: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), + fontSize: PropTypes.func, + rotate: PropTypes.func, + spiral: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), padding: PropTypes.oneOfType([PropTypes.number, PropTypes.func]), - rotate: PropTypes.oneOfType([PropTypes.number, PropTypes.func]), - width: PropTypes.number, + random: PropTypes.func, onWordClick: PropTypes.func, onWordMouseOut: PropTypes.func, onWordMouseOver: PropTypes.func, @@ -101,10 +111,15 @@ WordCloud.propTypes = { WordCloud.defaultProps = { width: 700, height: 600, - padding: 5, font: 'serif', - fontSizeMapper: defaultFontSizeMapper, - rotate: 0, + fontStyle: 'normal', + fontWeight: 'normal', + fontSize: (d) => Math.sqrt(d.value), + // eslint-disable-next-line no-bitwise + rotate: () => (~~(Math.random() * 6) - 3) * 30, + spiral: 'archimedean', + padding: 1, + random: Math.random, onWordClick: null, onWordMouseOver: null, onWordMouseOut: null, diff --git a/src/__tests__/WordCloud.spec.js b/src/__tests__/WordCloud.spec.js index 528e70d..575a420 100644 --- a/src/__tests__/WordCloud.spec.js +++ b/src/__tests__/WordCloud.spec.js @@ -10,13 +10,13 @@ const data = [ { text: 'duck', value: 10 }, ]; -it('should call custom fontSizeMapper', () => { - const fontSizeMapper = jest.fn().mockReturnValue(10); - renderer.create(); - expect(fontSizeMapper).toHaveBeenCalledTimes(data.length); +it('should call custom fontSize', () => { + const fontSize = jest.fn().mockReturnValue(10); + renderer.create(); + expect(fontSize).toHaveBeenCalledTimes(data.length); }); -it('should call custom rotater', () => { +it('should call custom rotate', () => { const rotate = jest.fn().mockReturnValue(1); renderer.create(); expect(rotate).toHaveBeenCalledTimes(data.length); diff --git a/src/defaultMappers/__tests__/.keep b/src/defaultMappers/__tests__/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/src/defaultMappers/defaultFontSizeMapper.js b/src/defaultMappers/defaultFontSizeMapper.js deleted file mode 100644 index dd7483c..0000000 --- a/src/defaultMappers/defaultFontSizeMapper.js +++ /dev/null @@ -1,3 +0,0 @@ -const defaultFontSizeMapper = (word) => word.value; - -export default defaultFontSizeMapper; diff --git a/src/defaultMappers/index.js b/src/defaultMappers/index.js deleted file mode 100644 index 33f5d08..0000000 --- a/src/defaultMappers/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default as defaultFontSizeMapper } from './defaultFontSizeMapper';