Socket
Socket
Sign inDemoInstall

font-picker-react

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

font-picker-react - npm Package Compare versions

Comparing version 1.3.0 to 2.0.0

317

lib/FontPicker.js

@@ -7,3 +7,3 @@ 'use strict';

var React__default = _interopDefault(React);
var FontPickerBase = _interopDefault(require('font-picker'));
var fontPicker = require('font-picker');

@@ -59,19 +59,65 @@ var classCallCheck = function (instance, Constructor) {

/**
* Font picker presentational component
* React interface for the font picker
* @prop {string} apiKey (required) - Google API key
* @prop {string} activeFont - Font that should be selected in the font picker and applied to the
* text (default: 'Open Sans'). Must be stored in component state, and be updated using an onChange
* listener. See README.md for an example.
* @prop {Object} options - Object with additional (optional) parameters:
* @prop {string} name - If you have multiple font pickers on your site, you need to give them
* unique names (which may only consist of letters and digits). These names must also be appended
* to the font picker's ID and the .apply-font class name.
* Example: If { name: 'main' }, use #font-picker-main and .apply-font-main
* @prop {string[]} families - If only specific fonts shall appear in the list, specify their
* names in an array
* @prop {string[]} categories - Array of font categories
* Possible values: 'sans-serif', 'serif', 'display', 'handwriting', 'monospace' (default: all
* categories)
* @prop {string[]} variants - Array of variants which the fonts must include and which will be
* downloaded; the first variant in the array will become the default variant (and will be used
* in the font picker and the .apply-font class)
* Example: ['regular', 'italic', '700', '700italic'] (default: ['regular'])
* @prop {number} limit - Maximum number of fonts to be displayed in the list (the least popular
* fonts will be omitted; default: 100)
* @prop {string} sort - Sorting attribute for the font list
* Possible values: 'alphabetical' (default), 'popularity'
* @prop {function} onChange - Function which is executed whenever the user changes the active font
* and its stylesheet finishes downloading
*/
var FontPickerUI = function (_Component) {
inherits(FontPickerUI, _Component);
var FontPicker = function (_Component) {
inherits(FontPicker, _Component);
function FontPickerUI(props) {
classCallCheck(this, FontPickerUI);
function FontPicker(props) {
classCallCheck(this, FontPicker);
var _this = possibleConstructorReturn(this, (FontPickerUI.__proto__ || Object.getPrototypeOf(FontPickerUI)).call(this, props));
var _this = possibleConstructorReturn(this, (FontPicker.__proto__ || Object.getPrototypeOf(FontPicker)).call(this, props));
_this.state = {
expanded: false
activeFont: _this.props.activeFont,
errorText: '',
expanded: false,
loadingStatus: 'loading' // possible values: 'loading', 'finished', 'error'
};
// initialize FontManager object and generate the font list
_this.fontManager = new fontPicker.FontManager(_this.props.apiKey, _this.props.activeFont, _this.props.options);
_this.fontManager.init().then(function () {
// font list has finished loading
_this.setState({
errorText: '',
loadingStatus: 'finished'
});
}).catch(function (err) {
// error while loading font list
_this.setState({
errorText: 'Error trying to fetch the list of available fonts',
loadingStatus: 'error'
});
console.error(_this.state.errorText);
console.error(err);
});
// function bindings
_this.closeEventListener = _this.closeEventListener.bind(_this);
_this.setActiveFont = _this.setActiveFont.bind(_this);
_this.onClose = _this.onClose.bind(_this);
_this.onScroll = _this.onScroll.bind(_this);

@@ -83,12 +129,13 @@ _this.toggleExpanded = _this.toggleExpanded.bind(_this);

/**
* Download the font previews for all visible font entries and the five after them
* After every component update, check whether the activeFont prop has changed. If so, change the
* font in the fontManager as well
*/
createClass(FontPickerUI, [{
key: 'onScroll',
value: function onScroll(e) {
var elementHeight = e.target.scrollHeight / this.props.fontList.length;
var downloadIndex = Math.ceil((e.target.scrollTop + e.target.clientHeight) / elementHeight);
this.props.downloadPreviews(downloadIndex + 5);
createClass(FontPicker, [{
key: 'componentDidUpdate',
value: function componentDidUpdate() {
if (this.state.activeFont !== this.props.activeFont) {
this.setActiveFont(this.props.activeFont);
}
}

@@ -101,4 +148,4 @@

}, {
key: 'closeEventListener',
value: function closeEventListener(e) {
key: 'onClose',
value: function onClose(e) {
var targetElement = e.target; // clicked element

@@ -120,2 +167,14 @@

/**
* Download the font previews for all visible font entries and the five after them
*/
}, {
key: 'onScroll',
value: function onScroll(e) {
var elementHeight = e.target.scrollHeight / this.fontManager.fonts.length;
var downloadIndex = Math.ceil((e.target.scrollTop + e.target.clientHeight) / elementHeight);
this.fontManager.downloadPreviews(downloadIndex + 5);
}
/**
* Set the font with the given font list index as the active one

@@ -125,6 +184,21 @@ */

}, {
key: 'selectFont',
value: function selectFont(index) {
this.toggleExpanded(); // collapse font list
this.props.selectFont(index);
key: 'setActiveFont',
value: function setActiveFont(fontFamily) {
var activeFontIndex = this.fontManager.setActiveFont(fontFamily);
if (activeFontIndex === -1) {
// error trying to change font
this.setState({
activeFont: fontFamily,
errorText: 'Cannot update activeFont: The font "' + fontFamily + '" is not in the font list',
loadingStatus: 'error'
});
console.error(this.state.errorText);
} else {
// font change successful
this.setState({
activeFont: fontFamily,
errorText: '',
loadingStatus: 'finished'
});
}
}

@@ -140,7 +214,11 @@

if (this.state.expanded) {
this.setState({ expanded: false });
document.removeEventListener('click', this.closeEventListener);
this.setState({
expanded: false
});
document.removeEventListener('click', this.onClose);
} else {
this.setState({ expanded: true });
document.addEventListener('click', this.closeEventListener);
this.setState({
expanded: true
});
document.addEventListener('click', this.onClose);
}

@@ -153,45 +231,41 @@ }

// generate <ul> with font names; fetch font previews on scroll
var fontList = React__default.createElement(
'ul',
{
className: this.state.expanded ? 'expanded' : '',
onScroll: this.onScroll
},
this.props.fontList.map(function (font, index) {
var fontId = font.family.replace(/\s+/g, '-').toLowerCase();
var isActive = font.family === _this2.props.activeFont.family;
return React__default.createElement(
'li',
{ key: font.family },
React__default.createElement(
'a',
{
role: 'button',
tabIndex: '0',
onClick: function onClick() {
return _this2.selectFont(index);
// generate <ul> with font list; fetch font previews on scroll
var fontList = void 0;
if (this.state.loadingStatus === 'finished') {
fontList = React__default.createElement(
'ul',
{ className: this.state.expanded ? 'expanded' : '', onScroll: this.onScroll },
this.fontManager.fonts.map(function (font) {
var isActive = font.family === _this2.state.activeFont;
var fontId = font.family.replace(/\s+/g, '-').toLowerCase();
return React__default.createElement(
'li',
{ key: font.family },
React__default.createElement(
'button',
{
className: 'font-' + fontId + ' ' + (isActive ? 'active-font' : ''),
onClick: function onClick() {
_this2.toggleExpanded();
_this2.props.onChange(font);
},
onKeyPress: function onKeyPress() {
_this2.toggleExpanded();
_this2.props.onChange(font);
}
},
onKeyPress: function onKeyPress() {
return _this2.selectFont(index);
},
className: 'font-' + fontId + ' ' + (isActive ? 'active-font' : '')
},
font.family
)
);
})
);
font.family
)
);
})
);
}
// render font picker button and attach font list to it
return React__default.createElement(
'div',
{
id: 'font-picker' + this.props.name,
title: this.props.loadingStatus === 'error' ? 'Error trying to fetch the list of available fonts' : ''
},
{ id: 'font-picker' + this.fontManager.name, title: this.state.errorText },
React__default.createElement(
'a',
'button',
{
role: 'button',
tabIndex: '0',
className: 'dropdown-button ' + (this.state.expanded ? 'expanded' : ''),

@@ -204,121 +278,10 @@ onClick: this.toggleExpanded,

null,
this.props.activeFont.family
this.state.activeFont
),
React__default.createElement('div', { className: 'dropdown-icon ' + this.props.loadingStatus })
React__default.createElement('div', { className: 'dropdown-icon ' + this.state.loadingStatus })
),
this.props.loadingStatus === 'finished' && fontList
this.state.loadingStatus === 'finished' && fontList
);
}
}]);
return FontPickerUI;
}(React.Component);
/**
* Font picker container component
* @prop {string} apiKey (required) - Google API key (can be generated at
* https://developers.google.com/fonts/docs/developer_api)
* @prop {string} defaultFont - Font that is selected on initialization (default: 'Open Sans')
* @prop {Object} options - Object with additional (optional) parameters:
* @prop {string} name - If you have multiple font pickers on your site, you need to give them
* unique names (which may only consist of letters and digits). These names must also be
* appended to the font picker's ID and the .apply-font class name.
* Example: if { name: 'main' }, then use #font-picker-main and .apply-font-main
* @prop {string[]} families - If only specific fonts shall appear in the list, specify their
* names in an array
* @prop {string[]} categories - Array of font categories
* Possible values: 'sans-serif', 'serif', 'display', 'handwriting', 'monospace' (default:
* all categories)
* @prop {string[]} variants - Array of variants which the fonts must include and which will be
* downloaded; the first variant in the array will become the default variant (and will be
* used in the font picker and the .apply-font class)
* Example: ['regular', 'italic', '700', '700italic'] (default: ['regular'])
* @prop {number} limit - Maximum number of fonts to be displayed in the list (the least popular
* fonts will be omitted; default: 100)
* @prop {string} sort - Sorting attribute for the font list
* Possible values: 'alphabetical' (default), 'popularity'
* @prop {function} onChange - Function which is executed whenever the user changes the active
* font and its stylesheet finishes downloading
*/
var FontPicker = function (_Component) {
inherits(FontPicker, _Component);
function FontPicker(props) {
classCallCheck(this, FontPicker);
var _this = possibleConstructorReturn(this, (FontPicker.__proto__ || Object.getPrototypeOf(FontPicker)).call(this, props));
_this.state = {
activeFont: {
family: _this.props.defaultFont
},
fontList: [],
loadingStatus: 'loading'
};
// initialize FontHandler object and generate the font list
var fontPickerBase = new FontPickerBase(_this.props.apiKey, _this.props.defaultFont, _this.props.options, _this.props.onChange);
_this.fontHandler = fontPickerBase.fontHandler;
_this.fontHandler.init().then(function () {
// on font list load: save it to component state
_this.setState({
activeFont: _this.fontHandler.activeFont,
fontList: _this.fontHandler.fonts,
loadingStatus: 'finished'
});
}).catch(function (err) {
console.error('Error trying to fetch the list of available fonts');
console.error(err);
_this.setState({
loadingStatus: 'error'
});
});
// function bindings
_this.selectFont = _this.selectFont.bind(_this);
_this.update = _this.update.bind(_this);
return _this;
}
/**
* Set the font with the given font list index as the active one
*/
createClass(FontPicker, [{
key: 'selectFont',
value: function selectFont(index) {
this.fontHandler.changeActiveFont(index);
this.update();
}
/**
* Updates the component state with the changed information in fontHandler
*/
}, {
key: 'update',
value: function update() {
this.setState({
activeFont: this.fontHandler.activeFont,
fontList: this.fontHandler.fonts
});
}
}, {
key: 'render',
value: function render() {
var _this2 = this;
return React__default.createElement(FontPickerUI, {
activeFont: this.state.activeFont,
downloadPreviews: function downloadPreviews(downloadIndex) {
return _this2.fontHandler.downloadPreviews(downloadIndex);
},
fontList: this.state.fontList,
loadingStatus: this.state.loadingStatus,
name: this.fontHandler.name,
selectFont: this.selectFont
});
}
}]);
return FontPicker;

@@ -325,0 +288,0 @@ }(React.Component);

{
"name": "font-picker-react",
"version": "1.3.0",
"description": "Font picker component for previewing, selecting, and downloading Google Fonts",
"version": "2.0.0",
"description": "Font selector component for Google Fonts",
"keywords": [

@@ -9,5 +9,8 @@ "fonts",

"selector",
"picker",
"component",
"preview",
"download",
"react",
"component"
"react-component"
],

@@ -20,5 +23,6 @@ "main": "lib/FontPicker.js",

"scripts": {
"start": "rollup -c --watch",
"start": "npm-run-all build --parallel start:*",
"start:rollup": "rollup -c --watch",
"start:storybook": "start-storybook -p 6006",
"build": "rollup -c",
"storybook": "start-storybook -p 6006",
"lint": "eslint .",

@@ -29,12 +33,12 @@ "precommit": "npm run lint",

"dependencies": {
"font-picker": "^1.3.0"
"font-picker": "^2.0.0"
},
"peerDependencies": {
"react": "^16.0.0"
"react": "^16.3.1"
},
"devDependencies": {
"@storybook/addon-actions": "^3.3.15",
"@storybook/addon-links": "^3.3.15",
"@storybook/addons": "^3.3.15",
"@storybook/react": "^3.3.15",
"@storybook/addon-actions": "^3.4.2",
"@storybook/addon-links": "^3.4.2",
"@storybook/addons": "^3.4.2",
"@storybook/react": "^3.4.2",
"babel-core": "^6.26.0",

@@ -46,9 +50,10 @@ "babel-plugin-external-helpers": "^6.22.0",

"eslint-config-airbnb": "^16.1.0",
"eslint-plugin-import": "^2.9.0",
"eslint-plugin-import": "^2.11.0",
"eslint-plugin-jsx-a11y": "^6.0.2",
"eslint-plugin-react": "^7.7.0",
"husky": "^0.14.3",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"rollup": "^0.57.1",
"npm-run-all": "^4.1.2",
"react": "^16.3.2",
"react-dom": "^16.3.2",
"rollup": "^0.58.0",
"rollup-plugin-babel": "^3.0.3"

@@ -55,0 +60,0 @@ },

@@ -6,6 +6,6 @@ # Font Picker for React

**A simple, customizable font selector allowing users to preview, choose, and use Google Fonts on your website.**
**A simple, customizable font picker allowing users to preview, select, and use Google Fonts on your website.**
* automatic font download and generation of the required CSS styles
* efficient font previews (previews in the list are loaded dynamically; the full font is only downloaded on selection)
* Automatic font download and generation of the required CSS styles
* Efficient font previews (previews are loaded dynamically and full fonts are only downloaded on selection)

@@ -17,3 +17,3 @@ → **[Demo](https://smeuli.github.io/font-picker)**

<p align="center">
<img src=".github/demo.gif" width=700 alt="Demo">
<img src=".github/demo.gif" width=700 alt="Demo">
</p>

@@ -24,28 +24,48 @@

### Setup
### 1. Setup
Add the package as a dependency using **NPM**:
Install the package using **NPM**:
```
```sh
npm install font-picker-react
```
Then add the **`<FontPicker />` component** somewhere in your React project:
### 2. Displaying the font picker
Add the **`<FontPicker />` component** to your React code:
```jsx
import React, { Component } from 'react';
import FontPicker from 'font-picker-react';
<FontPicker
apiKey="YOUR_API_KEY" // Google API key
defaultFont={'Open Sans'}
options={{ limit: 50 }}
/>
export default class ExampleComponent extends Component {
constructor() {
super();
this.state = { activeFont: 'Open Sans' };
}
render() {
return (
<div>
<FontPicker
apiKey="YOUR_API_KEY"
activeFont={this.state.activeFont}
onChange={nextFont => this.setState({ activeFont: nextFont.family })}
/>
<p className="apply-font">
The font will be applied to this text.
</p>
</div>
);
}
}
```
### Applying the selected font
### 3. Applying the selected font
**Add `className="apply-font"` to all JSX elements you want to apply the selected font to.**
When the user selects a font using the font picker, it will automatically be downloaded (added as a `<link>` to the document's head) and applied to all HTML elements of the `"apply-font"` class.
When the user selects a font, it will automatically be downloaded and applied to all HTML elements of the `"apply-font"` class.

@@ -55,10 +75,8 @@

### Props
The following **props** can be passed to the `FontPicker` component:
The following props can be passed to the `FontPicker` component:
* **`apiKey` (required)**: Google API key (can be generated [here](https://developers.google.com/fonts/docs/developer_api#APIKey))
* **`defaultFont`**: Font that is selected on initialization (default: `'Open Sans'`)
* **`activeFont`**: Font that should be selected in the font picker and applied to the text (default: `'Open Sans'`). Must be stored in component state, and be updated using an `onChange` listener
* **`options`**: Object with additional (optional) parameters:
* **`name`**: If you have multiple font pickers on your site, you need to give them unique names (which may only consist of letters and digits). These names must also be appended to the font picker's ID and the `.apply-font` class name; e.g. if `{ name: 'main' }`, then use `#font-picker-main` and `.apply-font-main`
* **`name`**: If you have multiple font pickers on your site, you need to give them unique names (which may only consist of letters and digits). These names must also be appended to the font picker's ID and the `.apply-font` class name; e.g. if `{ name: 'main' }`, use `#font-picker-main` and `.apply-font-main`
* **`families`**: If only specific fonts shall appear in the list, specify their names in an array (default: all font families)

@@ -72,7 +90,8 @@ * **`categories`**: Array of font categories – possible values: `'sans-serif', 'serif', 'display', handwriting', 'monospace'` (default: all categories)

## Build Process
## Contributing
To build the project locally, do the following:
* `git clone`
* `npm install`
* `npm start` to generate the library bundle using [Rollup](https://github.com/rollup/rollup) (in the `lib` directory)
* See the font picker in action using [Storybook](https://github.com/storybooks/storybook): `npm run storybook`
* `npm start` to generate the library bundle using [Rollup](https://github.com/rollup/rollup) and and start the [Storybook](https://github.com/storybooks/storybook) for testing the component interactively
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc