/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 |
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 |
67 | `;
68 |
69 | exports[`handle unexist color with default 1`] = `
70 |
133 | `;
134 |
135 | exports[`handle unexist position with default 1`] = `
136 |
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 |
286 | `;
287 |
288 | exports[`on left-bottom position 1`] = `
289 |
353 | `;
354 |
355 | exports[`on right position 1`] = `
356 |
419 | `;
420 |
421 | exports[`on right-bottom position 1`] = `
422 |
486 | `;
487 |
488 | exports[`with black color 1`] = `
489 |
552 | `;
553 |
554 | exports[`with green color 1`] = `
555 |
618 | `;
619 |
620 | exports[`with orange color 1`] = `
621 |
684 | `;
685 |
686 | exports[`with red color 1`] = `
687 |
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 |
--------------------------------------------------------------------------------