├── .babelrc ├── .editorconfig ├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── README.md ├── dst ├── react-github-fork-ribbon.js └── react-github-fork-ribbon.min.js ├── gulpfile.babel.js ├── package.json ├── src ├── index.js └── ribbonStyle.js ├── storybook ├── __conf__ │ └── mockConfig.js ├── __mocks__ │ ├── facade.js │ └── file.js ├── __tests__ │ ├── GithubForkRibbon.stories.js │ └── __snapshots__ │ │ └── GithubForkRibbon.stories.js.snap ├── addons.js ├── config.js ├── facade.js └── webpack.config.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ "es2015", { "loose": true } ], 4 | "react", 5 | "stage-3" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | indent_size = 2 13 | trim_trailing_whitespace = false 14 | 15 | [package.json] 16 | indent_size = 2 17 | 18 | [app/views/*.jade] 19 | indent_size = 2 20 | 21 | [*.js] 22 | indent_size = 2 23 | 24 | [*.jsx] 25 | indent_size = 2 26 | 27 | [*.ls] 28 | indent_size = 2 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # node 2 | node_modules/ 3 | 4 | *.log 5 | 6 | # transpile file 7 | component/ 8 | 9 | # gulpfile is transpile from gulpfile.babel.js 10 | gulpfile.js 11 | 12 | # test 13 | coverage/ 14 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # node 2 | node_modules/ 3 | _public/ 4 | test/ 5 | storybook/ 6 | 7 | # Else 8 | docs/ 9 | .editorconfig 10 | 11 | # Use Transpile file for publish 12 | src/ 13 | coverage/ 14 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | 6 | ## [0.7.1](https://github.com/jessy1092/react-github-fork-ribbon/compare/v0.7.0...v0.7.1) (2022-06-18) 7 | 8 | 9 | 10 | 11 | # [0.7.0](https://github.com/jessy1092/react-github-fork-ribbon/compare/v0.6.0...v0.7.0) (2022-06-18) 12 | 13 | 14 | ### Bug Fixes 15 | 16 | * added support for React 17 & 18 ([e3ddc1d](https://github.com/jessy1092/react-github-fork-ribbon/commit/e3ddc1d)) 17 | * Upgrade gulp to 4.0.2 ([6072c90](https://github.com/jessy1092/react-github-fork-ribbon/commit/6072c90)) 18 | 19 | 20 | 21 | 22 | ## [0.6.0](https://github.com/jessy1092/react-github-fork-ribbon/compare/v0.5.1...v0.6.0) (2018-08-12) 23 | 24 | 25 | ### Features 26 | 27 | * Support for custom class names ([0b5319b](https://github.com/jessy1092/react-github-fork-ribbon/commit/0b5319b)) 28 | 29 | ### Bug Fixes 30 | 31 | * add rel="noopener" to anchor ([3bf9999](https://github.com/jessy1092/react-github-fork-ribbon/commit/3bf9999)) 32 | * Make ribbon smoother in Firefox ([0b89e50](https://github.com/jessy1092/react-github-fork-ribbon/commit/0b89e50)) 33 | 34 | 35 | 36 | 37 | ## [0.5.1](https://github.com/jessy1092/react-github-fork-ribbon/compare/v0.5.0...v0.5.1) (2017-10-05) 38 | 39 | 40 | ### Bug Fixes 41 | 42 | * Support react 16.0 and upgrade development dependencies. close [#14](https://github.com/jessy1092/react-github-fork-ribbon/issues/14) ([53f72dd](https://github.com/jessy1092/react-github-fork-ribbon/commit/53f72dd)) 43 | 44 | 45 | 46 | 47 | # [0.5.0](https://github.com/jessy1092/react-github-fork-ribbon/compare/v0.4.5...v0.5.0) (2017-04-11) 48 | 49 | 50 | ### Features 51 | 52 | * Support jest snapshot testing ([ceba068](https://github.com/jessy1092/react-github-fork-ribbon/commit/ceba068)) 53 | * Support react v15.5 and remove v0.13 support ([ff2bcd1](https://github.com/jessy1092/react-github-fork-ribbon/commit/ff2bcd1)) 54 | 55 | 56 | 57 | 58 | ## [0.4.5](https://github.com/jessy1092/react-github-fork-ribbon/compare/v0.4.4...v0.4.5) (2017-03-11) 59 | 60 | 61 | - Refactor position and color set function 62 | - Remove object-assign library 63 | - Use storybook to help develop 64 | 65 | 66 | ## [0.4.4](https://github.com/jessy1092/react-github-fork-ribbon/compare/v0.4.3...v0.4.4) (2016-04-30) 67 | 68 | 69 | 70 | - Fix React 15 unitless number warning 71 | 72 | 73 | ## [0.4.3](https://github.com/jessy1092/react-github-fork-ribbon/compare/v0.4.2...v0.4.3) (2016-04-18) 74 | 75 | 76 | ### Bug Fixes 77 | 78 | * browserify setting. Exclude the React package for web usage ([8880565](https://github.com/jessy1092/react-github-fork-ribbon/commit/8880565)) 79 | 80 | 81 | ### Features 82 | 83 | * Support react v15.0 close [#10](https://github.com/jessy1092/react-github-fork-ribbon/issues/10) ([0812bd4](https://github.com/jessy1092/react-github-fork-ribbon/commit/0812bd4)) 84 | 85 | 86 | 87 | 88 | ## [0.4.2](https://github.com/jessy1092/react-github-fork-ribbon/compare/v0.4.1...v0.4.2) (2015-10-11) 89 | 90 | 91 | - Support React 0.14 92 | 93 | 94 | ## [0.4.1](https://github.com/jessy1092/react-github-fork-ribbon/compare/v0.4.0...v0.4.1) (2015-06-29) 95 | 96 | 97 | - Insert the relevant browser prefix. 98 | + Webkit, Moz, O, ms. 99 | 100 | 101 | # [0.4.0](https://github.com/jessy1092/react-github-fork-ribbon/compare/v0.3.0...v0.4.0) (2015-06-28) 102 | 103 | 104 | - Switch to vanilla inline styles. [PR#7](https://github.com/jessy1092/react-github-fork-ribbon/pull/7) 105 | - Update Dev-dependencies version. `babel` => 5.6.14, `browserify` => 10.2.4 106 | 107 | 108 | 109 | # [0.3.0](https://github.com/jessy1092/react-github-fork-ribbon/compare/v0.2.1...v0.3.0) (2015-03-28) 110 | 111 | 112 | 113 | - Support `react` 0.13.x and `react-style` 0.5.x version 114 | - Use ES6 feature. 115 | 116 | 117 | ## [0.2.1](https://github.com/jessy1092/react-github-fork-ribbon/compare/v0.2.0...v0.2.1) (2015-03-06) 118 | 119 | 120 | 121 | 122 | # [0.2.0](https://github.com/jessy1092/react-github-fork-ribbon/compare/v0.1.0...v0.2.0) (2015-03-06) 123 | 124 | 125 | - Add attribute: `color` 126 | - Transpile into vanilla js during prepublish. 127 | 128 | 129 | 130 | # 0.1.0 (2015-01-15) 131 | 132 | 133 | - Init 134 | - Add attribute: `href`, `target`, `position` 135 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | React GitHub Fork Ribbon 2 | ============= 3 | [![npm][npm-image]][npm-url] [![Dependency Status][david-dm-image]][david-dm-url] 4 | 5 | Pure inline style github fork ribbon on React component. The inline style css is from ["Fork me on GitHub" CSS ribbon](http://simonwhitaker.github.io/github-fork-ribbon-css/). 6 | 7 | | | React = 0.12 | React = 0.13 | React >= 0.14 | React >= 0.17 | 8 | | ------- | ------------ | ------------- | ------------- | ------------- | 9 | | Version | <= 0.2 | >= 0.3 < 0.5 | >= 0.5 | >= 0.7 | 10 | 11 | ## Usage 12 | 13 | ```sh 14 | npm install react-github-fork-ribbon 15 | ``` 16 | 17 | Ex. React 15.5 18 | ```js 19 | import React from 'react'; 20 | import ReactDOM from 'react-dom'; 21 | import GitHubForkRibbon from 'react-github-fork-ribbon'; 22 | 23 | const Content = () => ( 24 | 27 | Fork me on GitHub 28 | 29 | ); 30 | 31 | ReactDOM.render( 32 | , 33 | document.getElementById('content') 34 | ); 35 | ``` 36 | 37 | ## Attribute 38 | 39 | #### href 40 | 41 | It would be `` tag's attribute `href` 42 | 43 | #### target 44 | 45 | It would be `` tag's attribute `target` 46 | 47 | #### position 48 | 49 | It has four positions. 50 | - `left` 51 | - `right` 52 | - `left-bottom` 53 | - `right-bottom` 54 | 55 | ### color 56 | 57 | It has four color. 58 | - `red` 59 | - `orange` 60 | - `black` 61 | - `green` 62 | 63 | #### className 64 | 65 | It would be an html tag's attribute `class`. 66 | 67 | ## Release Notes 68 | 69 | see [CHANGELOG.md](https://github.com/jessy1092/react-github-fork-ribbon/blob/master/CHANGELOG.md) 70 | 71 | ## Contribute 72 | [![devDependency Status][david-dm-dev-image]][david-dm-dev-url] 73 | 74 | 1. Fork it. 75 | 2. Create your feature-branch `git checkout -b your-new-feature-branch` 76 | 3. Commit your change `git commit -am 'Add new feature'` 77 | 4. Push to the branch `git push origin your-new-feature-branch` 78 | 5. Create new Pull Request with `master` branch 79 | 80 | ## License 81 | 82 | The MIT License (MIT) 83 | 84 | Copyright (c) 2015-2017 Lee < jessy1092@gmail.com > 85 | 86 | Permission is hereby granted, free of charge, to any person obtaining a copy of 87 | this software and associated documentation files (the "Software"), to deal in 88 | the Software without restriction, including without limitation the rights to 89 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 90 | the Software, and to permit persons to whom the Software is furnished to do so, 91 | subject to the following conditions: 92 | 93 | The above copyright notice and this permission notice shall be included in all 94 | copies or substantial portions of the Software. 95 | 96 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 97 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 98 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 99 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 100 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 101 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 102 | 103 | [react-github-fork-ribbon-url]: https://github.com/jessy1092/react-github-fork-ribbon/releases 104 | 105 | [npm-image]: https://img.shields.io/npm/v/react-github-fork-ribbon.svg?style=flat-square 106 | [npm-url]: https://www.npmjs.com/package/react-github-fork-ribbon 107 | 108 | [david-dm-image]: https://david-dm.org/jessy1092/react-github-fork-ribbon.svg?style=flat-square 109 | [david-dm-url]: https://david-dm.org/jessy1092/react-github-fork-ribbon 110 | 111 | [david-dm-dev-image]: https://david-dm.org/jessy1092/react-github-fork-ribbon/dev-status.svg?style=flat-square 112 | [david-dm-dev-url]: https://david-dm.org/jessy1092/react-github-fork-ribbon#info=devDependencies 113 | -------------------------------------------------------------------------------- /dst/react-github-fork-ribbon.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } 20 | 21 | var positionMapping = { 22 | left: [_ribbonStyle.RibbonStyle.leftStyle, _ribbonStyle.RibbonStyleWrapper.leftStyle], 23 | right: [_ribbonStyle.RibbonStyle.rightStyle, _ribbonStyle.RibbonStyleWrapper.rightStyle], 24 | 'left-bottom': [_ribbonStyle.RibbonStyle.leftBottomStyle, _ribbonStyle.RibbonStyleWrapper.leftBottomStyle], 25 | 'right-bottom': [_ribbonStyle.RibbonStyle.rightBottomStyle, _ribbonStyle.RibbonStyleWrapper.rightBottomStyle] 26 | }; 27 | 28 | var colorMapping = { 29 | red: _ribbonStyle.RibbonStyle.redColor, 30 | orange: _ribbonStyle.RibbonStyle.orangeColor, 31 | black: _ribbonStyle.RibbonStyle.blackColor, 32 | green: _ribbonStyle.RibbonStyle.greenColor 33 | }; 34 | 35 | var GitHubForkRibbon = function GitHubForkRibbon(_ref) { 36 | var _ref$position = _ref.position, 37 | position = _ref$position === undefined ? 'right' : _ref$position, 38 | href = _ref.href, 39 | target = _ref.target, 40 | _ref$color = _ref.color, 41 | color = _ref$color === undefined ? 'red' : _ref$color, 42 | _ref$className = _ref.className, 43 | className = _ref$className === undefined ? '' : _ref$className, 44 | children = _ref.children, 45 | other = _objectWithoutProperties(_ref, ['position', 'href', 'target', 'color', 'className', 'children']); 46 | 47 | var positionStyle = positionMapping[position] || [_ribbonStyle.RibbonStyle.rightStyle, _ribbonStyle.RibbonStyleWrapper.rightStyle]; 48 | var colorStyle = colorMapping[color] || _ribbonStyle.RibbonStyle.redColor; 49 | 50 | if (positionStyle[0] === _ribbonStyle.RibbonStyle.rightStyle) { 51 | position = 'right'; 52 | } 53 | 54 | var ribbonStyle = _extends({}, _ribbonStyle.RibbonStyle.baseStyle, positionStyle[0], colorStyle); 55 | 56 | var wrapperStyle = _extends({}, _ribbonStyle.RibbonStyleWrapper.baseStyle, positionStyle[1]); 57 | 58 | return _react2.default.createElement( 59 | 'div', 60 | _extends({}, other, { 61 | className: 'github-fork-ribbon-wrapper ' + position + ' ' + className, 62 | style: wrapperStyle }), 63 | _react2.default.createElement( 64 | 'div', 65 | { className: 'github-fork-ribbon', 66 | style: ribbonStyle }, 67 | _react2.default.createElement( 68 | 'a', 69 | { href: href, 70 | target: target, 71 | style: _ribbonStyle.RibbonStyle.urlStyle, 72 | rel: 'noopener' }, 73 | children 74 | ) 75 | ) 76 | ); 77 | }; 78 | 79 | exports.default = global.RibbonStyle = GitHubForkRibbon; 80 | 81 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 82 | },{"./ribbonStyle":2}],2:[function(require,module,exports){ 83 | 'use strict'; 84 | 85 | Object.defineProperty(exports, "__esModule", { 86 | value: true 87 | }); 88 | /* 89 | * "Fork me on GitHub" CSS ribbon v0.1.1 | MIT License 90 | * https://github.com/simonwhitaker/github-fork-ribbon-css 91 | * 92 | * 20150116 Lee: use css source for inline style react component. 93 | */ 94 | var RibbonStyle = exports.RibbonStyle = { 95 | 96 | baseStyle: { 97 | /* The right and left classes determine the side we attach our banner to */ 98 | position: 'absolute', 99 | 100 | /* Add a bit of padding to give some substance outside the "stitching" */ 101 | padding: '2px 0', 102 | 103 | /* Set the base colour */ 104 | backgroundColor: '#a00', 105 | 106 | /* Set a gradient: transparent black at the top to almost-transparent black at the bottom */ 107 | // backgroundImage: '-webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0)), to(rgba(0, 0, 0, 0.15)))', 108 | // backgroundImage: '-webkit-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15))', 109 | // backgroundImage: '-moz-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15))', 110 | // backgroundImage: '-ms-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15))', 111 | // backgroundImage: '-o-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15))', 112 | backgroundImage: 'linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15))', 113 | 114 | /* Add a drop shadow */ 115 | WebkitBoxShadow: '0 2px 3px 0 rgba(0, 0, 0, 0.5)', 116 | MozBoxShadow: '0 2px 3px 0 rgba(0, 0, 0, 0.5)', 117 | boxShadow: '0 2px 3px 0 rgba(0, 0, 0, 0.5)', 118 | 119 | /* Set the font */ 120 | font: '700 13px "Helvetica Neue", Helvetica, Arial, sans-serif', 121 | 122 | zIndex: '9999', 123 | pointerEvents: 'auto' 124 | }, 125 | 126 | urlStyle: { 127 | /* Set the text properties */ 128 | color: '#fff', 129 | textDecoration: 'none', 130 | textShadow: '0 -1px rgba(0, 0, 0, 0.5)', 131 | textAlign: 'center', 132 | 133 | /* Set the geometry. If you fiddle with these you'll also need 134 | to tweak the top and right values in .github-fork-ribbon. */ 135 | width: '200px', 136 | lineHeight: '20px', 137 | 138 | /* Set the layout properties */ 139 | display: 'inline-block', 140 | padding: '2px 0', 141 | 142 | /* Add "stitching" effect */ 143 | borderWidth: '1px 0', 144 | borderStyle: 'dashed', 145 | // borderColor: '#fff', 146 | borderColor: 'rgba(255, 255, 255, 0.7)' 147 | }, 148 | 149 | redColor: { 150 | backgroundColor: '#a00' 151 | }, 152 | 153 | orangeColor: { 154 | backgroundColor: '#f80' 155 | }, 156 | 157 | blackColor: { 158 | backgroundColor: '#333' 159 | }, 160 | 161 | greenColor: { 162 | backgroundColor: '#090' 163 | }, 164 | 165 | leftStyle: { 166 | top: '42px', 167 | left: '-43px', 168 | 169 | WebkitTransform: 'rotate(-45deg)', 170 | MozTransform: 'rotate(-45deg)', 171 | msTransform: 'rotate(-45deg)', 172 | OTransform: 'rotate(-45deg)', 173 | transform: 'rotate(-45deg)' 174 | }, 175 | 176 | rightStyle: { 177 | top: '42px', 178 | right: '-43px', 179 | 180 | WebkitTransform: 'rotate(45deg)', 181 | MozTransform: 'rotate(45deg)', 182 | msTransform: 'rotate(45deg)', 183 | OTransform: 'rotate(45deg)', 184 | transform: 'rotate(45deg)' 185 | }, 186 | 187 | leftBottomStyle: { 188 | top: '80px', 189 | left: '-43px', 190 | 191 | WebkitTransform: 'rotate(45deg)', 192 | MozTransform: 'rotate(45deg)', 193 | msTransform: 'rotate(45deg)', 194 | OTransform: 'rotate(45deg)', 195 | transform: 'rotate(45deg)' 196 | }, 197 | 198 | rightBottomStyle: { 199 | top: '80px', 200 | right: '-43px', 201 | 202 | WebkitTransform: 'rotate(-45deg)', 203 | MozTransform: 'rotate(-45deg)', 204 | msTransform: 'rotate(-45deg)', 205 | OTransform: 'rotate(-45deg)', 206 | transform: 'rotate(-45deg)' 207 | } 208 | }; 209 | 210 | var RibbonStyleWrapper = exports.RibbonStyleWrapper = { 211 | 212 | baseStyle: { 213 | width: '150px', 214 | height: '150px', 215 | position: 'absolute', 216 | overflow: 'hidden', 217 | top: 0, 218 | zIndex: '9999', 219 | pointerEvents: 'none' 220 | }, 221 | 222 | fixedStyle: { 223 | position: 'fixed' 224 | }, 225 | 226 | leftStyle: { 227 | left: 0 228 | }, 229 | 230 | rightStyle: { 231 | right: 0 232 | }, 233 | 234 | leftBottomStyle: { 235 | position: 'fixed', 236 | top: 'inherit', 237 | bottom: 0, 238 | left: 0 239 | }, 240 | 241 | rightBottomStyle: { 242 | position: 'fixed', 243 | top: 'inherit', 244 | bottom: 0, 245 | right: 0 246 | } 247 | }; 248 | 249 | },{}]},{},[1]); 250 | -------------------------------------------------------------------------------- /dst/react-github-fork-ribbon.min.js: -------------------------------------------------------------------------------- 1 | !function e(t,o,r){function n(i,a){if(!o[i]){if(!t[i]){var b="function"==typeof require&&require;if(!a&&b)return b(i,!0);if(l)return l(i,!0);var f=new Error("Cannot find module '"+i+"'");throw f.code="MODULE_NOT_FOUND",f}var d=o[i]={exports:{}};t[i][0].call(d.exports,function(e){var o=t[i][1][e];return n(o?o:e)},d,d.exports,e,t,o,r)}return o[i].exports}for(var l="function"==typeof require&&require,i=0;i=0||Object.prototype.hasOwnProperty.call(e,r)&&(o[r]=e[r]);return o}Object.defineProperty(o,"__esModule",{value:!0});var n=Object.assign||function(e){for(var t=1;t { 16 | return gulp.src(src_files) 17 | .pipe(gbabel({presets: ["es2015", "react", "stage-3"]})) 18 | .pipe(gulp.dest('./component/')); 19 | }); 20 | 21 | gulp.task('browserify', () => { 22 | return browserify('./src/index.js') 23 | .transform('babelify', {presets: ['es2015', 'react', 'stage-3']}) 24 | .transform(globalShim.configure({ 25 | 'react': 'React' 26 | })) 27 | .bundle() 28 | .pipe(source('react-github-fork-ribbon.js')) 29 | .pipe(gulp.dest(build_path)) 30 | .pipe(buffer()) 31 | .pipe(uglify()) 32 | .pipe(grename('react-github-fork-ribbon.min.js')) 33 | .pipe(gulp.dest(build_path)); 34 | }); 35 | 36 | gulp.task('watch', () => { 37 | gulp.watch([src_files], gulp.series('build')); 38 | }); 39 | 40 | gulp.task('build', gulp.series('transpile', 'browserify')); 41 | gulp.task('dev', gulp.series('build', 'watch')); 42 | gulp.task('default', gulp.series('build')); 43 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-github-fork-ribbon", 3 | "description": "Pure inline style github fork ribbon on React component", 4 | "version": "0.7.1", 5 | "keywords": [ 6 | "fork", 7 | "GitHub", 8 | "ribbon", 9 | "react", 10 | "react-component" 11 | ], 12 | "contributor": [ 13 | { 14 | "name": "Lee", 15 | "email": "jessy1092@gmail.com" 16 | } 17 | ], 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/jessy1092/react-github-fork-ribbon" 21 | }, 22 | "bugs": { 23 | "url": "https://github.com/jessy1092/react-github-fork-ribbon/issues" 24 | }, 25 | "homepage": "http://jessy1092.github.io/react-github-fork-ribbon", 26 | "license": "MIT", 27 | "scripts": { 28 | "start": "gulp dev", 29 | "prepublish": "gulp transpile", 30 | "storybook": "start-storybook -p 8000 -c storybook", 31 | "test": "jest --coverage", 32 | "release": "standard-version" 33 | }, 34 | "engines": { 35 | "node": ">=0.10.x" 36 | }, 37 | "main": "component/index.js", 38 | "peerDependencies": { 39 | "react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" 40 | }, 41 | "devDependencies": { 42 | "@storybook/react": "^3.2.12", 43 | "babel": "^6.5.2", 44 | "babel-core": "^6.24.1", 45 | "babel-jest": "^23.4.2", 46 | "babel-loader": "^7.1.2", 47 | "babel-preset-es2015": "^6.24.1", 48 | "babel-preset-react": "^6.24.1", 49 | "babel-preset-stage-3": "^6.24.1", 50 | "babelify": "^7.2.0", 51 | "browserify": "^14.3.0", 52 | "browserify-global-shim": "^1.0.3", 53 | "enzyme": "^3.1.0", 54 | "enzyme-adapter-react-16": "^1.0.1", 55 | "enzyme-to-json": "^3.1.1", 56 | "gulp": "^4.0.2", 57 | "gulp-babel": "^6.1.2", 58 | "gulp-rename": "^1.2.2", 59 | "gulp-uglify": "^2.1.2", 60 | "gulp-util": "^3.0.6", 61 | "identity-obj-proxy": "^3.0.0", 62 | "jest": "^23.5.0", 63 | "react": "^16.0.0", 64 | "react-dom": "^16.0.0", 65 | "react-hot-loader": "3.0.0-beta.6", 66 | "react-test-renderer": "^16.0.0", 67 | "standard-version": "^4.4.0", 68 | "storybook-addon-specifications": "^2.1.1", 69 | "vinyl-buffer": "^1.0.0", 70 | "vinyl-source-stream": "^1.1.0" 71 | }, 72 | "dependencies": {}, 73 | "jest": { 74 | "setupFiles": [ 75 | "/storybook/__conf__/mockConfig.js" 76 | ], 77 | "testMatch": [ 78 | "**/storybook/**/*.stories.js", 79 | "**/src/**/*.spec.js" 80 | ], 81 | "automock": false, 82 | "globals": { 83 | "__TESTS__": true 84 | }, 85 | "unmockedModulePathPatterns": [ 86 | "/node_modules/react/", 87 | "/node_modules/react-dom/", 88 | "/node_modules/enzyme/", 89 | "/node_modules/react-addons-test-utils/" 90 | ], 91 | "moduleNameMapper": { 92 | "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/storybook/__mocks__/file.js", 93 | "\\.(css|less)$": "identity-obj-proxy" 94 | }, 95 | "coveragePathIgnorePatterns": [ 96 | "/storybook/", 97 | "/node_modules/" 98 | ], 99 | "snapshotSerializers": [ 100 | "enzyme-to-json/serializer" 101 | ] 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { 4 | RibbonStyle, 5 | RibbonStyleWrapper 6 | } from './ribbonStyle'; 7 | 8 | const positionMapping = { 9 | left: [RibbonStyle.leftStyle, RibbonStyleWrapper.leftStyle], 10 | right: [RibbonStyle.rightStyle, RibbonStyleWrapper.rightStyle], 11 | 'left-bottom': [RibbonStyle.leftBottomStyle, RibbonStyleWrapper.leftBottomStyle], 12 | 'right-bottom': [RibbonStyle.rightBottomStyle, RibbonStyleWrapper.rightBottomStyle], 13 | }; 14 | 15 | const colorMapping = { 16 | red: RibbonStyle.redColor, 17 | orange: RibbonStyle.orangeColor, 18 | black: RibbonStyle.blackColor, 19 | green: RibbonStyle.greenColor, 20 | }; 21 | 22 | const GitHubForkRibbon = ({position = 'right', href, target, color = 'red', className = '', children, ...other}) => { 23 | 24 | const positionStyle = positionMapping[position] || [RibbonStyle.rightStyle, RibbonStyleWrapper.rightStyle]; 25 | const colorStyle = colorMapping[color] || RibbonStyle.redColor; 26 | 27 | if (positionStyle[0] === RibbonStyle.rightStyle) { 28 | position = 'right'; 29 | } 30 | 31 | const ribbonStyle = { 32 | ...RibbonStyle.baseStyle, 33 | ...positionStyle[0], 34 | ...colorStyle 35 | }; 36 | 37 | const wrapperStyle = { 38 | ...RibbonStyleWrapper.baseStyle, 39 | ...positionStyle[1], 40 | }; 41 | 42 | return ( 43 |
46 |
48 | 52 | {children} 53 | 54 |
55 |
56 | ); 57 | }; 58 | 59 | export default global.RibbonStyle = GitHubForkRibbon; 60 | -------------------------------------------------------------------------------- /src/ribbonStyle.js: -------------------------------------------------------------------------------- 1 | /* 2 | * "Fork me on GitHub" CSS ribbon v0.1.1 | MIT License 3 | * https://github.com/simonwhitaker/github-fork-ribbon-css 4 | * 5 | * 20150116 Lee: use css source for inline style react component. 6 | */ 7 | export const RibbonStyle = { 8 | 9 | baseStyle: { 10 | /* The right and left classes determine the side we attach our banner to */ 11 | position: 'absolute', 12 | 13 | /* Add a bit of padding to give some substance outside the "stitching" */ 14 | padding: '2px 0', 15 | 16 | /* Set the base colour */ 17 | backgroundColor: '#a00', 18 | 19 | /* Set a gradient: transparent black at the top to almost-transparent black at the bottom */ 20 | // backgroundImage: '-webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0)), to(rgba(0, 0, 0, 0.15)))', 21 | // backgroundImage: '-webkit-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15))', 22 | // backgroundImage: '-moz-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15))', 23 | // backgroundImage: '-ms-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15))', 24 | // backgroundImage: '-o-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15))', 25 | backgroundImage: 'linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15))', 26 | 27 | /* Add a drop shadow */ 28 | WebkitBoxShadow: '0 2px 3px 0 rgba(0, 0, 0, 0.5)', 29 | MozBoxShadow: '0 2px 3px 0 rgba(0, 0, 0, 0.5)', 30 | boxShadow: '0 2px 3px 0 rgba(0, 0, 0, 0.5)', 31 | 32 | /* Set the font */ 33 | font: '700 13px "Helvetica Neue", Helvetica, Arial, sans-serif', 34 | 35 | zIndex: '9999', 36 | pointerEvents: 'auto' 37 | }, 38 | 39 | urlStyle: { 40 | /* Set the text properties */ 41 | color: '#fff', 42 | textDecoration: 'none', 43 | textShadow: '0 -1px rgba(0, 0, 0, 0.5)', 44 | textAlign: 'center', 45 | 46 | /* Set the geometry. If you fiddle with these you'll also need 47 | to tweak the top and right values in .github-fork-ribbon. */ 48 | width: '200px', 49 | lineHeight: '20px', 50 | 51 | /* Set the layout properties */ 52 | display: 'inline-block', 53 | padding: '2px 0', 54 | 55 | /* Add "stitching" effect */ 56 | borderWidth: '1px 0', 57 | borderStyle: 'dashed', 58 | // borderColor: '#fff', 59 | borderColor: 'rgba(255, 255, 255, 0.7)' 60 | }, 61 | 62 | redColor: { 63 | backgroundColor: '#a00' 64 | }, 65 | 66 | orangeColor: { 67 | backgroundColor: '#f80' 68 | }, 69 | 70 | blackColor: { 71 | backgroundColor: '#333' 72 | }, 73 | 74 | greenColor: { 75 | backgroundColor: '#090' 76 | }, 77 | 78 | leftStyle: { 79 | top: '42px', 80 | left: '-43px', 81 | 82 | WebkitTransform: 'rotate(-45deg)', 83 | MozTransform: 'rotate(-45deg)', 84 | msTransform: 'rotate(-45deg)', 85 | OTransform: 'rotate(-45deg)', 86 | transform: 'rotate(-45deg)' 87 | }, 88 | 89 | rightStyle: { 90 | top: '42px', 91 | right: '-43px', 92 | 93 | WebkitTransform: 'rotate(45deg)', 94 | MozTransform: 'rotate(45deg)', 95 | msTransform: 'rotate(45deg)', 96 | OTransform: 'rotate(45deg)', 97 | transform: 'rotate(45deg)' 98 | }, 99 | 100 | leftBottomStyle: { 101 | top: '80px', 102 | left: '-43px', 103 | 104 | WebkitTransform: 'rotate(45deg)', 105 | MozTransform: 'rotate(45deg)', 106 | msTransform: 'rotate(45deg)', 107 | OTransform: 'rotate(45deg)', 108 | transform: 'rotate(45deg)' 109 | }, 110 | 111 | rightBottomStyle: { 112 | top: '80px', 113 | right: '-43px', 114 | 115 | WebkitTransform: 'rotate(-45deg)', 116 | MozTransform: 'rotate(-45deg)', 117 | msTransform: 'rotate(-45deg)', 118 | OTransform: 'rotate(-45deg)', 119 | transform: 'rotate(-45deg)' 120 | } 121 | }; 122 | 123 | export const RibbonStyleWrapper = { 124 | 125 | baseStyle: { 126 | width: '150px', 127 | height: '150px', 128 | position: 'absolute', 129 | overflow: 'hidden', 130 | top: 0, 131 | zIndex: '9999', 132 | pointerEvents: 'none' 133 | }, 134 | 135 | fixedStyle: { 136 | position: 'fixed' 137 | }, 138 | 139 | leftStyle: { 140 | left: 0 141 | }, 142 | 143 | rightStyle: { 144 | right: 0 145 | }, 146 | 147 | leftBottomStyle: { 148 | position: 'fixed', 149 | top: 'inherit', 150 | bottom: 0, 151 | left: 0 152 | }, 153 | 154 | rightBottomStyle: { 155 | position: 'fixed', 156 | top: 'inherit', 157 | bottom: 0, 158 | right: 0 159 | } 160 | }; 161 | -------------------------------------------------------------------------------- /storybook/__conf__/mockConfig.js: -------------------------------------------------------------------------------- 1 | jest.mock('../facade'); 2 | 3 | global.requestAnimationFrame = function(callback) { 4 | setTimeout(callback, 0); 5 | }; 6 | -------------------------------------------------------------------------------- /storybook/__mocks__/facade.js: -------------------------------------------------------------------------------- 1 | import Enzyme from 'enzyme'; 2 | import Adapter from 'enzyme-adapter-react-16'; 3 | 4 | Enzyme.configure({ adapter: new Adapter() }); 5 | 6 | const { shallow } = Enzyme; 7 | 8 | export const action = () => () => {}; 9 | 10 | export const linkTo = () => {}; 11 | 12 | export const specs = spec => { 13 | spec(); 14 | }; 15 | 16 | export const describe = jasmine.currentEnv_.describe; 17 | export const it = jasmine.currentEnv_.it; 18 | export const beforeEach = jasmine.currentEnv_.beforeEach; 19 | export const afterEach = jasmine.currentEnv_.afterEach; 20 | export const xit = jasmine.currentEnv_.xit; 21 | export const xdescribe = jasmine.currentEnv_.xdescribe; 22 | export const fit = jasmine.currentEnv_.fit; 23 | export const after = () => {}; 24 | export const before = () => {}; 25 | 26 | export const snapshot = (name, func) => { 27 | it(name, () => func()); 28 | }; 29 | 30 | const createSnapshot = (name, story) => { 31 | it(name, () => { 32 | expect(shallow(story)).toMatchSnapshot(); 33 | }); 34 | }; 35 | 36 | export const storiesOf = function storiesOf() { 37 | const api = {}; 38 | let story; 39 | api.add = (name, func) => { 40 | story = func(); 41 | createSnapshot(name, story); 42 | return api; 43 | }; 44 | api.addWithInfo = (name, func) => { 45 | story = func(); 46 | createSnapshot(name, story); 47 | return api; 48 | }; 49 | return api; 50 | }; 51 | -------------------------------------------------------------------------------- /storybook/__mocks__/file.js: -------------------------------------------------------------------------------- 1 | module.exports = 'test-file-stub'; 2 | -------------------------------------------------------------------------------- /storybook/__tests__/GithubForkRibbon.stories.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { storiesOf, describe, it, specs } from '../facade'; 4 | 5 | import GitHubForkRibbon from '../../src'; 6 | 7 | storiesOf('GitHub fork ribbon/default', module) 8 | .add('default with right position and red color', () => { 9 | const component = ( 10 | 11 | Fork me on GitHub 12 | 13 | ); 14 | 15 | return component; 16 | }) 17 | .add('handle unexist position with default', () => { 18 | const component = ( 19 | 20 | Fork me on GitHub 21 | 22 | ); 23 | 24 | return component; 25 | }) 26 | .add('handle unexist color with default', () => { 27 | const component = ( 28 | 29 | Fork me on GitHub 30 | 31 | ); 32 | 33 | return component; 34 | }); 35 | 36 | storiesOf('GitHub fork ribbon/position', module) 37 | .add('on right position', () => { 38 | const component = ( 39 | 40 | Fork me on GitHub 41 | 42 | ); 43 | 44 | return component; 45 | }) 46 | .add('on left position', () => { 47 | const component = ( 48 | 49 | Fork me on GitHub 50 | 51 | ); 52 | 53 | return component; 54 | }) 55 | .add('on right-bottom position', () => { 56 | const component = ( 57 | 58 | Fork me on GitHub 59 | 60 | ); 61 | 62 | return component; 63 | }) 64 | .add('on left-bottom position', () => { 65 | const component = ( 66 | 67 | Fork me on GitHub 68 | 69 | ); 70 | 71 | return component; 72 | }); 73 | 74 | storiesOf('GitHub fork ribbon/color', module) 75 | .add('with red color', () => { 76 | const component = ( 77 | 78 | Fork me on GitHub 79 | 80 | ); 81 | 82 | return component; 83 | }) 84 | .add('with orange color', () => { 85 | const component = ( 86 | 87 | Fork me on GitHub 88 | 89 | ); 90 | 91 | return component; 92 | }) 93 | .add('with black color', () => { 94 | const component = ( 95 | 96 | Fork me on GitHub 97 | 98 | ); 99 | 100 | return component; 101 | }) 102 | .add('with green color', () => { 103 | const component = ( 104 | 105 | Fork me on GitHub 106 | 107 | ); 108 | 109 | return component; 110 | }); 111 | 112 | storiesOf('GitHub fork ribbon/className', module) 113 | .add('hidden on small devices up to 576px', () => { 114 | const component = ( 115 |
116 | 125 | 126 | Fork me on GitHub 127 | 128 |
129 | ); 130 | 131 | return component; 132 | }); 133 | -------------------------------------------------------------------------------- /storybook/__tests__/__snapshots__/GithubForkRibbon.stories.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`default with right position and red color 1`] = ` 4 |
19 |
43 | 63 | Fork me on GitHub 64 | 65 |
66 |
67 | `; 68 | 69 | exports[`handle unexist color with default 1`] = ` 70 |
85 |
109 | 129 | Fork me on GitHub 130 | 131 |
132 |
133 | `; 134 | 135 | exports[`handle unexist position with default 1`] = ` 136 |
151 |
175 | 195 | Fork me on GitHub 196 | 197 |
198 |
199 | `; 200 | 201 | exports[`hidden on small devices up to 576px 1`] = ` 202 |
203 | 212 | 217 | Fork me on GitHub 218 | 219 |
220 | `; 221 | 222 | exports[`on left position 1`] = ` 223 |
238 |
262 | 282 | Fork me on GitHub 283 | 284 |
285 |
286 | `; 287 | 288 | exports[`on left-bottom position 1`] = ` 289 |
305 |
329 | 349 | Fork me on GitHub 350 | 351 |
352 |
353 | `; 354 | 355 | exports[`on right position 1`] = ` 356 |
371 |
395 | 415 | Fork me on GitHub 416 | 417 |
418 |
419 | `; 420 | 421 | exports[`on right-bottom position 1`] = ` 422 |
438 |
462 | 482 | Fork me on GitHub 483 | 484 |
485 |
486 | `; 487 | 488 | exports[`with black color 1`] = ` 489 |
504 |
528 | 548 | Fork me on GitHub 549 | 550 |
551 |
552 | `; 553 | 554 | exports[`with green color 1`] = ` 555 |
570 |
594 | 614 | Fork me on GitHub 615 | 616 |
617 |
618 | `; 619 | 620 | exports[`with orange color 1`] = ` 621 |
636 |
660 | 680 | Fork me on GitHub 681 | 682 |
683 |
684 | `; 685 | 686 | exports[`with red color 1`] = ` 687 |
702 |
726 | 746 | Fork me on GitHub 747 | 748 |
749 |
750 | `; 751 | -------------------------------------------------------------------------------- /storybook/addons.js: -------------------------------------------------------------------------------- 1 | import 'storybook-addon-specifications/register'; 2 | import '@storybook/addon-actions/register'; 3 | import '@storybook/addon-links/register'; 4 | -------------------------------------------------------------------------------- /storybook/config.js: -------------------------------------------------------------------------------- 1 | import { configure } from '@storybook/react'; 2 | 3 | const req = require.context('./__tests__/', true, /stories\.js$/); 4 | 5 | function loadStories() { 6 | req.keys().forEach(req); 7 | } 8 | configure(loadStories, module); 9 | -------------------------------------------------------------------------------- /storybook/facade.js: -------------------------------------------------------------------------------- 1 | import { storiesOf as storiesOfReal } from '@storybook/react'; 2 | 3 | import { action as actionReal } from '@storybook/addon-actions'; 4 | 5 | import { linkTo as linkToReal } from '@storybook/addon-links'; 6 | 7 | import { 8 | specs as specsReal, 9 | describe as describeReal, 10 | it as itReal, 11 | beforeEach as beforeEachReal, 12 | before as beforeReal, 13 | after as afterReal, 14 | afterEach as afterEachReal, 15 | xit as xitReal, 16 | fit as fitReal, 17 | xdescribe as xdescribeReal, 18 | } from 'storybook-addon-specifications'; 19 | 20 | export const expect = require('expect'); // eslint-disable-line global-require 21 | 22 | export const storiesOf = storiesOfReal; 23 | export const action = actionReal; 24 | export const linkTo = linkToReal; 25 | export const specs = specsReal; 26 | export const describe = describeReal; 27 | export const it = itReal; 28 | 29 | export const beforeEach = beforeEachReal; 30 | export const afterEach = afterEachReal; 31 | export const before = beforeReal; 32 | export const after = afterReal; 33 | 34 | export const xit = xitReal; 35 | export const fit = fitReal; 36 | export const xdescribe = xdescribeReal; 37 | export const snapshot = () => {}; 38 | -------------------------------------------------------------------------------- /storybook/webpack.config.js: -------------------------------------------------------------------------------- 1 | require('babel-register'); 2 | 3 | const path = require('path'); 4 | 5 | module.exports = { 6 | module: { 7 | rules: [ 8 | { 9 | test: /\.js?$/, 10 | include: path.join(__dirname, '../src'), 11 | exclude: path.join(__dirname, 'node_modules'), 12 | loader: 'babel-loader', 13 | options: { 14 | plugins: ['react-hot-loader/babel'], 15 | }, 16 | }, 17 | ], 18 | }, 19 | externals: { 20 | jsdom: 'window', 21 | cheerio: 'window', 22 | 'react/lib/ExecutionEnvironment': true, 23 | 'react/lib/ReactContext': 'window', 24 | 'react/addons': true, 25 | }, 26 | }; 27 | --------------------------------------------------------------------------------