react-kofi-overlay 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +91 -0
- package/dist/Donate.d.ts +56 -0
- package/dist/Donate.js +70 -0
- package/dist/Donate.js.map +1 -0
- package/dist/bundle.js +11496 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/main.css +84 -0
- package/img/kofi_donation_widget_setup.png +0 -0
- package/package.json +35 -0
- package/src/Donate.module.scss +120 -0
- package/src/Donate.tsx +122 -0
- package/src/declarations.d.ts +4 -0
- package/src/index.tsx +3 -0
- package/tsconfig.json +16 -0
- package/webpack.config.js +43 -0
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Donate = void 0;
|
|
7
|
+
var Donate_1 = __importDefault(require("./Donate"));
|
|
8
|
+
exports.Donate = Donate_1.default;
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":";;;;;;AAAA,oDAA8B;AAEjB,QAAA,MAAM,GAAG,gBAAO,CAAA"}
|
package/dist/main.css
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
@keyframes kF0g9az8fVG6kOqOMufc {
|
|
2
|
+
from {
|
|
3
|
+
translate: 0 200%;
|
|
4
|
+
opacity: 0; }
|
|
5
|
+
to {
|
|
6
|
+
translate: 0;
|
|
7
|
+
opacity: 1; } }
|
|
8
|
+
|
|
9
|
+
.QSEpZEcKR0JDQr2RBSst {
|
|
10
|
+
display: inline-block;
|
|
11
|
+
background-color: #29abe0;
|
|
12
|
+
color: white;
|
|
13
|
+
padding: 0.5em 1em;
|
|
14
|
+
border-radius: 2em;
|
|
15
|
+
font-weight: bold; }
|
|
16
|
+
.QSEpZEcKR0JDQr2RBSst:hover {
|
|
17
|
+
background-color: #3eb3e3; }
|
|
18
|
+
.QSEpZEcKR0JDQr2RBSst:active {
|
|
19
|
+
background-color: #259aca; }
|
|
20
|
+
|
|
21
|
+
.OUfEeoWEwJM1UiF9qYa6 {
|
|
22
|
+
position: fixed;
|
|
23
|
+
z-index: 100;
|
|
24
|
+
width: calc(min(320px, 100%));
|
|
25
|
+
height: calc(min(580px, 95%));
|
|
26
|
+
bottom: 0;
|
|
27
|
+
right: 2em;
|
|
28
|
+
animation: kF0g9az8fVG6kOqOMufc 1s forwards ease-in-out;
|
|
29
|
+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); }
|
|
30
|
+
.OUfEeoWEwJM1UiF9qYa6 iframe {
|
|
31
|
+
width: 100%;
|
|
32
|
+
height: 100%;
|
|
33
|
+
border: 0;
|
|
34
|
+
border-radius: 1em 1em 0 0;
|
|
35
|
+
background-color: white; }
|
|
36
|
+
.OUfEeoWEwJM1UiF9qYa6 .IBUCc6fCjyxRl3Ek8DQA {
|
|
37
|
+
position: absolute;
|
|
38
|
+
right: 0;
|
|
39
|
+
top: 0;
|
|
40
|
+
background-color: white;
|
|
41
|
+
border-color: #ddd;
|
|
42
|
+
border-width: 1px;
|
|
43
|
+
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
|
|
44
|
+
aspect-ratio: 1;
|
|
45
|
+
translate: 33% -33%;
|
|
46
|
+
border-radius: 100%;
|
|
47
|
+
line-height: 0; }
|
|
48
|
+
.OUfEeoWEwJM1UiF9qYa6 .IBUCc6fCjyxRl3Ek8DQA:hover {
|
|
49
|
+
background-color: #e6e6e6; }
|
|
50
|
+
.OUfEeoWEwJM1UiF9qYa6 .IBUCc6fCjyxRl3Ek8DQA:active {
|
|
51
|
+
background-color: #cccccc; }
|
|
52
|
+
.OUfEeoWEwJM1UiF9qYa6 .XH4Q6flr1ggDa4pjIu7O {
|
|
53
|
+
color: gray;
|
|
54
|
+
width: 1.5rem;
|
|
55
|
+
height: 1.5rem; }
|
|
56
|
+
.OUfEeoWEwJM1UiF9qYa6 .efoQ9WoiKsTaNnaKB03U {
|
|
57
|
+
position: absolute;
|
|
58
|
+
bottom: 0;
|
|
59
|
+
left: 0;
|
|
60
|
+
width: 100%;
|
|
61
|
+
background-color: white;
|
|
62
|
+
text-align: center;
|
|
63
|
+
padding: 0.75rem;
|
|
64
|
+
font-size: 0.9rem;
|
|
65
|
+
border-top: 1px solid #ddd;
|
|
66
|
+
font-weight: 600;
|
|
67
|
+
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); }
|
|
68
|
+
.OUfEeoWEwJM1UiF9qYa6 .efoQ9WoiKsTaNnaKB03U a {
|
|
69
|
+
color: black;
|
|
70
|
+
text-shadow: none;
|
|
71
|
+
text-decoration: none; }
|
|
72
|
+
.OUfEeoWEwJM1UiF9qYa6 .efoQ9WoiKsTaNnaKB03U a:hover {
|
|
73
|
+
color: #29abe0; }
|
|
74
|
+
@media (max-width: 480px) {
|
|
75
|
+
.OUfEeoWEwJM1UiF9qYa6 {
|
|
76
|
+
right: 0;
|
|
77
|
+
width: 100%;
|
|
78
|
+
height: 100%; }
|
|
79
|
+
.OUfEeoWEwJM1UiF9qYa6 iframe {
|
|
80
|
+
border-radius: 0; }
|
|
81
|
+
.OUfEeoWEwJM1UiF9qYa6 .IBUCc6fCjyxRl3Ek8DQA {
|
|
82
|
+
translate: initial;
|
|
83
|
+
margin: 0.5rem; } }
|
|
84
|
+
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-kofi-overlay",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React component for accepting donations though Ko-fi without leaving your website",
|
|
5
|
+
"main": "dist/bundle.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
9
|
+
"build": "webpack && tsc"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [],
|
|
12
|
+
"author": "Harrison Liddiard",
|
|
13
|
+
"license": "ISC",
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"classnames": "^2.3.3",
|
|
16
|
+
"react": "^18.2.0",
|
|
17
|
+
"react-dom": "^18.2.0",
|
|
18
|
+
"react-icons": "^4.12.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@babel/core": "^7.23.6",
|
|
22
|
+
"@babel/preset-env": "^7.23.6",
|
|
23
|
+
"@babel/preset-react": "^7.23.3",
|
|
24
|
+
"@babel/preset-typescript": "^7.23.3",
|
|
25
|
+
"@types/react": "^18.2.45",
|
|
26
|
+
"babel-loader": "^9.1.3",
|
|
27
|
+
"css-loader": "^6.8.1",
|
|
28
|
+
"mini-css-extract-plugin": "^2.7.6",
|
|
29
|
+
"node-sass": "^9.0.0",
|
|
30
|
+
"sass-loader": "^13.3.2",
|
|
31
|
+
"typescript": "^5.3.3",
|
|
32
|
+
"webpack": "^5.89.0",
|
|
33
|
+
"webpack-cli": "^5.1.4"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
$kofi-default-color: #29abe0;
|
|
2
|
+
|
|
3
|
+
@keyframes open {
|
|
4
|
+
from {
|
|
5
|
+
translate: 0 200%;
|
|
6
|
+
opacity: 0;
|
|
7
|
+
}
|
|
8
|
+
to {
|
|
9
|
+
translate: 0;
|
|
10
|
+
opacity: 1;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.donateBtn {
|
|
15
|
+
display: inline-block;
|
|
16
|
+
background-color: $kofi-default-color;
|
|
17
|
+
color: white;
|
|
18
|
+
padding: 0.5em 1em;
|
|
19
|
+
border-radius: 2em;
|
|
20
|
+
font-weight: bold;
|
|
21
|
+
|
|
22
|
+
&:hover {
|
|
23
|
+
background-color: mix($kofi-default-color, white, 90%);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&:active {
|
|
27
|
+
background-color: mix($kofi-default-color, black, 90%);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.panel {
|
|
32
|
+
$overlay-shadow: 0 0 5px rgba(0,0,0, 0.1);
|
|
33
|
+
$border-color: #ddd;
|
|
34
|
+
|
|
35
|
+
position: fixed;
|
|
36
|
+
z-index: 100;
|
|
37
|
+
// Prevent Sass from using its built-in `min` function
|
|
38
|
+
// https://github.com/sass/node-sass/issues/2815#issuecomment-575926329
|
|
39
|
+
width: calc(min(320px, 100%));
|
|
40
|
+
height: calc(min(580px, 95%));
|
|
41
|
+
bottom: 0;
|
|
42
|
+
right: 2em;
|
|
43
|
+
animation: open 1s forwards ease-in-out;
|
|
44
|
+
box-shadow: 0 0 10px rgba(0,0,0, 0.5);
|
|
45
|
+
|
|
46
|
+
iframe {
|
|
47
|
+
width: 100%;
|
|
48
|
+
height: 100%;
|
|
49
|
+
border: 0;
|
|
50
|
+
border-radius: 1em 1em 0 0;
|
|
51
|
+
background-color: white;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.closeBtn {
|
|
55
|
+
position: absolute;
|
|
56
|
+
right: 0;
|
|
57
|
+
top: 0;
|
|
58
|
+
background-color: white;
|
|
59
|
+
border-color: $border-color;
|
|
60
|
+
border-width: 1px;
|
|
61
|
+
box-shadow: $overlay-shadow;
|
|
62
|
+
aspect-ratio: 1;
|
|
63
|
+
translate: 33% -33%;
|
|
64
|
+
border-radius: 100%;
|
|
65
|
+
line-height: 0;
|
|
66
|
+
|
|
67
|
+
&:hover {
|
|
68
|
+
background-color: mix(white, black, 90%);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
&:active {
|
|
72
|
+
background-color: mix(white, black, 80%);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.closeIcon {
|
|
77
|
+
color: gray;
|
|
78
|
+
width: 1.5rem;
|
|
79
|
+
height: 1.5rem;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.profileLink {
|
|
83
|
+
position: absolute;
|
|
84
|
+
bottom: 0;
|
|
85
|
+
left: 0;
|
|
86
|
+
width: 100%;
|
|
87
|
+
background-color: white;
|
|
88
|
+
text-align: center;
|
|
89
|
+
padding: 0.75rem;
|
|
90
|
+
font-size: 0.9rem;
|
|
91
|
+
border-top: 1px solid $border-color;
|
|
92
|
+
font-weight: 600;
|
|
93
|
+
box-shadow: $overlay-shadow;
|
|
94
|
+
|
|
95
|
+
a {
|
|
96
|
+
color: black;
|
|
97
|
+
text-shadow: none;
|
|
98
|
+
text-decoration: none;
|
|
99
|
+
|
|
100
|
+
&:hover {
|
|
101
|
+
color: $kofi-default-color;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@media (max-width: 480px) {
|
|
107
|
+
right: 0;
|
|
108
|
+
width: 100%;
|
|
109
|
+
height: 100%;
|
|
110
|
+
|
|
111
|
+
iframe {
|
|
112
|
+
border-radius: 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.closeBtn {
|
|
116
|
+
translate: initial;
|
|
117
|
+
margin: 0.5rem;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
package/src/Donate.tsx
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import React, { useState, CSSProperties } from 'react'
|
|
4
|
+
import classes from 'classnames'
|
|
5
|
+
|
|
6
|
+
import s from './Donate.module.scss'
|
|
7
|
+
import { IconContext } from 'react-icons'
|
|
8
|
+
import { BsX as CloseIcon } from 'react-icons/bs'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
export interface StyleDefs<T> {
|
|
12
|
+
/**
|
|
13
|
+
* Donate button – a <button> element.
|
|
14
|
+
*/
|
|
15
|
+
donateBtn?: T
|
|
16
|
+
/**
|
|
17
|
+
* Panel wrapper that popus up when donate button is clicked. By default,
|
|
18
|
+
* the panel is anchored to the bottom right of the viewport on desktop and
|
|
19
|
+
* full screen on mobile.
|
|
20
|
+
*/
|
|
21
|
+
panel?: T
|
|
22
|
+
/**
|
|
23
|
+
* Button to close the donate panel.
|
|
24
|
+
*/
|
|
25
|
+
closeBtn?: T
|
|
26
|
+
/**
|
|
27
|
+
* (X) icon within the panel close button.
|
|
28
|
+
*/
|
|
29
|
+
closeIcon?: T
|
|
30
|
+
/**
|
|
31
|
+
* Link to your Ko-fi profile. By default, it's anchored to the bottom of the donate panel.
|
|
32
|
+
*/
|
|
33
|
+
profileLink?: T
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface DonateProps {
|
|
37
|
+
/**
|
|
38
|
+
* Child nodes of the donate button. E.g., "Support me on Ko-fi"
|
|
39
|
+
*/
|
|
40
|
+
children: React.ReactNode
|
|
41
|
+
/**
|
|
42
|
+
* Your Ko-fi profile name. (ko-fi.com/[username])
|
|
43
|
+
*/
|
|
44
|
+
username: string
|
|
45
|
+
/**
|
|
46
|
+
* Optional custom class names to apply to the component.
|
|
47
|
+
*/
|
|
48
|
+
classNames?: StyleDefs<string>
|
|
49
|
+
/**
|
|
50
|
+
* Optional custom styles to apply to the component.
|
|
51
|
+
*/
|
|
52
|
+
styles?: StyleDefs<CSSProperties>
|
|
53
|
+
/**
|
|
54
|
+
* Optional function to be called when the donation form is opened or closed.
|
|
55
|
+
*/
|
|
56
|
+
onToggle?: (open: boolean) => void
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Component to display a button that opens a Ko-fi donation panel when clicked.
|
|
61
|
+
*
|
|
62
|
+
* @component
|
|
63
|
+
* @example
|
|
64
|
+
* <Donate username="liddiard">
|
|
65
|
+
* Support My Work
|
|
66
|
+
* </Donate>
|
|
67
|
+
*/
|
|
68
|
+
export default function Donate({
|
|
69
|
+
children,
|
|
70
|
+
username,
|
|
71
|
+
classNames = {},
|
|
72
|
+
styles = {},
|
|
73
|
+
onToggle = () => {}
|
|
74
|
+
}: DonateProps) {
|
|
75
|
+
const baseUrl = `https://ko-fi.com/${username}`
|
|
76
|
+
const [open, setOpen] = useState(false)
|
|
77
|
+
|
|
78
|
+
const handleOpen = (isOpen: boolean) => {
|
|
79
|
+
setOpen(isOpen)
|
|
80
|
+
onToggle(isOpen)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<>
|
|
85
|
+
<button
|
|
86
|
+
className={classes(s.donateBtn, classNames.donateBtn)}
|
|
87
|
+
style={styles.donateBtn}
|
|
88
|
+
onClick={() => handleOpen(true)}
|
|
89
|
+
>
|
|
90
|
+
{children}
|
|
91
|
+
</button>
|
|
92
|
+
{open ?
|
|
93
|
+
<div
|
|
94
|
+
className={classes(s.panel, classNames.panel)}
|
|
95
|
+
style={styles.panel}
|
|
96
|
+
>
|
|
97
|
+
<button
|
|
98
|
+
className={classes(s.closeBtn, classNames.closeBtn)}
|
|
99
|
+
style={styles.closeBtn}
|
|
100
|
+
onClick={() => handleOpen(false)}
|
|
101
|
+
>
|
|
102
|
+
<IconContext.Provider value={{
|
|
103
|
+
className: classes(s.closeIcon, classNames.closeIcon),
|
|
104
|
+
style: styles.closeIcon
|
|
105
|
+
}}>
|
|
106
|
+
<CloseIcon title="Close" />
|
|
107
|
+
</IconContext.Provider>
|
|
108
|
+
</button>
|
|
109
|
+
<iframe src={`${baseUrl}?hidefeed=true&widget=true&embed=true`} />
|
|
110
|
+
<div
|
|
111
|
+
className={classes(s.profileLink, classNames.profileLink)}
|
|
112
|
+
style={styles.profileLink}
|
|
113
|
+
>
|
|
114
|
+
<a href={baseUrl} target="_blank" rel="noreferrer">
|
|
115
|
+
ko-fi.com/{username}
|
|
116
|
+
</a>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
: null}
|
|
120
|
+
</>
|
|
121
|
+
)
|
|
122
|
+
}
|
package/src/index.tsx
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"outDir": "./dist/",
|
|
4
|
+
"sourceMap": true,
|
|
5
|
+
"noImplicitAny": true,
|
|
6
|
+
"module": "commonjs",
|
|
7
|
+
"target": "es5",
|
|
8
|
+
"jsx": "react",
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"declaration": true,
|
|
11
|
+
},
|
|
12
|
+
"include": [
|
|
13
|
+
"./src/**/*",
|
|
14
|
+
"src/declarations.d.ts"
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
entry: './src/index.tsx',
|
|
5
|
+
mode: 'none',
|
|
6
|
+
module: {
|
|
7
|
+
rules: [
|
|
8
|
+
{
|
|
9
|
+
test: /\.(ts|tsx)$/,
|
|
10
|
+
exclude: /node_modules/,
|
|
11
|
+
use: {
|
|
12
|
+
loader: 'babel-loader',
|
|
13
|
+
options: {
|
|
14
|
+
presets: [
|
|
15
|
+
'@babel/preset-env',
|
|
16
|
+
'@babel/preset-react',
|
|
17
|
+
'@babel/preset-typescript',
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
test: /\.scss$/,
|
|
24
|
+
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
resolve: {
|
|
29
|
+
extensions: ['.tsx', '.ts', '.js'],
|
|
30
|
+
},
|
|
31
|
+
output: {
|
|
32
|
+
filename: 'bundle.js',
|
|
33
|
+
path: __dirname + '/dist',
|
|
34
|
+
libraryTarget: 'umd',
|
|
35
|
+
library: 'KofiDonate',
|
|
36
|
+
umdNamedDefine: true,
|
|
37
|
+
},
|
|
38
|
+
plugins: [new MiniCssExtractPlugin()],
|
|
39
|
+
externals: {
|
|
40
|
+
react: 'react',
|
|
41
|
+
'react-dom': 'react-dom',
|
|
42
|
+
},
|
|
43
|
+
};
|