├── .vscode └── settings.json ├── .eslintignore ├── fonticonpicker.png ├── create-react-app.png ├── src ├── docs │ ├── picker.png │ ├── assets │ │ ├── icomoon │ │ │ ├── fonts │ │ │ │ ├── icomoon.eot │ │ │ │ ├── icomoon.ttf │ │ │ │ └── icomoon.woff │ │ │ └── Read Me.txt │ │ ├── fontello │ │ │ ├── font │ │ │ │ ├── fontello.eot │ │ │ │ ├── fontello.ttf │ │ │ │ └── fontello.woff │ │ │ ├── LICENSE.txt │ │ │ └── README.txt │ │ ├── superhero │ │ │ ├── fonts │ │ │ │ ├── superhero.ttf │ │ │ │ └── superhero.woff │ │ │ ├── Read Me.txt │ │ │ └── demo-files │ │ │ │ ├── demo.js │ │ │ │ └── demo.css │ │ └── superhero.css │ ├── scss │ │ ├── style.scss │ │ ├── layout │ │ │ ├── _main.scss │ │ │ ├── _footer.scss │ │ │ ├── _app.scss │ │ │ ├── _header.scss │ │ │ └── _sidebar.scss │ │ └── pages │ │ │ └── _introduction.scss │ ├── components │ │ ├── pages │ │ │ ├── 404.jsx │ │ │ ├── Meta.jsx │ │ │ ├── Props.jsx │ │ │ ├── Installation.jsx │ │ │ ├── Themes.jsx │ │ │ ├── Introduction.jsx │ │ │ └── BasicUsage.jsx │ │ ├── TableRenderer.jsx │ │ ├── ScrollToTop.jsx │ │ ├── CodeBlock.jsx │ │ ├── DocApp.jsx │ │ ├── Sidebar.jsx │ │ └── Routes.jsx │ ├── index.jsx │ ├── guides │ │ ├── usage-parts │ │ │ ├── 3-fipsmp.md │ │ │ ├── 1-fipncp.md │ │ │ ├── 5-fipcr.md │ │ │ ├── 4-fipar.md │ │ │ └── 2-fipcp.md │ │ ├── basicusage.md │ │ ├── meta.md │ │ ├── introduction.md │ │ └── installation.md │ ├── helpers │ │ ├── routes.js │ │ └── routeTransition.js │ ├── 404.html │ └── index.html ├── scss │ ├── components │ │ ├── _rfip.scss │ │ ├── _rfipsearch.scss │ │ ├── _rfipdropdown.scss │ │ ├── _rfipcategory.scss │ │ ├── _rfipbutton.scss │ │ └── _rfipicons.scss │ ├── default-theme.scss │ ├── blue-theme.scss │ ├── cyan-theme.scss │ ├── pink-theme.scss │ ├── red-theme.scss │ ├── teal-theme.scss │ ├── brown-theme.scss │ ├── green-theme.scss │ ├── indigo-theme.scss │ ├── purple-theme.scss │ ├── blue-grey-theme.scss │ ├── deep-orange-theme.scss │ ├── deep-purple-theme.scss │ ├── light-blue-theme.scss │ ├── base.scss │ ├── orange-theme.scss │ ├── base │ │ ├── _reset.scss │ │ ├── _variables.scss │ │ └── _mixin.scss │ └── themes │ │ └── _template.scss ├── assets │ └── fipicon │ │ ├── fonts │ │ ├── fontIconPicker.ttf │ │ ├── fontIconPicker.woff │ │ └── fontIconPicker.svg │ │ ├── Read Me.txt │ │ ├── style.css │ │ ├── demo-files │ │ ├── demo.js │ │ └── demo.css │ │ ├── demo.html │ │ └── selection.json └── js │ ├── ThemeBase.js │ ├── FontIconPicker.js │ ├── components │ ├── FipSearch.jsx │ ├── FipCategory.jsx │ ├── FipButton.jsx │ └── FipDropDown.jsx │ └── ThemeMaterial.js ├── docs ├── fonticonpicker.png ├── favicons │ ├── favicon.ico │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── apple-touch-icon.png │ ├── firefox_app_60x60.png │ ├── android-chrome-36x36.png │ ├── android-chrome-48x48.png │ ├── android-chrome-72x72.png │ ├── android-chrome-96x96.png │ ├── firefox_app_128x128.png │ ├── firefox_app_512x512.png │ ├── android-chrome-144x144.png │ ├── android-chrome-192x192.png │ ├── android-chrome-256x256.png │ ├── android-chrome-384x384.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon-57x57.png │ ├── apple-touch-icon-60x60.png │ ├── apple-touch-icon-72x72.png │ ├── apple-touch-icon-76x76.png │ ├── apple-touch-icon-114x114.png │ ├── apple-touch-icon-120x120.png │ ├── apple-touch-icon-144x144.png │ ├── apple-touch-icon-152x152.png │ ├── apple-touch-icon-167x167.png │ ├── apple-touch-icon-180x180.png │ ├── apple-touch-icon-precomposed.png │ ├── apple-touch-startup-image-320x460.png │ ├── apple-touch-startup-image-640x920.png │ ├── apple-touch-startup-image-1182x2208.png │ ├── apple-touch-startup-image-1242x2148.png │ ├── apple-touch-startup-image-1496x2048.png │ ├── apple-touch-startup-image-1536x2008.png │ ├── apple-touch-startup-image-640x1096.png │ ├── apple-touch-startup-image-748x1024.png │ ├── apple-touch-startup-image-750x1294.png │ ├── apple-touch-startup-image-768x1004.png │ ├── manifest.webapp │ └── manifest.json ├── assets │ ├── asset-34e26ea31670dd5229ee7d7ab5978b81.woff │ ├── asset-3ac0f7c0647773620f82ec59ba2874e3.ttf │ ├── asset-3bbb7142c2de96be81f33f02490b4d0f.woff │ ├── asset-4af291b190f613fa29d177f2fafd099d.eot │ ├── asset-8c2c34ece6757b8eace3fdcb7939d021.woff │ ├── asset-9e9559a32c9d33495e259629273b13b5.ttf │ ├── asset-a86caa7efa7c4269ec646a4dce6c6e92.ttf │ ├── asset-ac07f047856578fd1544a253dc441d67.ttf │ ├── asset-cb51d032f31aa60f59ba017e77616ec3.eot │ ├── asset-d55200c9395b20b924f1df9d850d0c74.woff │ └── asset-e5539dcf6082a05879d9a26211fb0bc4.svg └── 404.html ├── dist ├── assets │ ├── fontIconPicker.ttf │ ├── fontIconPicker.woff │ └── fontIconPicker.svg └── index.html ├── stylelint.config.js ├── __tests__ ├── unit │ ├── jest.test.js │ ├── FipSearch.unit.test.jsx │ ├── FipCategory.unit.test.jsx │ ├── FipDropDownPortal.unit.test.jsx │ ├── FipButton.unit.test.jsx │ ├── FipDropDown.unit.test.jsx │ ├── FontIconPicker.unit.test.jsx │ └── iconHelpers.test.js ├── .babelrc ├── .eslintrc.js ├── intg │ ├── 04_search_options.jsx │ ├── 05_category_options.jsx │ ├── 02_icon_and_search.jsx │ ├── 06_set_icons.jsx │ ├── 03_dropdown_button.jsx │ └── 01_default_value.jsx └── snapshots │ └── FontIconPicker.test.jsx ├── .npmignore ├── .prettierrc.json ├── .babelrc ├── postcss.config.js ├── scripts ├── enzymeSetup.js ├── cleanupDist.js └── index.html ├── jest.config.js ├── .eslintrc.js ├── CHANGELOG.md ├── LICENSE ├── .gitignore ├── .travis.yml ├── webpack.dev.config.js ├── package.json ├── webpack.config.js ├── webpack.doc.config.js └── CONTRIBUTING.md /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | build/ 3 | -------------------------------------------------------------------------------- /fonticonpicker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/fonticonpicker.png -------------------------------------------------------------------------------- /create-react-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/create-react-app.png -------------------------------------------------------------------------------- /src/docs/picker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/src/docs/picker.png -------------------------------------------------------------------------------- /docs/fonticonpicker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/fonticonpicker.png -------------------------------------------------------------------------------- /docs/favicons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/favicon.ico -------------------------------------------------------------------------------- /dist/assets/fontIconPicker.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/dist/assets/fontIconPicker.ttf -------------------------------------------------------------------------------- /dist/assets/fontIconPicker.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/dist/assets/fontIconPicker.woff -------------------------------------------------------------------------------- /docs/favicons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/favicon-16x16.png -------------------------------------------------------------------------------- /docs/favicons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/favicon-32x32.png -------------------------------------------------------------------------------- /stylelint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['stylelint-config-recommended-scss', 'stylelint-config-prettier'], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/favicons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-icon.png -------------------------------------------------------------------------------- /docs/favicons/firefox_app_60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/firefox_app_60x60.png -------------------------------------------------------------------------------- /docs/favicons/android-chrome-36x36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/android-chrome-36x36.png -------------------------------------------------------------------------------- /docs/favicons/android-chrome-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/android-chrome-48x48.png -------------------------------------------------------------------------------- /docs/favicons/android-chrome-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/android-chrome-72x72.png -------------------------------------------------------------------------------- /docs/favicons/android-chrome-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/android-chrome-96x96.png -------------------------------------------------------------------------------- /docs/favicons/firefox_app_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/firefox_app_128x128.png -------------------------------------------------------------------------------- /docs/favicons/firefox_app_512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/firefox_app_512x512.png -------------------------------------------------------------------------------- /src/scss/components/_rfip.scss: -------------------------------------------------------------------------------- 1 | .rfip { 2 | position: relative; 3 | display: inline-block; 4 | margin: 8px; 5 | vertical-align: middle; 6 | } 7 | -------------------------------------------------------------------------------- /docs/favicons/android-chrome-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/android-chrome-144x144.png -------------------------------------------------------------------------------- /docs/favicons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/android-chrome-192x192.png -------------------------------------------------------------------------------- /docs/favicons/android-chrome-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/android-chrome-256x256.png -------------------------------------------------------------------------------- /docs/favicons/android-chrome-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/android-chrome-384x384.png -------------------------------------------------------------------------------- /docs/favicons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/android-chrome-512x512.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /src/docs/assets/icomoon/fonts/icomoon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/src/docs/assets/icomoon/fonts/icomoon.eot -------------------------------------------------------------------------------- /src/docs/assets/icomoon/fonts/icomoon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/src/docs/assets/icomoon/fonts/icomoon.ttf -------------------------------------------------------------------------------- /__tests__/unit/jest.test.js: -------------------------------------------------------------------------------- 1 | describe('Jest Works', () => { 2 | test('seemlessly', () => { 3 | const a = 1; 4 | expect(a).toBe(1); 5 | }); 6 | }); 7 | -------------------------------------------------------------------------------- /docs/favicons/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-icon-167x167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-icon-167x167.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /src/assets/fipicon/fonts/fontIconPicker.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/src/assets/fipicon/fonts/fontIconPicker.ttf -------------------------------------------------------------------------------- /src/docs/assets/fontello/font/fontello.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/src/docs/assets/fontello/font/fontello.eot -------------------------------------------------------------------------------- /src/docs/assets/fontello/font/fontello.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/src/docs/assets/fontello/font/fontello.ttf -------------------------------------------------------------------------------- /src/docs/assets/fontello/font/fontello.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/src/docs/assets/fontello/font/fontello.woff -------------------------------------------------------------------------------- /src/docs/assets/icomoon/fonts/icomoon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/src/docs/assets/icomoon/fonts/icomoon.woff -------------------------------------------------------------------------------- /docs/favicons/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /src/assets/fipicon/fonts/fontIconPicker.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/src/assets/fipicon/fonts/fontIconPicker.woff -------------------------------------------------------------------------------- /src/docs/assets/superhero/fonts/superhero.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/src/docs/assets/superhero/fonts/superhero.ttf -------------------------------------------------------------------------------- /src/docs/assets/superhero/fonts/superhero.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/src/docs/assets/superhero/fonts/superhero.woff -------------------------------------------------------------------------------- /docs/favicons/apple-touch-startup-image-320x460.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-startup-image-320x460.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-startup-image-640x920.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-startup-image-640x920.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-startup-image-1182x2208.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-startup-image-1182x2208.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-startup-image-1242x2148.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-startup-image-1242x2148.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-startup-image-1496x2048.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-startup-image-1496x2048.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-startup-image-1536x2008.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-startup-image-1536x2008.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-startup-image-640x1096.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-startup-image-640x1096.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-startup-image-748x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-startup-image-748x1024.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-startup-image-750x1294.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-startup-image-750x1294.png -------------------------------------------------------------------------------- /docs/favicons/apple-touch-startup-image-768x1004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/favicons/apple-touch-startup-image-768x1004.png -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | __tests__/ 2 | .vscode/ 3 | coverage/ 4 | docs/ 5 | scripts/ 6 | src/ 7 | .* 8 | jest.config.js 9 | postcss.config.js 10 | stylelint.config.js 11 | webpack.* 12 | -------------------------------------------------------------------------------- /docs/assets/asset-34e26ea31670dd5229ee7d7ab5978b81.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/assets/asset-34e26ea31670dd5229ee7d7ab5978b81.woff -------------------------------------------------------------------------------- /docs/assets/asset-3ac0f7c0647773620f82ec59ba2874e3.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/assets/asset-3ac0f7c0647773620f82ec59ba2874e3.ttf -------------------------------------------------------------------------------- /docs/assets/asset-3bbb7142c2de96be81f33f02490b4d0f.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/assets/asset-3bbb7142c2de96be81f33f02490b4d0f.woff -------------------------------------------------------------------------------- /docs/assets/asset-4af291b190f613fa29d177f2fafd099d.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/assets/asset-4af291b190f613fa29d177f2fafd099d.eot -------------------------------------------------------------------------------- /docs/assets/asset-8c2c34ece6757b8eace3fdcb7939d021.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/assets/asset-8c2c34ece6757b8eace3fdcb7939d021.woff -------------------------------------------------------------------------------- /docs/assets/asset-9e9559a32c9d33495e259629273b13b5.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/assets/asset-9e9559a32c9d33495e259629273b13b5.ttf -------------------------------------------------------------------------------- /docs/assets/asset-a86caa7efa7c4269ec646a4dce6c6e92.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/assets/asset-a86caa7efa7c4269ec646a4dce6c6e92.ttf -------------------------------------------------------------------------------- /docs/assets/asset-ac07f047856578fd1544a253dc441d67.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/assets/asset-ac07f047856578fd1544a253dc441d67.ttf -------------------------------------------------------------------------------- /docs/assets/asset-cb51d032f31aa60f59ba017e77616ec3.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/assets/asset-cb51d032f31aa60f59ba017e77616ec3.eot -------------------------------------------------------------------------------- /docs/assets/asset-d55200c9395b20b924f1df9d850d0c74.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fontIconPicker/react-fonticonpicker/HEAD/docs/assets/asset-d55200c9395b20b924f1df9d850d0c74.woff -------------------------------------------------------------------------------- /src/scss/default-theme.scss: -------------------------------------------------------------------------------- 1 | // base 2 | @import 'base/palette'; 3 | @import 'base/variables'; 4 | @import 'base/mixin'; 5 | 6 | // theme 7 | $theme: default; 8 | @import 'themes/template'; 9 | -------------------------------------------------------------------------------- /src/scss/blue-theme.scss: -------------------------------------------------------------------------------- 1 | $theme: blue; 2 | $scheme: Blue; 3 | $bg: White; 4 | // base 5 | @import 'base/palette'; 6 | @import 'base/variables'; 7 | @import 'base/mixin'; 8 | 9 | // theme 10 | @import 'themes/template'; 11 | -------------------------------------------------------------------------------- /src/scss/components/_rfipsearch.scss: -------------------------------------------------------------------------------- 1 | // Search 2 | .rfipsearch { 3 | width: 100%; 4 | margin: 0 0 8px; 5 | input { 6 | width: 100%; 7 | display: block; 8 | height: 32px; 9 | line-height: 32px; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/scss/cyan-theme.scss: -------------------------------------------------------------------------------- 1 | $theme: cyan; 2 | $scheme: Cyan; 3 | $bg: White; 4 | // base 5 | @import 'base/palette'; 6 | @import 'base/variables'; 7 | @import 'base/mixin'; 8 | 9 | // theme 10 | @import 'themes/template'; 11 | -------------------------------------------------------------------------------- /src/scss/pink-theme.scss: -------------------------------------------------------------------------------- 1 | $theme: pink; 2 | $scheme: Pink; 3 | $bg: White; 4 | // base 5 | @import 'base/palette'; 6 | @import 'base/variables'; 7 | @import 'base/mixin'; 8 | 9 | // theme 10 | @import 'themes/template'; 11 | -------------------------------------------------------------------------------- /src/scss/red-theme.scss: -------------------------------------------------------------------------------- 1 | $theme: red; 2 | $scheme: Red; 3 | $bg: White; 4 | // base 5 | @import 'base/palette'; 6 | @import 'base/variables'; 7 | @import 'base/mixin'; 8 | 9 | // theme 10 | @import 'themes/template'; 11 | -------------------------------------------------------------------------------- /src/scss/teal-theme.scss: -------------------------------------------------------------------------------- 1 | $theme: teal; 2 | $scheme: Teal; 3 | $bg: White; 4 | // base 5 | @import 'base/palette'; 6 | @import 'base/variables'; 7 | @import 'base/mixin'; 8 | 9 | // theme 10 | @import 'themes/template'; 11 | -------------------------------------------------------------------------------- /src/scss/brown-theme.scss: -------------------------------------------------------------------------------- 1 | $theme: brown; 2 | $scheme: Brown; 3 | $bg: White; 4 | // base 5 | @import 'base/palette'; 6 | @import 'base/variables'; 7 | @import 'base/mixin'; 8 | 9 | // theme 10 | @import 'themes/template'; 11 | -------------------------------------------------------------------------------- /src/scss/green-theme.scss: -------------------------------------------------------------------------------- 1 | $theme: green; 2 | $scheme: Green; 3 | $bg: White; 4 | // base 5 | @import 'base/palette'; 6 | @import 'base/variables'; 7 | @import 'base/mixin'; 8 | 9 | // theme 10 | @import 'themes/template'; 11 | -------------------------------------------------------------------------------- /src/scss/indigo-theme.scss: -------------------------------------------------------------------------------- 1 | $theme: indigo; 2 | $scheme: Indigo; 3 | $bg: White; 4 | // base 5 | @import 'base/palette'; 6 | @import 'base/variables'; 7 | @import 'base/mixin'; 8 | 9 | // theme 10 | @import 'themes/template'; 11 | -------------------------------------------------------------------------------- /src/scss/purple-theme.scss: -------------------------------------------------------------------------------- 1 | $theme: purple; 2 | $scheme: Purple; 3 | $bg: White; 4 | // base 5 | @import 'base/palette'; 6 | @import 'base/variables'; 7 | @import 'base/mixin'; 8 | 9 | // theme 10 | @import 'themes/template'; 11 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "tabWidth": 4, 4 | "semi": true, 5 | "singleQuote": true, 6 | "trailingComma": "all", 7 | "bracketSpacing": true, 8 | "jsxBracketSameLine": false, 9 | "arrowParens": "avoid" 10 | } 11 | -------------------------------------------------------------------------------- /src/scss/blue-grey-theme.scss: -------------------------------------------------------------------------------- 1 | $theme: bluegrey; 2 | $scheme: Blue Grey; 3 | $bg: White; 4 | // base 5 | @import 'base/palette'; 6 | @import 'base/variables'; 7 | @import 'base/mixin'; 8 | 9 | // theme 10 | @import 'themes/template'; 11 | -------------------------------------------------------------------------------- /src/scss/deep-orange-theme.scss: -------------------------------------------------------------------------------- 1 | $theme: deeporange; 2 | $scheme: Deep Orange; 3 | $bg: White; 4 | // base 5 | @import 'base/palette'; 6 | @import 'base/variables'; 7 | @import 'base/mixin'; 8 | 9 | // theme 10 | @import 'themes/template'; 11 | -------------------------------------------------------------------------------- /src/scss/deep-purple-theme.scss: -------------------------------------------------------------------------------- 1 | $theme: deeppurple; 2 | $scheme: Deep Purple; 3 | $bg: White; 4 | // base 5 | @import 'base/palette'; 6 | @import 'base/variables'; 7 | @import 'base/mixin'; 8 | 9 | // theme 10 | @import 'themes/template'; 11 | -------------------------------------------------------------------------------- /src/scss/light-blue-theme.scss: -------------------------------------------------------------------------------- 1 | $theme: lightblue; 2 | $scheme: Light Blue; 3 | $bg: White; 4 | // base 5 | @import 'base/palette'; 6 | @import 'base/variables'; 7 | @import 'base/mixin'; 8 | 9 | // theme 10 | @import 'themes/template'; 11 | -------------------------------------------------------------------------------- /src/docs/assets/fontello/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Font license info 2 | 3 | 4 | ## Font Awesome 5 | 6 | Copyright (C) 2012 by Dave Gandy 7 | 8 | Author: Dave Gandy 9 | License: SIL () 10 | Homepage: http://fortawesome.github.com/Font-Awesome/ 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/docs/scss/style.scss: -------------------------------------------------------------------------------- 1 | @import '../../../node_modules/normalize.css/normalize.css'; 2 | @import '../../../node_modules/hamburgers/_sass/hamburgers/hamburgers'; 3 | @import '../../scss/base/palette'; 4 | 5 | @import 'layout/main'; 6 | 7 | @import 'pages/introduction'; 8 | -------------------------------------------------------------------------------- /src/docs/scss/layout/_main.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | @import 'header'; 6 | @import 'sidebar'; 7 | @import 'app'; 8 | @import 'footer'; 9 | -------------------------------------------------------------------------------- /__tests__/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["@babel/preset-env", { 4 | "targets": { 5 | "node": "9.0" 6 | }, 7 | "shippedProposals": true 8 | }], 9 | ["@babel/preset-react"] 10 | ], 11 | "plugins": [ 12 | ["@babel/plugin-proposal-class-properties"] 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["@babel/preset-env", { 4 | "targets": { 5 | "browsers": ["last 2 versions"] 6 | }, 7 | "shippedProposals": true 8 | }], 9 | ["@babel/preset-react"] 10 | ], 11 | "plugins": [ 12 | ["@babel/plugin-proposal-class-properties"] 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src/js/ThemeBase.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | // Import the icons 7 | import '../assets/fipicon/style.css'; 8 | 9 | // Import the styles 10 | import '../scss/base.scss'; 11 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | sourceMap: true, 3 | plugins: { 4 | 'autoprefixer': { 5 | browsers: 'last 2 versions', 6 | }, 7 | 'cssnano': { 8 | preset: 'default', 9 | reduceIdents: false, 10 | zindex: false, 11 | mergeIdents: false, 12 | discardUnused: false, 13 | }, 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /docs/favicons/manifest.webapp: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "name": "React fontIconPicker", 4 | "description": null, 5 | "icons": { 6 | "60": "firefox_app_60x60.png", 7 | "128": "firefox_app_128x128.png", 8 | "512": "firefox_app_512x512.png" 9 | }, 10 | "developer": { 11 | "name": null, 12 | "url": null 13 | } 14 | } -------------------------------------------------------------------------------- /src/scss/base.scss: -------------------------------------------------------------------------------- 1 | // Base 2 | @import 'base/reset'; 3 | 4 | // Components 5 | // 0. Mother Container 6 | @import 'components/rfip'; 7 | // 1. Button 8 | @import 'components/rfipbutton'; 9 | 10 | // 2. Dropdown 11 | @import 'components/rfipcategory'; 12 | @import 'components/rfipdropdown'; 13 | @import 'components/rfipicons'; 14 | @import 'components/rfipsearch'; 15 | -------------------------------------------------------------------------------- /scripts/enzymeSetup.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import { configure } from 'enzyme'; // eslint-disable-line 7 | import Adapter from 'enzyme-adapter-react-16'; // eslint-disable-line 8 | 9 | configure({ adapter: new Adapter() }); 10 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | verbose: true, 3 | collectCoverageFrom: [ 4 | 'src/js/components/**/*.{js,jsx}', 5 | 'src/js/helpers/**/*.{js,jsx}', 6 | ], 7 | collectCoverage: true, 8 | setupTestFrameworkScriptFile: './scripts/enzymeSetup.js', 9 | testPathIgnorePatterns: ['/node_modules/', '.eslintrc'], 10 | snapshotSerializers: ['enzyme-to-json/serializer'], 11 | }; 12 | -------------------------------------------------------------------------------- /src/scss/orange-theme.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | $theme: orange; 6 | $scheme: Orange; 7 | $bg: White; 8 | // base 9 | @import 'base/palette'; 10 | @import 'base/variables'; 11 | @import 'base/mixin'; 12 | 13 | // theme 14 | @import 'themes/template'; 15 | -------------------------------------------------------------------------------- /src/js/FontIconPicker.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | // Just a wrapper for main entry 6 | 7 | // Import main component 8 | import FontIconPicker from './components/FontIconPicker'; 9 | 10 | // And export it... man it does too much work 11 | export default FontIconPicker; 12 | -------------------------------------------------------------------------------- /src/docs/assets/icomoon/Read Me.txt: -------------------------------------------------------------------------------- 1 | Open *demo.html* to see a list of all the glyphs in your font along with their codes/ligatures. 2 | 3 | You won't need any of the files located under the *demo-files* directory when including the generated font in your own projects. 4 | 5 | You can import *selection.json* back to the IcoMoon app using the *Import Icons* button (or via Main Menu > Manage Projects) to retrieve your icon selection. 6 | -------------------------------------------------------------------------------- /src/docs/components/pages/404.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | import React from 'react'; 6 | 7 | const FourOFour = () => ( 8 |
9 |

The content you are looking for could not be found.

10 |

Sorry for that... Perhaps try going back to front page.

11 |
12 | ); 13 | export default FourOFour; 14 | -------------------------------------------------------------------------------- /src/docs/components/TableRenderer.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | import React from 'react'; 6 | import PropTypes from 'prop-types'; 7 | 8 | const TableRenderer = props => ( 9 | {props.children}
10 | ); 11 | 12 | TableRenderer.propTypes = { 13 | children: PropTypes.node.isRequired, 14 | }; 15 | 16 | export default TableRenderer; 17 | -------------------------------------------------------------------------------- /src/docs/index.jsx: -------------------------------------------------------------------------------- 1 | // import node stuff 2 | import React from 'react'; 3 | import { render } from 'react-dom'; 4 | 5 | // import local dependencies 6 | import DocApp from './components/DocApp'; 7 | import '../js/ThemeBase'; 8 | import '../js/ThemeMaterial'; 9 | 10 | // import styles 11 | import './assets/icomoon/style.css'; 12 | import './assets/superhero/style.css'; 13 | import './assets/fontello/css/fontello.css'; 14 | import './scss/style.scss'; 15 | 16 | render(, document.getElementById('app')); 17 | -------------------------------------------------------------------------------- /src/scss/components/_rfipdropdown.scss: -------------------------------------------------------------------------------- 1 | // Dropdown 2 | .rfipdropdown { 3 | width: 352px; 4 | position: absolute; 5 | left: 0; 6 | margin-top: -1px; 7 | z-index: 100000001; 8 | border-radius: 0 1px 4px 4px; 9 | 10 | // Selector box 11 | &__selector { 12 | overflow: hidden; 13 | padding: 16px; 14 | } 15 | 16 | // For animation 17 | &.fipappear-enter-active, 18 | &.fipappear-exit-active { 19 | .rfipdropdown__selector { 20 | transition: max-height 300ms ease-out, padding 300ms ease-out; 21 | padding: 16px; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/scss/base/_reset.scss: -------------------------------------------------------------------------------- 1 | // Reset style inside fip dropdown 2 | .rfipbtn, 3 | .rfipdropdown { 4 | margin: 0; 5 | padding: 0; 6 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 7 | 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 8 | 'Helvetica Neue', sans-serif; 9 | font-size: 14px; 10 | line-height: (24/14); 11 | vertical-align: baseline; 12 | 13 | box-sizing: border-box; 14 | * { 15 | box-sizing: border-box; 16 | margin: 0; 17 | padding: 0; 18 | } 19 | input, 20 | select { 21 | font-size: 14px; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/scss/components/_rfipcategory.scss: -------------------------------------------------------------------------------- 1 | // Category item 2 | .rfipcategory { 3 | width: 100%; 4 | margin: 0 0 8px; 5 | position: relative; 6 | select { 7 | width: 100%; 8 | display: block; 9 | height: 32px; 10 | line-height: 32px; 11 | border-radius: 0; 12 | -webkit-appearance: none; 13 | -moz-appearance: none; 14 | appearance: none; /* remove default arrow */ 15 | transition: border 250ms, box-shadow 250ms; 16 | background-color: transparent !important; 17 | } 18 | i { 19 | position: absolute; 20 | right: 2px; 21 | top: 0; 22 | font-size: 16px; 23 | line-height: 32px; 24 | z-index: -1; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/docs/components/pages/Meta.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import ReactMarkdown from 'react-markdown'; 8 | import meta from '../../guides/meta.md'; 9 | import codeRenderer from '../CodeBlock'; 10 | import TableRenderer from '../TableRenderer'; 11 | 12 | const Meta = () => ( 13 |
14 | 22 |
23 | ); 24 | 25 | export default Meta; 26 | -------------------------------------------------------------------------------- /src/docs/components/pages/Props.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import ReactMarkdown from 'react-markdown'; 8 | import props from '../../guides/props.md'; 9 | import codeRenderer from '../CodeBlock'; 10 | import TableRenderer from '../TableRenderer'; 11 | 12 | const Props = () => ( 13 |
14 | 22 |
23 | ); 24 | 25 | export default Props; 26 | -------------------------------------------------------------------------------- /src/js/components/FipSearch.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import PropTypes from 'prop-types'; 8 | 9 | const FipSearch = props => ( 10 |
11 | 18 |
19 | ); 20 | FipSearch.propTypes = { 21 | handleSearch: PropTypes.func.isRequired, 22 | value: PropTypes.string.isRequired, 23 | placeholder: PropTypes.string.isRequired, 24 | }; 25 | 26 | export default FipSearch; 27 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es6": true, 6 | "node": true 7 | }, 8 | "extends": [ 9 | "airbnb", 10 | "plugin:prettier/recommended", 11 | "prettier/react" 12 | ], 13 | "parser": "babel-eslint", 14 | "parserOptions": { 15 | "ecmaVersion": 2018, 16 | "ecmaFeatures": { 17 | "jsx": true 18 | }, 19 | "sourceType": "module" 20 | }, 21 | "rules": { 22 | "react/no-unused-prop-types": 1, 23 | "react/no-unused-state": 1, 24 | "no-unused-vars": 1, 25 | "prettier/prettier": ["error"], 26 | "import/no-extraneous-dependencies": 1, 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /__tests__/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "commonjs": true, 4 | "es6": true, 5 | "node": true, 6 | "jest/globals": true, 7 | }, 8 | "extends": [ 9 | "airbnb", 10 | "plugin:jest/recommended", 11 | "plugin:prettier/recommended", 12 | "prettier/react" 13 | ], 14 | "parser": "babel-eslint", 15 | "parserOptions": { 16 | "ecmaVersion": 2018, 17 | "ecmaFeatures": { 18 | "jsx": true 19 | }, 20 | "sourceType": "module" 21 | }, 22 | "rules": { 23 | "react/no-unused-prop-types": 1, 24 | "react/no-unused-state": 1, 25 | "no-unused-vars": 1, 26 | "prettier/prettier": ["error"] 27 | }, 28 | "plugins": ["jest"] 29 | }; 30 | -------------------------------------------------------------------------------- /src/docs/guides/usage-parts/3-fipsmp.md: -------------------------------------------------------------------------------- 1 | ### 3: Single and Multi Picker 2 | 3 | The source codes below were used for populating the examples. Here we cleverly 4 | destructure the `icons` from `props`. More on it [here](https://wesbos.com/destructuring-objects/). 5 | 6 | ```js 7 | // For Single Picker 8 | export const SinglePicker = ({icons}) => { 9 | return ( 10 | console.log(val)} 14 | /> 15 | ); 16 | } 17 | // For Multi Picker 18 | export const MultiPicker = ({icons}) => { 19 | return ( 20 | console.log(val)} 24 | isMulti 25 | /> 26 | ); 27 | } 28 | ``` 29 | -------------------------------------------------------------------------------- /src/assets/fipicon/Read Me.txt: -------------------------------------------------------------------------------- 1 | Open *demo.html* to see a list of all the glyphs in your font along with their codes/ligatures. 2 | 3 | To use the generated font in desktop programs, you can install the TTF font. In order to copy the character associated with each icon, refer to the text box at the bottom right corner of each glyph in demo.html. The character inside this text box may be invisible; but it can still be copied. See this guide for more info: https://icomoon.io/#docs/local-fonts 4 | 5 | You won't need any of the files located under the *demo-files* directory when including the generated font in your own projects. 6 | 7 | You can import *selection.json* back to the IcoMoon app using the *Import Icons* button (or via Main Menu → Manage Projects) to retrieve your icon selection. 8 | -------------------------------------------------------------------------------- /src/docs/assets/superhero/Read Me.txt: -------------------------------------------------------------------------------- 1 | Open *demo.html* to see a list of all the glyphs in your font along with their codes/ligatures. 2 | 3 | To use the generated font in desktop programs, you can install the TTF font. In order to copy the character associated with each icon, refer to the text box at the bottom right corner of each glyph in demo.html. The character inside this text box may be invisible; but it can still be copied. See this guide for more info: https://icomoon.io/#docs/local-fonts 4 | 5 | You won't need any of the files located under the *demo-files* directory when including the generated font in your own projects. 6 | 7 | You can import *selection.json* back to the IcoMoon app using the *Import Icons* button (or via Main Menu → Manage Projects) to retrieve your icon selection. 8 | -------------------------------------------------------------------------------- /src/js/ThemeMaterial.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import '../scss/blue-grey-theme.scss'; 7 | import '../scss/blue-theme.scss'; 8 | import '../scss/brown-theme.scss'; 9 | import '../scss/cyan-theme.scss'; 10 | import '../scss/deep-orange-theme.scss'; 11 | import '../scss/deep-purple-theme.scss'; 12 | import '../scss/default-theme.scss'; 13 | import '../scss/green-theme.scss'; 14 | import '../scss/indigo-theme.scss'; 15 | import '../scss/light-blue-theme.scss'; 16 | import '../scss/orange-theme.scss'; 17 | import '../scss/pink-theme.scss'; 18 | import '../scss/purple-theme.scss'; 19 | import '../scss/red-theme.scss'; 20 | import '../scss/teal-theme.scss'; 21 | -------------------------------------------------------------------------------- /src/docs/guides/usage-parts/1-fipncp.md: -------------------------------------------------------------------------------- 1 | ### 1: Non Categorized Picker 2 | 3 | The simplest configuration to init a `FontIconPicker` is as follows. 4 | 5 | ```js 6 | const MyComponent = () => { 7 | const icons = [ 8 | 'fab fa-accessible-icon', 9 | 'fas fa-ambulance', 10 | 'fas fa-bicycle', 11 | 'fas fa-bus', 12 | 'fas fa-car', 13 | 'fas fa-fighter-jet', 14 | 'fas fa-motorcycle', 15 | 'fas fa-paper-plane', 16 | 'far fa-paper-plane', 17 | 'fas fa-plane', 18 | 'fas fa-rocket', 19 | 'fas fa-ship', 20 | 'fas fa-shopping-cart', 21 | 'fas fa-space-shuttle', 22 | 'fas fa-subway', 23 | 'fas fa-taxi', 24 | 'fas fa-train', 25 | 'fas fa-truck', 26 | 'fas fa-wheelchair', 27 | ]; 28 | return ( 29 | console.log(val)} 33 | /> 34 | ); 35 | }; 36 | export default MyComponent; 37 | ``` 38 | -------------------------------------------------------------------------------- /__tests__/unit/FipSearch.unit.test.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import { shallow } from 'enzyme'; 8 | 9 | import FipSearch from '../../src/js/components/FipSearch'; 10 | 11 | describe('FipSearch Component', () => { 12 | const cb = jest.fn(); 13 | const props = { 14 | handleSearch: cb, 15 | value: 'foo', 16 | placeholder: 'bar', 17 | }; 18 | const wrapper = shallow(); 19 | test('renders input', () => { 20 | expect(wrapper.find('input.rfipsearch__input')).toHaveLength(1); 21 | }); 22 | test('calls handleSearch', () => { 23 | const event = { 24 | target: { 25 | value: 'change of foo', 26 | }, 27 | }; 28 | wrapper.find('input').simulate('change', event); 29 | expect(cb).toHaveBeenLastCalledWith(event); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /src/docs/scss/pages/_introduction.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | .fip-intro { 6 | .fonticonpicker-logo { 7 | height: 128px; 8 | width: 128px; 9 | @media screen and (min-width: 420px) { 10 | height: 256px; 11 | width: 256px; 12 | } 13 | } 14 | .fip-name { 15 | font-size: 24px; 16 | background: -webkit-linear-gradient( 17 | 45deg, 18 | #5456a3, 19 | #309647, 20 | #f38f31, 21 | #d22432 22 | ); 23 | -webkit-background-clip: text; 24 | -webkit-text-fill-color: transparent; 25 | font-family: 'Operator Mono SSm', 'Operator Mono Book', Consolas, Monaco, 26 | 'Andale Mono', 'Ubuntu Mono', monospace; 27 | font-style: italic; 28 | @media screen and (min-width: 420px) { 29 | font-size: 36px; 30 | } 31 | @media screen and (min-width: 720px) { 32 | font-size: 52px; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /__tests__/unit/FipCategory.unit.test.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import { shallow } from 'enzyme'; 8 | 9 | import FipCategory from '../../src/js/components/FipCategory'; 10 | 11 | describe('FipCategory Component', () => { 12 | const cb = jest.fn(); 13 | const props = { 14 | handleCategory: cb, 15 | value: 0, 16 | categories: ['foo', 'bar'], 17 | }; 18 | const wrapper = shallow(); 19 | test('renders select', () => { 20 | expect(wrapper.find('select.rfipcategory__select')).toHaveLength(1); 21 | }); 22 | test('calls handleChange', () => { 23 | const event = { 24 | target: { 25 | value: 1, 26 | }, 27 | }; 28 | wrapper.find('select.rfipcategory__select').simulate('change', event); 29 | expect(cb).toHaveBeenLastCalledWith(event); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | # React FontIconPicker Changelog 9 | 10 | All notable changes to this project will be documented in this file. 11 | 12 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 13 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). 14 | 15 | ## [1.2.0] - 2018-10-20 16 | 17 | ### Added 18 | 19 | * `closeOnSelect` to close dropdown on selecting icon. (#6) 20 | 21 | ## [1.1.0] - 2018-04-11 22 | 23 | ### Added 24 | 25 | * Dropdown will open on top if view port is small. 26 | * Use `click` instead of `mousedown` and `touchend` to close the dropdown. 27 | * Better docs. 28 | 29 | ## [1.0.0] - 2018-04-10 30 | 31 | First release. 32 | 33 | 47 | -------------------------------------------------------------------------------- /src/docs/guides/basicusage.md: -------------------------------------------------------------------------------- 1 | ## Usage Guide 2 | 3 | To use fonticonpicker, you essentially need one thing, `icons` props. It can 4 | be an `array` for non-categorized picker or an `plain object` for categorized 5 | icon picker. 6 | 7 | ### Required Props 8 | 9 | `FontIconPicker` requires only three props. 10 | 11 | 1. `icons`: Source of icons, could be an array or an object. 12 | 2. `onChange`: Function to call on value change. 13 | 3. `value`: Initial value. Should be an array for multi type or a string or number for single type. 14 | 15 | By default, `FontIconPicker` tries to render using `class`. So whatever you pass 16 | through `icons`, will be used like ``. This works good with 17 | fontawesome, icomoon etc. For some reason, if you want to use a custom attribute 18 | and convert the values to `hex`, then follow the examples. 19 | 20 | Also, `FontIconPicker` defaults to `isMulti` to `true`. So it provides you an 21 | interface to pick multiple icons. Also it expects the `value` to be an `array`. 22 | You can disable this by passing `isMulti={false}`. 23 | -------------------------------------------------------------------------------- /src/docs/scss/layout/_footer.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | // Footer 6 | .site-footer { 7 | background-color: palette(Grey, 100); 8 | display: flex; 9 | flex-flow: row wrap; 10 | justify-content: center; 11 | align-content: space-between; 12 | align-items: center; 13 | width: 100%; 14 | p { 15 | margin: 0; 16 | padding: 8px 16px; 17 | } 18 | .social { 19 | .link { 20 | font-size: 18px; 21 | text-decoration: none; 22 | margin: 0 8px; 23 | color: palette(Grey, 400); 24 | transition: color 250ms; 25 | 26 | &.github:hover { 27 | color: #4078c0; 28 | } 29 | &.twitter:hover { 30 | color: #1da1f2; 31 | } 32 | &.blog:hover { 33 | color: #d54e21; 34 | } 35 | &.wpquark:hover { 36 | color: #03a9f4; 37 | } 38 | } 39 | } 40 | 41 | @media screen and (min-width: 640px) { 42 | .copyright { 43 | margin-right: auto; 44 | } 45 | .social { 46 | margin-left: auto; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/assets/fipicon/style.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'fontIconPicker'; 3 | src: 4 | url('fonts/fontIconPicker.ttf?an4nl5') format('truetype'), 5 | url('fonts/fontIconPicker.woff?an4nl5') format('woff'), 6 | url('fonts/fontIconPicker.svg?an4nl5#fontIconPicker') format('svg'); 7 | font-weight: normal; 8 | font-style: normal; 9 | } 10 | 11 | [class^="fipicon-"], [class*=" fipicon-"] { 12 | /* use !important to prevent issues with browser extensions that change fonts */ 13 | font-family: 'fontIconPicker' !important; 14 | speak: none; 15 | font-style: normal; 16 | font-weight: normal; 17 | font-variant: normal; 18 | text-transform: none; 19 | line-height: 1; 20 | 21 | /* Better Font Rendering =========== */ 22 | -webkit-font-smoothing: antialiased; 23 | -moz-osx-font-smoothing: grayscale; 24 | } 25 | 26 | .fipicon-angle-left:before { 27 | content: "\f104"; 28 | } 29 | .fipicon-angle-right:before { 30 | content: "\f105"; 31 | } 32 | .fipicon-angle-up:before { 33 | content: "\f106"; 34 | } 35 | .fipicon-angle-down:before { 36 | content: "\f107"; 37 | } 38 | -------------------------------------------------------------------------------- /src/docs/guides/usage-parts/5-fipcr.md: -------------------------------------------------------------------------------- 1 | ### 5: Custom Renderer (SVG) 2 | 3 | Here we use a custom render function to print some SVG inside the picker element. 4 | Due to many ways of actually rendering SVGs (inline, with sprite, img tags etc) 5 | I have decided not to throw an actual `renderUsing='svg'` prop. Rather use the 6 | `renderFunc` prop to print SVGs on the go. 7 | 8 | The source code below assumes that you have the SVG from [here](https://github.com/fontIconPicker/react-fonticonpicker/blob/master/src/docs/assets/superhero.svg) 9 | printed directly after the opening `` of your HTML. 10 | 11 | Notice we return JSX or React Element from the function. 12 | 13 | ```js 14 | const renderSVG = svg => ( 15 | 16 | 17 | 18 | ); 19 | const MyComponent = () => { 20 | return ( 21 | val} 25 | renderFunc={renderSVG} 26 | theme="indigo" 27 | isMulti 28 | /> 29 | ); 30 | } 31 | export default MyComponent; 32 | ``` 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Swashata Ghosh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /src/docs/helpers/routes.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | const routes = [ 6 | { 7 | path: '/', 8 | component: 'Introduction', 9 | menu: 'Introduction', 10 | exact: true, 11 | }, 12 | { 13 | path: '/installation/', 14 | component: 'Installation', 15 | menu: 'Installation', 16 | exact: true, 17 | }, 18 | { 19 | link: '/basic-usage/', 20 | path: '/basic-usage/:partId?', 21 | component: 'BasicUsage', 22 | menu: 'Usage Guide', 23 | }, 24 | { 25 | path: '/examples/', 26 | component: 'Examples', 27 | menu: 'Live Examples', 28 | exact: true, 29 | }, 30 | { 31 | path: '/themes/', 32 | component: 'Themes', 33 | menu: 'Built-in Themes', 34 | exact: true, 35 | }, 36 | { 37 | path: '/props/', 38 | component: 'Props', 39 | menu: 'Available Props', 40 | exact: true, 41 | }, 42 | { 43 | path: '/meta/', 44 | component: 'Meta', 45 | menu: 'Contrib & Credit', 46 | exact: true, 47 | }, 48 | ]; 49 | 50 | export default routes; 51 | -------------------------------------------------------------------------------- /src/assets/fipicon/demo-files/demo.js: -------------------------------------------------------------------------------- 1 | if (!('boxShadow' in document.body.style)) { 2 | document.body.setAttribute('class', 'noBoxShadow'); 3 | } 4 | 5 | document.body.addEventListener("click", function(e) { 6 | var target = e.target; 7 | if (target.tagName === "INPUT" && 8 | target.getAttribute('class').indexOf('liga') === -1) { 9 | target.select(); 10 | } 11 | }); 12 | 13 | (function() { 14 | var fontSize = document.getElementById('fontSize'), 15 | testDrive = document.getElementById('testDrive'), 16 | testText = document.getElementById('testText'); 17 | function updateTest() { 18 | testDrive.innerHTML = testText.value || String.fromCharCode(160); 19 | if (window.icomoonLiga) { 20 | window.icomoonLiga(testDrive); 21 | } 22 | } 23 | function updateSize() { 24 | testDrive.style.fontSize = fontSize.value + 'px'; 25 | } 26 | fontSize.addEventListener('change', updateSize, false); 27 | testText.addEventListener('input', updateTest, false); 28 | testText.addEventListener('change', updateTest, false); 29 | updateSize(); 30 | }()); 31 | -------------------------------------------------------------------------------- /src/docs/assets/superhero/demo-files/demo.js: -------------------------------------------------------------------------------- 1 | if (!('boxShadow' in document.body.style)) { 2 | document.body.setAttribute('class', 'noBoxShadow'); 3 | } 4 | 5 | document.body.addEventListener("click", function(e) { 6 | var target = e.target; 7 | if (target.tagName === "INPUT" && 8 | target.getAttribute('class').indexOf('liga') === -1) { 9 | target.select(); 10 | } 11 | }); 12 | 13 | (function() { 14 | var fontSize = document.getElementById('fontSize'), 15 | testDrive = document.getElementById('testDrive'), 16 | testText = document.getElementById('testText'); 17 | function updateTest() { 18 | testDrive.innerHTML = testText.value || String.fromCharCode(160); 19 | if (window.icomoonLiga) { 20 | window.icomoonLiga(testDrive); 21 | } 22 | } 23 | function updateSize() { 24 | testDrive.style.fontSize = fontSize.value + 'px'; 25 | } 26 | fontSize.addEventListener('change', updateSize, false); 27 | testText.addEventListener('input', updateTest, false); 28 | testText.addEventListener('change', updateTest, false); 29 | updateSize(); 30 | }()); 31 | -------------------------------------------------------------------------------- /src/docs/guides/usage-parts/4-fipar.md: -------------------------------------------------------------------------------- 1 | ### 4: Attribute Rendering 2 | 3 | By default `FontIconPicker` sets `convertHex` to `true`. We need that because 4 | the icon values are not in unicode, rather its decimal value. Internally `FontIconPicker` 5 | will convert the decimal values to string code at that value. For this we use `String.fromCodePoint`. 6 | 7 | Since we pass only `numbers` with `icons`, we also pass an additional `search` 8 | prop to use the search field effectively. 9 | 10 | ```js 11 | const MyComponent = () => { 12 | const icons = [ 13 | 57436, 14 | 57437, 15 | 57438, 16 | 57439, 17 | 57524, 18 | 57525, 19 | 57526, 20 | 57527, 21 | ]; 22 | const search = [ 23 | 'Box add', 24 | 'Box remove', 25 | 'Download', 26 | 'Upload', 27 | 'List', 28 | 'List 2', 29 | 'Numbered list', 30 | 'Menu', 31 | ]; 32 | return ( 33 | console.log(val)} 38 | isMulti 39 | renderUsing="data-icomoon" 40 | convertHex={true} // this isn't needed 41 | /> 42 | ); 43 | } 44 | export default MyComponent; 45 | ``` 46 | -------------------------------------------------------------------------------- /src/docs/components/ScrollToTop.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | import React from 'react'; 6 | import PropTypes from 'prop-types'; 7 | import { withRouter } from 'react-router-dom'; 8 | 9 | class ScrollToTop extends React.Component { 10 | static propTypes = { 11 | location: PropTypes.shape({ 12 | pathname: PropTypes.string, 13 | }).isRequired, 14 | children: PropTypes.node.isRequired, 15 | }; 16 | componentDidUpdate(prevProps) { 17 | const { location: { pathname: currentPath } } = this.props; 18 | const { location: { pathname: prevPath } } = prevProps; 19 | const cpParts = currentPath.split('/'); 20 | const ppParts = prevPath.split('/'); 21 | if ( 22 | // pathname has changed 23 | currentPath !== prevPath && 24 | // and current pathname and previous pathname does not share something common 25 | cpParts[1] !== ppParts[1] 26 | ) { 27 | window.scrollTo(0, 0); 28 | } 29 | } 30 | 31 | render() { 32 | return this.props.children; 33 | } 34 | } 35 | 36 | export default withRouter(ScrollToTop); 37 | -------------------------------------------------------------------------------- /src/js/components/FipCategory.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | import React from 'react'; 6 | import PropTypes from 'prop-types'; 7 | 8 | class FipCategory extends React.PureComponent { 9 | static propTypes = { 10 | handleCategory: PropTypes.func.isRequired, 11 | value: PropTypes.number.isRequired, 12 | categories: PropTypes.arrayOf(PropTypes.string).isRequired, 13 | }; 14 | 15 | render() { 16 | return ( 17 |
18 | 33 | 38 |
39 | ); 40 | } 41 | } 42 | 43 | export default FipCategory; 44 | -------------------------------------------------------------------------------- /src/scss/base/_variables.scss: -------------------------------------------------------------------------------- 1 | $scheme: Grey !default; 2 | $bg: White !default; 3 | 4 | $text: palette(Grey, 800) !default; 5 | $icon-text: palette($scheme, 800) !default; 6 | 7 | $color-background: palette($bg, 500) !default; 8 | 9 | $elem-border-color: palette($scheme, 400) !default; 10 | $elem-border-focus-color: palette($scheme, 500) !default; 11 | 12 | $pager-bg-color: palette($scheme, 200) !default; 13 | $pager-bg-hover-color: palette($scheme, 400) !default; 14 | 15 | $ibox-bg-color: palette($scheme, 100) !default; 16 | $ibox-bg-selected-color: palette($scheme, 200) !default; 17 | $ibox-bg-hover-color: palette($scheme, 400) !default; 18 | 19 | $btn-bg-color: palette($bg, 500) !default; 20 | $btn-bg-dd-color: palette($scheme, 100) !default; 21 | $btn-border-color: palette($scheme, 300) !default; 22 | $btn-bg-hover-color: palette($scheme, 400) !default; 23 | $btn-bg-active-color: palette($scheme, 300) !default; 24 | 25 | $icon-border-color: palette($scheme, 200) !default; 26 | $empty-icon-color: palette($scheme, 300) !default; 27 | $error-icon-color: palette(Red, 200) !default; 28 | 29 | $del-bg-color: palette($scheme, 200) !default; 30 | $del-bg-hover-color: palette($scheme, 300) !default; 31 | -------------------------------------------------------------------------------- /src/docs/components/pages/Installation.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import ReactMarkdown from 'react-markdown'; 8 | import installation from '../../guides/installation.md'; 9 | import codeRenderer from '../CodeBlock'; 10 | import pkg from '../../../../package.json'; 11 | 12 | const Installation = () => ( 13 |
14 | 21 |

peerDependencies

22 |

FontIconPicker has the following dependencies.

23 |
24 | {Object.keys(pkg.peerDependencies).map(dep => ( 25 | 30 | {dep} 31 | 32 | {pkg.peerDependencies[dep]} 33 | 34 | 35 | ))} 36 |
37 |
38 | ); 39 | 40 | export default Installation; 41 | -------------------------------------------------------------------------------- /src/docs/components/CodeBlock.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import SyntaxHighlighter, { 5 | registerLanguage, 6 | } from 'react-syntax-highlighter/prism-light'; 7 | import jsx from 'react-syntax-highlighter/languages/prism/jsx'; 8 | import html from 'react-syntax-highlighter/languages/prism/markup'; 9 | import bash from 'react-syntax-highlighter/languages/prism/bash'; 10 | import scss from 'react-syntax-highlighter/languages/prism/scss'; 11 | import tomorrow from 'react-syntax-highlighter/styles/prism/tomorrow'; 12 | 13 | registerLanguage('js', jsx); 14 | registerLanguage('jsx', jsx); 15 | registerLanguage('html', html); 16 | registerLanguage('bash', bash); 17 | registerLanguage('scss', scss); 18 | 19 | const CodeBlock = props => ( 20 | 27 | {props.value} 28 | 29 | ); 30 | 31 | CodeBlock.displayName = 'codeBlock'; 32 | CodeBlock.propTypes = { 33 | value: PropTypes.string.isRequired, 34 | language: PropTypes.string, 35 | inline: PropTypes.bool, 36 | }; 37 | CodeBlock.defaultProps = { 38 | language: 'js', 39 | inline: false, 40 | }; 41 | 42 | export default CodeBlock; 43 | -------------------------------------------------------------------------------- /__tests__/unit/FipDropDownPortal.unit.test.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import { shallow } from 'enzyme'; 8 | 9 | import FipDropDownPortal from '../../src/js/components/FipDropDownPortal'; 10 | 11 | describe('FipDropDownPortal Component', () => { 12 | const domNode = document.createElement('div'); 13 | const btnNode = document.createElement('div'); 14 | const props = { 15 | appendRoot: 'body', 16 | domRef: { current: domNode }, 17 | btnRef: { current: btnNode }, 18 | className: 'foo', 19 | }; 20 | test('mounts to Node for valid DOM', () => { 21 | const wrapper = shallow( 22 | 23 |

Foo

24 |
, 25 | ); 26 | expect(wrapper.state('appendRoot')).toBe( 27 | document.querySelector('body'), 28 | ); 29 | }); 30 | test('mounts to self for invalid DOM', () => { 31 | const newProps = { 32 | ...props, 33 | appendRoot: false, 34 | }; 35 | const wrapper = shallow( 36 | 37 |

Foo

38 |
, 39 | ); 40 | expect(wrapper.state('appendRoot')).toBe('self'); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /src/docs/scss/layout/_app.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | // Main 6 | .site-main { 7 | display: flex; 8 | flex: 1 0 100%; 9 | flex-flow: row wrap; 10 | } 11 | 12 | // App 13 | .app-main { 14 | padding-top: 16px; 15 | overflow: hidden; 16 | padding-bottom: 64px; 17 | @media screen and (min-width: 720px) { 18 | min-height: calc(100vh - 124px); 19 | width: calc(100% - 225px); 20 | } 21 | } 22 | 23 | // Animation 24 | .route-wrapper { 25 | position: relative; 26 | @media screen and (min-width: 720px) { 27 | max-width: 980px; 28 | margin: 0 0 0 32px; 29 | } 30 | > div { 31 | position: relative; 32 | width: 100%; 33 | transform-origin: center center; 34 | padding-bottom: 16px; 35 | top: 0; 36 | } 37 | } 38 | 39 | .usage-wrapper { 40 | position: relative; 41 | > div { 42 | position: relative; 43 | width: 100%; 44 | transform-origin: center center; 45 | top: 0; 46 | } 47 | } 48 | 49 | h1, 50 | h2, 51 | h3, 52 | h4, 53 | h5, 54 | h6, 55 | pre, 56 | code, 57 | .badge { 58 | font-family: 'Operator Mono SSm', 'Operator Mono Book', Consolas, Monaco, 59 | 'Andale Mono', 'Ubuntu Mono', monospace !important; 60 | font-style: italic; 61 | } 62 | -------------------------------------------------------------------------------- /src/docs/scss/layout/_header.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | // Header 6 | .site-title { 7 | padding: 8px 80px 8px 8px; 8 | background-color: palette(Grey, 200); 9 | color: palette(Grey, 900); 10 | border-bottom: 1px solid palette(Grey, 300); 11 | h1 { 12 | margin: 0; 13 | font-size: 18px; 14 | text-transform: lowercase; 15 | font-style: italic; 16 | display: flex; 17 | align-items: center; 18 | sup { 19 | font-size: 8px; 20 | top: -1.5em; 21 | } 22 | 23 | .fip-github { 24 | margin-left: auto; 25 | color: palette(Grey, 400); 26 | text-decoration: none; 27 | transition: color 250ms; 28 | display: none; 29 | &:hover { 30 | color: palette(Grey, 600); 31 | } 32 | @media screen and (min-width: 332px) { 33 | display: block; 34 | } 35 | } 36 | } 37 | svg { 38 | height: 32px; 39 | width: 32px; 40 | margin-right: 16px; 41 | } 42 | 43 | @media screen and (min-width: 640px) { 44 | padding: 16px 80px 16px 16px; 45 | h1 { 46 | font-size: 32px; 47 | sup { 48 | font-size: 16px; 49 | top: -1em; 50 | } 51 | } 52 | svg { 53 | height: 48px; 54 | width: 48px; 55 | } 56 | } 57 | @media screen and (min-width: 720px) { 58 | padding: 16px 32px 16px 16px; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /scripts/cleanupDist.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | // ------------------ CAUTION ------------------// 7 | // ALWAYS RUN THIS FILE WHERE package.json IS // 8 | // OTHERWISE IT WILL NOT WORK // 9 | // ------------------ CAUTION ------------------// 10 | 11 | const fs = require('fs'); 12 | 13 | // Clean up files written by webpack 14 | // They don't have streamlined CSS support 15 | // yet, when they do, we will remove this 16 | // using rollup and node-sass isn't worth it 17 | // right now, so we do this bit manually 18 | const filesToRemove = [ 19 | './dist/base-theme.react.js.map', 20 | './dist/base-theme.react.js', 21 | './dist/material-theme.react.js.map', 22 | './dist/material-theme.react.js', 23 | ]; 24 | 25 | // Remove files 26 | filesToRemove.forEach(file => { 27 | fs.unlink(file, err => { 28 | if (err) { 29 | console.error(`couldn't remove ${file}`); 30 | console.error(err); 31 | } else { 32 | console.log(`Removed file ${file}`); 33 | } 34 | }); 35 | }); 36 | 37 | // Now copy the index.html too 38 | fs.copyFile('./scripts/index.html', './dist/index.html', err => { 39 | if (err) { 40 | console.error(`couldn't copy index.html file.`); 41 | console.error(err); 42 | } else { 43 | console.log('Copied index.html file'); 44 | } 45 | }); 46 | -------------------------------------------------------------------------------- /docs/favicons/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "React fontIconPicker", 3 | "short_name": "React fontIconPicker", 4 | "description": null, 5 | "dir": "auto", 6 | "lang": "en-US", 7 | "display": "standalone", 8 | "orientation": "any", 9 | "start_url": "/?homescreen=1", 10 | "background_color": "transparent", 11 | "icons": [ 12 | { 13 | "src": "android-chrome-36x36.png", 14 | "sizes": "36x36", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "android-chrome-48x48.png", 19 | "sizes": "48x48", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "android-chrome-72x72.png", 24 | "sizes": "72x72", 25 | "type": "image/png" 26 | }, 27 | { 28 | "src": "android-chrome-96x96.png", 29 | "sizes": "96x96", 30 | "type": "image/png" 31 | }, 32 | { 33 | "src": "android-chrome-144x144.png", 34 | "sizes": "144x144", 35 | "type": "image/png" 36 | }, 37 | { 38 | "src": "android-chrome-192x192.png", 39 | "sizes": "192x192", 40 | "type": "image/png" 41 | }, 42 | { 43 | "src": "android-chrome-256x256.png", 44 | "sizes": "256x256", 45 | "type": "image/png" 46 | }, 47 | { 48 | "src": "android-chrome-384x384.png", 49 | "sizes": "384x384", 50 | "type": "image/png" 51 | }, 52 | { 53 | "src": "android-chrome-512x512.png", 54 | "sizes": "512x512", 55 | "type": "image/png" 56 | } 57 | ] 58 | } -------------------------------------------------------------------------------- /__tests__/intg/04_search_options.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | import React from 'react'; 6 | import { mount } from 'enzyme'; 7 | 8 | import FontIconPicker from '../../src/js/FontIconPicker'; 9 | import FipButton from '../../src/js/components/FipButton'; 10 | import FipSearch from '../../src/js/components/FipSearch'; 11 | import * as iconDefs from '../../src/docs/helpers/iconDefs'; 12 | 13 | describe('Search Option', () => { 14 | test('shows up on showSearch', () => { 15 | const [valOne] = iconDefs.fontelloIcons.Others; 16 | const wrapper = mount( 17 | , 25 | ); 26 | wrapper.find(FipButton).simulate('click'); 27 | expect(wrapper.find(FipSearch)).toHaveLength(1); 28 | }); 29 | test('does not show up without showSearch', () => { 30 | const [valOne] = iconDefs.fontelloIcons.Others; 31 | const wrapper = mount( 32 | , 40 | ); 41 | wrapper.find(FipButton).simulate('click'); 42 | expect(wrapper.find(FipSearch)).toHaveLength(0); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /__tests__/intg/05_category_options.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | import React from 'react'; 6 | import { mount } from 'enzyme'; 7 | 8 | import FontIconPicker from '../../src/js/FontIconPicker'; 9 | import FipButton from '../../src/js/components/FipButton'; 10 | import FipCategory from '../../src/js/components/FipCategory'; 11 | import * as iconDefs from '../../src/docs/helpers/iconDefs'; 12 | 13 | describe('Category Option', () => { 14 | test('shows up on showCateogry', () => { 15 | const { Others: [valOne] } = iconDefs.fontelloIcons; 16 | const wrapper = mount( 17 | , 25 | ); 26 | wrapper.find(FipButton).simulate('click'); 27 | expect(wrapper.find(FipCategory)).toHaveLength(1); 28 | }); 29 | test('does not show up without categorized source', () => { 30 | const [valOne] = iconDefs.fontelloIcons.Others; 31 | const wrapper = mount( 32 | , 40 | ); 41 | wrapper.find(FipButton).simulate('click'); 42 | expect(wrapper.find(FipCategory)).toHaveLength(0); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Just a Sample to check if UMD is working 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /scripts/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Just a Sample to check if UMD is working 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /__tests__/unit/FipButton.unit.test.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import { shallow } from 'enzyme'; 8 | 9 | import FipButton from '../../src/js/components/FipButton'; 10 | 11 | describe('FipButton Component', () => { 12 | const handleDeleteValueCB = jest.fn(); 13 | const onClickCB = jest.fn(); 14 | const props = { 15 | className: 'foo', 16 | isOpen: true, 17 | onClick: onClickCB, 18 | domRef: React.createRef(), 19 | isMulti: true, 20 | value: ['foo', 'bar'], 21 | renderIcon: jest.fn(), 22 | handleDeleteValue: handleDeleteValueCB, 23 | noSelectedPlaceholder: 'foo', 24 | }; 25 | const wrapper = shallow(); 26 | 27 | test('handles click', () => { 28 | wrapper.instance().handleClick(); 29 | expect(onClickCB).toHaveBeenCalledTimes(1); 30 | }); 31 | test('handles keydown', () => { 32 | wrapper.instance().handleKeyDown({ keyCode: 32 }); 33 | expect(onClickCB).toHaveBeenCalledTimes(2); 34 | }); 35 | test('handles delete on click', () => { 36 | const eventMock = { stopPropagation: jest.fn() }; 37 | wrapper.instance().handleDelete(eventMock, 'foo'); 38 | expect(eventMock.stopPropagation).toHaveBeenCalledTimes(1); 39 | expect(handleDeleteValueCB).toHaveBeenLastCalledWith('foo'); 40 | }); 41 | test('handles delete on keydown', () => { 42 | const newCB = jest.fn(); 43 | wrapper.setProps({ handleDeleteValue: newCB }); 44 | wrapper.instance().handleDeleteKeyboard({ keyCode: 32 }); 45 | expect(newCB).toHaveBeenCalledTimes(1); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /src/scss/base/_mixin.scss: -------------------------------------------------------------------------------- 1 | /// Gives a card depth effect. 2 | /// @param {Number} $depth - depth level (between 1 and 5) 3 | /// @link http://www.google.com/design/spec/layout/layout-principles.html#layout-principles-dimensionality Google Design 4 | /// @requires {function} top-shadow 5 | /// @requires {function} bottom-shadow 6 | @mixin card($depth) { 7 | @if $depth < 1 { 8 | box-shadow: none; 9 | } @else if $depth > 5 { 10 | @warn 'Invalid $depth `#{$depth}` for mixin `card`.'; 11 | } @else { 12 | box-shadow: bottom-shadow($depth), top-shadow($depth); 13 | } 14 | } 15 | /// Computes a top-shadow for a card effect. 16 | /// @param {Number} $depth - depth level 17 | /// @return {List} 18 | @function top-shadow($depth) { 19 | $primary-offset: nth(1.5 3 10 14 19, $depth) * 1px; 20 | $blur: nth(1.5 3 10 14 19, $depth) * 4px; 21 | $color: rgba(black, nth(0.12 0.16 0.19 0.25 0.3, $depth)); 22 | 23 | @return 0 $primary-offset $blur $color; 24 | } 25 | 26 | /// Computes a bottom-shadow for a card effect. 27 | /// @param {Number} $depth - depth level 28 | /// @return {List} 29 | @function bottom-shadow($depth) { 30 | $primary-offset: nth(1.5 3 6 10 15, $depth) * 1px; 31 | $blur: nth(1 3 3 5 6, $depth) * 4px; 32 | $color: rgba(black, nth(0.24 0.23 0.23 0.22 0.22, $depth)); 33 | 34 | @return 0 $primary-offset $blur $color; 35 | } 36 | 37 | /// Input type element 38 | @mixin input($elem-border-color, $elem-border-focus-color) { 39 | border: 0 none; 40 | border-bottom: 1px solid $elem-border-color; 41 | transition: box-shadow 250ms, border 250ms; 42 | &:focus, 43 | &:active { 44 | border-bottom-color: $elem-border-focus-color; 45 | box-shadow: 0 1px 0 0 $elem-border-focus-color; 46 | outline: 0 none; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | # General 64 | .DS_Store 65 | .AppleDouble 66 | .LSOverride 67 | 68 | # Icon must end with two \r 69 | Icon 70 | 71 | 72 | # Thumbnails 73 | ._* 74 | 75 | # Files that might appear in the root of a volume 76 | .DocumentRevisions-V100 77 | .fseventsd 78 | .Spotlight-V100 79 | .TemporaryItems 80 | .Trashes 81 | .VolumeIcon.icns 82 | .com.apple.timemachine.donotpresent 83 | 84 | # Directories potentially created on remote AFP share 85 | .AppleDB 86 | .AppleDesktop 87 | Network Trash Folder 88 | Temporary Items 89 | .apdisk 90 | 91 | # Build 92 | build/ 93 | -------------------------------------------------------------------------------- /src/docs/scss/layout/_sidebar.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | // Navigation 6 | .sidebar { 7 | width: 100%; 8 | background-color: palette(Grey, 100); 9 | // Nav Toggle 10 | .hamburger { 11 | position: absolute; 12 | padding: 12px; 13 | top: 1px; 14 | right: 0; 15 | } 16 | 17 | .site-nav { 18 | position: relative; 19 | 20 | ul { 21 | width: 100%; 22 | list-style: none; 23 | margin: 0; 24 | padding: 0; 25 | border-bottom: 1px solid palette(Grey, 300); 26 | max-height: 0; 27 | transition: max-height 250ms; 28 | overflow: hidden; 29 | 30 | li { 31 | list-style: none; 32 | margin: 0; 33 | padding: 0; 34 | a { 35 | display: block; 36 | padding: 8px 16px; 37 | border-bottom: 1px solid palette(Grey, 300); 38 | color: palette(Grey, 800); 39 | background-color: palette(Grey, 100); 40 | transition: background-color 250ms; 41 | &.active, 42 | &:hover { 43 | background-color: palette(Grey, 200); 44 | } 45 | } 46 | &:last-child { 47 | a { 48 | border-bottom: 0 none; 49 | } 50 | } 51 | } 52 | } 53 | 54 | &.is-open ul { 55 | max-height: 400px; 56 | } 57 | } 58 | 59 | @media screen and (min-width: 640px) { 60 | .hamburger { 61 | top: 15px; 62 | right: 10px; 63 | } 64 | } 65 | 66 | @media screen and (min-width: 720px) { 67 | min-height: calc(100vh - 124px); 68 | width: 220px; 69 | overflow-y: auto; 70 | .hamburger { 71 | display: none; 72 | } 73 | .site-nav { 74 | margin: 0; 75 | 76 | ul { 77 | max-height: none; 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/docs/guides/meta.md: -------------------------------------------------------------------------------- 1 | ## Development Environment 2 | 3 | Development & Build is done with the help of [webpack](https://webpack.js.org/). 4 | 5 | First fork and git clone the repo on your machine. 6 | 7 | ```bash 8 | git clone git@github.com:/react-fonticonpicker.git 9 | ``` 10 | 11 | Now install all the dependencies. Make sure you have [nodejs](https://nodejs.org/en/) 12 | version 9 or higher. 13 | 14 | ```bash 15 | npm install 16 | ``` 17 | 18 | Now run the server with 19 | 20 | ```bash 21 | npm start 22 | ``` 23 | 24 | This will open a webpack dev server with hot reload. You can access the server 25 | from [http://localhost:7770](http://localhost:7770). 26 | 27 | Now make changes in the component and see it live. Also add unit tests and 28 | integration tests where applicable. 29 | 30 | If your changes invalidates snapshots, then make sure to update them too (with 31 | good reasons). 32 | 33 | When doing a PR, try not to build the docs or the dist. It will create unnecessary 34 | merge conflict. 35 | 36 | Other npm commands at disposal: 37 | 38 | * `npm run test`: Runs `eslint` followed by `stylelint` and `jest` tests. 39 | * `npm run start`: Runs a dev server with hot reload. 40 | * `npm run docs`: Builds the docs for production. 41 | * `npm run build`: Builds the UMD & CSS files for distribution. 42 | 43 | ## Credits 44 | 45 | React FontIconPicker has been developed by [Swashata](https://swashata.me) mainly for in use with [eForm](https://eform.live). 46 | The original idea came from [jQuery FontIconPicker](https://github.com/fontIconPicker/fontIconPicker) 47 | by [Alessandro Benoit](http://codeb.it). 48 | 49 | None of these would have been possible without the cool [Wes Bos 🔥](https://wesbos.com/) 50 | and his [react for beginners course](https://reactforbeginners.com/). It is awesome 😉. 51 | -------------------------------------------------------------------------------- /src/docs/guides/usage-parts/2-fipcp.md: -------------------------------------------------------------------------------- 1 | ### 2: Categorized Picker 2 | 3 | If you would like to show categories inside the picker, then make your `icons` a 4 | plain object. 5 | 6 | ```js 7 | const icons = { 8 | 'Users & People': [ 9 | 'fab fa-accessible-icon', 10 | 'fas fa-address-book', 11 | 'far fa-address-book', 12 | 'fas fa-address-card', 13 | 'far fa-address-card', 14 | 'fas fa-bed', 15 | 'fas fa-blind', 16 | 'fas fa-child', 17 | 'fas fa-female', 18 | 'fas fa-frown', 19 | 'far fa-frown', 20 | 'fas fa-id-badge', 21 | 'far fa-id-badge', 22 | 'fas fa-id-card', 23 | 'far fa-id-card', 24 | 'fas fa-male', 25 | 'fas fa-meh', 26 | 'far fa-meh', 27 | 'fas fa-power-off', 28 | 'fas fa-smile', 29 | 'far fa-smile', 30 | 'fas fa-street-view', 31 | 'fas fa-user', 32 | 'far fa-user', 33 | 'fas fa-user-circle', 34 | 'far fa-user-circle', 35 | 'fas fa-user-md', 36 | 'fas fa-user-plus', 37 | 'fas fa-user-secret', 38 | 'fas fa-user-times', 39 | 'fas fa-users', 40 | 'fas fa-wheelchair', 41 | ], 42 | Vehicles: [ 43 | 'fab fa-accessible-icon', 44 | 'fas fa-ambulance', 45 | 'fas fa-bicycle', 46 | 'fas fa-bus', 47 | 'fas fa-car', 48 | 'fas fa-fighter-jet', 49 | 'fas fa-motorcycle', 50 | 'fas fa-paper-plane', 51 | 'far fa-paper-plane', 52 | 'fas fa-plane', 53 | 'fas fa-rocket', 54 | 'fas fa-ship', 55 | 'fas fa-shopping-cart', 56 | 'fas fa-space-shuttle', 57 | 'fas fa-subway', 58 | 'fas fa-taxi', 59 | 'fas fa-train', 60 | 'fas fa-truck', 61 | 'fas fa-wheelchair', 62 | ], 63 | }; 64 | const MyComponent = () => { 65 | return ( 66 | console.log(val)} 70 | isMulti 71 | /> 72 | ); 73 | } 74 | export default MyComponent; 75 | ``` 76 | -------------------------------------------------------------------------------- /src/docs/helpers/routeTransition.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import { spring } from 'react-router-transition'; 7 | import presets from 'react-motion/lib/spring'; 8 | 9 | // wrap the `spring` helper to use a bouncy config 10 | function bounce(val) { 11 | return spring(val, presets.gentle); 12 | } 13 | 14 | // child matches will... 15 | export const fadeInLeft = { 16 | // start in a transparent, upscaled state 17 | atEnter: { 18 | opacity: 0, 19 | translateX: 250, 20 | transitionIndex: 0, 21 | }, 22 | // leave in a transparent, downscaled state 23 | atLeave: { 24 | opacity: bounce(0), 25 | translateX: bounce(-250), 26 | transitionIndex: 2, 27 | }, 28 | // and rest at an opaque, normally-scaled state 29 | atActive: { 30 | opacity: bounce(1), 31 | translateX: bounce(0), 32 | transitionIndex: 1, 33 | }, 34 | mapStyles(styles) { 35 | return { 36 | position: styles.transitionIndex <= 1 ? 'relative' : 'absolute', 37 | opacity: styles.opacity, 38 | transform: `translateX(${styles.translateX}px)`, 39 | }; 40 | }, 41 | }; 42 | 43 | export const fadeInUp = { 44 | // start in a transparent, upscaled state 45 | atEnter: { 46 | opacity: 0, 47 | translateY: 50, 48 | transitionIndex: 0, 49 | }, 50 | // leave in a transparent, downscaled state 51 | atLeave: { 52 | opacity: bounce(0), 53 | translateY: bounce(-50), 54 | transitionIndex: 2, 55 | }, 56 | // and rest at an opaque, normally-scaled state 57 | atActive: { 58 | opacity: bounce(1), 59 | translateY: bounce(0), 60 | transitionIndex: 1, 61 | }, 62 | mapStyles(styles) { 63 | return { 64 | position: styles.transitionIndex <= 1 ? 'relative' : 'absolute', 65 | opacity: styles.opacity, 66 | transform: `translateY(${styles.translateY}px)`, 67 | }; 68 | }, 69 | }; 70 | -------------------------------------------------------------------------------- /src/docs/components/DocApp.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | import React from 'react'; 6 | import { BrowserRouter, Route } from "react-router-dom"; // eslint-disable-line 7 | 8 | import Routes from './Routes'; 9 | import Logo from '../assets/fip.svg'; 10 | import pkg from '../../../package.json'; 11 | 12 | const DocApp = () => ( 13 | 14 |
15 |

16 | 17 | 21 | 22 | 23 | fonticonpickerv{pkg.version} 24 | 25 | 29 | 30 | 31 |

32 |
33 | 34 | 55 |
56 | ); 57 | 58 | export default DocApp; 59 | -------------------------------------------------------------------------------- /docs/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Single Page Apps for GitHub Pages 6 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/docs/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Single Page Apps for GitHub Pages 6 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/docs/components/Sidebar.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import PropTypes from 'prop-types'; 8 | import { NavLink } from 'react-router-dom'; 9 | import className from 'classnames'; 10 | import routes from '../helpers/routes'; 11 | 12 | class Sidebar extends React.Component { 13 | state = { 14 | isOpen: false, 15 | }; 16 | componentDidMount() { 17 | document.addEventListener('click', this.handleOuterClick); 18 | } 19 | 20 | componentWillUnmount() { 21 | document.removeEventListener('click', this.handleOuterClick); 22 | } 23 | 24 | btnRef = React.createRef(); 25 | 26 | handleOuterClick = e => { 27 | if (this.btnRef.current.contains(e.target)) { 28 | return; 29 | } 30 | this.setState({ isOpen: false }); 31 | }; 32 | 33 | handleToggle = e => { 34 | e.preventDefault(); 35 | this.setState(prevState => { 36 | const isOpen = !prevState.isOpen; 37 | return { isOpen }; 38 | }); 39 | }; 40 | 41 | render() { 42 | const menuClass = className('hamburger', 'hamburger--elastic', { 43 | 'is-active': this.state.isOpen, 44 | }); 45 | const navClass = className('site-nav', { 46 | 'is-open': this.state.isOpen, 47 | }); 48 | return ( 49 |
50 | 59 | 75 |
76 | ); 77 | } 78 | } 79 | 80 | export default Sidebar; 81 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '9' 4 | cache: 5 | directories: 6 | - "~/.npm" 7 | - node_modules 8 | install: 9 | - npm install -g codecov 10 | - npm install 11 | script: 12 | - npm test 13 | - codecov 14 | before_deploy: 15 | - npm run build 16 | - zip -r fonticonpicker.react.zip dist/* 17 | deploy: 18 | - provider: npm 19 | email: swashata4u@gmail.com 20 | api_key: 21 | secure: "bHgvGq9JqIEZ8ETc1JzpxUUQ1X6DYmAvPDUJ7qsa+l4QzrbZd4lXDgPRhd8rs7iHp2aLADK3QcObDGXEyH5/4hlGHRQUVewnSMJaGkl2o9JGf0lPwSWKnzfyr58p6e7r4IQhKyxT/4bVnlmdCCEseCtxRAIF1kcXnf8H4rnx79vPPTntgDwQ3M/ABI9CBQeU0/53idN0Dc67Sc7cbXqym4d+twnZe+sdRHpdyYWDvD+fWr7rvxp9VcHbdwS/W7Id0wKPImAX4XoG2RoMfzi/jH1Trlc8s6k2JhrKVAcGKknCZAm+QEM20GuYeCk4PjPzfxESYzS1dKpDIjCdvV5fOgNWIpublZTfAQQqFFgUNgWx5ilqOseDiLPoQX8WL/sJU0ZEikdT5nof1J15RwAYB7A/GlKSJmanI04DYZOb4d4oCtfYBYnHaT9r1AiaQQbWZqfOz87ZnphHbbPVf99psRcHxNsA8KyuY0FrTBiNpr05IDCZuoEmQX0lriN8dAtolka56pdZX5C0j+n574/dAK5j2VUMWSC325vu1s+c+2JKvxF3X1DIHpzvfZfa6IW+2RdKgqUmMnyln/jIEPIfj02xpFQix95YJpgNDyI8LP3GRRAMvWzC7h6MstiqVPft3snL8N3r//2/Yvtr82Eprl8NxBxka6L39OAv2dykVE8=" 22 | on: 23 | tags: true 24 | repo: fontIconPicker/react-fonticonpicker 25 | skip_cleanup: true 26 | overwrite: true 27 | - provider: releases 28 | api_key: 29 | secure: "L+pvvSqw7GW+pB5mzWRSYZ4GhHumFGtv2ZSu4SSysCmXIJTExccTgNXtrKpUjXaHC7GJGl0gpAq3Z1IE0LTFAgkRlHLq4OvY+UoTiOlof8dGr3BXEyc/hHOVo76pdxH1O4vycpc8Psin7FOINXj5TsV4DwyS/Q7yGS3PQoDasPY2491plZLTSujf18m+Bz984KT6PzHDo8j/tngcj+ZQhkmU1BJyvgoCF10i9vI3G0zQ14APlKFVJwPig4bzjYJ5u8kEqLjHgByZz+xvW98+0JJq+7hzqr9yj8FU4ZA/AruWYO9aCplIXmA9mfTcS+WNhkfIhAojNAt225+yBqv7qQbwfK5RRjGhQh+KvEJ2AtMdlhk4G/mhS433vudXbgU5lTyfT3BGia7V7GGuujYoZNBmqtJ+G6hYLHvsUh61QVjjKe/2drCY6XSSshFYwu/+fssXX00oSUnWWys7WfK7FHBLEDtHikz1T1IMDigTHoFTJXJBmHUNJCriC48UQP0VWZ9I+MTZIofHafhn+DvbHVzpK/6trMsEyiSRJQH3ZZYlQosNdObNz470LssFD9u2PBKPhH+T2Q4gZSDYbyDLUZKsf8K4NyAkt6hBX8hhxXTNw2MyLDAIbT5ns3dN+XEhEu3dqWb0Cd3h03ucJgCwXss0P4kMehAjokEXwzvEWik=" 30 | file: 31 | - fonticonpicker.react.zip 32 | on: 33 | tags: true 34 | repo: fontIconPicker/react-fonticonpicker 35 | skip_cleanup: true 36 | overwrite: true 37 | -------------------------------------------------------------------------------- /__tests__/intg/02_icon_and_search.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import { shallow } from 'enzyme'; 8 | 9 | import FontIconPicker from '../../src/js/FontIconPicker'; 10 | import FipIconContainer from '../../src/js/components/FipIconContainer'; 11 | import * as iconDefs from '../../src/docs/helpers/iconDefs'; 12 | 13 | describe('Icon & Search Source', () => { 14 | describe('In FontIconPicker Component', () => { 15 | test('get passed as props', () => { 16 | const icons = ['foo', 'bar']; 17 | const search = ['Foo', 'Bar']; 18 | const wrapper = shallow( 19 | , 25 | ); 26 | expect(wrapper.instance().props.icons).toEqual(icons); 27 | expect(wrapper.instance().props.search).toEqual(search); 28 | }); 29 | 30 | test('search can be null', () => { 31 | const icons = ['foo', 'bar']; 32 | const wrapper = shallow( 33 | , 39 | ); 40 | expect(wrapper.instance().props.icons).toEqual(icons); 41 | expect(wrapper.instance().props.search).toBe(null); 42 | }); 43 | }); 44 | 45 | describe('In FontIconContainer Component', () => { 46 | test('icons populate search if null', () => { 47 | const icons = ['foo', 'bar']; 48 | const props = { 49 | categories: null, 50 | currentCategory: null, 51 | isMulti: false, 52 | icons, 53 | search: null, 54 | value: '', 55 | currentSearch: '', 56 | handleChangeValue: jest.fn(), 57 | currentPage: 0, 58 | iconsPerPage: 20, 59 | handleChangePage: jest.fn(), 60 | renderIcon: jest.fn(), 61 | noIconPlaceholder: '', 62 | onChange: jest.fn(), 63 | }; 64 | const wrapper = shallow(); 65 | expect(wrapper.state('iconView')).toEqual(icons); 66 | expect(wrapper.state('titleView')).toEqual(icons); 67 | }); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /__tests__/unit/FipDropDown.unit.test.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import { shallow } from 'enzyme'; 8 | 9 | import FipDropDown from '../../src/js/components/FipDropDown'; 10 | import * as iconDefs from '../../src/docs/helpers/iconDefs'; 11 | 12 | describe('FipDropDown Component', () => { 13 | const handleChangeCategoryCB = jest.fn(); 14 | const handleChangePageCB = jest.fn(); 15 | const handleChangeSearchCB = jest.fn(); 16 | const props = { 17 | isMulti: false, 18 | value: 'foo', 19 | currentCategory: 0, 20 | currentPage: 0, 21 | currentSearch: '', 22 | icons: iconDefs.icomoonIcons['Other Icons'], 23 | search: iconDefs.icomoonIconsSearch['Other Icons'], 24 | showCategory: true, 25 | showSearch: true, 26 | iconsPerPage: 20, 27 | allCatPlaceholder: '', 28 | searchPlaceholder: '', 29 | noIconPlaceholder: '', 30 | renderIcon: jest.fn(), 31 | handleChangeValue: jest.fn(), 32 | handleChangeCategory: handleChangeCategoryCB, 33 | handleChangePage: handleChangePageCB, 34 | handleChangeSearch: handleChangeSearchCB, 35 | renderUsing: 'data-icomoon', 36 | }; 37 | const wrapper = shallow(); 38 | test('calls handleChangeCategory & handleChangePageCB on category update', () => { 39 | wrapper.instance().handleCategory({ target: { value: 1 } }); 40 | expect(handleChangeCategoryCB).toHaveBeenCalledTimes(1); 41 | expect(handleChangeCategoryCB).toHaveBeenLastCalledWith(1); 42 | expect(handleChangePageCB).toHaveBeenCalledTimes(1); 43 | expect(handleChangePageCB).toHaveBeenLastCalledWith(0); 44 | }); 45 | test('sets proper category on invalid input', () => { 46 | wrapper.instance().handleCategory({ target: { value: 'foo' } }); 47 | expect(handleChangeCategoryCB).toHaveBeenLastCalledWith(0); 48 | }); 49 | test('calls handleChangeSearch on search update', () => { 50 | wrapper.instance().handleSearch({ target: { value: 'foo' } }); 51 | expect(handleChangeSearchCB).toHaveBeenCalledTimes(1); 52 | expect(handleChangeSearchCB).toHaveBeenLastCalledWith('foo'); 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /src/docs/components/pages/Themes.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | import React from 'react'; 6 | import CodeBlock from '../CodeBlock'; 7 | import FontIconPicker from '../../../js/FontIconPicker'; 8 | import * as iconDefs from '../../helpers/iconDefs'; 9 | 10 | const Themes = () => ( 11 |
12 |

13 | FontIconPicker Themes 14 |

15 |

16 | Below are 14 prebuilt themes packed with FontIconPicker. 17 |

18 |

To use them, import the styles from your script.

19 | 20 | 25 | 26 |

27 | Now initiatie FontIconPicker with the{' '} 28 | theme props. 29 |

30 | 31 | v} 38 | isMulti 39 | theme="bluegrey" 40 | />`} 41 | /> 42 | 43 |
    44 | {[ 45 | 'bluegrey', 46 | 'blue', 47 | 'brown', 48 | 'cyan', 49 | 'deeporange', 50 | 'deeppurple', 51 | 'default', 52 | 'indigo', 53 | 'lightblue', 54 | 'orange', 55 | 'pink', 56 | 'purple', 57 | 'red', 58 | 'teal', 59 | ].map(theme => ( 60 |
  • 64 | v} 69 | isMulti 70 | theme={theme} 71 | noSelectedPlaceholder={`${theme} theme`} 72 | /> 73 | 74 | {theme} 75 | 76 |
  • 77 | ))} 78 |
79 |
80 | ); 81 | 82 | export default Themes; 83 | -------------------------------------------------------------------------------- /src/docs/components/Routes.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import { BrowserRouter, Route, Switch } from 'react-router-dom'; 8 | import { AnimatedSwitch, spring } from 'react-router-transition'; 9 | import presets from 'react-motion/lib/spring'; 10 | 11 | import Sidebar from './Sidebar'; 12 | import routes from '../helpers/routes'; 13 | import ScrollToTop from './ScrollToTop'; 14 | import FourOFour from './pages/404'; 15 | import BasicUsage from './pages/BasicUsage'; 16 | import Examples from './pages/Examples'; 17 | import Installation from './pages/Installation'; 18 | import Introduction from './pages/Introduction'; 19 | import Props from './pages/Props'; 20 | import Themes from './pages/Themes'; 21 | import Meta from './pages/Meta'; 22 | import { fadeInLeft } from '../helpers/routeTransition'; 23 | 24 | let routeBase = '/react-fonticonpicker'; 25 | if (process.env.NODE_ENV === 'development') { 26 | routeBase = '/'; 27 | } 28 | 29 | const components = { 30 | BasicUsage, 31 | Examples, 32 | Installation, 33 | Introduction, 34 | Props, 35 | Themes, 36 | Meta, 37 | }; 38 | 39 | const Routes = () => ( 40 | 41 | 42 |
43 | 44 |
45 |
46 | 53 | {routes.map(route => { 54 | const RouteComponent = 55 | components[route.component]; 56 | return ( 57 | 63 | ); 64 | })} 65 | 66 | 67 |
68 |
69 |
70 |
71 |
72 | ); 73 | 74 | export default Routes; 75 | -------------------------------------------------------------------------------- /webpack.dev.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const HtmlWebpackPlugin = require('html-webpack-plugin'); // eslint-disable-line 3 | const CleanWebpackPlugin = require('clean-webpack-plugin'); // eslint-disable-line 4 | const FaviconsWebpackPlugin = require('favicons-webpack-plugin'); // eslint-disable-line 5 | const HtmlWebpackInlineSVGPlugin = require('html-webpack-inline-svg-plugin'); // eslint-disable-line 6 | 7 | module.exports = { 8 | entry: path.join(__dirname, 'src/docs'), 9 | devtool: 'inline-source-map', 10 | output: { 11 | path: path.join(__dirname, 'build'), 12 | filename: 'bundle.js', 13 | publicPath: '/', 14 | }, 15 | module: { 16 | rules: [ 17 | { 18 | test: /\.(js|jsx)$/, 19 | use: ['babel-loader', 'eslint-loader'], 20 | exclude: /node_modules/, 21 | }, 22 | { 23 | test: /\.css$/, 24 | use: [ 25 | { 26 | loader: 'style-loader', 27 | }, 28 | { 29 | loader: 'css-loader', 30 | options: { 31 | sourceMap: true, 32 | }, 33 | }, 34 | ], 35 | }, 36 | { 37 | test: /\.scss$/, 38 | use: [ 39 | { 40 | loader: 'style-loader', 41 | }, 42 | { 43 | loader: 'css-loader', 44 | options: { 45 | sourceMap: true, 46 | }, 47 | }, 48 | { 49 | loader: 'sass-loader', 50 | options: { 51 | sourceMap: true, 52 | }, 53 | }, 54 | ], 55 | }, 56 | { 57 | test: /\.(woff|woff2|eot|ttf|otf|svg|png|jpg|gif)(\?v=\d+\.\d+\.\d+)?$/, 58 | use: [ 59 | { 60 | loader: 'file-loader', 61 | options: {}, 62 | }, 63 | ], 64 | }, 65 | { 66 | test: /\.(md)$/, 67 | use: 'raw-loader', 68 | }, 69 | ], 70 | }, 71 | plugins: [ 72 | new CleanWebpackPlugin(['build']), 73 | new FaviconsWebpackPlugin(path.join(__dirname, 'src/docs/picker.png')), 74 | new HtmlWebpackPlugin({ 75 | template: path.join(__dirname, 'src/docs/index.html'), 76 | svgoConfig: { 77 | removeHiddenElems: false, 78 | }, 79 | }), 80 | new HtmlWebpackInlineSVGPlugin({ 81 | runPreEmit: true, 82 | }), 83 | ], 84 | resolve: { 85 | extensions: ['.js', '.jsx'], 86 | }, 87 | devServer: { 88 | contentBase: path.join(__dirname, 'build'), 89 | port: 7770, 90 | overlay: true, 91 | historyApiFallback: true, 92 | }, 93 | mode: 'development', 94 | }; 95 | -------------------------------------------------------------------------------- /src/scss/components/_rfipbutton.scss: -------------------------------------------------------------------------------- 1 | // Button 2 | .rfipbtn { 3 | width: 136px; 4 | display: flex; 5 | flex-flow: row nowrap; 6 | min-height: 50px; 7 | border-radius: 2px; 8 | cursor: pointer; 9 | transition: box-shadow 250ms, border-color 250ms; 10 | outline: 0 none; 11 | user-select: none; 12 | 13 | // open 14 | &--open { 15 | border-radius: 2px 2px 0 0; 16 | } 17 | 18 | // dropdown button 19 | &__button { 20 | width: 48px; 21 | margin-left: auto; 22 | display: flex; 23 | align-items: center; /* x axis center */ 24 | justify-content: center; /* y axis center */ 25 | height: auto; /* auto height to fix the flex */ 26 | transition: background 250ms, box-shadow 250ms; 27 | 28 | i { 29 | font-size: 32px; 30 | transition: transform 250ms; 31 | } 32 | 33 | // Open 34 | &--open { 35 | i { 36 | transform: rotate(-180deg); 37 | } 38 | } 39 | } 40 | 41 | // current 42 | &__current { 43 | display: flex; 44 | flex-flow: row nowrap; 45 | align-items: center; 46 | justify-content: center; 47 | flex: 0 0 86px; 48 | padding: 2px; 49 | } 50 | 51 | // multi 52 | &--multi { 53 | width: 258px; 54 | 55 | // current 56 | .rfipbtn__current { 57 | flex-flow: row wrap; 58 | justify-content: flex-start; 59 | flex-basis: 212px; 60 | align-content: center; 61 | } 62 | } 63 | 64 | // icon 65 | &__icon { 66 | margin: 2px; 67 | padding: 0; 68 | height: 28px; 69 | width: 48px; 70 | display: flex; 71 | flex-flow: row nowrap; 72 | align-items: center; 73 | justify-content: space-between; 74 | border-radius: 2px; 75 | 76 | // empty 77 | &--empty { 78 | font-size: 14px; 79 | line-height: 16px; 80 | margin-left: 8px; 81 | text-align: center; 82 | text-transform: lowercase; 83 | font-style: italic; 84 | } 85 | } 86 | 87 | // elm 88 | &__elm { 89 | display: flex; 90 | height: 28px; 91 | width: 28px; 92 | align-items: center; 93 | justify-content: center; 94 | font-size: 18px; 95 | img, 96 | svg { 97 | height: 18px; 98 | width: auto; 99 | } 100 | } 101 | 102 | // del 103 | &__del { 104 | width: 18px; 105 | display: flex; 106 | height: 28px; 107 | align-items: center; 108 | justify-content: center; 109 | transition: background-color 250ms; 110 | cursor: pointer; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /dist/assets/fontIconPicker.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/assets/fipicon/fonts/fontIconPicker.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /docs/assets/asset-e5539dcf6082a05879d9a26211fb0bc4.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React FontIconPicker Component 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 45 | 46 | 47 | 48 | 49 |
50 | 51 | 52 | -------------------------------------------------------------------------------- /src/scss/components/_rfipicons.scss: -------------------------------------------------------------------------------- 1 | // Icons box 2 | .rfipicons { 3 | // Pager 4 | &__pager { 5 | display: flex; 6 | flex-flow: row nowrap; 7 | height: 24px; 8 | line-height: 24px; 9 | align-items: center; 10 | margin-bottom: 8px; 11 | } 12 | 13 | // num 14 | &__num { 15 | width: 100px; 16 | margin-right: auto; 17 | } 18 | // current page 19 | &__cp { 20 | width: 32px; 21 | margin-right: 8px; 22 | height: 24px; 23 | line-height: 24px; 24 | text-align: right; 25 | } 26 | // separator 27 | &__sp { 28 | margin-right: 8px; 29 | } 30 | // total page 31 | &__tp { 32 | margin-right: 8px; 33 | } 34 | 35 | // arrows 36 | &__arrow { 37 | margin-left: auto; 38 | width: 56px; 39 | display: flex; 40 | flex-flow: row nowrap; 41 | justify-content: flex-end; 42 | align-items: center; 43 | height: 24px; 44 | user-select: none; 45 | } 46 | // left and right 47 | &__right { 48 | margin-left: auto; 49 | } 50 | &__left, 51 | &__right { 52 | cursor: pointer; 53 | width: 24px; 54 | height: 24px; 55 | position: relative; 56 | transition: background-color 250ms, border 250ms; 57 | outline: 0 none; 58 | border-radius: 2px; 59 | font-size: 18px; 60 | } 61 | 62 | // Label 63 | &__label { 64 | height: 22px; 65 | width: 22px; 66 | display: flex; 67 | align-items: center; 68 | justify-content: center; 69 | img { 70 | height: 18px; 71 | width: 18px; 72 | } 73 | } 74 | 75 | // Icon Selector 76 | &__selector { 77 | display: flex; 78 | flex: 1 1 20%; 79 | flex-flow: row wrap; 80 | align-content: center; 81 | justify-content: flex-start; 82 | } 83 | 84 | // Individual icon box 85 | &__ibox { 86 | display: flex; 87 | align-items: center; 88 | justify-content: center; 89 | height: 100%; 90 | width: 100%; 91 | transition: background-color 250ms, border 250ms; 92 | border-radius: 2px; 93 | outline: 0 none; 94 | font-size: 20px; 95 | img, 96 | svg { 97 | max-height: 24px; 98 | width: auto; 99 | } 100 | > * { 101 | transform: scale(1); 102 | transition: transform 250ms; 103 | transform-origin: center; 104 | } 105 | &:hover { 106 | > * { 107 | transform: scale(1.8); 108 | } 109 | } 110 | // Error 111 | &--error { 112 | text-transform: lowercase; 113 | font-style: italic; 114 | } 115 | } 116 | 117 | // Invidual icons 118 | &__icon { 119 | width: 20%; 120 | height: 64px; 121 | padding: 1px; 122 | display: flex; 123 | align-items: center; 124 | justify-content: center; 125 | cursor: pointer; 126 | 127 | // Error 128 | &--error { 129 | display: block; 130 | padding: 16px; 131 | text-align: center; 132 | font-size: 24px; 133 | width: 100%; 134 | line-height: 1; 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/assets/fipicon/demo-files/demo.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0; 3 | margin: 0; 4 | font-family: sans-serif; 5 | font-size: 1em; 6 | line-height: 1.5; 7 | color: #555; 8 | background: #fff; 9 | } 10 | h1 { 11 | font-size: 1.5em; 12 | font-weight: normal; 13 | } 14 | small { 15 | font-size: .66666667em; 16 | } 17 | a { 18 | color: #e74c3c; 19 | text-decoration: none; 20 | } 21 | a:hover, a:focus { 22 | box-shadow: 0 1px #e74c3c; 23 | } 24 | .bshadow0, input { 25 | box-shadow: inset 0 -2px #e7e7e7; 26 | } 27 | input:hover { 28 | box-shadow: inset 0 -2px #ccc; 29 | } 30 | input, fieldset { 31 | font-family: sans-serif; 32 | font-size: 1em; 33 | margin: 0; 34 | padding: 0; 35 | border: 0; 36 | } 37 | input { 38 | color: inherit; 39 | line-height: 1.5; 40 | height: 1.5em; 41 | padding: .25em 0; 42 | } 43 | input:focus { 44 | outline: none; 45 | box-shadow: inset 0 -2px #449fdb; 46 | } 47 | .glyph { 48 | font-size: 16px; 49 | width: 15em; 50 | padding-bottom: 1em; 51 | margin-right: 4em; 52 | margin-bottom: 1em; 53 | float: left; 54 | overflow: hidden; 55 | } 56 | .liga { 57 | width: 80%; 58 | width: calc(100% - 2.5em); 59 | } 60 | .talign-right { 61 | text-align: right; 62 | } 63 | .talign-center { 64 | text-align: center; 65 | } 66 | .bgc1 { 67 | background: #f1f1f1; 68 | } 69 | .fgc1 { 70 | color: #999; 71 | } 72 | .fgc0 { 73 | color: #000; 74 | } 75 | p { 76 | margin-top: 1em; 77 | margin-bottom: 1em; 78 | } 79 | .mvm { 80 | margin-top: .75em; 81 | margin-bottom: .75em; 82 | } 83 | .mtn { 84 | margin-top: 0; 85 | } 86 | .mtl, .mal { 87 | margin-top: 1.5em; 88 | } 89 | .mbl, .mal { 90 | margin-bottom: 1.5em; 91 | } 92 | .mal, .mhl { 93 | margin-left: 1.5em; 94 | margin-right: 1.5em; 95 | } 96 | .mhmm { 97 | margin-left: 1em; 98 | margin-right: 1em; 99 | } 100 | .mls { 101 | margin-left: .25em; 102 | } 103 | .ptl { 104 | padding-top: 1.5em; 105 | } 106 | .pbs, .pvs { 107 | padding-bottom: .25em; 108 | } 109 | .pvs, .pts { 110 | padding-top: .25em; 111 | } 112 | .unit { 113 | float: left; 114 | } 115 | .unitRight { 116 | float: right; 117 | } 118 | .size1of2 { 119 | width: 50%; 120 | } 121 | .size1of1 { 122 | width: 100%; 123 | } 124 | .clearfix:before, .clearfix:after { 125 | content: " "; 126 | display: table; 127 | } 128 | .clearfix:after { 129 | clear: both; 130 | } 131 | .hidden-true { 132 | display: none; 133 | } 134 | .textbox0 { 135 | width: 3em; 136 | background: #f1f1f1; 137 | padding: .25em .5em; 138 | line-height: 1.5; 139 | height: 1.5em; 140 | } 141 | #testDrive { 142 | display: block; 143 | padding-top: 24px; 144 | line-height: 1.5; 145 | } 146 | .fs0 { 147 | font-size: 16px; 148 | } 149 | .fs1 { 150 | font-size: 28px; 151 | } 152 | 153 | -------------------------------------------------------------------------------- /src/docs/assets/superhero/demo-files/demo.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0; 3 | margin: 0; 4 | font-family: sans-serif; 5 | font-size: 1em; 6 | line-height: 1.5; 7 | color: #555; 8 | background: #fff; 9 | } 10 | h1 { 11 | font-size: 1.5em; 12 | font-weight: normal; 13 | } 14 | small { 15 | font-size: .66666667em; 16 | } 17 | a { 18 | color: #e74c3c; 19 | text-decoration: none; 20 | } 21 | a:hover, a:focus { 22 | box-shadow: 0 1px #e74c3c; 23 | } 24 | .bshadow0, input { 25 | box-shadow: inset 0 -2px #e7e7e7; 26 | } 27 | input:hover { 28 | box-shadow: inset 0 -2px #ccc; 29 | } 30 | input, fieldset { 31 | font-family: sans-serif; 32 | font-size: 1em; 33 | margin: 0; 34 | padding: 0; 35 | border: 0; 36 | } 37 | input { 38 | color: inherit; 39 | line-height: 1.5; 40 | height: 1.5em; 41 | padding: .25em 0; 42 | } 43 | input:focus { 44 | outline: none; 45 | box-shadow: inset 0 -2px #449fdb; 46 | } 47 | .glyph { 48 | font-size: 16px; 49 | width: 15em; 50 | padding-bottom: 1em; 51 | margin-right: 4em; 52 | margin-bottom: 1em; 53 | float: left; 54 | overflow: hidden; 55 | } 56 | .liga { 57 | width: 80%; 58 | width: calc(100% - 2.5em); 59 | } 60 | .talign-right { 61 | text-align: right; 62 | } 63 | .talign-center { 64 | text-align: center; 65 | } 66 | .bgc1 { 67 | background: #f1f1f1; 68 | } 69 | .fgc1 { 70 | color: #999; 71 | } 72 | .fgc0 { 73 | color: #000; 74 | } 75 | p { 76 | margin-top: 1em; 77 | margin-bottom: 1em; 78 | } 79 | .mvm { 80 | margin-top: .75em; 81 | margin-bottom: .75em; 82 | } 83 | .mtn { 84 | margin-top: 0; 85 | } 86 | .mtl, .mal { 87 | margin-top: 1.5em; 88 | } 89 | .mbl, .mal { 90 | margin-bottom: 1.5em; 91 | } 92 | .mal, .mhl { 93 | margin-left: 1.5em; 94 | margin-right: 1.5em; 95 | } 96 | .mhmm { 97 | margin-left: 1em; 98 | margin-right: 1em; 99 | } 100 | .mls { 101 | margin-left: .25em; 102 | } 103 | .ptl { 104 | padding-top: 1.5em; 105 | } 106 | .pbs, .pvs { 107 | padding-bottom: .25em; 108 | } 109 | .pvs, .pts { 110 | padding-top: .25em; 111 | } 112 | .unit { 113 | float: left; 114 | } 115 | .unitRight { 116 | float: right; 117 | } 118 | .size1of2 { 119 | width: 50%; 120 | } 121 | .size1of1 { 122 | width: 100%; 123 | } 124 | .clearfix:before, .clearfix:after { 125 | content: " "; 126 | display: table; 127 | } 128 | .clearfix:after { 129 | clear: both; 130 | } 131 | .hidden-true { 132 | display: none; 133 | } 134 | .textbox0 { 135 | width: 3em; 136 | background: #f1f1f1; 137 | padding: .25em .5em; 138 | line-height: 1.5; 139 | height: 1.5em; 140 | } 141 | #testDrive { 142 | display: block; 143 | padding-top: 24px; 144 | line-height: 1.5; 145 | } 146 | .fs0 { 147 | font-size: 16px; 148 | } 149 | .fs1 { 150 | font-size: 32px; 151 | } 152 | 153 | -------------------------------------------------------------------------------- /src/scss/themes/_template.scss: -------------------------------------------------------------------------------- 1 | // Button 2 | .rfipbtn--#{$theme} { 3 | background-color: $btn-bg-color; 4 | border: 1px solid $btn-border-color; 5 | 6 | &:active, 7 | &:focus { 8 | @include card(1); 9 | border: 1px solid $btn-bg-hover-color; 10 | } 11 | 12 | // dropdown button 13 | .rfipbtn { 14 | &__button { 15 | border: 0 none transparent; 16 | border-left: 1px solid $btn-border-color; 17 | background-color: $btn-bg-dd-color; 18 | color: $icon-text; 19 | 20 | &:hover { 21 | background-color: $btn-bg-hover-color; 22 | } 23 | 24 | &:active { 25 | box-shadow: inset 0 0 10px 0 $btn-bg-active-color; 26 | } 27 | } 28 | 29 | // icon 30 | &__icon { 31 | border: 1px solid $icon-border-color; 32 | color: $icon-text; 33 | 34 | // empty 35 | &--empty { 36 | color: $empty-icon-color; 37 | } 38 | } 39 | 40 | // del 41 | &__del { 42 | background-color: $del-bg-color; 43 | 44 | &:hover { 45 | background-color: $del-bg-hover-color; 46 | } 47 | 48 | &:focus, 49 | &:active { 50 | outline: 1px solid $del-bg-hover-color; 51 | } 52 | } 53 | } 54 | } 55 | 56 | .rfipdropdown--#{$theme} { 57 | @include card(5); 58 | color: $text; 59 | 60 | input, 61 | select { 62 | color: $text; 63 | } 64 | 65 | background-color: $color-background; 66 | border: 1px solid $btn-border-color; 67 | // Category item 68 | .rfipcategory { 69 | select { 70 | background-color: $color-background; 71 | @include input($elem-border-color, $elem-border-focus-color); 72 | } 73 | } 74 | 75 | // Icons box 76 | .rfipicons { 77 | // current page 78 | &__cp { 79 | @include input($elem-border-color, $elem-border-focus-color); 80 | } 81 | 82 | &__left, 83 | &__right { 84 | background-color: $pager-bg-color; 85 | border: 1px solid $pager-bg-color; 86 | color: $icon-text; 87 | &:hover { 88 | background-color: $pager-bg-hover-color; 89 | border: 1px solid $pager-bg-hover-color; 90 | } 91 | &:focus, 92 | &:active { 93 | border: 1px solid $pager-bg-hover-color; 94 | } 95 | } 96 | 97 | // Individual icon box 98 | &__ibox { 99 | background-color: $ibox-bg-color; 100 | border: 1px solid $ibox-bg-color; 101 | color: $icon-text; 102 | &:hover { 103 | background-color: $ibox-bg-hover-color; 104 | border: 1px solid $ibox-bg-hover-color; 105 | } 106 | &:focus, 107 | &:active { 108 | border: 1px solid $ibox-bg-hover-color; 109 | } 110 | &--error { 111 | color: $error-icon-color; 112 | } 113 | } 114 | 115 | // Invidual icons 116 | &__icon { 117 | // selected 118 | &--selected { 119 | .rfipicons__ibox { 120 | background-color: $ibox-bg-selected-color; 121 | } 122 | } 123 | } 124 | } 125 | 126 | // Search 127 | .rfipsearch { 128 | input { 129 | @include input($elem-border-color, $elem-border-focus-color); 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/docs/assets/fontello/README.txt: -------------------------------------------------------------------------------- 1 | This webfont is generated by http://fontello.com open source project. 2 | 3 | 4 | ================================================================================ 5 | Please, note, that you should obey original font licences, used to make this 6 | webfont pack. Details available in LICENSE.txt file. 7 | 8 | - Usually, it's enough to publish content of LICENSE.txt file somewhere on your 9 | site in "About" section. 10 | 11 | - If your project is open-source, usually, it will be ok to make LICENSE.txt 12 | file publically available in your repository. 13 | 14 | - Fonts, used in Fontello, don't require to make clickable links on your site. 15 | But any kind of additional authors crediting is welcome. 16 | ================================================================================ 17 | 18 | 19 | Comments on archive content 20 | --------------------------- 21 | 22 | - /font/* - fonts in different formats 23 | 24 | - /css/* - different kinds of css, for all situations. Should be ok with 25 | twitter bootstrap. Also, you can skip style and assign icon classes 26 | directly to text elements, if you don't mind about IE7. 27 | 28 | - demo.html - demo file, to show your webfont content 29 | 30 | - LICENSE.txt - license info about source fonts, used to build your one. 31 | 32 | - config.json - keeps your settings. You can import it back to fontello anytime, 33 | to continue your work 34 | 35 | 36 | Why so many CSS files ? 37 | ----------------------- 38 | 39 | Because we like to fit all your needs :) 40 | 41 | - basic file, .css - is usually enougth, in contains @font-face 42 | and character codes definition 43 | 44 | - *-ie7.css - if you need IE7 support, but still don't wish to put char codes 45 | directly into html 46 | 47 | - *-codes.css and *-ie7-codes.css - if you like to use your own @font-face 48 | rules, but still wish to benefit of css generation. That can be very 49 | convenient for automated assets build systems. When you need to update font - 50 | no needs to manually edit files, just override old version with archive 51 | content. See fontello source codes for example. 52 | 53 | - *-embedded.css - basic css file, but with embedded WOFF font, to avoid 54 | CORS issues in Firefox and IE9+, when fonts are hosted on the separate domain. 55 | We strongly recommend to resolve this issue by `Access-Control-Allow-Origin` 56 | server headers. But if you ok with dirty hack - this file is for you. Note, 57 | that data url moved to separate @font-face to avoid problems with `. 10 | * **Class Renderer** - Render icons by class ``. 11 | * **Custom Renderer** - Use your own function to return an icon or SVG. 12 | 13 | This has been rewritten from scratch and it is not a wrapper around 14 | [jQuery Font Icon Picker](https://fonticonpicker.github.io). 15 | 16 | ### TL;DR 17 | 18 | 1. Install FontIconPicker and dependencies from NPM. 19 | 20 | ```bash 21 | npm install classnames prop-types react-transition-group @fonticonpicker/react-fonticonpicker --save 22 | ``` 23 | 24 | 2. Bring in your webfonts (eg, icomoon or fontawesome). 25 | 26 | ```html 27 | 28 | ``` 29 | 30 | 3. Import FontIconPicker. 31 | 32 | ```js 33 | import FontIconPicker from '@fonticonpicker/react-fonticonpicker'; 34 | import '@fonticonpicker/react-fonticonpicker/dist/fonticonpicker.base-theme.react.css'; 35 | import '@fonticonpicker/react-fonticonpicker/dist/fonticonpicker.material-theme.react.css'; 36 | ``` 37 | 38 | 4. Initialize with source and optionally search. 39 | 40 | ```js 41 | import React, { Component } from 'react'; 42 | import FontIconPicker from '@fonticonpicker/react-fonticonpicker'; 43 | import logo from './logo.svg'; 44 | import './App.css'; 45 | import '@fonticonpicker/react-fonticonpicker/dist/fonticonpicker.base-theme.react.css'; 46 | import '@fonticonpicker/react-fonticonpicker/dist/fonticonpicker.material-theme.react.css'; 47 | 48 | class App extends Component { 49 | constructor(props) { 50 | super(props); 51 | this.state = { 52 | value: 'fipicon-angle-left', 53 | }; 54 | } 55 | handleChange = (value) => { 56 | this.setState({ value }); 57 | } 58 | render() { 59 | const props = { 60 | icons: ['fipicon-angle-left', 'fipicon-angle-right', 'fipicon-angle-up', 'fipicon-angle-down'], 61 | theme: 'bluegrey', 62 | renderUsing: 'class', 63 | value: this.state.value, 64 | onChange: this.handleChange, 65 | isMulti: false, 66 | }; 67 | return ( 68 |
69 |
70 | logo 71 |

Welcome to React

72 |
73 | 74 |
75 | ); 76 | } 77 | } 78 | 79 | export default App; 80 | ``` 81 | 82 | The example above assumed you are using [create-react-app](https://github.com/facebook/create-react-app). The source of `iconDefs` can be 83 | found [here](https://github.com/fontIconPicker/react-fonticonpicker/blob/master/src/docs/helpers/iconDefs.js). You can check the guides for more information. 84 | -------------------------------------------------------------------------------- /__tests__/intg/06_set_icons.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | import React from 'react'; 6 | import { mount } from 'enzyme'; 7 | 8 | import FontIconPicker from '../../src/js/FontIconPicker'; 9 | import FipButton from '../../src/js/components/FipButton'; 10 | import * as iconDefs from '../../src/docs/helpers/iconDefs'; 11 | 12 | describe('Clicking Icons', () => { 13 | const { 14 | Others: [valOne, valTwo, valThree, valFour], 15 | } = iconDefs.fontelloIcons; 16 | const props = { 17 | icons: iconDefs.fontelloIcons.Others, 18 | onChange: jest.fn(), 19 | isMulti: false, 20 | renderUsing: 'class', 21 | value: valOne, 22 | showCateogry: true, 23 | }; 24 | const clickerSelector = '.rfipicons__ibox'; 25 | test('toggles value on single select', () => { 26 | const wrapper = mount(); 27 | wrapper.find(FipButton).simulate('click'); 28 | expect(wrapper.state('value')).toBe(valOne); 29 | wrapper 30 | .find(clickerSelector) 31 | .at(0) 32 | .simulate('click'); 33 | expect(wrapper.state('value')).toBe(''); 34 | wrapper 35 | .find(clickerSelector) 36 | .at(1) 37 | .simulate('click'); 38 | expect(wrapper.state('value')).toBe(valTwo); 39 | }); 40 | test('toggles value on multi select', () => { 41 | const wrapper = mount( 42 | , 45 | ); 46 | wrapper.find(FipButton).simulate('click'); 47 | expect(wrapper.state('value')).toEqual([valOne, valTwo]); 48 | wrapper 49 | .find(clickerSelector) 50 | .at(0) 51 | .simulate('click'); 52 | expect(wrapper.state('value')).toEqual([valTwo]); 53 | wrapper 54 | .find(clickerSelector) 55 | .at(1) 56 | .simulate('click'); 57 | expect(wrapper.state('value')).toHaveLength(0); 58 | wrapper 59 | .find(clickerSelector) 60 | .at(2) 61 | .simulate('click'); 62 | expect(wrapper.state('value')).toEqual([valThree]); 63 | wrapper 64 | .find(clickerSelector) 65 | .at(3) 66 | .simulate('click'); 67 | expect(wrapper.state('value')).toEqual([valThree, valFour]); 68 | wrapper 69 | .find(clickerSelector) 70 | .at(2) 71 | .simulate('click'); 72 | expect(wrapper.state('value')).toEqual([valFour]); 73 | }); 74 | test('expect dropdown to stay open after selecting icon when closeOnSelect is false', () => { 75 | const thisProps = { 76 | ...props, 77 | closeOnSelect: false, 78 | }; 79 | const wrapper = mount(); 80 | wrapper.find(FipButton).simulate('click'); 81 | expect(wrapper.state('isOpen')).toBe(true); 82 | wrapper 83 | .find(clickerSelector) 84 | .at(0) 85 | .simulate('click'); 86 | expect(wrapper.state('isOpen')).toBe(true); 87 | }); 88 | test('expect dropdown to close after selecting icon when closeOnSelect is false', () => { 89 | const thisProps = { 90 | ...props, 91 | closeOnSelect: true, 92 | }; 93 | const wrapper = mount(); 94 | wrapper.find(FipButton).simulate('click'); 95 | expect(wrapper.state('isOpen')).toBe(true); 96 | wrapper 97 | .find(clickerSelector) 98 | .at(0) 99 | .simulate('click'); 100 | expect(wrapper.state('isOpen')).toBe(false); 101 | }); 102 | }); 103 | -------------------------------------------------------------------------------- /src/js/components/FipButton.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import PropTypes from 'prop-types'; 8 | import classNames from 'classnames'; 9 | 10 | class FipButton extends React.PureComponent { 11 | static propTypes = { 12 | className: PropTypes.string.isRequired, 13 | isOpen: PropTypes.bool.isRequired, 14 | onClick: PropTypes.func.isRequired, 15 | domRef: PropTypes.object.isRequired, // eslint-disable-line 16 | isMulti: PropTypes.bool.isRequired, 17 | value: PropTypes.oneOfType([ 18 | PropTypes.number, 19 | PropTypes.string, 20 | PropTypes.arrayOf( 21 | PropTypes.oneOfType([PropTypes.number, PropTypes.string]), 22 | ), 23 | ]).isRequired, 24 | renderIcon: PropTypes.func.isRequired, 25 | handleDeleteValue: PropTypes.func.isRequired, 26 | noSelectedPlaceholder: PropTypes.string.isRequired, 27 | }; 28 | 29 | handleClick = () => { 30 | this.props.onClick(); 31 | }; 32 | 33 | handleKeyDown = event => { 34 | // Toggle on enter or keyspace 35 | if (event.keyCode === 32 || event.keyCode === 13) { 36 | this.props.onClick(); 37 | } 38 | }; 39 | 40 | handleDelete = (event, icon) => { 41 | event.stopPropagation(); 42 | this.props.handleDeleteValue(icon); 43 | }; 44 | 45 | handleDeleteKeyboard = (event, icon) => { 46 | if (event.keyCode === 32 || event.keyCode === 13) { 47 | this.props.handleDeleteValue(icon); 48 | } 49 | }; 50 | 51 | renderIcon(icon) { 52 | if (icon === '' || icon === null || icon === undefined) { 53 | return this.renderEmptyIcon(); 54 | } 55 | return ( 56 | 57 | 58 | {this.props.renderIcon(icon)} 59 | 60 | this.handleDelete(e, icon)} 63 | onKeyDown={e => this.handleDeleteKeyboard(e, icon)} 64 | tabIndex={0} 65 | role="button" 66 | > 67 | × 68 | 69 | 70 | ); 71 | } 72 | 73 | renderEmptyIcon = () => ( 74 | 75 | {this.props.noSelectedPlaceholder} 76 | 77 | ); 78 | 79 | renderCurrentIcons() { 80 | if (this.props.isMulti) { 81 | if (!this.props.value.length) { 82 | return this.renderEmptyIcon(); 83 | } 84 | return this.props.value.map(icon => this.renderIcon(icon)); 85 | } 86 | return this.renderIcon(this.props.value); 87 | } 88 | 89 | render() { 90 | const handlers = { 91 | onClick: this.handleClick, 92 | onKeyDown: this.handleKeyDown, 93 | onFocus: this.handleFocus, 94 | onBlur: this.handleBlur, 95 | tabIndex: 0, 96 | }; 97 | 98 | const btnClass = classNames( 99 | 'rfipbtn__button', 100 | `rfipbtn__button--${this.props.isOpen ? 'open' : 'close'}`, 101 | ); 102 | 103 | const elmClass = classNames(this.props.className); 104 | 105 | return ( 106 |
107 |
108 | {this.renderCurrentIcons()} 109 |
110 |
111 | 116 |
117 |
118 | ); 119 | } 120 | } 121 | 122 | export default FipButton; 123 | -------------------------------------------------------------------------------- /__tests__/intg/03_dropdown_button.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import { shallow, mount } from 'enzyme'; 8 | 9 | import FontIconPicker from '../../src/js/FontIconPicker'; 10 | import FipButton from '../../src/js/components/FipButton'; 11 | import * as iconDefs from '../../src/docs/helpers/iconDefs'; 12 | 13 | describe('Clicking Button', () => { 14 | test('changes class', () => { 15 | // Just a callback 16 | const cb = () => null; 17 | const wrapper = shallow( 18 | , 19 | ); 20 | expect( 21 | wrapper.find(FipButton).hasClass('rfipbtn--open'), 22 | ).not.toBeTruthy(); 23 | expect(wrapper.find(FipButton).hasClass('rfipbtn--close')).toBeTruthy(); 24 | wrapper.find(FipButton).simulate('click'); 25 | expect(wrapper.find(FipButton).hasClass('rfipbtn--open')).toBeTruthy(); 26 | expect( 27 | wrapper.find(FipButton).hasClass('rfipbtn--close'), 28 | ).not.toBeTruthy(); 29 | }); 30 | 31 | test('mounts portal', () => { 32 | const cb = () => null; 33 | const wrapper = shallow( 34 | , 39 | ); 40 | expect(wrapper.render().find('.rfipdropdown')).toHaveLength(0); 41 | wrapper.find(FipButton).simulate('click'); 42 | expect(wrapper.render().find('.rfipdropdown')).toHaveLength(1); 43 | }); 44 | 45 | test('unmounts portal on double click', () => { 46 | const cb = () => null; 47 | const wrapper = shallow( 48 | , 53 | ); 54 | expect(wrapper.render().find('.rfipdropdown')).toHaveLength(0); 55 | wrapper.find(FipButton).simulate('click'); 56 | expect(wrapper.render().find('.rfipdropdown')).toHaveLength(1); 57 | wrapper.find(FipButton).simulate('click'); 58 | expect(wrapper.render().find('.rfipdropdown')).toHaveLength(0); 59 | }); 60 | }); 61 | 62 | // Check delete on dropdown button 63 | describe('Clicking Delete', () => { 64 | describe('On Multi Picker', () => { 65 | test('deletes from value array', () => { 66 | const [valOne, valTwo] = iconDefs.fontelloIcons.Others; 67 | const wrapper = mount( 68 | , 75 | ); 76 | expect(wrapper.state('value')).toEqual([valOne, valTwo]); 77 | // Now delete 78 | wrapper 79 | .find('.rfipbtn__del') 80 | .at(0) 81 | .simulate('click'); 82 | expect(wrapper.state('value')).toEqual([valTwo]); 83 | }); 84 | }); 85 | describe('On Single Picker', () => { 86 | test('sets value to empty string', () => { 87 | const [valOne] = iconDefs.fontelloIcons.Others; 88 | const wrapper = mount( 89 | , 96 | ); 97 | expect(wrapper.state('value')).toBe(valOne); 98 | // Now delete 99 | wrapper 100 | .find('.rfipbtn__del') 101 | .at(0) 102 | .simulate('click'); 103 | expect(wrapper.state('value')).toBe(''); 104 | }); 105 | }); 106 | }); 107 | -------------------------------------------------------------------------------- /src/docs/components/pages/Introduction.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | import React from 'react'; 6 | import ReactMarkdown from "react-markdown"; // eslint-disable-line 7 | 8 | import FontIconPicker from '../../../js/FontIconPicker'; 9 | import intro from '../../guides/introduction.md'; 10 | import * as iconDefs from '../../helpers/iconDefs'; 11 | import codeRenderer from '../CodeBlock'; 12 | 13 | class Introduction extends React.Component { 14 | state = { 15 | vFontAwesome: ['fab fa-accessible-icon', 'fas fa-rss'], 16 | vIcoMoon: 57571, 17 | }; 18 | 19 | handleFontAwesome = values => { 20 | this.setState({ vFontAwesome: values }); 21 | }; 22 | 23 | handleIcoMoon = value => { 24 | this.setState({ vIcoMoon: value }); 25 | }; 26 | 27 | render() { 28 | return ( 29 |
30 |
31 | 32 | 36 | 37 |

React FontIconPicker

38 |

39 | 40 | codecov 44 | {' '} 45 | 46 | Build Status 50 | {' '} 51 | 52 | jest 56 | {' '} 57 | 58 | npm version 63 | {' '} 64 | 65 | peerDependencies Status 69 | {' '} 70 | 71 | GitHub license 75 | 76 |

77 |
78 | 86 | 95 |
96 |
97 | 104 |
105 | ); 106 | } 107 | } 108 | 109 | export default Introduction; 110 | -------------------------------------------------------------------------------- /__tests__/unit/FontIconPicker.unit.test.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import { shallow, mount } from 'enzyme'; 8 | 9 | import FontIconPicker from '../../src/js/components/FontIconPicker'; 10 | import * as iconDefs from '../../src/docs/helpers/iconDefs'; 11 | 12 | describe('FontIconPicker Component', () => { 13 | const { Others: [valOne, valTwo] } = iconDefs.fontelloIcons; 14 | const onChangeCBSingle = jest.fn(); 15 | const onChangeCBMulti = jest.fn(); 16 | const propsMulti = { 17 | icons: iconDefs.fontelloIcons.Others, 18 | onChange: onChangeCBMulti, 19 | value: [valOne, valTwo], 20 | isMulti: true, 21 | }; 22 | const propsSingle = { 23 | icons: iconDefs.fontelloIcons.Others, 24 | onChange: onChangeCBSingle, 25 | value: valOne, 26 | isMulti: false, 27 | renderUsing: 'class', 28 | }; 29 | describe('On Single Picker Mode', () => { 30 | test('calls onChange on handleChangeValue', () => { 31 | const wrapper = shallow(); 32 | wrapper.instance().handleChangeValue(valOne); 33 | expect(onChangeCBSingle).toHaveBeenLastCalledWith(''); 34 | wrapper.instance().handleChangeValue(valTwo); 35 | expect(onChangeCBSingle).toHaveBeenLastCalledWith(valTwo); 36 | }); 37 | test('calls onChange on handleDeleteValue', () => { 38 | const cb = jest.fn(); 39 | const wrapper = shallow( 40 | , 41 | ); 42 | wrapper.instance().handleDeleteValue(valOne); 43 | expect(cb).toHaveBeenLastCalledWith(''); 44 | }); 45 | }); 46 | describe('On Multi Picker Mode', () => { 47 | test('calls onChange on handleChangeValue', () => { 48 | const wrapper = shallow(); 49 | wrapper.instance().handleChangeValue(valOne); 50 | expect(onChangeCBMulti).toHaveBeenLastCalledWith( 51 | expect.arrayContaining([valTwo]), 52 | ); 53 | wrapper.instance().handleChangeValue(valTwo); 54 | expect(onChangeCBMulti).toHaveBeenLastCalledWith( 55 | expect.arrayContaining([]), 56 | ); 57 | }); 58 | test('calls onChange on handleDeleteValue', () => { 59 | const cb = jest.fn(); 60 | const wrapper = shallow( 61 | , 62 | ); 63 | wrapper.instance().handleDeleteValue(valOne); 64 | expect(cb).toHaveBeenLastCalledWith( 65 | expect.arrayContaining([valTwo]), 66 | ); 67 | wrapper.instance().handleDeleteValue(valTwo); 68 | expect(cb).toHaveBeenLastCalledWith(expect.arrayContaining([])); 69 | }); 70 | }); 71 | test('handleChangePage sets state currentPage', () => { 72 | const wrapper = shallow(); 73 | wrapper.instance().handleChangePage(1); 74 | expect(wrapper.state('currentPage')).toBe(1); 75 | }); 76 | test('handleChangeCategory sets state currentPage and currentCategory', () => { 77 | const wrapper = shallow(); 78 | wrapper.instance().handleChangePage(2); 79 | expect(wrapper.state('currentPage')).toBe(2); 80 | wrapper.instance().handleChangeCategory(1); 81 | expect(wrapper.state('currentPage')).toBe(0); 82 | expect(wrapper.state('currentCategory')).toBe(1); 83 | }); 84 | test('handleChangeSearch sets state currentPage and currentSearch', () => { 85 | const wrapper = shallow(); 86 | wrapper.instance().handleChangePage(2); 87 | expect(wrapper.state('currentPage')).toBe(2); 88 | wrapper.instance().handleChangeSearch('foo'); 89 | expect(wrapper.state('currentPage')).toBe(0); 90 | expect(wrapper.state('currentSearch')).toBe('foo'); 91 | }); 92 | }); 93 | -------------------------------------------------------------------------------- /src/docs/guides/installation.md: -------------------------------------------------------------------------------- 1 | ## Installation and Setup 2 | 3 | The preferred way to install [`FontIconPicker`](https://www.npmjs.com/package/@fonticonpicker/react-fonticonpicker) is 4 | through npm. You are probably using it anyway for your project. So add fonticonpicker as your dependency. 5 | 6 | ### Install using NPM 7 | 8 | ```bash 9 | npm install --save @fonticonpicker/react-fonticonpicker 10 | ``` 11 | 12 | Now you can import the component class and styles. 13 | 14 | #### ES6 Style Import 15 | 16 | ```js 17 | import FontIconPicker from '@fonticonpicker/react-fonticonpicker'; 18 | ``` 19 | 20 | #### ES5 Style Import 21 | 22 | ```js 23 | const FontIconPicker = require('@fonticonpicker/react-fonticonpicker'); 24 | ``` 25 | 26 | #### Import the css files 27 | 28 | If you are using [webpack](https://webpack.js.org) with style loader, then you 29 | can easily do something like 30 | 31 | ```js 32 | import '@fonticonpicker/react-fonticonpicker/dist/fonticonpicker.base-theme.react.css'; 33 | import '@fonticonpicker/react-fonticonpicker/dist/fonticonpicker.material-theme.react.css'; 34 | ``` 35 | 36 | pointing to the relative path of `node_modules` directory. 37 | 38 | If you are not using webpack, then you simply include the css file in your build 39 | tool. For example, in your application's main `scss` file: 40 | 41 | ```scss 42 | @import './node_modules/@fonticonpicker/react-fonticonpicker/dist/fonticonpicker.base-theme.react.css'; 43 | @import './node_modules/@fonticonpicker/react-fonticonpicker/dist/fonticonpicker.material-theme.react.css'; 44 | ``` 45 | 46 | Or if you want to use the style files directly: 47 | 48 | ```html 49 | 50 | 51 | ``` 52 | 53 | As you have noticed, there are two CSS files required: 54 | 55 | 1. `base-theme`: Includes the basic layout style for fonticonpicker to work. 56 | It does not have any coloring or theming. 57 | 2. `material-theme`: Includes theming for all the styles in this demo. 58 | 59 | ### Use with CDN 60 | 61 | For some reason, if you'd prefer the CDN, then it is available at [unpkg.com](https://unpkg.com/@fonticonpicker/react-fonticonpicker/dist/). 62 | 63 | Place them in your HTML document, along with UMD builds of peer dependencies. 64 | 65 | ```html 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | ``` 77 | 78 | ### Download Source 79 | 80 | We distribute production version of source file through [github releases](https://github.com/fontIconPicker/react-fonticonpicker/releases). Head over there 81 | and download `fonticonpicker.react.zip` file. 82 | 83 | Now extract the zip and use the source as you would use from CDN. 84 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@fonticonpicker/react-fonticonpicker", 3 | "version": "1.2.0", 4 | "description": "A react component to show a picker element to select font icons or SVG.", 5 | "main": "dist/fonticonpicker.react.js", 6 | "directories": { 7 | "doc": "docs" 8 | }, 9 | "scripts": { 10 | "test": "eslint src/js/** src/docs/components/** src/docs/helpers/** && stylelint src/scss/** && jest", 11 | "start": "webpack-dev-server --hot --config webpack.dev.config.js --host 0.0.0.0 --open", 12 | "docs": "webpack --config webpack.doc.config.js", 13 | "build": "webpack --config webpack.config.js && node scripts/cleanupDist.js", 14 | "prepare": "webpack --config webpack.config.js && node scripts/cleanupDist.js" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/fontIconPicker/react-fonticonpicker.git" 19 | }, 20 | "keywords": [ 21 | "react", 22 | "react-component", 23 | "fonticonpicker", 24 | "svgpicker", 25 | "iconpicker" 26 | ], 27 | "author": "Swashata Ghosh (https://swashata.me)", 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/fontIconPicker/react-fonticonpicker/issues" 31 | }, 32 | "homepage": "https://github.com/fontIconPicker/react-fonticonpicker#readme", 33 | "peerDependencies": { 34 | "react": "^16.3.0", 35 | "react-dom": "^16.3.0", 36 | "classnames": "^2.2.5", 37 | "prop-types": "^15.6.1", 38 | "react-transition-group": "^2.3.0" 39 | }, 40 | "devDependencies": { 41 | "@babel/cli": "^7.0.0-beta.42", 42 | "@babel/core": "^7.0.0-beta.42", 43 | "@babel/plugin-proposal-class-properties": "^7.0.0-beta.42", 44 | "@babel/preset-env": "^7.0.0-beta.42", 45 | "@babel/preset-react": "^7.0.0-beta.42", 46 | "autoprefixer": "^8.2.0", 47 | "babel-core": "^7.0.0-bridge.0", 48 | "babel-eslint": "^8.2.2", 49 | "babel-jest": "^22.4.3", 50 | "babel-loader": "^8.0.0-beta.2", 51 | "classnames": "^2.2.5", 52 | "clean-webpack-plugin": "^0.1.19", 53 | "copy-webpack-plugin": "^4.5.1", 54 | "css-loader": "^0.28.11", 55 | "cssnano": "^3.10.0", 56 | "enzyme": "^3.3.0", 57 | "enzyme-adapter-react-16": "^1.1.1", 58 | "enzyme-to-json": "^3.3.3", 59 | "eslint": "^4.19.1", 60 | "eslint-config-airbnb": "^16.1.0", 61 | "eslint-config-prettier": "^2.9.0", 62 | "eslint-loader": "^2.0.0", 63 | "eslint-plugin-import": "^2.9.0", 64 | "eslint-plugin-jest": "^21.15.0", 65 | "eslint-plugin-jsx-a11y": "^6.0.3", 66 | "eslint-plugin-prettier": "^2.6.0", 67 | "eslint-plugin-react": "^7.7.0", 68 | "extract-text-webpack-plugin": "^4.0.0-beta.0", 69 | "favicons-webpack-plugin": "0.0.8", 70 | "file-loader": "^1.1.11", 71 | "hamburgers": "^0.9.3", 72 | "html-webpack-inline-svg-plugin": "^1.2.4", 73 | "html-webpack-plugin": "^3.1.0", 74 | "jest": "^22.4.3", 75 | "node-sass": "^4.9.4", 76 | "normalize.css": "^8.0.0", 77 | "postcss-loader": "^2.1.3", 78 | "prettier": "1.11.1", 79 | "prop-types": "^15.6.1", 80 | "raw-loader": "^0.5.1", 81 | "react": "^16.3.0", 82 | "react-dom": "^16.3.0", 83 | "react-hot-loader": "^4.0.0", 84 | "react-markdown": "^3.3.0", 85 | "react-router-dom": "^4.2.2", 86 | "react-router-transition": "^1.2.1", 87 | "react-syntax-highlighter": "^7.0.2", 88 | "react-transition-group": "^2.3.0", 89 | "sass-loader": "^6.0.7", 90 | "style-loader": "^0.20.3", 91 | "stylelint": "^9.2.0", 92 | "stylelint-config-prettier": "^3.0.4", 93 | "stylelint-config-recommended-scss": "^3.2.0", 94 | "stylelint-scss": "^3.0.0", 95 | "webpack": "^4.4.1", 96 | "webpack-bundle-analyzer": "^2.11.1", 97 | "webpack-cli": "^2.0.13", 98 | "webpack-dev-server": "^3.1.1" 99 | }, 100 | "dependencies": {}, 101 | "publishConfig": { 102 | "access": "public" 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); // eslint-disable-line // eslint-disable-line 3 | const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); // eslint-disable-line 4 | const CleanWebpackPlugin = require('clean-webpack-plugin'); // eslint-disable-line 5 | const webpack = require('webpack'); // eslint-disable-line 6 | const pkg = require('./package.json'); 7 | 8 | const banner = ` 9 | React FontIconPicker 10 | 11 | React Component to show a picker element to pick font-icons & svg 12 | 13 | @author Swashata Ghosh 14 | @version ${pkg.version} 15 | @link https://github.com/fontIconPicker/react-fonticonpicker 16 | @license MIT 17 | 18 | Copyright (c) ${new Date().getFullYear()} Swashata Ghosh 19 | 20 | This software is released under the MIT License. 21 | https://opensource.org/licenses/MIT 22 | `; 23 | const addBanner = new webpack.BannerPlugin({ 24 | banner, 25 | raw: false, 26 | entryOnly: true, 27 | include: /\.(js|jsx|css)$/, 28 | }); 29 | const extractSass = new ExtractTextPlugin({ 30 | filename: 'fonticonpicker.[name].react.css', 31 | }); 32 | 33 | module.exports = { 34 | entry: { 35 | fonticonpicker: path.join(__dirname, 'src/js/FontIconPicker.js'), 36 | 'base-theme': path.join(__dirname, 'src/js/ThemeBase.js'), 37 | 'material-theme': path.join(__dirname, 'src/js/ThemeMaterial.js'), 38 | }, 39 | output: { 40 | path: path.join(__dirname, 'dist'), 41 | filename: '[name].react.js', 42 | library: 'FontIconPicker', 43 | libraryExport: 'default', 44 | libraryTarget: 'umd', 45 | }, 46 | devtool: 'source-map', 47 | externals: { 48 | react: { 49 | commonjs: 'react', 50 | commonjs2: 'react', 51 | amd: 'react', 52 | root: 'React', 53 | }, 54 | 'react-dom': { 55 | commonjs: 'react-dom', 56 | commonjs2: 'react-dom', 57 | amd: 'react-dom', 58 | root: 'ReactDOM', 59 | }, 60 | classnames: { 61 | commonjs: 'classnames', 62 | commonjs2: 'classnames', 63 | amd: 'classnames', 64 | root: 'classNames', 65 | }, 66 | 'prop-types': { 67 | commonjs: 'prop-types', 68 | commonjs2: 'prop-types', 69 | amd: 'prop-types', 70 | root: 'PropTypes', 71 | }, 72 | 'react-transition-group': { 73 | commonjs: 'react-transition-group', 74 | commonjs2: 'react-transition-group', 75 | amd: 'react-transition-group', 76 | root: 'ReactTransitionGroup', 77 | }, 78 | }, 79 | module: { 80 | rules: [ 81 | { 82 | test: /\.(js|jsx)$/, 83 | use: ['babel-loader'], 84 | exclude: /node_modules/, 85 | }, 86 | { 87 | test: /\.css$/, 88 | use: extractSass.extract({ 89 | fallback: 'style-loader', 90 | use: [ 91 | { 92 | loader: 'css-loader', 93 | options: { 94 | importLoaders: 1, 95 | sourceMap: true, 96 | }, 97 | }, 98 | { 99 | loader: 'postcss-loader', 100 | options: { 101 | sourceMap: true, 102 | }, 103 | }, 104 | ], 105 | }), 106 | }, 107 | { 108 | test: /\.scss$/, 109 | use: extractSass.extract({ 110 | fallback: 'style-loader', 111 | use: [ 112 | { 113 | loader: 'css-loader', 114 | options: { 115 | importLoaders: 1, 116 | sourceMap: true, 117 | }, 118 | }, 119 | { 120 | loader: 'postcss-loader', 121 | options: { 122 | sourceMap: true, 123 | }, 124 | }, 125 | { 126 | loader: 'sass-loader', 127 | options: { 128 | sourceMap: true, 129 | }, 130 | }, 131 | ], 132 | }), 133 | }, 134 | { 135 | test: /\.(woff|woff2|eot|ttf|otf|svg|png|jpg|gif)(\?v=\d+\.\d+\.\d+)?$/, 136 | use: [ 137 | { 138 | loader: 'file-loader', 139 | options: { 140 | name: '[name].[ext]', 141 | outputPath: 'assets/', 142 | }, 143 | }, 144 | ], 145 | }, 146 | ], 147 | }, 148 | plugins: [ 149 | new CleanWebpackPlugin(['dist']), 150 | addBanner, 151 | new UglifyJSPlugin({ 152 | sourceMap: true, 153 | }), 154 | extractSass, 155 | ], 156 | resolve: { 157 | extensions: ['.js', '.jsx'], 158 | }, 159 | mode: 'production', 160 | }; 161 | -------------------------------------------------------------------------------- /__tests__/snapshots/FontIconPicker.test.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import { mount } from 'enzyme'; 8 | 9 | import FontIconPicker from '../../src/js/components/FontIconPicker'; 10 | import FipButton from '../../src/js/components/FipButton'; 11 | 12 | const icons = { 13 | 'Web Applications': [ 14 | 57436, 15 | 57437, 16 | 57438, 17 | 57439, 18 | 57524, 19 | 57525, 20 | 57526, 21 | 57527, 22 | 57528, 23 | 57531, 24 | 57532, 25 | 57533, 26 | 57534, 27 | 57535, 28 | 57536, 29 | 57537, 30 | 57541, 31 | 57545, 32 | 57691, 33 | 57692, 34 | ], 35 | 'Business Icons': [ 36 | 57347, 37 | 57348, 38 | 57375, 39 | 57376, 40 | 57377, 41 | 57379, 42 | 57403, 43 | 57406, 44 | 57432, 45 | 57433, 46 | 57434, 47 | 57435, 48 | 57450, 49 | 57453, 50 | 57456, 51 | 57458, 52 | 57460, 53 | 57461, 54 | 57463, 55 | ], 56 | }; 57 | const iconSearch = { 58 | 'Web Applications': [ 59 | 'Box add', 60 | 'Box remove', 61 | 'Download', 62 | 'Upload', 63 | 'List', 64 | 'List 2', 65 | 'Numbered list', 66 | 'Menu', 67 | 'Menu 2', 68 | 'Cloud download', 69 | 'Cloud upload', 70 | 'Download 2', 71 | 'Upload 2', 72 | 'Download 3', 73 | 'Upload 3', 74 | 'Globe', 75 | 'Attachment', 76 | 'Bookmark', 77 | 'Embed', 78 | 'Code', 79 | ], 80 | 'Business Icons': [ 81 | 'Office', 82 | 'Newspaper', 83 | 'Book', 84 | 'Books', 85 | 'Library', 86 | 'Profile', 87 | 'Support', 88 | 'Address book', 89 | 'Cabinet', 90 | 'Drawer', 91 | 'Drawer 2', 92 | 'Drawer 3', 93 | 'Bubble', 94 | 'Bubble 2', 95 | 'User', 96 | 'User 2', 97 | 'User 3', 98 | 'User 4', 99 | 'Busy', 100 | ], 101 | }; 102 | const changeMock = jest.fn(); 103 | const [valOne, valTwo] = icons['Business Icons']; 104 | const propsDefault = { 105 | icons, 106 | search: iconSearch, 107 | theme: 'bluegrey', 108 | onChange: changeMock, 109 | renderUsing: 'data-icomoon', 110 | }; 111 | describe('Single Picker', () => { 112 | const propsMulti = { 113 | ...propsDefault, 114 | isMulti: true, 115 | value: [valOne, valTwo], 116 | }; 117 | test('With Category & Search', () => { 118 | const thisProps = { 119 | ...propsMulti, 120 | showCategory: true, 121 | showSearch: true, 122 | }; 123 | const wrapper = mount(); 124 | wrapper.find(FipButton).simulate('click'); 125 | expect(wrapper).toMatchSnapshot(); 126 | }); 127 | test('Without Category & With Search', () => { 128 | const thisProps = { 129 | ...propsMulti, 130 | showCategory: false, 131 | showSearch: true, 132 | }; 133 | const wrapper = mount(); 134 | wrapper.find(FipButton).simulate('click'); 135 | expect(wrapper).toMatchSnapshot(); 136 | }); 137 | test('Without Category & Search', () => { 138 | const thisProps = { 139 | ...propsMulti, 140 | showCategory: false, 141 | showSearch: false, 142 | }; 143 | const wrapper = mount(); 144 | wrapper.find(FipButton).simulate('click'); 145 | expect(wrapper).toMatchSnapshot(); 146 | }); 147 | }); 148 | describe('Multi Picker', () => { 149 | const propsSingle = { 150 | ...propsDefault, 151 | isMulti: false, 152 | value: valOne, 153 | }; 154 | test('With Category & Search', () => { 155 | const thisProps = { 156 | ...propsSingle, 157 | showCategory: true, 158 | showSearch: true, 159 | }; 160 | const wrapper = mount(); 161 | wrapper.find(FipButton).simulate('click'); 162 | expect(wrapper).toMatchSnapshot(); 163 | }); 164 | test('Without Category & With Search', () => { 165 | const thisProps = { 166 | ...propsSingle, 167 | showCategory: false, 168 | showSearch: true, 169 | }; 170 | const wrapper = mount(); 171 | wrapper.find(FipButton).simulate('click'); 172 | expect(wrapper).toMatchSnapshot(); 173 | }); 174 | test('Without Category & Search', () => { 175 | const thisProps = { 176 | ...propsSingle, 177 | showCategory: false, 178 | showSearch: false, 179 | }; 180 | const wrapper = mount(); 181 | wrapper.find(FipButton).simulate('click'); 182 | expect(wrapper).toMatchSnapshot(); 183 | }); 184 | }); 185 | -------------------------------------------------------------------------------- /__tests__/intg/01_default_value.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import { shallow } from 'enzyme'; 8 | 9 | import FontIconPicker from '../../src/js/FontIconPicker'; 10 | import * as iconDefs from '../../src/docs/helpers/iconDefs'; 11 | 12 | // Check internal value conversion 13 | describe('Default value', () => { 14 | describe('When Null Converts to', () => { 15 | test('string for single picker', () => { 16 | // callback to test the value 17 | const cb = jest.fn(); 18 | shallow( 19 | , 26 | ); 27 | // Check the initial value 28 | expect(cb).toHaveBeenCalledTimes(1); 29 | expect(cb.mock.calls[0][0]).toBe(''); 30 | }); 31 | test('array for multi picker', () => { 32 | // callback to test the value 33 | const cb = jest.fn(); 34 | shallow( 35 | , 42 | ); 43 | // Check the initial value 44 | expect(cb).toHaveBeenCalledTimes(1); 45 | expect(Array.isArray(cb.mock.calls[0][0])).toBe(true); 46 | expect(cb.mock.calls[0][0]).toHaveLength(0); 47 | }); 48 | }); 49 | 50 | describe('When Not Null Converts to', () => { 51 | test('string for single picker', () => { 52 | // callback to test the value 53 | const cb = jest.fn(); 54 | shallow( 55 | , 62 | ); 63 | // Check the initial value 64 | expect(cb).toHaveBeenCalledTimes(1); 65 | expect(cb.mock.calls[0][0]).toBe(''); 66 | }); 67 | test('array for multi picker', () => { 68 | // callback to test the value 69 | const cb = jest.fn(); 70 | shallow( 71 | , 78 | ); 79 | // Check the initial value 80 | expect(cb).toHaveBeenCalledTimes(1); 81 | expect(Array.isArray(cb.mock.calls[0][0])).toBe(true); 82 | expect(cb.mock.calls[0][0]).toHaveLength(0); 83 | }); 84 | }); 85 | 86 | describe('Calls onChange on Parent', () => { 87 | test('for single picker', () => { 88 | const cb = jest.fn(); 89 | shallow( 90 | , 97 | ); 98 | // Check the initial value 99 | expect(cb).toHaveBeenCalledTimes(1); 100 | }); 101 | test('for multi picker', () => { 102 | const cb = jest.fn(); 103 | shallow( 104 | , 111 | ); 112 | // Check the initial value 113 | expect(cb).toHaveBeenCalledTimes(1); 114 | }); 115 | }); 116 | 117 | describe('Retains Correct Values', () => { 118 | test('for single picker', () => { 119 | const cb = jest.fn(); 120 | const value = iconDefs.icomoonIcons['Other Icons'][0]; 121 | shallow( 122 | , 129 | ); 130 | // Check the initial value 131 | expect(cb).toHaveBeenCalledTimes(1); 132 | expect(cb.mock.calls[0][0]).toBe(value); 133 | }); 134 | test('for multi picker', () => { 135 | const cb = jest.fn(); 136 | const value = iconDefs.icomoonIcons['Other Icons']; 137 | shallow( 138 | , 145 | ); 146 | // Check the initial value 147 | expect(cb).toHaveBeenCalledTimes(1); 148 | expect(cb.mock.calls[0][0]).toEqual(value); 149 | }); 150 | }); 151 | }); 152 | -------------------------------------------------------------------------------- /__tests__/unit/iconHelpers.test.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import * as iconHelpers from '../../src/js/helpers/iconHelpers'; 7 | 8 | describe('flattenPossiblyCategorizedSource', () => { 9 | test('is a pure function', () => { 10 | const source = { 11 | Foo: [1, 2, 3], 12 | Bar: [4, 5, 6], 13 | }; 14 | const result = iconHelpers.flattenPossiblyCategorizedSource( 15 | source, 16 | 'Foo', 17 | ); 18 | source.Foo = ['a', 'b', 'c']; 19 | expect(result).toEqual([1, 2, 3]); 20 | }); 21 | test('returns a copy of array', () => { 22 | const source = ['foo', 'bar']; 23 | expect(iconHelpers.flattenPossiblyCategorizedSource(source)).toEqual( 24 | source, 25 | ); 26 | }); 27 | test('returns full flattened object for null category', () => { 28 | const source = { 29 | Foo: [0, 1, 2], 30 | Bar: [3, 4, 5], 31 | }; 32 | expect( 33 | iconHelpers.flattenPossiblyCategorizedSource(source, null), 34 | ).toEqual([0, 1, 2, 3, 4, 5]); 35 | }); 36 | test('returns scoped source for category', () => { 37 | const source = { 38 | Foo: [0, 1, 2], 39 | Bar: [3, 4, 5], 40 | }; 41 | expect( 42 | iconHelpers.flattenPossiblyCategorizedSource(source, 'Foo'), 43 | ).toEqual([0, 1, 2]); 44 | }); 45 | test('returns empty array when category not found', () => { 46 | const source = { 47 | Foo: [0, 1, 2], 48 | Bar: [3, 4, 5], 49 | }; 50 | expect( 51 | iconHelpers.flattenPossiblyCategorizedSource(source, 'FooBar'), 52 | ).toHaveLength(0); 53 | }); 54 | }); 55 | 56 | describe('getPossibleCategories', () => { 57 | test('returns null if source is array', () => { 58 | const source = ['foo', 'bar']; 59 | expect(iconHelpers.getPossibleCategories(source)).toBeNull(); 60 | }); 61 | test('returns object keys as an array', () => { 62 | const source = { 63 | Foo: 'a', 64 | Bar: 'b', 65 | }; 66 | expect(iconHelpers.getPossibleCategories(source)).toEqual([ 67 | 'Foo', 68 | 'Bar', 69 | ]); 70 | }); 71 | }); 72 | 73 | describe('convertToHex', () => { 74 | const expected = String.fromCodePoint(65); 75 | test('converts number to code point', () => { 76 | expect(iconHelpers.convertToHex(65)).toBe(expected); 77 | }); 78 | test('converts string to code point', () => { 79 | expect(iconHelpers.convertToHex('65')).toBe(expected); 80 | }); 81 | }); 82 | 83 | describe('isArrayEqual', () => { 84 | test('tackles non arrays', () => { 85 | expect(iconHelpers.isArrayEqual('foo', ['a'])).toBeFalsy(); 86 | }); 87 | test('tackles random ordered arrays', () => { 88 | expect( 89 | iconHelpers.isArrayEqual(['Foo', 'Bar'], ['Bar', 'Foo']), 90 | ).toBeTruthy(); 91 | }); 92 | test('returns false when arrays not equal', () => { 93 | expect( 94 | iconHelpers.isArrayEqual(['foo', 'bar'], ['foo', 'notbar']), 95 | ).toBeFalsy(); 96 | }); 97 | }); 98 | 99 | describe('getSourceType', () => { 100 | test('returns null for null', () => { 101 | expect(iconHelpers.getSourceType(null)).toBe('null'); 102 | }); 103 | test('returns array for array', () => { 104 | expect(iconHelpers.getSourceType([])).toBe('array'); 105 | }); 106 | test('returns object for object', () => { 107 | expect(iconHelpers.getSourceType({})).toBe('object'); 108 | }); 109 | test('returns number for number', () => { 110 | expect(iconHelpers.getSourceType(1.1)).toBe('number'); 111 | }); 112 | test('returns string for string', () => { 113 | expect(iconHelpers.getSourceType('foo')).toBe('string'); 114 | }); 115 | }); 116 | 117 | describe('InvalidSourceException', () => { 118 | test('instantiates with proper variables', () => { 119 | const err = new iconHelpers.InvalidSourceException('array', 'object'); 120 | expect(err.toString()).toBe( 121 | 'Invalid Source Exception: Expected of type: object, found: array', 122 | ); 123 | }); 124 | }); 125 | 126 | describe('debounce', () => { 127 | let mutate = false; 128 | const mutator = () => { 129 | mutate = true; 130 | }; 131 | 132 | const watcher = () => 133 | new Promise(resolve => { 134 | setTimeout(() => { 135 | resolve(); 136 | }, 200); 137 | }); 138 | 139 | test('works properly', () => { 140 | iconHelpers.debounce(() => mutator(), 100)(); 141 | iconHelpers.debounce(() => mutator(), 100)(); 142 | iconHelpers.debounce(() => mutator(), 100)(); 143 | 144 | expect(mutate).toBe(false); 145 | 146 | return watcher().then(() => { 147 | expect(mutate).toBe(true); 148 | }); 149 | }); 150 | }); 151 | -------------------------------------------------------------------------------- /src/js/components/FipDropDown.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | 6 | import React from 'react'; 7 | import PropTypes from 'prop-types'; 8 | import FipCategory from './FipCategory'; 9 | import FipSearch from './FipSearch'; 10 | import FipIconContainer from './FipIconContainer'; 11 | import { getPossibleCategories } from '../helpers/iconHelpers'; 12 | 13 | class FipDropDown extends React.PureComponent { 14 | static propTypes = { 15 | isMulti: PropTypes.bool.isRequired, 16 | value: PropTypes.oneOfType([ 17 | PropTypes.number, 18 | PropTypes.string, 19 | PropTypes.arrayOf(PropTypes.any), 20 | ]).isRequired, 21 | currentCategory: PropTypes.number.isRequired, 22 | currentPage: PropTypes.number.isRequired, 23 | currentSearch: PropTypes.string.isRequired, 24 | icons: PropTypes.oneOfType([ 25 | PropTypes.arrayOf(PropTypes.number), 26 | PropTypes.arrayOf(PropTypes.string), 27 | PropTypes.objectOf( 28 | PropTypes.oneOfType([ 29 | PropTypes.arrayOf(PropTypes.number), 30 | PropTypes.arrayOf(PropTypes.string), 31 | ]), 32 | ), 33 | ]).isRequired, 34 | /* eslint-disable */ 35 | search: PropTypes.oneOfType([ 36 | PropTypes.object, 37 | PropTypes.arrayOf(PropTypes.string), 38 | ]), 39 | /* eslint-enable */ 40 | showCategory: PropTypes.bool.isRequired, 41 | showSearch: PropTypes.bool.isRequired, 42 | iconsPerPage: PropTypes.number.isRequired, 43 | allCatPlaceholder: PropTypes.string.isRequired, // eslint-disable-line 44 | searchPlaceholder: PropTypes.string.isRequired, // eslint-disable-line 45 | noIconPlaceholder: PropTypes.string.isRequired, // eslint-disable-line 46 | renderIcon: PropTypes.func.isRequired, 47 | handleChangeValue: PropTypes.func.isRequired, 48 | handleChangeCategory: PropTypes.func.isRequired, 49 | handleChangePage: PropTypes.func.isRequired, 50 | handleChangeSearch: PropTypes.func.isRequired, 51 | }; 52 | 53 | static defaultProps = { 54 | search: null, 55 | }; 56 | 57 | static getDerivedStateFromProps(nextProps) { 58 | // Get categories and flattened source 59 | let categories = getPossibleCategories(nextProps.icons); 60 | if (categories !== null) { 61 | categories = [nextProps.allCatPlaceholder, ...categories]; 62 | } 63 | // assign to the state 64 | // rest is handled by props 65 | return { categories, searchString: nextProps.currentSearch }; 66 | } 67 | 68 | constructor(props) { 69 | super(props); 70 | this.state = {}; 71 | } 72 | 73 | /** 74 | * Handle category change 75 | * 76 | * Sets internal state and also calls the parent app. 77 | */ 78 | handleCategory = event => { 79 | // Get the category 80 | let currentCategory = parseInt(event.target.value, 10); 81 | if (Number.isNaN(currentCategory)) { 82 | currentCategory = 0; 83 | } 84 | // call the external handler 85 | this.props.handleChangeCategory(currentCategory); 86 | 87 | // Also change the pagenumber to 0 88 | this.props.handleChangePage(0); 89 | }; 90 | 91 | handleSearch = event => { 92 | const currentSearch = event.target.value; 93 | // Change the state of the parent 94 | this.props.handleChangeSearch(currentSearch); 95 | }; 96 | 97 | render() { 98 | return ( 99 |
100 | {this.props.showSearch ? ( 101 | 106 | ) : null} 107 | 108 | {this.props.showCategory && 109 | this.state.categories && 110 | this.state.categories.length ? ( 111 | 116 | ) : null} 117 | 118 | 133 |
134 | ); 135 | } 136 | } 137 | 138 | export default FipDropDown; 139 | -------------------------------------------------------------------------------- /src/assets/fipicon/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IcoMoon Demo 6 | 7 | 8 | 9 | 10 | 11 |
12 |

Font Name: fontIconPicker (Glyphs: 4)

13 |
14 |
15 |

Grid Size: 14

16 |
17 |
18 | 19 | 20 | 21 | fipicon-angle-left 22 |
23 |
24 | 25 | 26 |
27 |
28 | liga: 29 | 30 |
31 |
32 |
33 |
34 | 35 | 36 | 37 | fipicon-angle-right 38 |
39 |
40 | 41 | 42 |
43 |
44 | liga: 45 | 46 |
47 |
48 |
49 |
50 | 51 | 52 | 53 | fipicon-angle-up 54 |
55 |
56 | 57 | 58 |
59 |
60 | liga: 61 | 62 |
63 |
64 |
65 |
66 | 67 | 68 | 69 | fipicon-angle-down 70 |
71 |
72 | 73 | 74 |
75 |
76 | liga: 77 | 78 |
79 |
80 |
81 | 82 | 83 |
84 |

Font Test Drive

85 | 90 | 92 |
  93 |
94 |
95 | 96 |
97 |

Generated by IcoMoon

98 |
99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /src/docs/assets/superhero.css: -------------------------------------------------------------------------------- 1 | .svg_004-green_lantern, 2 | .svg_003-spiderman, 3 | .svg_005-hawkeye, 4 | .svg_007-thor, 5 | .svg_006-captain_america, 6 | .svg_009-green_arrow, 7 | .svg_008-loki, 8 | .svg_014-wonder_woman, 9 | .svg_017-punisher, 10 | .svg_016-flash, 11 | .svg_019-bpdr, 12 | .svg_020-joker, 13 | .svg_022-two-face, 14 | .svg_025-xavier, 15 | .svg_024-magneto, 16 | .svg_027-human_torch, 17 | .svg_030-dr_manhattan, 18 | .svg_031-rorschach, 19 | .svg_033-the_riddler, 20 | .svg_032-venom, 21 | .svg_035-spawn, 22 | .svg_034-aquaman, 23 | .svg_036-ghost_rider, 24 | .svg_037-rocketeer, 25 | .svg_038-the_atom, 26 | .svg_039-nick_fury, 27 | .svg_040-cyclops, 28 | .svg_042-deadpool, 29 | .svg_044-solar, 30 | .svg_043-dr_spectrum, 31 | .svg_045-black_widow, 32 | .svg_046-iron_fist, 33 | .svg_049-tmnt, 34 | .svg_050-the_spirit, 35 | .svg_051-dr_octopus, 36 | .svg_055-deathstroke, 37 | .svg_053-gambit, 38 | .svg_052-red_skull, 39 | .svg_054-scarecrow, 40 | .svg_056-brainiac, 41 | .svg_059-black_adam, 42 | .svg_058-karnak, 43 | .svg_060-penguin, 44 | .svg_061-shredder, 45 | .svg_064-bane, 46 | .svg_069-penguins_umbrella, 47 | .svg_070-starlords_element_gun, 48 | .svg_073-lukes_2nd_lightsaber, 49 | .svg_075-green_goblins_pumpkin, 50 | .svg_077-elektras_sais, 51 | .svg_080-jokers_buzzer, 52 | .svg_081-leonardos_katana, 53 | .svg_085-freeze_ray_gun, 54 | .svg_086-new_freeze_ray_gun, 55 | .svg_089-ghost_riders_hellfire_chain, 56 | .svg_090-dr_stranges_eye_of_agamotto, 57 | .svg_091-gl_power_ring, 58 | .svg_092-the_phantoms_ring, 59 | .svg_095-dr_fate, 60 | .svg_098-avengers, 61 | .svg_096-x-men_logo, 62 | .svg_097-fantastic_4 { 63 | width: 460px; 64 | height: 460px; 65 | } 66 | .svg_002-robin { 67 | width: 452.082px; 68 | height: 452.082px; 69 | } 70 | .svg_001-batman, 71 | .svg_021-two-face_coin { 72 | width: 460.001px; 73 | height: 460.001px; 74 | } 75 | .svg_011-superman { 76 | width: 442px; 77 | height: 442px; 78 | } 79 | .svg_010-hulk { 80 | width: 450px; 81 | height: 450px; 82 | } 83 | .svg_012-daredevil { 84 | width: 380.9px; 85 | height: 380.9px; 86 | } 87 | .svg_015-catwoman { 88 | width: 387.688px; 89 | height: 387.688px; 90 | } 91 | .svg_013-wolverine { 92 | width: 429.975px; 93 | height: 429.975px; 94 | } 95 | .svg_018-ironman { 96 | width: 467.289px; 97 | height: 467.289px; 98 | } 99 | .svg_023-silver_surfer { 100 | width: 460.005px; 101 | height: 460.005px; 102 | } 103 | .svg_026-thing { 104 | width: 452.486px; 105 | height: 452.486px; 106 | } 107 | .svg_029-infinity_gauntlet { 108 | width: 459.94px; 109 | height: 459.94px; 110 | } 111 | .svg_028-mr_fantastic { 112 | width: 490.178px; 113 | height: 490.178px; 114 | } 115 | .svg_041-judge_dredd { 116 | width: 459.493px; 117 | height: 459.493px; 118 | } 119 | .svg_047-poison_ivy { 120 | width: 460.002px; 121 | height: 460.002px; 122 | } 123 | .svg_048-dr_doom { 124 | width: 461.727px; 125 | height: 461.727px; 126 | } 127 | .svg_057-moon_knight { 128 | width: 452.014px; 129 | height: 452.014px; 130 | } 131 | .svg_063-superman-hair { 132 | width: 459.974px; 133 | height: 459.974px; 134 | } 135 | .svg_062-hawkeye { 136 | width: 464.773px; 137 | height: 464.773px; 138 | } 139 | .svg_065-adamantium_shield { 140 | width: 454px; 141 | height: 454px; 142 | } 143 | .svg_066-daredevil_glasses { 144 | width: 444px; 145 | height: 444px; 146 | } 147 | .svg_067-mutagen { 148 | width: 442.001px; 149 | height: 442.001px; 150 | } 151 | .svg_071-hemans_power_sword { 152 | width: 459.994px; 153 | height: 459.994px; 154 | } 155 | .svg_068-hellboys_good_samaritan { 156 | width: 459.975px; 157 | height: 459.975px; 158 | } 159 | .svg_072-lukes_1st_lightsaber { 160 | width: 498.254px; 161 | height: 498.254px; 162 | } 163 | .svg_074-daredevils_billy_cub { 164 | width: 459.98px; 165 | height: 459.98px; 166 | } 167 | .svg_076-kryptonita { 168 | width: 441.988px; 169 | height: 441.988px; 170 | } 171 | .svg_078-bow_and_arrow { 172 | width: 459.993px; 173 | height: 459.993px; 174 | } 175 | .svg_079-jokers_gun { 176 | width: 506.271px; 177 | height: 506.271px; 178 | } 179 | .svg_082-michelangelos_nunchakus { 180 | width: 460.032px; 181 | height: 460.032px; 182 | } 183 | .svg_083-donatellos_bo_staff { 184 | width: 460.037px; 185 | height: 460.037px; 186 | } 187 | .svg_084-raphaels_sais { 188 | width: 470.199px; 189 | height: 470.199px; 190 | } 191 | .svg_088-mjolnir { 192 | width: 460.006px; 193 | height: 460.006px; 194 | } 195 | .svg_087-adamantium_claws { 196 | width: 472.002px; 197 | height: 472.002px; 198 | } 199 | .svg_093-batarang { 200 | width: 441.996px; 201 | height: 441.996px; 202 | } 203 | .svg_094-batmans_utility_belt { 204 | width: 482px; 205 | height: 482px; 206 | } 207 | .svg_099-spiderman-spider { 208 | width: 470.002px; 209 | height: 470.002px; 210 | } 211 | .svg_100-spiderman-web { 212 | width: 471px; 213 | height: 471px; 214 | } 215 | -------------------------------------------------------------------------------- /webpack.doc.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const HtmlWebpackPlugin = require('html-webpack-plugin'); // eslint-disable-line 3 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); // eslint-disable-line 4 | const CleanWebpackPlugin = require('clean-webpack-plugin'); // eslint-disable-line 5 | const FaviconsWebpackPlugin = require('favicons-webpack-plugin'); // eslint-disable-line 6 | const HtmlWebpackInlineSVGPlugin = require('html-webpack-inline-svg-plugin'); // eslint-disable-line 7 | const CopyWebpackPlugin = require('copy-webpack-plugin'); // eslint-disable-line 8 | const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); 9 | const webpack = require('webpack'); // eslint-disable-line 10 | const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); // eslint-disable-line 11 | const pkg = require('./package.json'); 12 | 13 | const banner = ` 14 | React FontIconPicker 15 | 16 | React Component to show a picker element to pick font-icons & svg 17 | 18 | @author Swashata Ghosh 19 | @version ${pkg.version} 20 | @link https://github.com/fontIconPicker/react-fonticonpicker 21 | @license MIT 22 | 23 | Copyright (c) ${new Date().getFullYear()} Swashata Ghosh 24 | 25 | This software is released under the MIT License. 26 | https://opensource.org/licenses/MIT 27 | `; 28 | 29 | const addBanner = new webpack.BannerPlugin({ 30 | banner, 31 | raw: false, 32 | entryOnly: true, 33 | include: /\.(js|jsx|css)$/, 34 | }); 35 | const extractSass = new ExtractTextPlugin({ 36 | filename: 'style-[name].css', 37 | }); 38 | 39 | module.exports = { 40 | entry: path.join(__dirname, 'src/docs/index.jsx'), 41 | output: { 42 | path: path.join(__dirname, 'docs'), 43 | filename: 'bundle-[name].js', 44 | publicPath: 'https://fonticonpicker.github.io/react-fonticonpicker/', 45 | }, 46 | devtool: 'source-map', 47 | module: { 48 | rules: [ 49 | { 50 | test: /\.(js|jsx)$/, 51 | use: ['babel-loader'], 52 | exclude: /node_modules/, 53 | }, 54 | { 55 | test: /\.css$/, 56 | use: extractSass.extract({ 57 | fallback: 'style-loader', 58 | use: [ 59 | { 60 | loader: 'css-loader', 61 | options: { 62 | importLoaders: 1, 63 | sourceMap: true, 64 | }, 65 | }, 66 | { 67 | loader: 'postcss-loader', 68 | options: { 69 | sourceMap: true, 70 | }, 71 | }, 72 | ], 73 | }), 74 | }, 75 | { 76 | test: /\.scss$/, 77 | use: extractSass.extract({ 78 | fallback: 'style-loader', 79 | use: [ 80 | { 81 | loader: 'css-loader', 82 | options: { 83 | importLoaders: 1, 84 | sourceMap: true, 85 | }, 86 | }, 87 | { 88 | loader: 'postcss-loader', 89 | options: { 90 | sourceMap: true, 91 | }, 92 | }, 93 | { 94 | loader: 'sass-loader', 95 | options: { 96 | sourceMap: true, 97 | }, 98 | }, 99 | ], 100 | }), 101 | }, 102 | { 103 | test: /\.(woff|woff2|eot|ttf|otf|svg|png|jpg|gif)(\?v=\d+\.\d+\.\d+)?$/, 104 | use: [ 105 | { 106 | loader: 'file-loader', 107 | options: { 108 | name: 'asset-[hash].[ext]', 109 | outputPath: 'assets/', 110 | }, 111 | }, 112 | ], 113 | }, 114 | { 115 | test: /\.(md)$/, 116 | use: 'raw-loader', 117 | }, 118 | ], 119 | }, 120 | plugins: [ 121 | new CleanWebpackPlugin(['docs']), 122 | new FaviconsWebpackPlugin({ 123 | logo: path.join(__dirname, 'src/docs/picker.png'), 124 | prefix: 'favicons/', 125 | background: 'transparent', 126 | theme_color: '#E3F2FD', 127 | title: 'React fontIconPicker', 128 | }), 129 | addBanner, 130 | new UglifyJSPlugin({ 131 | sourceMap: true, 132 | }), 133 | new HtmlWebpackPlugin({ 134 | template: path.join(__dirname, 'src/docs/index.html'), 135 | svgoConfig: { 136 | removeHiddenElems: false, 137 | }, 138 | }), 139 | new HtmlWebpackInlineSVGPlugin({ 140 | runPreEmit: true, 141 | }), 142 | extractSass, 143 | new CopyWebpackPlugin([ 144 | { 145 | from: './src/docs/404.html', 146 | to: './404.html', 147 | }, 148 | { 149 | from: './fonticonpicker.png', 150 | to: './fonticonpicker.png', 151 | }, 152 | ]), 153 | new BundleAnalyzerPlugin({ 154 | analyzerMode: 'static', 155 | }), 156 | ], 157 | resolve: { 158 | extensions: ['.js', '.jsx'], 159 | }, 160 | optimization: { 161 | splitChunks: { 162 | chunks: 'async', 163 | minSize: 30000, 164 | minChunks: 1, 165 | maxAsyncRequests: 5, 166 | maxInitialRequests: 3, 167 | automaticNameDelimiter: '~', 168 | name: true, 169 | cacheGroups: { 170 | vendors: { 171 | test: /[\\/]node_modules[\\/]/, 172 | name: 'vendors', 173 | chunks: 'all', 174 | }, 175 | library: { 176 | test: /[\\/]src\/js[\\/]/, 177 | name: 'library', 178 | chunks: 'all', 179 | }, 180 | docs: { 181 | test: /[\\/]src\/docs[\\/]/, 182 | name: 'docs', 183 | chunks: 'all', 184 | }, 185 | }, 186 | }, 187 | }, 188 | mode: 'production', 189 | }; 190 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | # Contributing 9 | 10 | When contributing to this repository, please first discuss the change you wish to make via issue, 11 | email, or any other method with the owners of this repository before making a change. 12 | 13 | Please note we have a code of conduct, please follow it in all your interactions with the project. 14 | 15 | ## How to Setup 16 | 17 | The [README](README.md#development-environment) has a comprehensive guide on how to setup this project 18 | locally on your machine. A `TL;DR` version is 19 | 20 | 1. Install Nodejs >= 9 ( 8 may also work ). 21 | 2. Clone this repo. 22 | 3. Run `npm install` on the project folder. This will set things up. 23 | 4. Run `npm run serve` to see all examples and ui in the browser. 24 | 5. Edit files and make changes in `src` directory. Your browser will hot relaod. 25 | 6. Write down tests for new features. 26 | 27 | ## Pull Request Process 28 | 29 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a 30 | build. 31 | 2. Update the README.md with details of changes to the interface, this includes new 32 | variables, APIs etc. 33 | 3. Increase the version numbers in any examples files and the README.md to the new version that this 34 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 35 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you 36 | do not have permission to do that, you may request the second reviewer to merge it for you. 37 | 38 | ## Code of Conduct 39 | 40 | ### Our Pledge 41 | 42 | In the interest of fostering an open and welcoming environment, we as 43 | contributors and maintainers pledge to making participation in our project and 44 | our community a harassment-free experience for everyone, regardless of age, body 45 | size, disability, ethnicity, gender identity and expression, level of experience, 46 | nationality, personal appearance, race, religion, or sexual identity and 47 | orientation. 48 | 49 | ### Our Standards 50 | 51 | Examples of behavior that contributes to creating a positive environment 52 | include: 53 | 54 | * Using welcoming and inclusive language 55 | * Being respectful of differing viewpoints and experiences 56 | * Gracefully accepting constructive criticism 57 | * Focusing on what is best for the community 58 | * Showing empathy towards other community members 59 | 60 | Examples of unacceptable behavior by participants include: 61 | 62 | * The use of sexualized language or imagery and unwelcome sexual attention or 63 | advances 64 | * Trolling, insulting/derogatory comments, and personal or political attacks 65 | * Public or private harassment 66 | * Publishing others' private information, such as a physical or electronic 67 | address, without explicit permission 68 | * Other conduct which could reasonably be considered inappropriate in a 69 | professional setting 70 | 71 | ### Our Responsibilities 72 | 73 | Project maintainers are responsible for clarifying the standards of acceptable 74 | behavior and are expected to take appropriate and fair corrective action in 75 | response to any instances of unacceptable behavior. 76 | 77 | Project maintainers have the right and responsibility to remove, edit, or 78 | reject comments, commits, code, wiki edits, issues, and other contributions 79 | that are not aligned to this Code of Conduct, or to ban temporarily or 80 | permanently any contributor for other behaviors that they deem inappropriate, 81 | threatening, offensive, or harmful. 82 | 83 | ### Scope 84 | 85 | This Code of Conduct applies both within project spaces and in public spaces 86 | when an individual is representing the project or its community. Examples of 87 | representing a project or community include using an official project e-mail 88 | address, posting via an official social media account, or acting as an appointed 89 | representative at an online or offline event. Representation of a project may be 90 | further defined and clarified by project maintainers. 91 | 92 | ### Enforcement 93 | 94 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 95 | reported by contacting the project team at [swashata4u at gmail dot com]. All 96 | complaints will be reviewed and investigated and will result in a response that 97 | is deemed necessary and appropriate to the circumstances. The project team is 98 | obligated to maintain confidentiality with regard to the reporter of an incident. 99 | Further details of specific enforcement policies may be posted separately. 100 | 101 | Project maintainers who do not follow or enforce the Code of Conduct in good 102 | faith may face temporary or permanent repercussions as determined by other 103 | members of the project's leadership. 104 | 105 | ### Attribution 106 | 107 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 108 | available at [http://contributor-covenant.org/version/1/4][version] 109 | 110 | [homepage]: http://contributor-covenant.org 111 | [version]: http://contributor-covenant.org/version/1/4/ 112 | -------------------------------------------------------------------------------- /src/docs/components/pages/BasicUsage.jsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Swashata Ghosh 2 | // 3 | // This software is released under the MIT License. 4 | // https://opensource.org/licenses/MIT 5 | import React from 'react'; 6 | import ReactMarkdown from 'react-markdown'; 7 | import { Route, NavLink } from 'react-router-dom'; 8 | import { AnimatedSwitch, spring } from 'react-router-transition'; 9 | import presets from 'react-motion/lib/spring'; 10 | 11 | import FontIconPicker from '../../../js/FontIconPicker'; 12 | import * as iconDefs from '../../helpers/iconDefs'; 13 | import basicusage from '../../guides/basicusage.md'; 14 | import fipncp from '../../guides/usage-parts/1-fipncp.md'; 15 | import fipcp from '../../guides/usage-parts/2-fipcp.md'; 16 | import fipsmp from '../../guides/usage-parts/3-fipsmp.md'; 17 | import fipar from '../../guides/usage-parts/4-fipar.md'; 18 | import fipcr from '../../guides/usage-parts/5-fipcr.md'; 19 | import codeRenderer from '../CodeBlock'; 20 | import { fadeInUp } from '../../helpers/routeTransition'; 21 | 22 | const noop = () => {}; 23 | 24 | const FipNoCategory = () => ( 25 |
26 | Output: 27 | 33 |
34 | ); 35 | 36 | const FipCategory = () => ( 37 |
38 | Output: 39 | 45 |
46 | ); 47 | 48 | const FipPickers = () => ( 49 |
50 | Output: 51 | 57 | 63 |
64 | ); 65 | 66 | const FipAttribute = () => ( 67 |
68 | Output: 69 | 77 |
78 | ); 79 | 80 | const renderSVG = svg => ( 81 | 82 | 83 | 84 | ); 85 | const FipCustom = () => ( 86 |
87 | Output: 88 | 96 |
97 | ); 98 | 99 | const FipNCP = () => ( 100 |
101 | 102 | 109 |
110 | ); 111 | const FipCP = () => ( 112 |
113 | 114 | 121 |
122 | ); 123 | const FipSMP = () => ( 124 |
125 | 126 | 133 |
134 | ); 135 | const FipAR = () => ( 136 |
137 | 138 | 145 |
146 | ); 147 | const FipCR = () => ( 148 |
149 | 150 | 157 |
158 | ); 159 | 160 | const links = { 161 | fipncp: { 162 | title: 'Non Categorized Picker', 163 | component: FipNCP, 164 | path: '', 165 | }, 166 | fipcp: { 167 | title: 'Categorized Picker', 168 | component: FipCP, 169 | path: 'fip-non-categorized-picker/', 170 | }, 171 | fipsmp: { 172 | title: 'Single/Multi Picker', 173 | component: FipSMP, 174 | path: 'fip-types-of-pickers/', 175 | }, 176 | fipar: { 177 | title: 'Attribute Rendering', 178 | component: FipAR, 179 | path: 'fip-attribute-rendering/', 180 | }, 181 | fipcr: { 182 | title: 'Custom Rendering SVG', 183 | component: FipCR, 184 | path: 'fip-custom-rendering/', 185 | }, 186 | }; 187 | 188 | const BasicUsage = () => ( 189 |
190 | 197 | 198 |

Examples with Code

199 |
200 | 213 |
214 | 221 | {Object.keys(links).map(key => ( 222 | 228 | ))} 229 | 230 |
231 | ); 232 | 233 | export default BasicUsage; 234 | -------------------------------------------------------------------------------- /src/assets/fipicon/selection.json: -------------------------------------------------------------------------------- 1 | { 2 | "IcoMoonType": "selection", 3 | "icons": [ 4 | { 5 | "icon": { 6 | "paths": [ 7 | "M358.286 310.857c0 4.571-2.286 9.714-5.714 13.143l-224.571 224.571 224.571 224.571c3.429 3.429 5.714 8.571 5.714 13.143s-2.286 9.714-5.714 13.143l-28.571 28.571c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-266.286-266.286c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l266.286-266.286c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l28.571 28.571c3.429 3.429 5.714 8 5.714 13.143z" 8 | ], 9 | "width": 384, 10 | "attrs": [], 11 | "isMulticolor": false, 12 | "isMulticolor2": false, 13 | "tags": [ 14 | "angle-left" 15 | ], 16 | "defaultCode": 61700, 17 | "grid": 14 18 | }, 19 | "attrs": [], 20 | "properties": { 21 | "name": "angle-left", 22 | "id": 233, 23 | "order": 7, 24 | "prevSize": 28, 25 | "code": 61700 26 | }, 27 | "setIdx": 0, 28 | "setId": 0, 29 | "iconIdx": 233 30 | }, 31 | { 32 | "icon": { 33 | "paths": [ 34 | "M340 548.571c0 4.571-2.286 9.714-5.714 13.143l-266.286 266.286c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-28.571-28.571c-3.429-3.429-5.714-8-5.714-13.143 0-4.571 2.286-9.714 5.714-13.143l224.571-224.571-224.571-224.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l28.571-28.571c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l266.286 266.286c3.429 3.429 5.714 8.571 5.714 13.143z" 35 | ], 36 | "width": 347.4285714285714, 37 | "attrs": [], 38 | "isMulticolor": false, 39 | "isMulticolor2": false, 40 | "tags": [ 41 | "angle-right" 42 | ], 43 | "defaultCode": 61701, 44 | "grid": 14 45 | }, 46 | "attrs": [], 47 | "properties": { 48 | "name": "angle-right", 49 | "id": 234, 50 | "order": 6, 51 | "prevSize": 28, 52 | "code": 61701 53 | }, 54 | "setIdx": 0, 55 | "setId": 0, 56 | "iconIdx": 234 57 | }, 58 | { 59 | "icon": { 60 | "paths": [ 61 | "M614.286 676.571c0 4.571-2.286 9.714-5.714 13.143l-28.571 28.571c-3.429 3.429-8 5.714-13.143 5.714-4.571 0-9.714-2.286-13.143-5.714l-224.571-224.571-224.571 224.571c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-28.571-28.571c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l266.286-266.286c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l266.286 266.286c3.429 3.429 5.714 8.571 5.714 13.143z" 62 | ], 63 | "width": 658.2857142857142, 64 | "attrs": [], 65 | "isMulticolor": false, 66 | "isMulticolor2": false, 67 | "tags": [ 68 | "angle-up" 69 | ], 70 | "defaultCode": 61702, 71 | "grid": 14 72 | }, 73 | "attrs": [], 74 | "properties": { 75 | "name": "angle-up", 76 | "id": 235, 77 | "order": 4, 78 | "prevSize": 28, 79 | "code": 61702 80 | }, 81 | "setIdx": 0, 82 | "setId": 0, 83 | "iconIdx": 235 84 | }, 85 | { 86 | "icon": { 87 | "paths": [ 88 | "M614.286 420.571c0 4.571-2.286 9.714-5.714 13.143l-266.286 266.286c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-266.286-266.286c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l28.571-28.571c3.429-3.429 8-5.714 13.143-5.714 4.571 0 9.714 2.286 13.143 5.714l224.571 224.571 224.571-224.571c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l28.571 28.571c3.429 3.429 5.714 8.571 5.714 13.143z" 89 | ], 90 | "width": 658.2857142857142, 91 | "attrs": [], 92 | "isMulticolor": false, 93 | "isMulticolor2": false, 94 | "tags": [ 95 | "angle-down" 96 | ], 97 | "defaultCode": 61703, 98 | "grid": 14 99 | }, 100 | "attrs": [], 101 | "properties": { 102 | "name": "angle-down", 103 | "id": 236, 104 | "order": 5, 105 | "prevSize": 28, 106 | "code": 61703 107 | }, 108 | "setIdx": 0, 109 | "setId": 0, 110 | "iconIdx": 236 111 | } 112 | ], 113 | "height": 1024, 114 | "metadata": { 115 | "name": "fontIconPicker", 116 | "url": "https://fonticonpicker.github.io", 117 | "designer": "FontAwesome", 118 | "designerURL": "https://fontawesome.com/l", 119 | "license": "Custom", 120 | "licenseURL": "https://fontawesome.com/license" 121 | }, 122 | "preferences": { 123 | "showGlyphs": true, 124 | "showCodes": true, 125 | "showQuickUse": true, 126 | "showQuickUse2": true, 127 | "showSVGs": true, 128 | "fontPref": { 129 | "prefix": "fipicon-", 130 | "metadata": { 131 | "fontFamily": "fontIconPicker", 132 | "majorVersion": 1, 133 | "minorVersion": 0, 134 | "fontURL": "https://fonticonpicker.github.io", 135 | "description": "A lightweight iconpicker for the web. Both jQuery & React version available", 136 | "designer": "FontAwesome", 137 | "license": "Custom", 138 | "licenseURL": "https://fontawesome.com/license", 139 | "designerURL": "https://fontawesome.com/l", 140 | "copyright": "Swashata Ghosh" 141 | }, 142 | "metrics": { 143 | "emSize": 1024, 144 | "baseline": 6.25, 145 | "whitespace": 50 146 | }, 147 | "embed": false, 148 | "noie8": true, 149 | "ie7": false, 150 | "showSelector": true, 151 | "showMetrics": false, 152 | "showMetadata": true 153 | }, 154 | "imagePref": { 155 | "prefix": "icon-", 156 | "png": true, 157 | "useClassSelector": true, 158 | "color": 0, 159 | "bgColor": 16777215 160 | }, 161 | "historySize": 50 162 | } 163 | } --------------------------------------------------------------------------------